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