]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-2558,CSPACE-2556: When returning lists of authority references (terms used...
authorAron Roberts <aron@socrates.berkeley.edu>
Fri, 30 Jul 2010 23:48:30 +0000 (23:48 +0000)
committerAron Roberts <aron@socrates.berkeley.edu>
Fri, 30 Jul 2010 23:48:30 +0000 (23:48 +0000)
services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java
services/common/src/main/java/org/collectionspace/services/common/document/DocumentUtils.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java

index 44041b891f19c56bd2009de1f8d97a43191f359e..e281c4c0158c5fd62fd834b9d46a14d3ec389279 100644 (file)
@@ -373,7 +373,9 @@ public abstract class AbstractDocumentHandlerImpl<T, TL, WT, WTL>
     @Override
     public abstract String getQProperty(String prop);
 
-    /* (non-Javadoc)
+    /* 
+     * Strip Nuxeo's schema name from the start of the field / element name.
+     * (non-Javadoc)
      * @see org.collectionspace.services.common.document.DocumentHandler#getUnQProperty(java.lang.String)
      */
     @Override
index cff812ba5044aaebacefcd17a4fe2dd875f89b4f..b05c43d38aac3638c01e751960360e717a838e3e 100644 (file)
@@ -473,8 +473,7 @@ public class DocumentUtils {
         root.setAttribute("xmlns:" + ns, xc.getNamespaceURI());
         document.appendChild(root);
 
-        SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class);
-        Schema schema = schemaManager.getSchema(partMeta.getLabel());
+        Schema schema = getSchema(partMeta.getLabel());
         
         buildDocument(document, root, objectProps, schema);
         
@@ -557,6 +556,11 @@ public class DocumentUtils {
        }
     }
 
