[ 
https://issues.apache.org/jira/browse/CMIS-968?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15118497#comment-15118497
 ] 

Xian Zou edited comment on CMIS-968 at 1/27/16 6:58 AM:
--------------------------------------------------------

I debugged the program more and found the chemistry client (createDocument 
method in 
org.apache.chemistry.opencmis.client.bindings.spi.browser.ObjectServiceImpl.java.)
 does not send the secondary object type ids to server part.  I would debug 
more for the issue. In the meanwhile , please help to check whether my code to 
set secondary type ids in my previous comment is correct.


was (Author: xzou):
I would attach whole code of  createUpdateProperties methods in 
AbstractBrowserServiceCall.java to help analyze the issue. You also can check 
whether my code is the latest code. If not, please correct me.

public Properties createUpdateProperties(ControlParser controlParser, String 
typeId, List<String> secondaryTypeIds,
            List<String> objectIds, TypeCache typeCache) {
        Map<String, List<String>> properties = controlParser.getProperties();
        if (properties == null) {
            return null;
        }

        // load primary type
        if (typeId != null) {
            TypeDefinition typeDef = typeCache.getTypeDefinition(typeId);
            if (typeDef == null) {
                throw new CmisInvalidArgumentException("Invalid type: " + 
typeId);
            }
        }

        // load secondary types
        List<String> secondaryObjectTypeIdsValues = 
properties.get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
        if (isNotEmpty(secondaryObjectTypeIdsValues)) {
            for (String secTypeId : secondaryObjectTypeIdsValues) {
                TypeDefinition typeDef = typeCache.getTypeDefinition(secTypeId);
                if (typeDef == null) {
                    throw new CmisInvalidArgumentException("Invalid type: " + 
secTypeId);
                }
            }
        }

        if (secondaryTypeIds != null) {
            for (String secTypeId : secondaryTypeIds) {
                TypeDefinition typeDef = typeCache.getTypeDefinition(secTypeId);
                if (typeDef == null) {
                    throw new CmisInvalidArgumentException("Invalid secondary 
type: " + secTypeId);
                }
            }
        }

        // create properties
        PropertiesImpl result = new PropertiesImpl();
        for (Map.Entry<String, List<String>> property : properties.entrySet()) {
            PropertyDefinition<?> propDef = 
typeCache.getPropertyDefinition(property.getKey());
            if (propDef == null && objectIds != null) {
                for (String objectId : objectIds) {
                    typeCache.getTypeDefinitionForObject(objectId);
                    propDef = 
typeCache.getPropertyDefinition(property.getKey());
                    if (propDef != null) {
                        break;
                    }
                }
            }
            if (propDef == null) {
                throw new CmisInvalidArgumentException(property.getKey() + " is 
unknown!");
            }

            result.addProperty(createPropertyData(propDef, 
property.getValue()));
        }

        return result;
    }

Here are my analysis.
1. In these code, we can see the code only check whether the updated properties 
are in the type definition of primary object type. See below.
 // create properties
        PropertiesImpl result = new PropertiesImpl();
        for (Map.Entry<String, List<String>> property : properties.entrySet()) {
            PropertyDefinition<?> propDef = 
typeCache.getPropertyDefinition(property.getKey());
            if (propDef == null && objectIds != null) {
                for (String objectId : objectIds) {
                    typeCache.getTypeDefinitionForObject(objectId);
                    propDef = 
typeCache.getPropertyDefinition(property.getKey());
                    if (propDef != null) {
                        break;
                    }
                }
            }
            if (propDef == null) {
                throw new CmisInvalidArgumentException(property.getKey() + " is 
unknown!");
            }

            result.addProperty(createPropertyData(propDef, 
property.getValue()));
        }

2. For the type definition of secondary object types, the code only check 
whether the typedef is not null to see whether we define the secondary object 
type, but it dose not check whether the updated properties is in the property 
list of the secondary object type. See code below.
if (secondaryTypeIds != null) {
            for (String secTypeId : secondaryTypeIds) {
                TypeDefinition typeDef = typeCache.getTypeDefinition(secTypeId);
                if (typeDef == null) {
                    throw new CmisInvalidArgumentException("Invalid secondary 
type: " + secTypeId);
                }
            }
        }
In my case, the PropertyIds.EXPIRATION_DATE and PropertyIds.DESTRUCTION_DATE 
should be gotten/checked from the property list of secondary object type 
SecondaryTypeIds.DESTRUCTION_CLIENT_MANAGED_RETENTION. But the existence check 
of property and adding it in result is just from primary object type. It is 
wrong for any properties in secondary object type and that's why I proposed two 
possible solutions in my original question.

Thanks.

> Broswer binding failed to check the property list for secondary type when 
> update/create properties for secondary type 
> ----------------------------------------------------------------------------------------------------------------------
>
>                 Key: CMIS-968
>                 URL: https://issues.apache.org/jira/browse/CMIS-968
>             Project: Chemistry
>          Issue Type: Bug
>          Components: opencmis-server
>    Affects Versions: OpenCMIS 0.13.0
>         Environment: Windows2008R2 
>            Reporter: Xian Zou
>
> I am developing retention management in CMIS1.1 which 
> cmis:secondaryObjectTypeIds is cmis:rm_destructionRetention. After complete 
> the server code for CM repository, I tried to develop a JUNIT case to 
> create/update a document with the cmis:rm_expirationDate and 
> cmis:rm_destructionDate property. All create/update operations works as 
> design for atompub binding, but failed in browser binding with the following 
> error.
> org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException:
>  cmis:rm_expirationDate is unknown!
>       at 
> org.apache.chemistry.opencmis.client.bindings.spi.browser.AbstractBrowserBindingService.convertStatusCode(AbstractBrowserBindingService.java:249)
>       at 
> org.apache.chemistry.opencmis.client.bindings.spi.browser.AbstractBrowserBindingService.post(AbstractBrowserBindingService.java:377)
>       at 
> org.apache.chemistry.opencmis.client.bindings.spi.browser.ObjectServiceImpl.updateProperties(ObjectServiceImpl.java:400)
>       at 
> org.apache.chemistry.opencmis.client.runtime.AbstractCmisObject.updateProperties(AbstractCmisObject.java:349)
>       at 
> org.apache.chemistry.opencmis.client.runtime.AbstractCmisObject.updateProperties(AbstractCmisObject.java:313)
>       at 
> com.ibm.ecm.cmis.test.opencmis.util.TestUtils.updateDocument(TestUtils.java:2568)
>       at 
> com.ibm.ecm.cmis.test.opencmis.object.common.DocumentCRUD.createDocument(DocumentCRUD.java:172)
> Here is my sample code for the update logic as the example.
> Map<String, Object> updateProperties = new HashMap<String, Object>();
>             String newName = "updatedname" + TestUtils.getRandomInt(10000);
>             updateProperties.put("cmis:name", newName);
>             updateProperties.put("clbNonGroup.CMISString", newName);
>             Calendar c = getTestCalendar(2);
>             Calendar c2 = getTestCalendar(3);
>             updateProperties.put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, 
> secondObjTypeIds);
>             updateProperties.put(PropertyIds.EXPIRATION_DATE, c);
>             updateProperties.put(PropertyIds.DESTRUCTION_DATE, c2);
>             Document updatedDoc = TestUtils.updateDocument(session, 
> doc.getId(), updateProperties);
> I checked the chemistry code and found the following logic may cause the 
> "cmis:rm_expirationDate is unknown!" error" in createNewProperties and 
> createUpdateProperties methods in AbstractBrowserServiceCall.java.
>  PropertiesImpl result = new PropertiesImpl();
>         for (Map.Entry<String, List<String>> property : 
> properties.entrySet()) {
>             PropertyDefinition<?> propDef = 
> typeCache.getPropertyDefinition(property.getKey());
>             if (propDef == null && objectIds != null) {
>                 for (String objectId : objectIds) {
>                     typeCache.getTypeDefinitionForObject(objectId);
>                     propDef = 
> typeCache.getPropertyDefinition(property.getKey());
>                     if (propDef != null) {
>                         break;
>                     }
>                 }
>             }
>             if (propDef == null) {
>                 throw new CmisInvalidArgumentException(property.getKey() + " 
> is unknown!");
>             }
>             result.addProperty(createPropertyData(propDef, 
> property.getValue()));
>         }
> Actually, when we create/update an document, the type definition in the code 
> above will be gotten from the primary object type. The properties for 
> secondary object types will not be gotten in the type definitions , so I 
> think it should be a bug for browser binding. Here are some possible 
> solutions for the issue.
> Possible solution 1: Don't check the properties and throw the 
> CmisInvalidArgumentException(property.getKey() + " is unknown!"); exception 
> for browser binding like other bindings.
> Possible solution 2: Check the properties in type definitions in both primary 
> object type and all possible/passed secondary types. If we find the property 
> in either of them. We will not throw the exception.
> If I develop the code in wrong way, please tell me how to write it correctly.
> Thanks.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to