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