]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
8d2aafc50239fec677a116b509f38ed53f556502
[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.nuxeo.client.java;
25
26 import java.io.InputStream;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Set;
32
33 import javax.ws.rs.WebApplicationException;
34 import javax.ws.rs.core.MediaType;
35 import javax.ws.rs.core.Response;
36
37 import org.collectionspace.services.jaxb.AbstractCommonList;
38 import org.collectionspace.services.common.authorityref.AuthorityRefList;
39 import org.collectionspace.services.common.context.MultipartServiceContext;
40 import org.collectionspace.services.common.context.ServiceContext;
41 import org.collectionspace.services.common.document.BadRequestException;
42 import org.collectionspace.services.common.document.DocumentUtils;
43 import org.collectionspace.services.common.document.DocumentWrapper;
44 import org.collectionspace.services.common.document.DocumentFilter;
45 import org.collectionspace.services.common.service.ObjectPartType;
46 import org.collectionspace.services.common.vocabulary.RefNameUtils;
47
48 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
49 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
50 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
51 import org.nuxeo.ecm.core.api.DocumentModel;
52 import org.nuxeo.ecm.core.api.DocumentModelList;
53 import org.nuxeo.ecm.core.api.model.PropertyException;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56 import org.w3c.dom.Document;
57
58 /**
59  * RemoteDocumentModelHandler
60  *
61  * $LastChangedRevision: $
62  * $LastChangedDate: $
63  * @param <T> 
64  * @param <TL> 
65  */
66 public abstract class RemoteDocumentModelHandlerImpl<T, TL>
67         extends DocumentModelHandler<T, TL> {
68
69     /** The logger. */
70     private final Logger logger = LoggerFactory.getLogger(RemoteDocumentModelHandlerImpl.class);
71
72     /* (non-Javadoc)
73      * @see org.collectionspace.services.common.document.AbstractDocumentHandlerImpl#setServiceContext(org.collectionspace.services.common.context.ServiceContext)
74      */
75     @Override
76     public void setServiceContext(ServiceContext ctx) {  //FIXME: Apply proper generics to ServiceContext<MultipartInput, MultipartOutput>
77         if(ctx instanceof MultipartServiceContext){
78             super.setServiceContext(ctx);
79         }else{
80             throw new IllegalArgumentException("setServiceContext requires instance of " +
81                     MultipartServiceContext.class.getName());
82         }
83     }
84
85     /* (non-Javadoc)
86      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#completeUpdate(org.collectionspace.services.common.document.DocumentWrapper)
87      */
88     @Override
89     public void completeUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
90         DocumentModel docModel = wrapDoc.getWrappedObject();
91         //return at least those document part(s) that were received
92         Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
93         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
94         List<InputPart> inputParts = ctx.getInput().getParts();
95         for(InputPart part : inputParts){
96             String partLabel = part.getHeaders().getFirst("label");
97             ObjectPartType partMeta = partsMetaMap.get(partLabel);
98 //            extractPart(docModel, partLabel, partMeta);
99                         Map<String, Object> unQObjectProperties = extractPart(docModel, partLabel, partMeta);
100                         addOutputPart(unQObjectProperties, partLabel, partMeta);
101         }
102     }
103
104     /**
105      * Adds the output part.
106      *
107      * @param unQObjectProperties the un q object properties
108      * @param schema the schema
109      * @param partMeta the part meta
110      * @throws Exception the exception
111      */
112     private void addOutputPart(Map<String, Object> unQObjectProperties, String schema, ObjectPartType partMeta)
113                 throws Exception {
114                 Document doc = DocumentUtils.buildDocument(partMeta, schema,
115                                 unQObjectProperties);
116                 if (logger.isDebugEnabled() == true) {                  
117                         logger.debug(DocumentUtils.xmlToString(doc));
118                 }
119                 MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
120                 ctx.addOutputPart(schema, doc, partMeta.getContent().getContentType());
121     }    
122     
123     /**
124      * Extract paging info.
125      *
126      * @param commonsList the commons list
127      * @return the tL
128      * @throws Exception the exception
129      */
130     protected TL extractPagingInfo(TL theCommonList, DocumentWrapper<DocumentModelList> wrapDoc)
131         throws Exception {
132         AbstractCommonList commonList = (AbstractCommonList)theCommonList;
133         
134         DocumentFilter docFilter = this.getDocumentFilter();
135         long pageSize = docFilter.getPageSize();
136         long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
137         // set the page size and page number
138         commonList.setPageNum(pageNum);
139         commonList.setPageSize(pageSize);
140         DocumentModelList docList = wrapDoc.getWrappedObject();
141         // Set num of items in list. this is useful to our testing framework.
142         commonList.setItemsInPage(docList.size());
143         // set the total result size
144         commonList.setTotalItems(docList.totalSize());
145         
146         return (TL)commonList;
147     }
148     
149     
150         /* (non-Javadoc)
151          * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#extractAllParts(org.collectionspace.services.common.document.DocumentWrapper)
152          */
153         @Override
154         public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc)
155                         throws Exception {
156
157                 DocumentModel docModel = wrapDoc.getWrappedObject();
158                 String[] schemas = docModel.getDeclaredSchemas();
159                 Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
160                 for (String schema : schemas) {
161                         ObjectPartType partMeta = partsMetaMap.get(schema);
162                         if (partMeta == null) {
163                                 continue; // unknown part, ignore
164                         }
165                         Map<String, Object> unQObjectProperties = extractPart(docModel, schema, partMeta);
166                         addOutputPart(unQObjectProperties, schema, partMeta);
167                 }
168         }
169
170     /* (non-Javadoc)
171      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#fillAllParts(org.collectionspace.services.common.document.DocumentWrapper)
172      */
173     @Override
174     public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
175
176         //TODO filling extension parts should be dynamic
177         //Nuxeo APIs lack to support stream/byte[] input, get/setting properties is
178         //not an ideal way of populating objects.
179         DocumentModel docModel = wrapDoc.getWrappedObject();
180         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
181         MultipartInput input = ctx.getInput();
182         if(input.getParts().isEmpty()){
183             String msg = "No payload found!";
184             logger.error(msg + "Ctx=" + getServiceContext().toString());
185             throw new BadRequestException(msg);
186         }
187
188         Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
189
190         //iterate over parts received and fill those parts
191         List<InputPart> inputParts = input.getParts();
192         for(InputPart part : inputParts){
193
194             String partLabel = part.getHeaders().getFirst("label");
195             if (partLabel == null) {
196                 String msg = "Part label is missing or empty!";
197                 logger.error(msg + "Ctx=" + getServiceContext().toString());
198                 throw new BadRequestException(msg);
199             }
200             
201             //skip if the part is not in metadata
202             if(!partsMetaMap.containsKey(partLabel)){
203                 continue;
204             }
205             ObjectPartType partMeta = partsMetaMap.get(partLabel);
206             fillPart(part, docModel, partMeta);
207         }//rof
208
209     }
210
211     /**
212      * fillPart fills an XML part into given document model
213      * @param part to fill
214      * @param docModel for the given object
215      * @param partMeta metadata for the object to fill
216      * @throws Exception
217      */
218     protected void fillPart(InputPart part, DocumentModel docModel, ObjectPartType partMeta)
219             throws Exception {
220         InputStream payload = part.getBody(InputStream.class, null);
221
222         //check if this is an xml part
223         if(part.getMediaType().equals(MediaType.APPLICATION_XML_TYPE)){
224             if(payload != null){
225                 Document document = DocumentUtils.parseDocument(payload, partMeta);
226                 //TODO: callback to handler if registered to validate the
227                 //document
228                 Map<String, Object> objectProps = DocumentUtils.parseProperties(document.getFirstChild());
229                 docModel.setProperties(partMeta.getLabel(), objectProps);
230             }
231         }
232     }
233
234     /**
235      * extractPart extracts an XML object from given DocumentModel
236      * @param docModel
237      * @param schema of the object to extract
238      * @param partMeta metadata for the object to extract
239      * @throws Exception
240      */
241     protected Map<String, Object> extractPart(DocumentModel docModel, String schema, ObjectPartType partMeta)
242             throws Exception {
243         return extractPart( docModel, schema, partMeta, null );
244     }
245     
246     /**
247      * extractPart extracts an XML object from given DocumentModel
248      * @param docModel
249      * @param schema of the object to extract
250      * @param partMeta metadata for the object to extract
251      * @throws Exception
252      */
253     protected Map<String, Object> extractPart(
254                 DocumentModel docModel, String schema, ObjectPartType partMeta,
255                 Map<String, Object> addToMap)
256             throws Exception {
257         Map<String, Object> result = null;
258         
259         MediaType mt = MediaType.valueOf(partMeta.getContent().getContentType());
260         if (mt.equals(MediaType.APPLICATION_XML_TYPE)){
261             Map<String, Object> objectProps = docModel.getProperties(schema);
262             //unqualify properties before sending the doc over the wire (to save bandwidh)
263             //FIXME: is there a better way to avoid duplication of a collection?
264             Map<String, Object> unQObjectProperties = 
265                 (addToMap!=null)? addToMap:(new HashMap<String, Object>());
266             Set<Entry<String, Object>> qualifiedEntries = objectProps.entrySet();
267             for(Entry<String, Object> entry : qualifiedEntries){
268                 String unqProp = getUnQProperty(entry.getKey());
269                 unQObjectProperties.put(unqProp, entry.getValue());
270             }
271             result = unQObjectProperties;
272         } //TODO: handle other media types
273         
274         return result;
275     }
276     
277     /* (non-Javadoc)
278      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#getAuthorityRefs(org.collectionspace.services.common.document.DocumentWrapper, java.util.List)
279      */
280     @Override
281     public AuthorityRefList getAuthorityRefs(
282                 DocumentWrapper<DocumentModel> docWrapper,
283                 List<String> authRefFields) throws PropertyException {
284         AuthorityRefList authRefList = new AuthorityRefList();
285         try {
286                 DocumentModel docModel = docWrapper.getWrappedObject();
287                 List<AuthorityRefList.AuthorityRefItem> list = authRefList.getAuthorityRefItem();
288
289                 for (String field : authRefFields) {
290                         String refName = (String) docModel.getPropertyValue(field);
291                         if (refName == null)
292                                 continue;
293                         try {
294                                 RefNameUtils.AuthorityTermInfo termInfo = RefNameUtils
295                                 .parseAuthorityTermInfo(refName);
296                                 AuthorityRefList.AuthorityRefItem ilistItem = new AuthorityRefList.AuthorityRefItem();
297                                 ilistItem.setRefName(refName);
298                                 ilistItem.setAuthDisplayName(termInfo.inAuthority.displayName);
299                                 ilistItem.setItemDisplayName(termInfo.displayName);
300                                 ilistItem.setSourceField(field);
301                                 ilistItem.setUri(termInfo.getRelativeUri());
302                                 list.add(ilistItem);
303                         } catch (Exception e) {
304                                 // FIXME: Do we need to throw this Exception here?
305                                 if (logger.isDebugEnabled()) {
306                                         logger.debug("Caught exception in getAuthorityRefs", e);
307                                 }
308                         }
309                 }
310         } catch (PropertyException pe) {
311                 String msg = "Attempted to retrieve value for invalid or missing authority field. "
312                         + "Check authority field properties in tenant bindings.";
313                 logger.warn(msg, pe);
314                 throw pe;
315         } catch (Exception e) {
316                 if (logger.isDebugEnabled()) {
317                         logger.debug("Caught exception in getAuthorityRefs", e);
318                 }
319                 Response response = Response.status(
320                                 Response.Status.INTERNAL_SERVER_ERROR).entity(
321                                 "Failed to retrieve authority references").type(
322                                 "text/plain").build();
323                 throw new WebApplicationException(response);
324         }
325         return authRefList;
326     }
327 }