]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
5372482b77136e48f5c03ba24809e8281937b99e
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.nuxeo.elasticsearch;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import javax.ws.rs.core.HttpHeaders;
13
14 import org.apache.commons.lang3.StringUtils;
15
16 import org.codehaus.jackson.JsonGenerator;
17 import org.codehaus.jackson.JsonNode;
18 import org.codehaus.jackson.map.ObjectMapper;
19 import org.codehaus.jackson.node.ObjectNode;
20 import org.codehaus.jackson.node.TextNode;
21
22 import org.collectionspace.services.common.api.RefNameUtils;
23
24 import org.nuxeo.ecm.automation.jaxrs.io.documents.JsonESDocumentWriter;
25 import org.nuxeo.ecm.core.api.CoreSession;
26 import org.nuxeo.ecm.core.api.DocumentModel;
27 import org.nuxeo.ecm.core.api.DocumentModelList;
28
29 public class CSJsonESDocumentWriter extends JsonESDocumentWriter {
30     private static ObjectMapper objectMapper = new ObjectMapper();
31
32     @Override
33     public void writeDoc(JsonGenerator jg, DocumentModel doc, String[] schemas,
34             Map<String, String> contextParameters, HttpHeaders headers)
35             throws IOException {
36
37         // Compute and store fields that should be indexed with this document in ElasticSearch.
38         // TODO: Make this configurable. This is currently hardcoded for the materials profile and
39         // the Material Order application.
40
41         ObjectNode denormValues = objectMapper.createObjectNode();
42
43         String docType = doc.getType();
44
45         if (docType.startsWith("Materialitem")) {
46             CoreSession session = doc.getCoreSession();
47
48             // Store the csids of media records that reference this material authority item via the
49             // coverage field.
50
51             String refName = (String) doc.getProperty("collectionspace_core", "refName");
52
53             if (StringUtils.isNotEmpty(refName)) {
54                 String escapedRefName = refName.replace("'", "\\'");
55                 String tenantId = (String) doc.getProperty("collectionspace_core", "tenantId");
56                 String mediaQuery = String.format("SELECT * FROM Media WHERE media_common:coverage = '%s' AND ecm:currentLifeCycleState = 'project' AND collectionspace_core:tenantId = '%s' ORDER BY media_common:identificationNumber", escapedRefName, tenantId);
57
58                 DocumentModelList mediaDocs = session.query(mediaQuery);
59                 List<JsonNode> mediaCsids = new ArrayList<JsonNode>();
60
61                 if (mediaDocs.size() > 0) {
62                     Iterator<DocumentModel> iterator = mediaDocs.iterator();
63
64                     while (iterator.hasNext()) {
65                         DocumentModel mediaDoc = iterator.next();
66
67                         if (isMediaPublished(mediaDoc)) {
68                             String mediaCsid = (String) mediaDoc.getName();
69
70                             mediaCsids.add(new TextNode(mediaCsid));
71                         }
72                     }
73                 }
74
75                 denormValues.putArray("mediaCsid").addAll(mediaCsids);
76             }
77
78             // Compute the title of the record for the public browser, and store it so that it can
79             // be used for sorting ES query results.
80
81             String title = computeTitle(doc);
82
83             if (title != null) {
84                 denormValues.put("title", title);
85             }
86
87             List<Map<String, Object>> termGroups = (List<Map<String, Object>>) doc.getProperty("materials_common", "materialTermGroupList");
88             List<String> commercialNames = findTermDisplayNamesWithFlag(termGroups, "commercial");
89             List<String> commonNames = findTermDisplayNamesWithFlag(termGroups, "common");
90
91             // Find and store the commercial names and common names for this item. This simplifies
92             // search and display in the Material Order application.
93
94             if (commercialNames.size() > 0) {
95                 denormValues.putArray("commercialNames").addAll(jsonNodes(commercialNames));
96             }
97
98             if (commonNames.size() > 0) {
99                 denormValues.putArray("commonNames").addAll(jsonNodes(commonNames));
100             }
101
102             // Combine term creator organizations and term editor organizations into a holding
103             // institutions field.
104
105             Set<String> holdingInstitutions = new HashSet<String>();
106
107             holdingInstitutions.addAll(getTermAttributionContributors(doc));
108             holdingInstitutions.addAll(getTermAttributionEditors(doc));
109
110             if (holdingInstitutions.size() > 0) {
111                 denormValues.putArray("holdingInstitutions").addAll(jsonNodes(holdingInstitutions));
112             }
113         }
114
115         // Below is sample code for denormalizing fields from the computed current location (place
116         // item) into collection object documents. This was written for the public browser
117         // prototype for public art.
118
119         /*
120         if (docType.startsWith("CollectionObject")) {
121             CoreSession session = doc.getCoreSession();
122
123             String refName = (String) doc.getProperty("collectionobjects_common", "computedCurrentLocation");
124
125             if (StringUtils.isNotEmpty(refName)) {
126                 String escapedRefName = refName.replace("'", "\\'");
127                 String placeQuery = String.format("SELECT * FROM PlaceitemTenant5000 WHERE places_common:refName = '%s'", escapedRefName);
128
129                 DocumentModelList placeDocs = session.query(placeQuery, 1);
130
131                 if (placeDocs.size() > 0) {
132                     DocumentModel placeDoc = placeDocs.get(0);
133
134                     String placementType = (String) placeDoc.getProperty("places_publicart:placementType").getValue();
135
136                     if (placementType != null) {
137                         denormValues.put("placementType", placementType);
138                     }
139
140                     Property geoRefGroup;
141
142                     try {
143                         geoRefGroup = placeDoc.getProperty("places_common:placeGeoRefGroupList/0");
144                     } catch (PropertyNotFoundException e) {
145                         geoRefGroup = null;
146                     }
147
148                     if (geoRefGroup != null) {
149                         Double decimalLatitude = (Double) geoRefGroup.getValue("decimalLatitude");
150                         Double decimalLongitude = (Double) geoRefGroup.getValue("decimalLongitude");
151
152                         if (decimalLatitude != null && decimalLongitude != null) {
153                             ObjectNode geoPointNode = objectMapper.createObjectNode();
154
155                             geoPointNode.put("lat", decimalLatitude);
156                             geoPointNode.put("lon", decimalLongitude);
157
158                             denormValues.put("geoPoint", geoPointNode);
159                         }
160                     }
161                 }
162             }
163
164             String uri = (String) doc.getProperty("collectionobjects_core", "uri");
165             String csid = uri.substring(uri.lastIndexOf('/') + 1);
166             String mediaQuery = String.format("SELECT media_common:blobCsid, media_common:title FROM Relation WHERE relations_common:subjectCsid = '%s' AND relations_common:objectDocumentType = 'Media'", csid);
167
168             DocumentModelList mediaDocs = session.query(mediaQuery, 1);
169
170             if (mediaDocs.size() > 0) {
171
172             }
173         }
174         */
175
176         jg.writeStartObject();
177
178         writeSystemProperties(jg, doc);
179         writeSchemas(jg, doc, schemas);
180         writeContextParameters(jg, doc, contextParameters);
181         writeDenormValues(jg, doc, denormValues);
182
183         jg.writeEndObject();
184         jg.flush();
185     }
186
187     public void writeDenormValues(JsonGenerator jg, DocumentModel doc, ObjectNode denormValues) throws IOException {
188         if (denormValues != null && denormValues.size() > 0) {
189             if (jg.getCodec() == null) {
190                 jg.setCodec(objectMapper);
191             }
192
193             Iterator<Map.Entry<String, JsonNode>> entries = denormValues.getFields();
194
195             while (entries.hasNext()) {
196                 Map.Entry<String, JsonNode> entry = entries.next();
197
198                 jg.writeFieldName("collectionspace_denorm:" + entry.getKey());
199                 jg.writeTree(entry.getValue());
200             }
201         }
202     }
203
204     /**
205      * Compute a title for the public browser. This needs to be indexed in ES so that it can
206      * be used for sorting. (Even if it's just extracting the primary value.)
207      */
208     private String computeTitle(DocumentModel doc) {
209         List<Map<String, Object>> termGroups = (List<Map<String, Object>>) doc.getProperty("materials_common", "materialTermGroupList");
210         String primaryDisplayName = null;
211
212         if (termGroups.size() > 0) {
213             Map<String, Object> primaryTermGroup = termGroups.get(0);
214             primaryDisplayName = (String) primaryTermGroup.get("termDisplayName");
215         }
216
217         return primaryDisplayName;
218     }
219
220     private String findFirstTermDisplayNameWithFlag(List<Map<String, Object>> termGroups, String flagShortId) {
221         String termDisplayName = null;
222
223         for (Map<String, Object> termGroup : termGroups) {
224             String termFlag = (String) termGroup.get("termFlag");
225
226             if (termFlag != null && termFlag.contains("(" + flagShortId + ")")) {
227                 String candidateTermDisplayName = (String) termGroup.get("termDisplayName");
228
229                 if (StringUtils.isNotEmpty(candidateTermDisplayName)) {
230                     termDisplayName = candidateTermDisplayName;
231                     break;
232                 }
233             }
234         }
235
236         return termDisplayName;
237     }
238
239     private List<String> findTermDisplayNamesWithFlag(List<Map<String, Object>> termGroups, String flagShortId) {
240         List<String> termDisplayNames = new ArrayList<String>();
241
242         for (Map<String, Object> termGroup : termGroups) {
243             String termFlag = (String) termGroup.get("termFlag");
244
245             if (termFlag != null && termFlag.contains("(" + flagShortId + ")")) {
246                 String candidateTermDisplayName = (String) termGroup.get("termDisplayName");
247
248                 if (StringUtils.isNotEmpty(candidateTermDisplayName)) {
249                     termDisplayNames.add(candidateTermDisplayName);
250                 }
251             }
252         }
253
254         return termDisplayNames;
255     }
256
257     private Set<String> getTermAttributionContributors(DocumentModel doc) {
258         Set orgs = new HashSet<String>();
259
260         List<Map<String, Object>> groups = (List<Map<String, Object>>) doc.getProperty("materials_common", "materialTermAttributionContributingGroupList");
261
262         for (Map<String, Object> group : groups) {
263             String org = (String) group.get("materialTermAttributionContributingOrganization");
264
265             orgs.add(org);
266         }
267
268         return orgs;
269     }
270
271     private Set<String> getTermAttributionEditors(DocumentModel doc) {
272         Set orgs = new HashSet<String>();
273
274         List<Map<String, Object>> groups = (List<Map<String, Object>>) doc.getProperty("materials_common", "materialTermAttributionEditingGroupList");
275
276         for (Map<String, Object> group : groups) {
277             String org = (String) group.get("materialTermAttributionEditingOrganization");
278
279             orgs.add(org);
280         }
281
282         return orgs;
283     }
284
285     private boolean isMediaPublished(DocumentModel mediaDoc) {
286         List<String> publishToValues = (List<String>) mediaDoc.getProperty("media_materials", "publishToList");
287         boolean isPublished = false;
288
289         for (int i=0; i<publishToValues.size(); i++) {
290             String value = publishToValues.get(i);
291             String shortId = RefNameUtils.getItemShortId(value);
292
293             if (shortId.equals("all") || shortId.equals("materialorder")) {
294                 isPublished = true;
295                 break;
296             }
297         }
298
299         return isPublished;
300     }
301
302     private List<JsonNode> jsonNodes(Collection<String> values) {
303         List<JsonNode> nodes = new ArrayList<JsonNode>();
304         Iterator<String> iterator = values.iterator();
305
306         while (iterator.hasNext()) {
307             String value = iterator.next();
308
309             nodes.add(new TextNode(value));
310         }
311
312         return nodes;
313     }
314 }