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