]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
77d0d98416134cd27c160e8ff2b31cc26a1cab8d
[tmp/jakarta-migration.git] /
1 /**\r
2  *  This document is a part of the source code and related artifacts\r
3  *  for CollectionSpace, an open source collections management system\r
4  *  for museums and related institutions:\r
5 \r
6  *  http://www.collectionspace.org\r
7  *  http://wiki.collectionspace.org\r
8 \r
9  *  Copyright 2009 University of California at Berkeley\r
10 \r
11  *  Licensed under the Educational Community License (ECL), Version 2.0.\r
12  *  You may not use this file except in compliance with this License.\r
13 \r
14  *  You may obtain a copy of the ECL 2.0 License at\r
15 \r
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt\r
17 \r
18  *  Unless required by applicable law or agreed to in writing, software\r
19  *  distributed under the License is distributed on an "AS IS" BASIS,\r
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
21  *  See the License for the specific language governing permissions and\r
22  *  limitations under the License.\r
23  */\r
24 package org.collectionspace.services.common.vocabulary;\r
25 \r
26 import java.util.ArrayList;\r
27 import java.util.Collection;\r
28 import java.util.HashMap;\r
29 import java.util.Iterator;\r
30 import java.util.List;\r
31 import java.util.Map;\r
32 \r
33 import org.nuxeo.ecm.core.api.ClientException;\r
34 import org.nuxeo.ecm.core.api.DocumentModel;\r
35 import org.nuxeo.ecm.core.api.DocumentModelList;\r
36 import org.slf4j.Logger;\r
37 import org.slf4j.LoggerFactory;\r
38 \r
39 import org.collectionspace.services.common.ServiceMain;\r
40 import org.collectionspace.services.common.context.ServiceContext;\r
41 import org.collectionspace.services.common.authorityref.AuthorityRefDocList;\r
42 import org.collectionspace.services.common.authorityref.AuthorityRefList;\r
43 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;\r
44 import org.collectionspace.services.common.context.ServiceBindingUtils;\r
45 import org.collectionspace.services.common.document.DocumentException;\r
46 import org.collectionspace.services.common.document.DocumentNotFoundException;\r
47 import org.collectionspace.services.common.document.DocumentUtils;\r
48 import org.collectionspace.services.common.document.DocumentWrapper;\r
49 import org.collectionspace.services.common.repository.RepositoryClient;\r
50 import org.collectionspace.services.common.service.ServiceBindingType;\r
51 import org.collectionspace.services.jaxb.AbstractCommonList;\r
52 import org.collectionspace.services.nuxeo.util.NuxeoUtils;\r
53 \r
54 /**\r
55  * RefNameServiceUtils is a collection of services utilities related to refName usage.\r
56  *\r
57  * $LastChangedRevision: $\r
58  * $LastChangedDate: $\r
59  */\r
60 public class RefNameServiceUtils {\r
61 \r
62     private final Logger logger = LoggerFactory.getLogger(RefNameServiceUtils.class);\r
63 \r
64     public static AuthorityRefDocList getAuthorityRefDocs(ServiceContext ctx,\r
65             RepositoryClient repoClient,\r
66             String serviceType,\r
67             String refName,\r
68             int pageSize, int pageNum, boolean computeTotal) throws DocumentException, DocumentNotFoundException {\r
69         AuthorityRefDocList wrapperList = new AuthorityRefDocList();\r
70         AbstractCommonList commonList = (AbstractCommonList) wrapperList;\r
71         commonList.setPageNum(pageNum);\r
72         commonList.setPageSize(pageSize);\r
73         \r
74         List<AuthorityRefDocList.AuthorityRefDocItem> list =\r
75                 wrapperList.getAuthorityRefDocItem();\r
76         TenantBindingConfigReaderImpl tReader =\r
77                 ServiceMain.getInstance().getTenantBindingConfigReader();\r
78         List<ServiceBindingType> servicebindings = tReader.getServiceBindingsByType(ctx.getTenantId(), serviceType);\r
79         if (servicebindings == null || servicebindings.isEmpty()) {\r
80             return null;\r
81         }\r
82         // Need to escape the quotes in the refName\r
83         // TODO What if they are already escaped?\r
84         String escapedRefName = refName.replaceAll("'", "\\\\'");\r
85 //      String domain = \r
86 //              tReader.getTenantBinding(ctx.getTenantId()).getRepositoryDomain();\r
87         ArrayList<String> docTypes = new ArrayList<String>();\r
88         Map<String, ServiceBindingType> queriedServiceBindings = new HashMap<String, ServiceBindingType>();\r
89         Map<String, Map<String, String>> authRefFieldsByService = new HashMap<String, Map<String, String>>();\r
90         StringBuilder whereClause = new StringBuilder();\r
91         boolean fFirst = true;\r
92         List<String> authRefFieldPaths = new ArrayList<String>();\r
93         for (ServiceBindingType sb : servicebindings) {\r
94             authRefFieldPaths =\r
95                     ServiceBindingUtils.getAllPartsPropertyValues(sb,\r
96                     ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);\r
97             if (authRefFieldPaths.isEmpty()) {\r
98                 continue;\r
99             }\r
100             String authRefPath = "";\r
101             String ancestorAuthRefFieldName = "";\r
102             Map<String, String> authRefFields = new HashMap<String, String>();\r
103             for (int i = 0; i < authRefFieldPaths.size(); i++) {\r
104                 // fieldName = DocumentUtils.getDescendantOrAncestor(authRefFields.get(i));\r
105                 authRefPath = authRefFieldPaths.get(i);\r
106                 ancestorAuthRefFieldName = DocumentUtils.getAncestorAuthRefFieldName(authRefFieldPaths.get(i));\r
107                 authRefFields.put(authRefPath, ancestorAuthRefFieldName);\r
108             }\r
109 \r
110             String docType = sb.getObject().getName();\r
111             queriedServiceBindings.put(docType, sb);\r
112             authRefFieldsByService.put(docType, authRefFields);\r
113             docTypes.add(docType);\r
114             /*\r
115             // HACK - need to get qualified properties from the ServiceBinding\r
116             String prefix = "";\r
117             if(docType.equalsIgnoreCase("Intake"))\r
118             prefix = "intakes_common:";\r
119             else if(docType.equalsIgnoreCase("Loanin"))\r
120             prefix = "loansin_common:";\r
121             else if(docType.equalsIgnoreCase("Acquisition"))\r
122             prefix = "acquisitions_common:";\r
123              */\r
124             Collection<String> fields = authRefFields.values();\r
125             for (String field : fields) {\r
126                 // Build up the where clause for each authRef field\r
127                 if (fFirst) {\r
128                     fFirst = false;\r
129                 } else {\r
130                     whereClause.append(" OR ");\r
131                 }\r
132                 //whereClause.append(prefix);\r
133                 whereClause.append(field);\r
134                 whereClause.append("='");\r
135                 whereClause.append(escapedRefName);\r
136                 whereClause.append("'");\r
137             }\r
138         }\r
139         String whereClauseStr = whereClause.toString(); // for debugging\r
140         if (fFirst) // found no authRef fields - nothing to query\r
141         {\r
142             return wrapperList;\r
143         }\r
144         String fullQuery = whereClause.toString(); // for debug\r
145         // Now we have to issue the search\r
146         DocumentWrapper<DocumentModelList> docListWrapper = repoClient.findDocs(ctx,\r
147                 docTypes, whereClause.toString(), pageSize, pageNum, computeTotal);\r
148         // Now we gather the info for each document into the list and return\r
149         DocumentModelList docList = docListWrapper.getWrappedObject();\r
150         // Set num of items in list. this is useful to our testing framework.\r
151         commonList.setItemsInPage(docList.size());\r
152         // set the total result size\r
153         commonList.setTotalItems(docList.totalSize());\r
154         Iterator<DocumentModel> iter = docList.iterator();\r
155         while (iter.hasNext()) {\r
156             DocumentModel docModel = iter.next();\r
157             AuthorityRefDocList.AuthorityRefDocItem ilistItem = new AuthorityRefDocList.AuthorityRefDocItem();\r
158             String csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());\r
159             String docType = docModel.getDocumentType().getName();\r
160             ServiceBindingType sb = queriedServiceBindings.get(docType);\r
161             if (sb == null) {\r
162                 throw new RuntimeException(\r
163                         "getAuthorityRefDocs: No Service Binding for docType: " + docType);\r
164             }\r
165             String serviceContextPath = "/" + sb.getName().toLowerCase() + "/";\r
166             // The id and URI are the same on all doctypes\r
167             ilistItem.setDocId(csid);\r
168             ilistItem.setUri(serviceContextPath + csid);\r
169             ilistItem.setDocType(docType);\r
170             ilistItem.setDocNumber(\r
171                     ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NUMBER_PROP, docModel));\r
172             ilistItem.setDocName(\r
173                     ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NAME_PROP, docModel));\r
174             // Now, we have to loop over the authRefFieldsByService to figure\r
175             // out which field matched this. Ignore multiple matches.\r
176             Map<String,String> matchingAuthRefFields = authRefFieldsByService.get(docType);\r
177             if (matchingAuthRefFields == null || matchingAuthRefFields.isEmpty()) {\r
178                 throw new RuntimeException(\r
179                         "getAuthorityRefDocs: internal logic error: can't fetch authRefFields for DocType.");\r
180             }\r
181             String authRefAncestorField = "";\r
182             String authRefDescendantField = "";\r
183             String sourceField = "";\r
184             boolean fRefFound = false;\r
185             // Use this if we go to qualified field names\r
186             for (String path : matchingAuthRefFields.keySet()) {\r
187                 try {\r
188                     authRefAncestorField = (String) matchingAuthRefFields.get(path);\r
189                     authRefDescendantField = DocumentUtils.getDescendantOrAncestor(path);\r
190                     String[] strings = authRefAncestorField.split(":");\r
191                     if (strings.length != 2) {\r
192                         throw new RuntimeException(\r
193                                 "getAuthorityRefDocs: Bad configuration of path to authority reference field.");\r
194                     }\r
195                     // strings[0] holds a schema name, such as "intakes_common"\r
196                     //\r
197                     // strings[1] holds:\r
198                     // * The name of an authority reference field, such as "depositor";\r
199                     //   or\r
200                     // * The name of an ancestor (e.g. parent, grandparent ...) field,\r
201                     //   such as "fieldCollectors", of a repeatable authority reference\r
202                     //   field, such as "fieldCollector".\r
203                     Object fieldValue = docModel.getProperty(strings[0], strings[1]);\r
204                     fRefFound = refNameFoundInField(refName, fieldValue);\r
205                     if (fRefFound) {\r
206                         sourceField = authRefDescendantField;\r
207                         ilistItem.setSourceField(sourceField);\r
208                         // FIXME Returns only the first field in which the refName is found.\r
209                         // We may want to return all; this may require multiple sourceFields\r
210                         // in the list item schema; or else multiple list items, one per sourceField.\r
211                         // See CSPACE-2863 for a discussion of how this might be handled.\r
212                         break;\r
213                     }\r
214 \r
215                 } catch (ClientException ce) {\r
216                     throw new RuntimeException(\r
217                             "getAuthorityRefDocs: Problem fetching: " + sourceField, ce);\r
218                 }\r
219             }\r
220             // Used before going to schema-qualified field names.\r
221             /*\r
222             for(String field:matchingAuthRefFields){\r
223             try {\r
224             if(refName.equals(docModel.getPropertyValue(field))) {\r
225             ilistItem.setSourceField(field);\r
226             fRefFound = true;\r
227             break;\r
228             }\r
229             } catch(ClientException ce) {\r
230             throw new RuntimeException(\r
231             "getAuthorityRefDocs: Problem fetching: "+field, ce);\r
232             }\r
233             }\r
234              * \r
235              */\r
236             if (!fRefFound) {\r
237                 throw new RuntimeException(\r
238                         "getAuthorityRefDocs: Could not find refname in object:"\r
239                         + docType + ":" + csid);\r
240             }\r
241             list.add(ilistItem);\r
242         }\r
243         return wrapperList;\r
244     }\r
245 \r
246     /*\r
247      * Identifies whether the refName was found in the supplied field.\r
248      *\r
249      * Only works for:\r
250      * * Scalar fields\r
251      * * Repeatable scalar fields (aka multi-valued fields)\r
252      *\r
253      * Does not work for:\r
254      * * Structured fields (complexTypes)\r
255      * * Repeatable structured fields (repeatable complexTypes)\r
256      */\r
257     private static boolean refNameFoundInField(String refName, Object fieldValue) {\r
258 \r
259         boolean result = false;\r
260         if (fieldValue instanceof List) {\r
261             List<String> fieldValueList = (List) fieldValue;\r
262             for (String listItemValue : fieldValueList) {\r
263                 if (refName.equalsIgnoreCase(listItemValue)) {\r
264                     result = true;\r
265                     break;\r
266                 }\r
267 \r
268             }\r
269         } else if (fieldValue instanceof String){\r
270             if (refName.equalsIgnoreCase((String)fieldValue)) {\r
271                 result = true;\r
272             }\r
273         }\r
274         return result;\r
275     }\r
276 }\r
277 \r