source: MDService2/trunk/MDService2/src/eu/clarin/cmdi/mdservice/model/Query.java @ 1488

Last change on this file since 1488 was 1488, checked in by vronk, 13 years ago

output - method, DOCTYPE, encoding issues (trying to unify for xhtml (but not over all xsls yet); test-suite update

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