]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
35c85b80c6f9c777ce2370157806b7d0d6d437a0
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.common.vocabulary.nuxeo;
25
26 import java.util.Map;
27
28 import javax.ws.rs.core.Response;
29
30 import org.collectionspace.services.client.AuthorityClient;
31 import org.collectionspace.services.client.CollectionSpaceClient;
32 import org.collectionspace.services.client.PayloadInputPart;
33 import org.collectionspace.services.client.VocabularyClient;
34 import org.collectionspace.services.client.PoxPayloadIn;
35 import org.collectionspace.services.client.PoxPayloadOut;
36 import org.collectionspace.services.common.ResourceMap;
37 import org.collectionspace.services.common.XmlTools;
38 import org.collectionspace.services.common.api.RefName;
39 import org.collectionspace.services.common.api.RefName.Authority;
40 import org.collectionspace.services.common.api.RefNameUtils;
41 import org.collectionspace.services.common.api.RefNameUtils.AuthorityInfo;
42 import org.collectionspace.services.common.api.Tools;
43 import org.collectionspace.services.common.context.ServiceContext;
44 import org.collectionspace.services.common.document.DocumentException;
45 import org.collectionspace.services.common.document.DocumentNotFoundException;
46 import org.collectionspace.services.common.document.DocumentWrapper;
47 import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
48 import org.collectionspace.services.common.vocabulary.AuthorityJAXBSchema;
49 import org.collectionspace.services.common.vocabulary.AuthorityResource;
50 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
51 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
52 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.SpecifierForm;
53 import org.collectionspace.services.config.service.ObjectPartType;
54 import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
55 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
56 import org.collectionspace.services.nuxeo.client.java.RepositoryClientImpl;
57 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
58 import org.dom4j.Document;
59 import org.dom4j.Element;
60 import org.nuxeo.ecm.core.api.ClientException;
61 import org.nuxeo.ecm.core.api.DocumentModel;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 /**
66  * AuthorityDocumentModelHandler
67  *
68  * $LastChangedRevision: $
69  * $LastChangedDate: $
70  */
71 public abstract class AuthorityDocumentModelHandler<AuthCommon>
72         extends NuxeoDocumentModelHandler<AuthCommon> {
73
74     private final Logger logger = LoggerFactory.getLogger(AuthorityDocumentModelHandler.class); 
75     protected String authorityCommonSchemaName;
76     protected String authorityItemCommonSchemaName;
77
78     public AuthorityDocumentModelHandler(String authorityCommonSchemaName, String authorityItemCommonSchemaName) {
79         this.authorityCommonSchemaName = authorityCommonSchemaName;
80         this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
81     }
82     
83     /**
84      * The entity type expected from the JAX-RS Response object
85      */
86     public Class<String> getEntityResponseType() {
87         return String.class;
88     }
89         
90     protected PayloadInputPart extractPart(Response res, String partLabel)
91             throws Exception {
92             PoxPayloadIn input = new PoxPayloadIn((String)res.readEntity(getEntityResponseType()));
93             PayloadInputPart payloadInputPart = input.getPart(partLabel);
94             if (payloadInputPart == null) {
95                 logger.error("Part " + partLabel + " was unexpectedly null.");
96             }
97             return payloadInputPart;
98     }
99     
100     @Override
101     public boolean handleSync(DocumentWrapper<Object> wrapDoc) throws Exception {
102         boolean result = false;
103         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = getServiceContext();
104         Specifier specifier = (Specifier) wrapDoc.getWrappedObject();
105         //
106         // Get the rev number of the authority so we can compare with rev number of shared authority
107         //
108         DocumentModel docModel = NuxeoUtils.getDocFromSpecifier(ctx, getRepositorySession(), authorityCommonSchemaName, specifier);
109         Long rev = (Long) NuxeoUtils.getProperyValue(docModel, AuthorityJAXBSchema.REV);
110         String shortId = (String) NuxeoUtils.getProperyValue(docModel, AuthorityJAXBSchema.SHORT_IDENTIFIER);
111         String refName = (String) NuxeoUtils.getProperyValue(docModel, AuthorityJAXBSchema.REF_NAME);
112         //
113         // Using the short ID of the local authority, created a URN specifier to retrieve the SAS authority
114         //
115         Specifier sasSpecifier = new Specifier(SpecifierForm.URN_NAME, RefNameUtils.createShortIdRefName(shortId));
116         PoxPayloadIn sasPayloadIn = getPayloadIn(ctx, sasSpecifier);
117
118         Long sasRev = getRevision(sasPayloadIn);
119         if (sasRev > rev) {
120                 ResourceMap resourceMap = ctx.getResourceMap();
121                 String resourceName = ctx.getClient().getServiceName();
122                 AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
123                 PoxPayloadOut payloadOut = authorityResource.update(ctx, resourceMap, null, docModel.getName(), sasPayloadIn);
124                 if (payloadOut != null) {
125                         ctx.setOutput(payloadOut);
126                         result = true;
127                 }
128         }
129         
130         return result;
131     }
132         
133     private PoxPayloadIn getPayloadIn(ServiceContext ctx, Specifier specifier) throws Exception {
134         PoxPayloadIn result = null;
135         
136         AuthorityClient client = (AuthorityClient) ctx.getClient();
137         Response res = client.read(specifier.value);
138         try {
139                 int statusCode = res.getStatus();
140         
141                 // Check the status code of the response: does it match
142                 // the expected response(s)?
143                 if (logger.isDebugEnabled()) {
144                     logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode);
145                 }
146                 
147             result = new PoxPayloadIn((String)res.readEntity(getEntityResponseType())); // Get the entire response!             
148         } finally {
149                 res.close();
150         }
151         
152         return result;
153     }
154
155     /*
156      * Non standard injection of CSID into common part, since caller may access through
157      * shortId, and not know the CSID.
158      * @see org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl#extractPart(org.nuxeo.ecm.core.api.DocumentModel, java.lang.String, org.collectionspace.services.common.service.ObjectPartType)
159      */
160     @Override
161     protected Map<String, Object> extractPart(DocumentModel docModel, String schema, ObjectPartType partMeta)
162             throws Exception {
163         Map<String, Object> unQObjectProperties = super.extractPart(docModel, schema, partMeta);
164
165         // Add the CSID to the common part
166         if (partMeta.getLabel().equalsIgnoreCase(authorityCommonSchemaName)) {
167             String csid = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
168             unQObjectProperties.put("csid", csid);
169         }
170
171         return unQObjectProperties;
172     }
173     
174     public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
175         super.fillAllParts(wrapDoc, action);
176         //
177         // Update the record's revision number on both CREATE and UPDATE actions
178         //
179         updateRevNumbers(wrapDoc);
180     }
181     
182     protected void updateRevNumbers(DocumentWrapper<DocumentModel> wrapDoc) {
183         DocumentModel documentModel = wrapDoc.getWrappedObject();
184         Long rev = (Long)documentModel.getProperty(authorityCommonSchemaName, AuthorityJAXBSchema.REV);
185         if (rev == null) {
186                 rev = (long)0;
187         } else {
188                 rev++;
189         }
190         documentModel.setProperty(authorityCommonSchemaName, AuthorityJAXBSchema.REV, rev);
191     }
192     
193     @Override
194     public void handleCreate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
195         super.handleCreate(wrapDoc);
196         // CSPACE-3178:
197         // Uncomment once debugged and App layer is read to integrate
198         // Experimenting with this uncommented now ...
199         handleDisplayNameAsShortIdentifier(wrapDoc.getWrappedObject(), authorityCommonSchemaName);
200         updateRefnameForAuthority(wrapDoc, authorityCommonSchemaName);//CSPACE-3178
201     }
202     
203     protected String buildWhereForShortId(String name) {
204         return authorityCommonSchemaName
205                 + ":" + AuthorityJAXBSchema.SHORT_IDENTIFIER
206                 + "='" + name + "'";
207     }
208     
209     private boolean isUnique(DocumentModel docModel, String schemaName) throws DocumentException {
210         return true;
211     }
212     
213     private boolean temp_isUnique(DocumentModel docModel, String schemaName) throws DocumentException {
214         boolean result = true;
215         
216         ServiceContext ctx = this.getServiceContext();
217         String shortIdentifier = (String) docModel.getProperty(schemaName, AuthorityJAXBSchema.SHORT_IDENTIFIER);
218         String nxqlWhereClause = buildWhereForShortId(shortIdentifier);
219         try {
220                         DocumentWrapper<DocumentModel> searchResultWrapper = getRepositoryClient(ctx).findDoc(ctx, nxqlWhereClause);
221                         if (searchResultWrapper != null) {
222                                 result = false;
223                                 if (logger.isInfoEnabled() == true) {
224                                         DocumentModel searchResult = searchResultWrapper.getWrappedObject();
225                                         String debugMsg = String.format("Could not create a new authority with a short identifier of '%s', because one already exists with the same short identifer: CSID = '%s'",
226                                                         shortIdentifier, searchResult.getName());
227                                         logger.trace(debugMsg);
228                                 }
229                         }
230                 } catch (DocumentNotFoundException e) {
231                         // Not a problem, just means we couldn't find another authority with that short ID
232                 }
233         
234         return result;
235     }
236
237     /**
238      * If no short identifier was provided in the input payload,
239      * generate a short identifier from the display name. Either way though,
240      * the short identifier needs to be unique.
241      */
242     private void handleDisplayNameAsShortIdentifier(DocumentModel docModel, String schemaName) throws Exception {
243         String shortIdentifier = (String) docModel.getProperty(schemaName, AuthorityJAXBSchema.SHORT_IDENTIFIER);
244         String displayName = (String) docModel.getProperty(schemaName, AuthorityJAXBSchema.DISPLAY_NAME);
245         String shortDisplayName = "";
246         String generateShortIdentifier = null;
247         if (Tools.isEmpty(shortIdentifier)) {
248                 generateShortIdentifier = AuthorityIdentifierUtils.generateShortIdentifierFromDisplayName(displayName, shortDisplayName);
249             docModel.setProperty(schemaName, AuthorityJAXBSchema.SHORT_IDENTIFIER, shortIdentifier);
250         }
251         
252         if (isUnique(docModel, schemaName) == false) {
253                 String shortId = generateShortIdentifier == null ? shortIdentifier : generateShortIdentifier;
254                 String errMsgVerb = generateShortIdentifier == null ? "supplied" : "generated";
255                 String errMsg = String.format("The %s short identifier '%s' was not unique, so the new authority could not be created.",
256                                 errMsgVerb, shortId);
257                 throw new DocumentException(errMsg);
258         }
259     }
260  
261     /**
262      * Generate a refName for the authority from the short identifier
263      * and display name.
264      * 
265      * All refNames for authorities are generated.  If a client supplies
266      * a refName, it will be overwritten during create (per this method) 
267      * or discarded during update (per filterReadOnlyPropertiesForPart).
268      * 
269      * @see #filterReadOnlyPropertiesForPart(Map<String, Object>, org.collectionspace.services.common.service.ObjectPartType)
270      * 
271      */
272     protected void updateRefnameForAuthority(DocumentWrapper<DocumentModel> wrapDoc, String schemaName) throws Exception {
273         DocumentModel docModel = wrapDoc.getWrappedObject();
274         RefName.Authority authority = (Authority) getRefName(getServiceContext(), docModel);
275         String refName = authority.toString();
276         docModel.setProperty(schemaName, AuthorityJAXBSchema.REF_NAME, refName);
277     }
278     
279     @Override
280     public RefName.RefNameInterface getRefName(ServiceContext ctx,
281                 DocumentModel docModel) {
282         RefName.RefNameInterface refname = null;
283
284         try {
285                 String shortIdentifier = (String) docModel.getProperty(authorityCommonSchemaName, AuthorityJAXBSchema.SHORT_IDENTIFIER);
286                 String displayName = (String) docModel.getProperty(authorityCommonSchemaName, AuthorityJAXBSchema.DISPLAY_NAME);
287                 RefName.Authority authority = RefName.Authority.buildAuthority(ctx.getTenantName(),
288                         ctx.getServiceName(),
289                         null,   // Only use shortId form!!!
290                         shortIdentifier,
291                         displayName);
292                 refname = authority;
293         } catch (Exception e) {
294                 logger.error(e.getMessage(), e);
295         }
296         
297         return refname;
298     }
299     
300     @Override
301     protected String getRefnameDisplayName(DocumentWrapper<DocumentModel> docWrapper) {
302         String result = null;
303         
304         DocumentModel docModel = docWrapper.getWrappedObject();
305         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = this.getServiceContext();
306         RefName.Authority refname = (RefName.Authority)getRefName(ctx, docModel);
307         result = refname.getDisplayName();
308         
309         return result;
310     }    
311     
312     public String getShortIdentifier(String authCSID, String schemaName) throws Exception {
313         String shortIdentifier = null;
314         CoreSessionInterface repoSession = null;
315
316         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = this.getServiceContext();
317         RepositoryClientImpl nuxeoRepoClient = (RepositoryClientImpl)this.getRepositoryClient(ctx);
318         try {
319                 repoSession = nuxeoRepoClient.getRepositorySession(ctx);
320             DocumentWrapper<DocumentModel> wrapDoc = nuxeoRepoClient.getDocFromCsid(ctx, repoSession, authCSID);
321             DocumentModel docModel = wrapDoc.getWrappedObject();
322             if (docModel == null) {
323                 throw new DocumentNotFoundException(String.format("Could not find authority resource with CSID='%s'.", authCSID));
324             }
325             shortIdentifier = (String) docModel.getProperty(schemaName, AuthorityJAXBSchema.SHORT_IDENTIFIER);
326         } catch (ClientException ce) {
327             throw new RuntimeException("AuthorityDocHandler Internal Error: cannot get shortId!", ce);
328         } finally {
329                 if (repoSession != null) {
330                         nuxeoRepoClient.releaseRepositorySession(ctx, repoSession);
331                 }
332         }
333         
334         return shortIdentifier;
335     }
336
337     /**
338      * Filters out selected values supplied in an update request.
339      * 
340      * @param objectProps the properties filtered out from the update payload
341      * @param partMeta metadata for the object to fill
342      */
343     @Override
344     public void filterReadOnlyPropertiesForPart(
345             Map<String, Object> objectProps, ObjectPartType partMeta) {
346         super.filterReadOnlyPropertiesForPart(objectProps, partMeta);
347         String commonPartLabel = getServiceContext().getCommonPartLabel();
348         if (partMeta.getLabel().equalsIgnoreCase(commonPartLabel)) {
349             objectProps.remove(AuthorityJAXBSchema.CSID);
350             objectProps.remove(AuthorityJAXBSchema.SHORT_IDENTIFIER);
351             objectProps.remove(AuthorityJAXBSchema.REF_NAME);
352         }
353     }    
354 }