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