001/**
002 * Copyright (C) 2014  Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/
003 *
004 * This file is part of Dicoogle/dicoogle.
005 *
006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * Dicoogle/dicoogle is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with Dicoogle.  If not, see <http://www.gnu.org/licenses/>.
018 */
019/** 
020 * Based on a String it will able to separate the strings
021 * and it will be easly extended
022 *
023 * NOTE:
024 * The main proposal of the class is that Search GUI call it
025 * and further for QueryRetrieve Service
026 * 
027 */
028package pt.ua.dicoogle.core;
029
030
031import java.util.ArrayList;
032import java.util.Iterator;
033import java.util.StringTokenizer;
034
035import pt.ua.dicoogle.sdk.utils.TagsStruct;
036
037/**
038 *
039 * @author Luís A. Bastião Silva <bastiao@ua.pt>
040 */
041public class QueryExpressionBuilder
042{
043
044    private ArrayList <String> tokens = null ;
045
046    private ArrayList <String> tags = null ;
047
048
049
050    public QueryExpressionBuilder(String text, ArrayList tags)
051    {
052        this(text);
053        this.tags = tags ;
054    }
055
056
057    public QueryExpressionBuilder(String freetext)
058    {
059
060            setTokens(new ArrayList<String>());
061
062            freetext = freetext.replace("^", " ");
063
064             StringTokenizer st = new StringTokenizer(freetext);
065
066             /** XXX probably it can be improved, there're some strange charsets
067              * put it up set
068              */
069
070             while (st.hasMoreTokens())
071             {
072               String ss = st.nextToken();
073               if (ss.contains("^"))
074               {
075                    for (String newToken : ss.split("^"))
076                        tokens.add(newToken);
077
078               }
079               else
080                tokens.add(ss);
081             }
082
083
084             /**
085              * Get tags ;
086              * it it allocated in Run Time, so I have instance access to
087              * singletone
088              */
089
090             TagsStruct _tags = TagsStruct.getInstance();
091
092             this.tags = _tags.getDIMAlias();
093
094    }
095
096    /**
097     * @return the tokens
098     */
099    public ArrayList<String> getTokens()
100    {
101        return tokens;
102    }
103
104    /**
105     * @param tokens the tokens to set
106     */
107    public void setTokens(ArrayList<String> tokens)
108    {
109        this.tokens = tokens;
110    }
111
112
113    public String getQueryString()
114    {
115        /** It will be used to call the Lucene - Indexer
116         * It crucial respect the BNF grammer able to search in library
117         */
118        String queryString = "" ;
119
120
121        /** Search in Lucene in freetext is non-Trivial
122         *  There are some constrains by the library Lunce 2.X
123         *  it was implemented with the repeat of fields
124         *
125         *  Get it for free text: "Smith CT", where the tags domain is:
126         *  PatientName and Modality
127         *
128         *  the result should be:
129         *
130         *  (PatientName=Smith OR Modality=Smith) OR
131         *  (PatientName=CT OR Modality=CT)
132         *
133         *  More general expression was:
134         *  (field1=a1 or field2=a1 or field3=a3 .. or fieldn=an) or
135         *  (...)
136         *  (field1=z1 or field2=z2 or field3=z3 .. or fiendn=zn)
137         *
138         *  This way the search will be in free text really
139         *
140         */
141
142        Iterator<String> itTokens = tokens.iterator();
143        Iterator<String> itTags;
144
145        String token = null ;
146
147        /** Build the query string
148         *
149         * Iterating for each token
150         */
151        while(itTokens.hasNext())
152        {
153            /**
154             * Iterating each tags
155             */
156            queryString += "(";
157            String tag = null ;
158
159            token = itTokens.next();
160            itTags = tags.iterator();
161            while (itTags.hasNext())
162            {
163
164                tag = itTags.next();
165                queryString += tag+":"+token ;
166                /**
167                 * If it have next then the logical condition will continue
168                 * in next iteration
169                 */
170                if (itTags.hasNext())
171                {
172                    queryString += " OR ";
173                }
174            }
175            queryString += "OR others:" + token + " )";
176
177            if (itTokens.hasNext())
178            {
179                queryString += " AND ";
180            }
181
182        }
183
184        return queryString;
185    }
186
187    /**
188     * @return the tags
189     */
190    public ArrayList<String> getTags()
191    {
192        return tags;
193    }
194
195    /**
196     * @param tags the tags to set
197     */
198    public void setTags(ArrayList<String> tags)
199    {
200        this.tags = tags;
201    }
202
203}