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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.nuxeo.client.java;
26 import java.io.InputStream;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Map.Entry;
32 import javax.ws.rs.core.MediaType;
33 import org.collectionspace.services.common.repository.DocumentWrapper;
34 import org.collectionspace.services.common.repository.AbstractDocumentHandler;
35 import org.collectionspace.services.common.repository.BadRequestException;
36 import org.collectionspace.services.common.repository.DocumentUtils;
37 import org.collectionspace.services.common.service.ObjectPartType;
38 import org.collectionspace.services.nuxeo.client.*;
39 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
41 import org.nuxeo.ecm.core.api.DocumentModel;
42 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.w3c.dom.Document;
48 * DocumentModelHandler is a base abstract Nuxeo document handler
49 * using Nuxeo Java Remote APIs for CollectionSpace services
51 * $LastChangedRevision: $
54 public abstract class DocumentModelHandler<T, TL>
55 extends AbstractDocumentHandler<T, TL> {
57 private final Logger logger = LoggerFactory.getLogger(DocumentModelHandler.class);
58 private RepositoryInstance repositorySession;
59 //key=schema, value=documentpart
62 * getRepositorySession returns Nuxeo Repository Session
65 public RepositoryInstance getRepositorySession() {
66 return repositorySession;
70 * setRepositorySession sets repository session
73 public void setRepositorySession(RepositoryInstance repoSession) {
74 this.repositorySession = repoSession;
78 public void handleCreate(DocumentWrapper wrapDoc) throws Exception {
79 fillAllParts(wrapDoc);
83 public void handleUpdate(DocumentWrapper wrapDoc) throws Exception {
84 fillAllParts(wrapDoc);
88 public void handleGet(DocumentWrapper wrapDoc) throws Exception {
89 extractAllParts(wrapDoc);
93 public void handleGetAll(DocumentWrapper wrapDoc) throws Exception {
94 setCommonPartList(extractCommonPartList(wrapDoc));
98 public void completeUpdate(DocumentWrapper wrapDoc) throws Exception {
99 DocumentModel docModel = (DocumentModel) wrapDoc.getWrappedObject();
100 //return at least those document part(s) that were received
101 Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
102 List<InputPart> inputParts = getServiceContext().getInput().getParts();
103 for(InputPart part : inputParts){
104 String partLabel = part.getHeaders().getFirst("label");
105 ObjectPartType partMeta = partsMetaMap.get(partLabel);
106 extractObject(docModel, partLabel, partMeta);
111 public void extractAllParts(DocumentWrapper wrapDoc) throws Exception {
113 DocumentModel docModel = (DocumentModel) wrapDoc.getWrappedObject();
114 String[] schemas = docModel.getDeclaredSchemas();
115 Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
116 for(String schema : schemas){
117 ObjectPartType partMeta = partsMetaMap.get(schema);
118 if(partMeta == null){
119 continue; //unknown part, ignore
121 extractObject(docModel, schema, partMeta);
126 public abstract T extractCommonPart(DocumentWrapper wrapDoc) throws Exception;
129 public void fillAllParts(DocumentWrapper wrapDoc) throws Exception {
131 //TODO filling extension parts should be dynamic
132 //Nuxeo APIs lack to support stream/byte[] input, get/setting properties is
133 //not an ideal way of populating objects.
134 DocumentModel docModel = (DocumentModel) wrapDoc.getWrappedObject();
135 MultipartInput input = getServiceContext().getInput();
136 if(input.getParts().isEmpty()){
137 String msg = "No payload found!";
138 logger.error(msg + "Ctx=" + getServiceContext().toString());
139 throw new BadRequestException(msg);
142 Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
144 //iterate over parts received and fill those parts
145 List<InputPart> inputParts = input.getParts();
146 for(InputPart part : inputParts){
148 String partLabel = part.getHeaders().getFirst("label");
149 //skip if the part is not in metadata
150 if(!partsMetaMap.containsKey(partLabel)){
153 InputStream payload = part.getBody(InputStream.class, null);
155 //check if this is an xml part
156 if(part.getMediaType().equals(MediaType.APPLICATION_XML_TYPE)){
158 Document document = DocumentUtils.parseDocument(payload);
159 //TODO: callback to handler if registered to validate the
161 Map<String, Object> objectProps = DocumentUtils.parseProperties(document);
162 docModel.setProperties(partLabel, objectProps);
170 public abstract void fillCommonPart(T obj, DocumentWrapper wrapDoc) throws Exception;
173 public abstract TL extractCommonPartList(DocumentWrapper wrapDoc) throws Exception;
176 public abstract T getCommonPart();
179 public abstract void setCommonPart(T obj);
182 public abstract TL getCommonPartList();
185 public abstract void setCommonPartList(TL obj);
188 * @see org.collectionspace.services.common.repository.DocumentHandler#getDocumentType()
191 public abstract String getDocumentType();
194 * extractObject extracts an XML object from given DocumentModel
196 * @param schema of the object to extract
197 * @param partMeta metadata for the object to extract
200 protected void extractObject(DocumentModel docModel, String schema, ObjectPartType partMeta)
202 MediaType mt = MediaType.valueOf(partMeta.getContent().getContentType());
203 if(mt.equals(MediaType.APPLICATION_XML_TYPE)){
204 Map<String, Object> objectProps = docModel.getProperties(schema);
205 //unqualify properties before sending the doc over the wire (to save bandwidh)
206 //FIXME: is there a better way to avoid duplication of a collection?
207 Map<String, Object> unQObjectProperties = new HashMap<String, Object>();
208 Set<Entry<String, Object>> qualifiedEntries = objectProps.entrySet();
209 for(Entry<String, Object> entry : qualifiedEntries){
210 String unqProp = getUnQProperty(entry.getKey());
211 unQObjectProperties.put(unqProp, entry.getValue());
213 Document doc = DocumentUtils.buildDocument(partMeta, schema, unQObjectProperties);
214 if(logger.isDebugEnabled()){
215 DocumentUtils.writeDocument(doc, System.out);
217 getServiceContext().addOutputPart(schema, doc, partMeta.getContent().getContentType());
218 } //TODO: handle other media types