+    public static Schema getSchema(String label) {
+        SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class);
+        return schemaManager.getSchema(label);
+    }
+
 
     /**
      * Insert multi values.
index 51b8fc4e64ed6b7eb364f2e57c52f3867108d3fc..ed91ad635dc37ab453ec71f75679dd36783aba5e 100644 (file)
@@ -50,9 +50,23 @@ import org.collectionspace.services.common.vocabulary.RefNameUtils;
 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
+
 import org.nuxeo.ecm.core.api.DocumentModel;
 import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.api.model.PropertyException;
+
+import org.nuxeo.ecm.core.schema.SchemaManager;
+import org.nuxeo.ecm.core.schema.TypeConstants;
+import org.nuxeo.ecm.core.schema.types.ComplexType;
+import org.nuxeo.ecm.core.schema.types.Field;
+import org.nuxeo.ecm.core.schema.types.ListType;
+import org.nuxeo.ecm.core.schema.types.Schema;
+import org.nuxeo.ecm.core.schema.types.Type;
+import org.nuxeo.ecm.core.schema.types.primitives.StringType;
+import org.nuxeo.ecm.core.schema.types.FieldImpl;
+import org.nuxeo.ecm.core.schema.types.QName;
+import org.nuxeo.runtime.api.Framework;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -76,11 +90,11 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
      */
     @Override
     public void setServiceContext(ServiceContext ctx) {  //FIXME: Apply proper generics to ServiceContext<MultipartInput, MultipartOutput>
-        if(ctx instanceof MultipartServiceContext){
+        if (ctx instanceof MultipartServiceContext) {
             super.setServiceContext(ctx);
-        }else{
-            throw new IllegalArgumentException("setServiceContext requires instance of " +
-                    MultipartServiceContext.class.getName());
+        } else {
+            throw new IllegalArgumentException("setServiceContext requires instance of "
+                    MultipartServiceContext.class.getName());
         }
     }
 
@@ -94,12 +108,12 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
         Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
         List<InputPart> inputParts = ctx.getInput().getParts();
-        for(InputPart part : inputParts){
+        for (InputPart part : inputParts) {
             String partLabel = part.getHeaders().getFirst("label");
             ObjectPartType partMeta = partsMetaMap.get(partLabel);
 //            extractPart(docModel, partLabel, partMeta);
-                       Map<String, Object> unQObjectProperties = extractPart(docModel, partLabel, partMeta);
-                       addOutputPart(unQObjectProperties, partLabel, partMeta);
+            Map<String, Object> unQObjectProperties = extractPart(docModel, partLabel, partMeta);
+            addOutputPart(unQObjectProperties, partLabel, partMeta);
         }
     }
 
@@ -112,16 +126,16 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
      * @throws Exception the exception
      */
     private void addOutputPart(Map<String, Object> unQObjectProperties, String schema, ObjectPartType partMeta)
-               throws Exception {
-               Document doc = DocumentUtils.buildDocument(partMeta, schema,
-                               unQObjectProperties);
-               if (logger.isDebugEnabled() == true) {                  
-                       logger.debug(DocumentUtils.xmlToString(doc));
-               }
-               MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
-               ctx.addOutputPart(schema, doc, partMeta.getContent().getContentType());
-    }    
-    
+            throws Exception {
+        Document doc = DocumentUtils.buildDocument(partMeta, schema,
+                unQObjectProperties);
+        if (logger.isDebugEnabled() == true) {
+            logger.debug(DocumentUtils.xmlToString(doc));
+        }
+        MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
+        ctx.addOutputPart(schema, doc, partMeta.getContent().getContentType());
+    }
+
     /**
      * Extract paging info.
      *
@@ -130,44 +144,43 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
      * @throws Exception the exception
      */
     protected TL extractPagingInfo(TL theCommonList, DocumentWrapper<DocumentModelList> wrapDoc)
-       throws Exception {
-       AbstractCommonList commonList = (AbstractCommonList)theCommonList;
-       
-       DocumentFilter docFilter = this.getDocumentFilter();
-       long pageSize = docFilter.getPageSize();
-       long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
-       // set the page size and page number
-       commonList.setPageNum(pageNum);
-       commonList.setPageSize(pageSize);
-       DocumentModelList docList = wrapDoc.getWrappedObject();
-       // Set num of items in list. this is useful to our testing framework.
-       commonList.setItemsInPage(docList.size());
-       // set the total result size
-       commonList.setTotalItems(docList.totalSize());
-       
-       return (TL)commonList;
+            throws Exception {
+        AbstractCommonList commonList = (AbstractCommonList) theCommonList;
+
+        DocumentFilter docFilter = this.getDocumentFilter();
+        long pageSize = docFilter.getPageSize();
+        long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
+        // set the page size and page number
+        commonList.setPageNum(pageNum);
+        commonList.setPageSize(pageSize);
+        DocumentModelList docList = wrapDoc.getWrappedObject();
+        // Set num of items in list. this is useful to our testing framework.
+        commonList.setItemsInPage(docList.size());
+        // set the total result size
+        commonList.setTotalItems(docList.totalSize());
+
+        return (TL) commonList;
+    }
+
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#extractAllParts(org.collectionspace.services.common.document.DocumentWrapper)
+     */
+    @Override
+    public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc)
+            throws Exception {
+
+        DocumentModel docModel = wrapDoc.getWrappedObject();
+        String[] schemas = docModel.getDeclaredSchemas();
+        Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
+        for (String schema : schemas) {
+            ObjectPartType partMeta = partsMetaMap.get(schema);
+            if (partMeta == null) {
+                continue; // unknown part, ignore
+            }
+            Map<String, Object> unQObjectProperties = extractPart(docModel, schema, partMeta);
+            addOutputPart(unQObjectProperties, schema, partMeta);
+        }
     }
-    
-    
-       /* (non-Javadoc)
-        * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#extractAllParts(org.collectionspace.services.common.document.DocumentWrapper)
-        */
-       @Override
-       public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc)
-                       throws Exception {
-
-               DocumentModel docModel = wrapDoc.getWrappedObject();
-               String[] schemas = docModel.getDeclaredSchemas();
-               Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
-               for (String schema : schemas) {
-                       ObjectPartType partMeta = partsMetaMap.get(schema);
-                       if (partMeta == null) {
-                               continue; // unknown part, ignore
-                       }
-                       Map<String, Object> unQObjectProperties = extractPart(docModel, schema, partMeta);
-                       addOutputPart(unQObjectProperties, schema, partMeta);
-               }
-       }
 
     /* (non-Javadoc)
      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#fillAllParts(org.collectionspace.services.common.document.DocumentWrapper)
@@ -181,7 +194,7 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
         DocumentModel docModel = wrapDoc.getWrappedObject();
         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
         MultipartInput input = ctx.getInput();
-        if(input.getParts().isEmpty()){
+        if (input.getParts().isEmpty()) {
             String msg = "No payload found!";
             logger.error(msg + "Ctx=" + getServiceContext().toString());
             throw new BadRequestException(msg);
@@ -191,7 +204,7 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
 
         //iterate over parts received and fill those parts
         List<InputPart> inputParts = input.getParts();
-        for(InputPart part : inputParts){
+        for (InputPart part : inputParts) {
 
             String partLabel = part.getHeaders().getFirst("label");
             if (partLabel == null) {
@@ -199,10 +212,10 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
                 logger.error(msg + "Ctx=" + getServiceContext().toString());
                 throw new BadRequestException(msg);
             }
-            
+
             //skip if the part is not in metadata
             ObjectPartType partMeta = partsMetaMap.get(partLabel);
-            if(partMeta==null){
+            if (partMeta == null) {
                 continue;
             }
             fillPart(part, docModel, partMeta, action);
@@ -220,20 +233,20 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
     protected void fillPart(InputPart part, DocumentModel docModel, ObjectPartType partMeta, Action action)
             throws Exception {
         InputStream payload = part.getBody(InputStream.class, null);
-        
+
 // TODO for sub-docs - after we parse the doc, we need to look for elements that are configured as 
 // subitem lists, for this part (schema), pull them out, and set them aside for later processing.
 
         //check if this is an xml part
-        if(part.getMediaType().equals(MediaType.APPLICATION_XML_TYPE)){
-            if(payload != null){
+        if (part.getMediaType().equals(MediaType.APPLICATION_XML_TYPE)) {
+            if (payload != null) {
                 Document document = DocumentUtils.parseDocument(payload, partMeta,
-                               false /*don't validate*/);
+                        false /*don't validate*/);
                 //TODO: callback to handler if registered to validate the
                 //document
                 Map<String, Object> objectProps = DocumentUtils.parseProperties(document.getFirstChild());
