]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-7124: Added workaround to Nuxeo bug that prevented the clearing of structured...
authorremillet <remillet@yahoo.com>
Tue, 11 Jul 2017 00:30:08 +0000 (17:30 -0700)
committerremillet <remillet@yahoo.com>
Tue, 11 Jul 2017 00:30:08 +0000 (17:30 -0700)
services/claim/client/src/main/resources/collectionspace-client.properties [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java

diff --git a/services/claim/client/src/main/resources/collectionspace-client.properties b/services/claim/client/src/main/resources/collectionspace-client.properties
new file mode 100644 (file)
index 0000000..0ec3d76
--- /dev/null
@@ -0,0 +1,6 @@
+#url of the collectionspace server
+cspace.url=http://localhost:8180/cspace-services/
+cspace.ssl=false
+cspace.auth=true
+cspace.user=admin@anthro.collectionspace.org
+cspace.password=Administrator
index 78c134e5200e2a8ea6f4a1a2c030916c2cd60896..65e2ca771d9b6235aece2213654241af15c95287 100644 (file)
@@ -24,7 +24,9 @@
 package org.collectionspace.services.nuxeo.client.java;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -85,7 +87,11 @@ import org.dom4j.Element;
 import org.nuxeo.ecm.core.api.DocumentModel;
 import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.api.DocumentNotFoundException;
+import org.nuxeo.ecm.core.api.impl.DataModelImpl;
+import org.nuxeo.ecm.core.api.model.DocumentPart;
+import org.nuxeo.ecm.core.api.model.Property;
 import org.nuxeo.ecm.core.api.model.PropertyException;
+import org.nuxeo.ecm.core.api.model.impl.ScalarProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -433,20 +439,105 @@ public abstract class   RemoteDocumentModelHandlerImpl<T, TL>
      * @param partMeta metadata for the object to fill
      * @throws Exception
      */
-    protected void fillPart(PayloadInputPart part, DocumentModel docModel,
-            ObjectPartType partMeta, Action action, ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx)
-            throws Exception {
-        //check if this is an xml part
-        if (part.getMediaType().equals(MediaType.APPLICATION_XML_TYPE)) {
-               Element element = part.getElementBody();
-            Map<String, Object> objectProps = DocumentUtils.parseProperties(partMeta, element, ctx);
-                if (action == Action.UPDATE) {
-                    this.filterReadOnlyPropertiesForPart(objectProps, partMeta);
-                }
-                docModel.setProperties(partMeta.getLabel(), objectProps);
-            }
-        }
-
+       protected void fillPart(PayloadInputPart part, DocumentModel docModel, ObjectPartType partMeta, Action action,
+                       ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
+               // check if this is an xml part
+               if (part.getMediaType().equals(MediaType.APPLICATION_XML_TYPE)) {
+                       Element element = part.getElementBody();
+                       Map<String, Object> objectProps = DocumentUtils.parseProperties(partMeta, element, ctx);
+                       if (action == Action.UPDATE) {
+                               this.filterReadOnlyPropertiesForPart(objectProps, partMeta);
+                       }
+                       String schemaName = partMeta.getLabel();
+                       docModel.setProperties(schemaName, objectProps);
+                       Set<String> fieldNameSet = getFieldNamesSet(objectProps);
+                       setFieldsDirty(docModel, schemaName, fieldNameSet);  // Force Nuxeo to update EVERY field by marking them dirty/modified
+               }
+       }
+       
+       
+       /**
+        * Due to an apparent Nuxeo bug, we need to explicitly mark all fields as dirty for updates
+        * to take place properly.  See https://issues.collectionspace.org/browse/CSPACE-7124
+        * 
+        * We should improve this code by marking dirty/modified only the fields that were part of the UPDATE/PUT request
+        * payload.  The current code will mark any field with a name in the 'fieldNameSet' set.  Since field names do not
+        * have to be unique in document/record, we might end up unnecessarily marking some fields as modified -not ideal but
+        * better than brute-force marking ALL fields as modified.
+        * 
+        * @param docModel
+        * @param schemaName
+        */
+       private void setFieldsDirty(DocumentModel docModel, String schemaName, Set<String> fieldNameSet) {
+        DataModelImpl dataModel = (DataModelImpl) docModel.getDataModel(schemaName);
+        DocumentPart documentPart = dataModel.getDocumentPart();
+        setFieldsDirty(documentPart.getChildren(), fieldNameSet);
+    }
+       
+       /**
+        * Recursively step through all the children and sub-children setting their dirty flags.
+        * See https://issues.collectionspace.org/browse/CSPACE-7124
+        * @param children
+        */
+       private void setFieldsDirty(Collection<Property> children, Set<String> fieldNameSet) {
+               if (children != null && (children.size() > 0)) {
+                       for (Property prop : children ) {
+                               String propName = prop.getName();
+                               logger.debug(propName);
+                   if (prop.isPhantom() == false) {
+                       if (prop.isScalar() == false) {
+                               setFieldsDirty(prop.getChildren(), fieldNameSet);
+                       } else if (fieldNameSet.contains(propName)) {
+                               ScalarProperty scalarProp = (ScalarProperty)prop;
+                               scalarProp.setIsModified();
+                       }
+                   }
+               }
+               }
+       }
+       
+       /*
+        * Gets the set of field names used in a map of properties.  We'll use this make our workaround to a
+        * bug (See https://issues.collectionspace.org/browse/CSPACE-7124) more efficient by only marking fields
+        * with names in this set as modified -ie, needing persisting.
+        * 
+        * Since the map of properties can contain other maps of properties as values, there can be duplicate
+        * field names in the 'objectProps' map.  And since we're creating a set, there can be no duplicates in the result.
+        * 
+        */
+       private Set<String> getFieldNamesSet(Map<String, Object> objectProps) {
+               HashSet<String> result = new HashSet<String>();
+               
+               addFieldNamesToSet(result, objectProps);
+               
+               return result;
+       }
+       
+       private void addFieldNamesToSet(Set<String> fieldNameSet, List<Object> valueList) {
+               for (Object value : valueList) {
+                       if (value instanceof List) {
+                               addFieldNamesToSet(fieldNameSet, (List<Object>)value);
+                       } else if (value instanceof Map) {
+                               addFieldNamesToSet(fieldNameSet, (Map<String, Object>)value);
+                       } else {
+                               logger.debug(value.toString());
+                       }
+               }
+       }
+               
+       private void addFieldNamesToSet(Set<String> fieldNameSet, Map<String, Object> objectProps) {
+               for (String key : objectProps.keySet()) {
+                       Object value = objectProps.get(key);
+                       if (value instanceof Map) {
+                               addFieldNamesToSet(fieldNameSet, (Map<String, Object>)value);
+                       } else if (value instanceof List) {
+                               addFieldNamesToSet(fieldNameSet, (List)value);
+                       } else {
+                               fieldNameSet.add(key);
+                       }
+               }
+       }
+       
     /**
      * Filters out read only properties, so they cannot be set on update.
      * TODO: add configuration support to do this generally