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