]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
16be5b55abd8fda7e0376e214a0b19b639a5588d
[tmp/jakarta-migration.git] /
1 /**     \r
2  * QueryManagerNuxeoImpl.java\r
3  *\r
4  * {Purpose of This Class}\r
5  *\r
6  * {Other Notes Relating to This Class (Optional)}\r
7  *\r
8  * $LastChangedBy: $\r
9  * $LastChangedRevision: $\r
10  * $LastChangedDate: $\r
11  *\r
12  * This document is a part of the source code and related artifacts\r
13  * for CollectionSpace, an open source collections management system\r
14  * for museums and related institutions:\r
15  *\r
16  * http://www.collectionspace.org\r
17  * http://wiki.collectionspace.org\r
18  *\r
19  * Copyright © 2009 {Contributing Institution}\r
20  *\r
21  * Licensed under the Educational Community License (ECL), Version 2.0.\r
22  * You may not use this file except in compliance with this License.\r
23  *\r
24  * You may obtain a copy of the ECL 2.0 License at\r
25  * https://source.collectionspace.org/collection-space/LICENSE.txt\r
26  */\r
27 package org.collectionspace.services.common.query.nuxeo;\r
28 \r
29 import org.slf4j.Logger;\r
30 import org.slf4j.LoggerFactory;\r
31 \r
32 import java.util.regex.Pattern;\r
33 \r
34 import org.nuxeo.ecm.core.api.DocumentModel;\r
35 import org.nuxeo.ecm.core.api.DocumentModelList;\r
36 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;\r
37 import org.nuxeo.ecm.core.client.NuxeoClient;\r
38 \r
39 import org.collectionspace.services.jaxb.InvocableJAXBSchema;\r
40 import org.collectionspace.services.nuxeo.client.java.NuxeoConnector;\r
41 import org.collectionspace.services.client.IQueryManager;\r
42 import org.collectionspace.services.common.invocable.Invocable;\r
43 import org.collectionspace.services.common.invocable.InvocableUtils;\r
44 import org.collectionspace.services.common.storage.DatabaseProductType;\r
45 import org.collectionspace.services.common.storage.JDBCTools;\r
46 \r
47 public class QueryManagerNuxeoImpl implements IQueryManager {\r
48 \r
49         private static String ECM_FULLTEXT_LIKE = "ecm:fulltext"\r
50                         + SEARCH_TERM_SEPARATOR + IQueryManager.SEARCH_LIKE;\r
51         private static String SEARCH_LIKE_FORM = null;\r
52 \r
53         private final Logger logger = LoggerFactory\r
54                         .getLogger(QueryManagerNuxeoImpl.class);\r
55 \r
56         // Consider that letters, letter-markers, numbers, '_' and apostrophe are\r
57         // words\r
58         private static Pattern nonWordChars = Pattern\r
59                         .compile("[^\\p{L}\\p{M}\\p{N}_']");\r
60         private static Pattern unescapedDblQuotes = Pattern.compile("(?<!\\\\)\"");\r
61         private static Pattern unescapedSingleQuote = Pattern.compile("(?<!\\\\)'");\r
62         private static Pattern kwdSearchProblemChars = Pattern\r
63                         .compile("[\\:\\(\\)]");\r
64         private static Pattern kwdSearchHyphen = Pattern.compile(" - ");\r
65 \r
66         private static String getLikeForm() {\r
67                 if (SEARCH_LIKE_FORM == null) {\r
68                         try {\r
69                                 DatabaseProductType type = JDBCTools.getDatabaseProductType();\r
70                                 if (type == DatabaseProductType.MYSQL) {\r
71                                         SEARCH_LIKE_FORM = IQueryManager.SEARCH_LIKE;\r
72                                 } else if (type == DatabaseProductType.POSTGRESQL) {\r
73                                         SEARCH_LIKE_FORM = IQueryManager.SEARCH_ILIKE;\r
74                                 }\r
75                         } catch (Exception e) {\r
76                                 SEARCH_LIKE_FORM = IQueryManager.SEARCH_LIKE;\r
77                         }\r
78                 }\r
79                 return SEARCH_LIKE_FORM;\r
80         }\r
81 \r
82         // TODO: This is currently just an example fixed query. This should\r
83         // eventually be\r
84         // removed or replaced with a more generic method.\r
85         /*\r
86          * (non-Javadoc)\r
87          * \r
88          * @see\r
89          * org.collectionspace.services.common.query.IQueryManager#execQuery(java\r
90          * .lang.String)\r
91          */\r
92         @Override\r
93         @Deprecated\r
94         public void execQuery(String queryString) {\r
95                 NuxeoClient client = null;\r
96                 try {\r
97                         client = NuxeoConnector.getInstance().getClient();\r
98                         RepositoryInstance repoSession = client.openRepository();\r
99 \r
100                         DocumentModelList docModelList = repoSession\r
101                                         .query("SELECT * FROM Relation WHERE relation:relationtype.documentId1='updated-Subject-1'");\r
102                         // DocumentModelList docModelList =\r
103                         // repoSession.query("SELECT * FROM Relation");\r
104                         // DocumentModelList docModelList =\r
105                         // repoSession.query("SELECT * FROM CollectionObject WHERE collectionobject:objectNumber='objectNumber-1251305545865'");\r
106                         for (DocumentModel docModel : docModelList) {\r
107                                 System.out\r
108                                                 .println("--------------------------------------------");\r
109                                 System.out.println(docModel.getPathAsString());\r
110                                 System.out.println(docModel.getName());\r
111                                 System.out.println(docModel.getPropertyValue("dc:title"));\r
112                                 // System.out.println("documentId1=" +\r
113                                 // docModel.getProperty("relation",\r
114                                 // "relationtype/documentId1").toString());\r
115                         }\r
116 \r
117                 } catch (Exception e) {\r
118                         // TODO Auto-generated catch block\r
119                         e.printStackTrace();\r
120                 }\r
121         }\r
122 \r
123         @Override\r
124         public String createWhereClauseFromAdvancedSearch(String advancedSearch) {\r
125                 String result = null;\r
126                 //\r
127                 // Process search term.  FIXME: REM - Do we need to perform and string filtering here?\r
128                 //\r
129                 if (advancedSearch != null && !advancedSearch.isEmpty()) {\r
130                         StringBuffer advancedSearchWhereClause = new StringBuffer(\r
131                                         advancedSearch);\r
132                         result = advancedSearchWhereClause.toString();\r
133                 }\r
134                 \r
135                 return result;\r
136         }\r
137 \r
138         /*\r
139          * (non-Javadoc)\r
140          * \r
141          * @see org.collectionspace.services.common.query.IQueryManager#\r
142          * createWhereClauseFromKeywords(java.lang.String)\r
143          */\r
144         // TODO handle keywords containing escaped punctuation chars, then we need\r
145         // to qualify the\r
146         // search by matching on the fulltext.simpletext field.\r
147         // TODO handle keywords containing unescaped double quotes by matching the\r
148         // phrase\r
149         // against the fulltext.simpletext field.\r
150         // Both these require using JDBC, since we cannot get to the fulltext table\r
151         // in NXQL\r
152         @Override\r
153         public String createWhereClauseFromKeywords(String keywords) {\r
154                 String result = null;\r
155                 StringBuffer fullTextWhereClause = new StringBuffer(SEARCH_GROUP_OPEN);\r
156                 // StringBuffer phraseWhereClause = new StringBuffer(SEARCH_GROUP_OPEN);\r
157                 boolean phrasesToAdd = false;\r
158                 // Split on unescaped double quotes to handle phrases\r
159                 String[] phrases = unescapedDblQuotes.split(keywords.trim());\r
160                 boolean first = true;\r
161                 for (String phrase : phrases) {\r
162                         String trimmed = phrase.trim();\r
163                         // Ignore empty strings from match, or goofy input\r
164                         if (trimmed.isEmpty())\r
165                                 continue;\r
166                         // Add the phrase to the string to pass in for full text matching.\r
167                         // Note that we can pass in a set of words and it will do the OR for\r
168                         // us.\r
169                         if (first) {\r
170                                 fullTextWhereClause.append(ECM_FULLTEXT_LIKE + "'");\r
171                                 first = false;\r
172                         } else {\r
173                                 fullTextWhereClause.append(SEARCH_TERM_SEPARATOR);\r
174                         }\r
175                         // ignore the special chars except single quote here - can't hurt\r
176                         // TODO this should become a special function that strips things the\r
177                         // fulltext will ignore, including non-word chars and too-short\r
178                         // words,\r
179                         // and escaping single quotes. Can return a boolean for anything\r
180                         // stripped,\r
181                         // which triggers the back-up search. We can think about whether\r
182                         // stripping\r
183                         // short words not in a quoted phrase should trigger the backup.\r
184                         trimmed = unescapedSingleQuote.matcher(trimmed).replaceAll("\\\\'");\r
185                         // If there are non-word chars in the phrase, we need to match the\r
186                         // phrase exactly against the fulltext table for this object\r
187                         // if(nonWordChars.matcher(trimmed).matches()) {\r
188                         // }\r
189                         // Replace problem chars with spaces. Patches CSPACE-4147,\r
190                         // CSPACE-4106\r
191                         trimmed = kwdSearchProblemChars.matcher(trimmed).replaceAll(" ");\r
192                         trimmed = kwdSearchHyphen.matcher(trimmed).replaceAll(" ");\r
193 \r
194                         fullTextWhereClause.append(trimmed);\r
195                         if (logger.isTraceEnabled() == true) {\r
196                                 logger.trace("Current built whereClause is: "\r
197                                                 + fullTextWhereClause.toString());\r
198                         }\r
199                 }\r
200                 if (first) {\r
201                         throw new RuntimeException(\r
202                                         "No usable keywords specified in string:[" + keywords + "]");\r
203                 }\r
204                 fullTextWhereClause.append("'" + SEARCH_GROUP_CLOSE);\r
205 \r
206                 result = fullTextWhereClause.toString();\r
207                 if (logger.isDebugEnabled()) {\r
208                         logger.debug("Final built WHERE clause is: " + result);\r
209                 }\r
210 \r
211                 return result;\r
212         }\r
213 \r
214         /*\r
215          * (non-Javadoc)\r
216          * \r
217          * @see org.collectionspace.services.common.query.IQueryManager#\r
218          * createWhereClauseFromKeywords(java.lang.String)\r
219          */\r
220         // TODO handle keywords containing escaped punctuation chars, then we need\r
221         // to qualify the\r
222         // search by matching on the fulltext.simpletext field.\r
223         // TODO handle keywords containing unescaped double quotes by matching the\r
224         // phrase\r
225         // against the fulltext.simpletext field.\r
226         // Both these require using JDBC, since we cannot get to the fulltext table\r
227         // in NXQL\r
228         @Override\r
229         public String createWhereClauseForPartialMatch(String field,\r
230                         String partialTerm) {\r
231                 String trimmed = (partialTerm == null) ? "" : partialTerm.trim();\r
232                 if (trimmed.isEmpty()) {\r
233                         throw new RuntimeException("No partialTerm specified.");\r
234                 }\r
235                 if (field == null || field.isEmpty()) {\r
236                         throw new RuntimeException("No match field specified.");\r
237                 }\r
238                 String ptClause = field + getLikeForm() + "'%"\r
239                                 + unescapedSingleQuote.matcher(trimmed).replaceAll("\\\\'")\r
240                                 + "%'";\r
241                 return ptClause;\r
242         }\r
243 \r
244         /**\r
245          * Creates a filtering where clause from docType, for invocables.\r
246          * \r
247          * @param docType\r
248          *            the docType\r
249          * \r
250          * @return the string\r
251          */\r
252         @Override\r
253         public String createWhereClauseForInvocableByDocType(String schema,\r
254                         String docType) {\r
255                 String trimmed = (docType == null) ? "" : docType.trim();\r
256                 if (trimmed.isEmpty()) {\r
257                         throw new RuntimeException("No docType specified.");\r
258                 }\r
259                 if (schema == null || schema.isEmpty()) {\r
260                         throw new RuntimeException("No match schema specified.");\r
261                 }\r
262                 String wClause = schema + ":" + InvocableJAXBSchema.FOR_DOC_TYPES\r
263                                 + " = '" + trimmed + "'";\r
264                 return wClause;\r
265         }\r
266 \r
267         /**\r
268          * Creates a filtering where clause from invocation mode, for invocables.\r
269          * \r
270          * @param mode\r
271          *            the mode\r
272          * \r
273          * @return the string\r
274          */\r
275         @Override\r
276         public String createWhereClauseForInvocableByMode(String schema, String mode) {\r
277                 String trimmed = (mode == null) ? "" : mode.trim();\r
278                 if (trimmed.isEmpty()) {\r
279                         throw new RuntimeException("No docType specified.");\r
280                 }\r
281                 if (schema == null || schema.isEmpty()) {\r
282                         throw new RuntimeException("No match schema specified.");\r
283                 }\r
284                 String wClause = InvocableUtils.getPropertyNameForInvocationMode(\r
285                                 schema, trimmed) + " != 0";\r
286                 return wClause;\r
287         }\r
288 \r
289         /**\r
290          * @param input\r
291          * @return true if there were any chars filtered, that will require a backup\r
292          *         qualifying search on the actual text.\r
293          */\r
294         private boolean filterForFullText(String input) {\r
295                 boolean fFilteredChars = false;\r
296 \r
297                 return fFilteredChars;\r
298         }\r
299 }\r