-                if(action==Action.UPDATE) {
-                       this.filterReadOnlyPropertiesForPart(objectProps, partMeta);
+                if (action == Action.UPDATE) {
+                    this.filterReadOnlyPropertiesForPart(objectProps, partMeta);
                 }
                 docModel.setProperties(partMeta.getLabel(), objectProps);
             }
@@ -247,8 +260,8 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
      * @param partMeta metadata for the object to fill
      */
     public void filterReadOnlyPropertiesForPart(
-               Map<String, Object> objectProps, ObjectPartType partMeta) {
-       // Currently a no-op, but can be overridden in Doc handlers.
+            Map<String, Object> objectProps, ObjectPartType partMeta) {
+        // Currently a no-op, but can be overridden in Doc handlers.
     }
 
     /**
@@ -260,9 +273,9 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
      */
     protected Map<String, Object> extractPart(DocumentModel docModel, String schema, ObjectPartType partMeta)
             throws Exception {
-       return extractPart( docModel, schema, partMeta, null );
+        return extractPart(docModel, schema, partMeta, null);
     }
-    
+
     /**
      * extractPart extracts an XML object from given DocumentModel
      * @param docModel
@@ -271,109 +284,132 @@ public abstract class RemoteDocumentModelHandlerImpl<T, TL>
      * @throws Exception
      */
     protected Map<String, Object> extractPart(
-               DocumentModel docModel, String schema, ObjectPartType partMeta,
-               Map<String, Object> addToMap)
+            DocumentModel docModel, String schema, ObjectPartType partMeta,
+            Map<String, Object> addToMap)
             throws Exception {
-       Map<String, Object> result = null;
-       
+        Map<String, Object> result = null;
+
         MediaType mt = MediaType.valueOf(partMeta.getContent().getContentType());
-        if (mt.equals(MediaType.APPLICATION_XML_TYPE)){
+        if (mt.equals(MediaType.APPLICATION_XML_TYPE)) {
             Map<String, Object> objectProps = docModel.getProperties(schema);
             //unqualify properties before sending the doc over the wire (to save bandwidh)
             //FIXME: is there a better way to avoid duplication of a collection?
-            Map<String, Object> unQObjectProperties = 
-               (addToMap!=null)? addToMap:(new HashMap<String, Object>());
+            Map<String, Object> unQObjectProperties =
+                    (addToMap != null) ? addToMap : (new HashMap<String, Object>());
             Set<Entry<String, Object>> qualifiedEntries = objectProps.entrySet();
-            for(Entry<String, Object> entry : qualifiedEntries){
+            for (Entry<String, Object> entry : qualifiedEntries) {
                 String unqProp = getUnQProperty(entry.getKey());
                 unQObjectProperties.put(unqProp, entry.getValue());
             }
             result = unQObjectProperties;
         } //TODO: handle other media types
-        
+
         return result;
     }
-    
+
     /* (non-Javadoc)
      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#getAuthorityRefs(org.collectionspace.services.common.document.DocumentWrapper, java.util.List)
      */
     @Override
     public AuthorityRefList getAuthorityRefs(
-               DocumentWrapper<DocumentModel> docWrapper,
-               List<String> authRefFields) throws PropertyException {
-        final String FIELD_REFNAME_DELIMITER = "|";
-        final String FIELD_REFNAME_DELIMITER_REGEX = "\\" + FIELD_REFNAME_DELIMITER;
-       AuthorityRefList authRefList = new AuthorityRefList();
-       try {
-               DocumentModel docModel = docWrapper.getWrappedObject();
-               List<AuthorityRefList.AuthorityRefItem> list = authRefList.getAuthorityRefItem();
-
-               for (String field : authRefFields) {
-                        // FIXME If the code used below doesn't support
-                        // arbitrary levels of nesting; e.g. "get all authrefs
-                        // in any children of a parent," then we might use
-                        // docModel.getProperties() instead,
-                        List<String> refNames = new ArrayList<String>();
-                        Object val = docModel.getPropertyValue(field);
-                        if (val instanceof String)
-                         refNames.add((String) val);
-                        else if (val instanceof List) {
-                          refNames = (List<String>) val;
+            DocumentWrapper<DocumentModel> docWrapper,
+            List<String> authRefFieldNames) throws PropertyException {
+
+        final String SCHEMA_FIELD_DELIMITER = ":";
+        AuthorityRefList authRefList = new AuthorityRefList();
+        List<AuthorityRefList.AuthorityRefItem> list = authRefList.getAuthorityRefItem();
+        String refName = "";
+
+        try {
+            DocumentModel docModel = docWrapper.getWrappedObject();
+
+            for (String authRefFieldName : authRefFieldNames) {
+
+                String schemaName = "";
+                // FIXME: Replacing the following by an existing utility
+                // method or, if not already present, create a new utility
+                // method for this task in the common package.
+                if (authRefFieldName.indexOf(SCHEMA_FIELD_DELIMITER) > 0) {
+                    String[] authRefFieldNameParts =
+                            authRefFieldName.split(SCHEMA_FIELD_DELIMITER);
+                    schemaName = authRefFieldNameParts[0];
+                    authRefFieldName = authRefFieldNameParts[1];
+                }
+
+                Schema schema = DocumentUtils.getSchema(schemaName);
+                Field field = schema.getField(authRefFieldName);
+                Type type = field.getType();
+
+                if (type.isSimpleType()) {
+                    Object obj = docModel.getPropertyValue(authRefFieldName);
+                    if (obj != null) {
+                        refName = (String) obj;
+                        if (refName != null || ! refName.trim().isEmpty()) {
+                            list.add(authorityRefListItem(authRefFieldName, refName));
                         }
-                        for (String refName : refNames) {
-                            if (refName == null || refName.trim().isEmpty())
-                                    continue;
-                            try {
-                                    // If the refName is prefixed by a field name
-                                    // and a delimiter, this means that it was
-                                    // found in a child of the specified authref field.
-                                    //
-                                    // Store the child field's name as the field name.
-                                    // Then strip off the child's name and the delimiter
-                                    // from the refName.
-                                    //
-                                    // FIXME: Move this 'split' code to its own utility method.
-                                    // FIXME: Verify that the behavior description above
-                                    // is accurate for arbitrary levels of nesting.
-                                    if (refName.indexOf(FIELD_REFNAME_DELIMITER) > 0) {
-                                        String[] refNameParts =
-                                            refName.split(FIELD_REFNAME_DELIMITER_REGEX);
-                                        field = refNameParts[0];
-                                        refName = refNameParts[1];
-                                    }
-                                    
-                                    RefNameUtils.AuthorityTermInfo termInfo = RefNameUtils
-                                    .parseAuthorityTermInfo(refName);
-                                    AuthorityRefList.AuthorityRefItem ilistItem = new AuthorityRefList.AuthorityRefItem();
-                                    ilistItem.setRefName(refName);
-                                    ilistItem.setAuthDisplayName(termInfo.inAuthority.displayName);
-                                    ilistItem.setItemDisplayName(termInfo.displayName);
-                                    ilistItem.setSourceField(field);
-                                    ilistItem.setUri(termInfo.getRelativeUri());
-                                    list.add(ilistItem);
-                            } catch (Exception e) {
-                                    // FIXME: Do we need to throw this Exception here?
-                                    if (logger.isDebugEnabled()) {
-                                            logger.debug("Caught exception in getAuthorityRefs", e);
-                                    }
+                    }
+                // FIXME: The following assumes a very simple structure
+                // for repeatable single scalar fields: a parent (continer)
+                // element, containing 0-n child elements, each of the same
+                // name and type, with values capable of being meaningfully
+                // cast to String.
+                //
+                // Past release 1.0a, repeatability may consist
+                // of arbitrary nesting and complexity, rather than
+                // scalars and single-level lists.  When needed, that
+                // might be implemented here via recursion through
+                // nested listTypes and/or complexTypes.
+                } else if (type.isListType()) {
+                    // Get the name of the child field that comprises
+                    // value instances of the parent (container) field.
+                    ListType ltype = (ListType) type;
+                    field = ltype.getField();
+                    String childAuthRefFieldName = field.getName().getLocalName();
+                    // For each value instance, add its refName to the authRefs list,
+                    // with its source field name set to the child field's name.
+                    List<Object> valuesList = (List<Object>) docModel.getPropertyValue(authRefFieldName);
+                   for (Object obj : valuesList) {
+                        if (obj != null) {
+                            refName = (String) obj;
+                            if (refName != null || ! refName.trim().isEmpty()) {
+                                list.add(authorityRefListItem(childAuthRefFieldName, refName));
                             }
                         }
-               }
-       } catch (PropertyException pe) {
-               String msg = "Attempted to retrieve value for invalid or missing authority field. "
-                       + "Check authority field properties in tenant bindings.";
-               logger.warn(msg, pe);
-               throw pe;
-       } catch (Exception e) {
-               if (logger.isDebugEnabled()) {
-                       logger.debug("Caught exception in getAuthorityRefs", e);
-               }
-               Response response = Response.status(
-                               Response.Status.INTERNAL_SERVER_ERROR).entity(
-                               "Failed to retrieve authority references").type(
-                               "text/plain").build();
-               throw new WebApplicationException(response);
-       }
-       return authRefList;
+                    }
+                }
+
+            }
+
+        } catch  (PropertyException pe) {
+            String msg = "Attempted to retrieve value for invalid or missing authority field. "
+                    + "Check authority field properties in tenant bindings.";
+            logger.warn(msg, pe);
+            throw pe;
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Caught exception in getAuthorityRefs", e);
+            }
+            Response response = Response.status(
+                    Response.Status.INTERNAL_SERVER_ERROR).entity(
+                    "Failed to retrieve authority references").type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        }
+        return authRefList;
     }
+
+        public AuthorityRefList.AuthorityRefItem authorityRefListItem(String authRefFieldName, String refName) {
+
+            AuthorityRefList.AuthorityRefItem ilistItem = new AuthorityRefList.AuthorityRefItem();
+            try {
+                RefNameUtils.AuthorityTermInfo termInfo = RefNameUtils.parseAuthorityTermInfo(refName);
+                ilistItem.setRefName(refName);
+                ilistItem.setAuthDisplayName(termInfo.inAuthority.displayName);
+                ilistItem.setItemDisplayName(termInfo.displayName);
+                ilistItem.setSourceField(authRefFieldName);
+                ilistItem.setUri(termInfo.getRelativeUri());
+            } catch (Exception e) {
+            }
+            return ilistItem;
+        }
 }