source: MDService2/branches/MDService_simple3/src/eu/clarin/cmdi/mdservice/model/Query.java @ 1626

Last change on this file since 1626 was 1626, checked in by gaba, 13 years ago
File size: 14.1 KB
Line 
1package eu.clarin.cmdi.mdservice.model;
2
3/**
4 * The main model class, carrying users_query
5 * able to parse and transform the user-string
6 * and execute the query, ie issue appropriate request on the MDRepository
7 * getting the url-wording right from MDRepositoryProxy
8 *   
9 * At the moment just responsible for querying MDRepository
10 * perhaps unify approach for other proxies - subtyping this Class 
11 */
12
13import java.io.IOException;
14import java.net.MalformedURLException;
15import java.net.URL;
16import java.util.HashMap;
17import java.util.Iterator;
18import java.util.Map;
19import java.util.Set;
20
21import javax.xml.parsers.DocumentBuilder;
22import javax.xml.parsers.DocumentBuilderFactory;
23
24import org.apache.log4j.Logger;
25import org.w3c.dom.Document;
26import org.z3950.zing.cql.CQLNode;
27import org.z3950.zing.cql.CQLParseException;
28import org.z3950.zing.cql.CQLParser;
29
30import eu.clarin.cmdi.mdservice.internal.Utils;
31import eu.clarin.cmdi.mdservice.internal.MDTransformer;
32import eu.clarin.cmdi.mdservice.internal.NoStylesheetException;
33
34public class Query {   
35       
36        public static Logger log = Logger.getLogger("Query");
37       
38        public static String COLLECTION = "collection";
39        public static String COLUMNS = "columns";
40        public static String MODEL = "model";
41        public static String VALUES = "values";
42        public static String RECORDSET = "search";
43        public static String RECORD = "record";
44        public static String SRUEXTERN = "sruextern";
45       
46        public static String PARSED = "parsed";
47        public static String UNPARSED = "unparsed";
48        public static String PARSEERROR = "parseerror";
49       
50        private String type;
51       
52        private String syntax = "cql";  /* cql, cmdIndex, xpath */
53        //private String query_string;
54        //private String full_query_string;
55        private CQLNode query_cql;
56        private String msg;
57        /**
58         * temporary default;
59         */
60        //private String collection="";
61        //private String columns="Id,name";
62        //private String startItem = "1";
63        //private String maximumItems = "50";
64        //private String options = null;
65        //private String sort;
66        //private int maxdepth=1;
67       
68        private Map<String,String[]> params = new HashMap<String,String[]>() {{
69                String[] sarr = new String[1];
70                sarr[0] = "1";
71                put("startItem", sarr); 
72                sarr = new String[1];
73                sarr[0] = "50";
74                put("maximumItems", sarr);     
75                sarr = new String[1];
76                sarr[0] = "Id,name";
77                put("columns", sarr);
78                sarr = new String[1];
79                sarr[0] = "1";
80                put("maxdepth", sarr);
81               
82        }};
83       
84        private Map sruMap = null;
85        /**
86         * reference to the result-object
87         */
88        private Result result = new Result(this);
89
90       
91        public Query(String queryString) {             
92                this(queryString, MODEL);
93        }
94
95        /**     
96         * main constructor, with user's querystring and type of the query, and context-collection (at the moment just one)
97         * @param queryString
98         * @param type
99         * @param collection
100         */
101
102        public Query(String queryString, String type, String collection, String columns) {
103                this.type =type;
104                addParam("query", queryString);
105                //if (queryString == null)queryString ="";
106                //setFullQueryString(queryString);
107                setFullQueryString();
108                addParam("collection", collection);
109                addParam("columns",columns);
110        }
111       
112        /**     
113         * main constructor, with user's querystring and type of the query, and context-collection (at the moment just one)
114         * @param queryString
115         * @param type
116         * @param collection
117         */
118
119        public Query(String queryString, String type, String collection) {
120                this( queryString, type, collection, "Id,name");
121        }
122
123        /**     
124         * another constructor, with user's querystring and type of the query;
125         * problematic not setting the collection! 
126         * @param queryString
127         * @param type
128         */
129
130        public Query(String queryString, String type) {
131                this(queryString, type, "");
132        }
133       
134        /**     
135         * another constructor, with user's querystring and type of the query;
136         * @param type
137         * @param _params
138         */
139
140        public Query( String type, Map<String,String[]> _params) {
141               
142                this.type = type;
143                params = _params;
144                this.setFullQueryString();
145        }
146       
147        /**     
148         * another constructor, with user's querystring and type of the query;
149         * @param _params
150         */
151
152        public Query(Map<String,String[]> _params) {
153                this("search", _params);
154                //this("search", _params);
155                /*
156                String query = null , collections = "", columns = "";
157                if (!(_params.get("query")==null)) {
158                        query=(String)params.get("query")[0];
159                } else {
160                        // error
161                        return;
162                }
163                this(queryString, "search", "");
164                params = _params;
165                */
166        }
167       
168        public void setParams(Map<String,String[]> _params){
169                params = _params;
170        }
171       
172        /**
173         * Gets the local parameter map.
174         *
175         * @return
176         */
177        public Map<String,String[]> getParams() {               
178                return params;
179        }
180
181        /**
182         * Add parameter into local parameter map.
183         *
184         * @param key - parameter key
185         * @param value - parameter value
186         */
187        public void addParam(String key, String value){
188                String[] sarr = new String[1];
189                sarr[0] = value;
190                params.put(key, sarr); 
191        }
192        /**
193         * This is for simplified access to the the values of the request-parameters
194         * They are stored in the parameters-map as a String-array,
195         * but in most(?) situations, we expect just a simple string.
196         * @param key
197         * @return
198         */
199        public String getParam(String key) {
200                String v = "";
201                if (!(params.get(key)==null)) v=(String)params.get(key)[0];
202                return v;
203        }
204
205       
206        public Boolean isStatus(String qstatus) {
207                return (qstatus.equals(getStatus()));
208        }
209       
210        public String getStatus() {
211                if (type.equals(Query.RECORDSET) && query_cql== null && (!getParam("query").equals(""))) {
212                        return Query.PARSEERROR;
213                } else {
214                        return Query.UNPARSED;
215                }
216               
217        }
218       
219        public String getType() {
220                return type;
221        }
222
223        public void setType(String type) {
224                this.type = type;
225        }
226
227
228        //public void setFullQueryString(String queryString) {
229        public void setFullQueryString() {
230               
231                String query_string = getParam("query");
232               
233                //if (queryString.trim().length() == 0){
234                //      queryString = null;
235                //}
236               
237                log.debug("QUERY.FULLQUERYSTRING:" + query_string);
238                if (type.equals(RECORDSET) && (query_string.length() > 0)) {   
239                        parse();
240                        //preprocess();
241                }
242                       
243        }
244       
245        /*
246        public String getFullQueryString() {
247                return full_query_string;
248        }
249*/
250        /*
251        public void setCollection(String collection) {
252                if (collection!=null) {
253                        this.collection = collection;
254                }
255        }
256       
257        public String getCollection() {
258                return collection;
259        }
260       
261        public String getColumns() {
262                return columns;
263        }
264       
265        public void setColumns(String columns) {
266                if (columns!=null) {
267                        this.columns = columns;
268                }
269        }
270       
271        public String getOptions() {
272                return options;
273        }
274
275        public void setOptions(String options) {
276                this.options = options;
277        }
278
279        public String getSort() {
280                return sort;
281        }
282
283        public void setSort(String sort) {
284                this.sort = sort;
285        }
286
287        public String getStartItem() {
288                return startItem;
289        }
290       
291        public void setStartItem(String startItem) {
292                if (startItem!=null) {
293                        if (startItem.equals("")){
294                                // sets default startItem
295                                this.startItem = "1";
296                        }else {
297                                this.startItem = startItem;
298                        }
299                }
300        }
301       
302        public String getMaximumItems() {
303                return maximumItems;
304        }
305       
306        public void setMaximumItems(String maximumItems) {
307                if (maximumItems!=null) {
308                        if (maximumItems.equals("")){
309                                this.maximumItems = "50";
310                        } else {
311                                this.maximumItems = maximumItems;       
312                        }
313                }
314        }
315        public void setMaxdepth(int maxdepth) {
316                if (maxdepth > 0) {
317                        this.maxdepth = maxdepth;
318                }
319        }
320
321        public int getMaxdepth() {
322                return maxdepth;
323        }
324*/
325        public void setResult(Result result) {
326                this.result = result;
327        }
328
329
330        public Result getResult() {
331                return result;
332        }
333       
334        public String getMsg() {
335                return msg;
336        }
337
338        public void setMsg(String msg) {
339                this.msg = msg;
340        }
341
342       
343        public Map getSruMap() {
344                return sruMap;
345        }
346
347        public void setSruMap(Map sruMap) {
348                this.sruMap = sruMap;
349        }
350
351       
352        public static String getSimpleQueryString(String querystring) {
353                String[] arr_and = querystring.split(" and ");
354                String simple_form = "";
355                String simple_form_all = "";
356                String rel = "";
357               
358                for( int i=0;i<arr_and.length;i++){
359                        arr_and[i] = arr_and[i].trim();
360                        String[] arr_or = arr_and[i].split(" or ");
361                        simple_form = "";
362                        for( int j=0;j<arr_or.length;j++){
363                                arr_or[j] = arr_or[j].trim();
364                                while (arr_or[j].substring(0,1).equals("(") ) {
365                                        arr_or[j] = arr_or[j].substring(1,arr_or[j].length());
366                                        arr_or[j] = arr_or[j].trim();
367                                }
368                                while ( arr_or[j].substring(arr_or[j].length()-1,arr_or[j].length()).equals(")")){
369                                        arr_or[j] = arr_or[j].substring(0,arr_or[j].length()-1);
370                                        arr_or[j] = arr_or[j].trim();
371                                }
372                                if (j > 0) { 
373                                        rel = " or ";
374                                } else {
375                                        rel = "";
376                                }
377                                simple_form = simple_form + rel + arr_or[j];
378                        }
379                       
380                        if (arr_or.length > 1){
381                                simple_form = "(" + simple_form + ") ";
382                        }
383                        if (i > 0) { 
384                                rel = " and  ";
385                        } else {
386                                rel = "";
387                        }
388                        simple_form_all = simple_form_all + rel + simple_form;
389                       
390                }
391               
392                return simple_form_all;
393        }
394        /**
395         * construct the URL-Param
396         * @return
397         * @throws MalformedURLException
398         * TODO url-encode (especially the query-param) !
399         */
400        public String toURLParam() throws MalformedURLException {
401               
402                String targetRequest;
403               
404                if (type.equals(MODEL)) {
405                        //targetRequest = fromCMDIndex2Xpath() + "&maxdepth=" + getMaxdepth()  ; /* + "&maxdepth=" + getMaxdepth() );  "&collection=" + getCollection() + */
406                        targetRequest = fromCMDIndex2Xpath() + "&maxdepth=" + getParam("maxdepth")  ; /* + "&maxdepth=" + getMaxdepth() );  "&collection=" + getCollection() + */
407                } 
408                else if (type.equals(COLLECTION)) {
409                        targetRequest = getParam("collection") + "&maxdepth=" + getParam("maxdepth")  ; /* + "&maxdepth=" + getMaxdepth() );  "&collection=" + getCollection() + */
410
411                } else if (type.equals(SRUEXTERN)) {
412                        targetRequest = "";//fromCMDIndex2Xpath() + "&maxdepth=" + getMaxdepth()  ; /* + "&maxdepth=" + getMaxdepth() );  "&collection=" + getCollection() + */
413                       
414                        Set set = sruMap.entrySet();
415                        Iterator i = set.iterator();
416                       
417                    while(i.hasNext()){
418                              Map.Entry me = (Map.Entry)i.next();
419                              targetRequest = targetRequest + "&" + me.getKey() + "=" + me.getValue();
420                        }
421                                       
422                } else if (type.equals(VALUES)) {
423                        targetRequest = fromCMDIndex2Xpath() ; /* + "&maxdepth=" + getMaxdepth() );  "&collection=" + getCollection() + */
424                       
425                        if (getParam("startItem") != null) {
426                                targetRequest = targetRequest +  "&startItem=" + getParam("startItem");
427                        }
428                        if (getParam("maximumItems") != null) {
429                                targetRequest = targetRequest +  "&maxItems=" + getParam("maximumItems");
430                        }
431                        if (getParam("sort") != null) {
432                                targetRequest = targetRequest +  "&sort=" + getParam("sort");
433                        }
434                       
435                } else if (type.equals(RECORD)) {
436                        //  2010-07-11 this is just a hack, because url-encoding the handle acted strange
437                        //String corrid = getQueryString().replace('_', '/');
438                        //  2010-12-28 needed for the lucene-index to recognize..
439                                //  probably not the best place to handle -> move to repository: sanitize-query?
440                        String corrid = getParam("query").replace(":","\\:").toLowerCase();
441                        log.debug("Query.toURLParam.corrid=" + corrid);
442                        targetRequest = "//MdSelfLink[ft:query(.,'" + corrid + "')]";                   
443                } else {
444                                if (query_cql == null){
445                                        targetRequest =  "//*" + "&collection=" + getParam("collection");
446                                } else {
447                                        targetRequest = toXPath() + "&collection=" + getParam("collection");   
448                                }
449                                if (!getParam("startItem").equals("")) {
450                                        targetRequest = targetRequest +  "&startItem=" + getParam("startItem");
451                                }
452                                if (!getParam("maximumItems").equals("")) {
453                                        targetRequest = targetRequest +  "&maxItems=" + getParam("maximumItems");
454                                }
455                                if ((!getParam("options").equals(""))) {
456                                        targetRequest = targetRequest +  "&format=xml-" + getParam("options");
457                                }
458                }
459       
460                return targetRequest;
461               
462}
463       
464        /**
465         * tries to parse the full_query_string according the CQL-syntax
466         * if successful returns the root-node of the parse-tree
467         */
468        public CQLNode parse() {
469                 
470          try {
471                CQLParser parser = new CQLParser();             
472                // cannot accept '-' at the CQL beginning
473                String local_full_query_string = getParam("query");
474                local_full_query_string = local_full_query_string.replace("-", "%2D");
475
476                query_cql = parser.parse(local_full_query_string);
477          }
478                catch (CQLParseException e) {
479                        // TODO better handling of failed parse 
480                        setMsg("Query.ParseError-"+ e.getClass() + ": " + e.getMessage());
481                } catch (IOException e) {
482                        // TODO Auto-generated catch block
483                        e.printStackTrace();
484                }
485               
486       
487                return query_cql;
488        }
489       
490        /**
491         */
492        public void  preprocess() {
493                 
494          try { 
495                log.debug(toXCQL());
496                       
497               
498                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
499                DocumentBuilder builder = factory.newDocumentBuilder();
500                Document doc = builder.parse(new org.xml.sax.InputSource(new java.io.StringReader(toXCQL())));
501                       
502                //log.debug("document created");
503                SearchClauses searchclauses = new SearchClauses(doc);
504                //do the processing
505                searchclauses.process();
506                String xml_s = searchclauses.toXML();
507               
508               
509          }
510                catch (Exception e) {
511                        e.printStackTrace();
512                }
513                return;
514        }
515       
516        /**
517         * provides a xml-version of the query (if parsed successfully)
518         * according to the XCQL-schema defined in the SRU/CQL standard
519         * @return
520         */
521        public String toXCQL() {       
522                 return query_cql.toXCQL(0);
523        }
524
525        /**
526         * provides a xpath version of the query, based on the XCQL-version,
527         * applying a stylesheet on the XCQL-version 
528         * @return XPath-query
529         * @throws IOException
530         */
531        public String toXPath() {       
532                MDTransformer transformer = new MDTransformer();
533                transformer.setParams(MDTransformer.createParamsMap("XCQL2XPATH"));
534                try {
535                        return transformer.transformXML(toXCQL());
536                } catch (NoStylesheetException e) {
537                        setMsg("Query.toXPath-"+ e.getClass() + ": " + e.getMessage());
538                        return "";
539                }
540        }
541
542        /**
543         * if the query is just a path-like structure
544         * "transforms" the cmdIndex-format to appropriate XPath, means replace('.', '/') ;)
545         * and resolves back possible profile-prefix
546         * @return
547         */
548        public String fromCMDIndex2Xpath() {
549                String xpath = "";
550                String query_string= getParam("query");
551                if (query_string.contains(":")) {
552                        int delim_index = query_string.indexOf(":");
553                        String profile_name = query_string.substring(0,delim_index );
554                        Termset res = (Termset) Termset.getTermset(profile_name);                         
555                        if (res!=null) {
556                                profile_name= res.getAttr("name");
557                        } 
558                        if (profile_name.equals("")) {
559                                xpath=query_string.substring(delim_index); 
560                        } else {
561                                xpath = profile_name + "//" + query_string.substring(delim_index+1);
562                        }
563                               
564                } else {
565                        xpath = query_string; 
566                }
567                               
568                 return xpath.replace(".", "//"); 
569        }       
570}
Note: See TracBrowser for help on using the repository browser.