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

Last change on this file since 1800 was 1800, checked in by gaba, 12 years ago

FCS first version

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