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