cancel
Showing results for 
Search instead for 
Did you mean: 

creating a document log per document using CMIS

wemu
Champ in-the-making
Champ in-the-making
Hello

I'm new to CMIS so please be a little patient with me Smiley Happy

We use Alfresco 4.x to store our documents and Apache Chemistry to communicate with Alfresco.

We added a new document type into alfresco to store tif images along with some meta data. I now want to add some log-statements to these documents. Here is the model:


<?xml version="1.0" encoding="UTF-8"?>
<!– Definition of new Model –>
<model name="zpe:zpeModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
   <!– Optional meta-data about the model –>
   <description>ZPE Model</description>
   <version>1.0</version>
   <imports>
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
      <import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
   </imports>
   <namespaces>
      <namespace uri="http://www.domain.com/zpe/1.0" prefix="zpe"/>
   </namespaces>

   <types>
      <type name="zpe:zpeDocument">
         <title>ZPE document</title>
         <parent>cm:content</parent>
         <properties>
            <property name="zpe:centId">
               <type>d:long</type>
               <mandatory>true</mandatory>
            </property>
            <property name="zpe:documentType">
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="zpe:documentStatus">
               <type>d:text</type>
            </property>
            <!–
            Quite a few more
            –>
         </properties>
         <associations>
            <child-association name="zpe:documentLogs">
               <title>Comments</title>
               <source>
                  <mandatory>false</mandatory>
                  <many>false</many>
               </source>
               <target>
                  <class>zpe:documentLog</class>
                  <mandatory>false</mandatory>
                  <many>true</many>
               </target>
            </child-association>
         </associations>
      </type>

      <type name="zpe:documentLog">
         <title>Document log</title>
         <parent>cm:content</parent>
         <properties>
            <property name="zpe:logText">
               <type>d:text</type>
               <index enabled="false" />
            </property>
            <property name="zpe:logUsername">
               <type>d:text</type>
               <index enabled="false" />
            </property>
            <property name="zpe:logDate">
               <type>d:datetime</type>
               <index enabled="false" />
            </property>
         </properties>
      </type>
   </types>
</model>



I want to use CMIS to add several "zpe:documentLogs" to a "zpe:zpeDocument" (the tif image)

Currently the zpe:zpeDocument are in Alfresco but I struggle to get used to the CMIS API:


private String createCmisNode(final String folderIdString) {
   ObjectId folderId = new ObjectId() {
      @Override
      public String getId() {
         return folderIdString;
      }
   };
   Map<String, Object> properties = new HashMap<>();
   properties.put(PropertyIds.OBJECT_TYPE_ID, ZpeAlfType.ZPE_DOCUMENT_LOG.getTypeName());
   properties.put(PropertyIds.NAME, "zpeDocumentLogName");

   ContentStream contentStream = null;

   ObjectId objectNode = session.createDocument(properties, folderId, contentStream, VersioningState.NONE);
   return  objectNode.getId();
}

public void createZpeDocumentLog(final String cmisObjectId, Map<String, Object> properties, String documentType) throws IOException {

   // cmisObjectId = "workspace://SpacesStore/addb1495-90a4-4842-8bf0-b3b27de56410"

   OperationContext operationContext = session.createOperationContext();
   operationContext.setCacheEnabled(true);
   operationContext.setIncludeAcls(true);
   operationContext.setIncludePolicies(true);
   operationContext.setIncludeRelationships(IncludeRelationships.BOTH);

   session.setDefaultContext(operationContext);   

    CmisObject cmisObject = session.getObject(cmisObjectId);
   
   AlfrescoDocument tiffAlfDoc = (AlfrescoDocument) cmisObject;
   List<Folder> parents = tiffAlfDoc.getParents(operationContext); // TODO: takes several seconds!
   if (CollectionUtils.isEmpty(parents)) {
      throw new IOException("The given cmoObjectId has no parent folder");
   }
   Folder tiffFileParentFolder = parents.get(0);
   String propertyValue = tiffFileParentFolder.getPropertyValue(PropertyIds.OBJECT_ID);

   // create cmisObject of type "Node" to be able to add the documentLog there
   // later create a relation / association between the tif cmisObject and this node cmisObject
   final String cmisLogNodeObjectId = createCmisNode(propertyValue);
   
   // create relation:
   Document doc = (Document)session.getObject(new ObjectId() {
      @Override
      public String getId() {
         return cmisObjectId; // tiff image
      }
   });

   //Retrieve or create the log/logs

   CmisObject log = session.getObject(new ObjectId() {
      @Override
      public String getId() {
         return cmisLogNodeObjectId; // log document
      }
   });

   AlfrescoDocument alfDoc = (AlfrescoDocument) doc;
   alfDoc.addAspect("P:cm:referencesnode");
   Map<String, String> relProps = new HashMap<String, String>();
   relProps.put("cmis:sourceId", doc.getId());
   relProps.put("cmis:targetId", log.getId());
   relProps.put("cmis:objectTypeId", "zpe:documentLogs");
   session.createRelationship(relProps, null, null, null);



}


There are some issues with this:
it throws an exception: org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException: Invalid typeId zpe:documentLogs

AlfrescoDocument.getParents is very slow. Several seconds. Is there an easy / quick way to use the cmisObjectId of a document to retrieve its parent folder?

It now creates a document in alfresco using name "zpeDocumentLogName". This fails for the second documentLog (the name is already used).
But I want to have it added as Metadata to the tif-document and not as some "file" beside it.

Is there a way to add the documentLog entries into the metadata of the tif image? Or do I need to create a document?
And what is a smart way to create unique names then? (application is clustered so I dont want to use timestamps)

Or is the model not ok and instead of types we should use something else?

thanks a lot!
4 REPLIES 4

sujaypillai
Confirmed Champ
Confirmed Champ
Hello Wemu,

Did you check out the default audit trail provided by Alfresco? You can read more about it here : https://wiki.alfresco.com/wiki/Content_Auditing#Example_Audit_Trail

wemu
Champ in-the-making
Champ in-the-making
Hello

No I didn't check that until now. But that audit trail does not really match what I do. The document is not touched at all. The process around it which tries to get a new version of the document happens inside my application while Alfresco just stores the document and waits for the new version. The logs are meant to document the actions taken in the application.

It does no like like the audit trail is something for me in this case 😕

Hello Wemu,

I changed your model definition as below by adding the association as an aspect -

<?xml version="1.0" encoding="UTF-8"?>
<!– Definition of new Model –>
<model name="zpe:zpeModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
   <!– Optional meta-data about the model –>
   <description>ZPE Model</description>
   <version>1.0</version>
   <imports>
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
      <import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
   </imports>
   <namespaces>
      <namespace uri="http://www.domain.com/zpe/1.0" prefix="zpe"/>
   </namespaces>

   <types>
      <type name="zpe:zpeDocument">
         <title>ZPE document</title>
         <parent>cm:content</parent>
         <properties>
            <property name="zpe:centId">
               <type>d:long</type>
               <mandatory>true</mandatory>
            </property>
            <property name="zpe:documentType">
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="zpe:documentStatus">
               <type>d:text</type>
            </property>
            <!–
            Quite a few more
            –>
         </properties>
         <associations>
            <child-association name="zpe:documentLogs">
               <title>Comments</title>
               <source>
                  <mandatory>false</mandatory>
                  <many>false</many>
               </source>
               <target>
                  <class>zpe:documentLog</class>
                  <mandatory>false</mandatory>
                  <many>true</many>
               </target>
            </child-association>
         </associations>
      </type>

      <type name="zpe:documentLog">
         <title>Document log</title>
         <parent>cm:content</parent>
         <properties>
            <property name="zpe:logText">
               <type>d:text</type>
               <index enabled="false" />
            </property>
            <property name="zpe:logUsername">
               <type>d:text</type>
               <index enabled="false" />
            </property>
            <property name="zpe:logDate">
               <type>d:datetime</type>
               <index enabled="false" />
            </property>
         </properties>
      </type>
   </types>
   <aspects>
      <aspect name="zpe:docLoggable">
      <title>Document Log</title>
      <associations>
         <association name="zpe:docLogs">
            <source>
              <mandatory>false</mandatory>
              <many>false</many>
            </source>
            <target>
              <class>zpe:documentLog</class>
              <mandatory>false</mandatory>
              <many>true</many>
            </target>
         </association>
      </associations>
      </aspect>
   </aspects>
</model>


And using the below code to create documents and its association -

                Map<String, Object> properties = new HashMap<String, Object>();
      properties.put(PropertyIds.OBJECT_TYPE_ID, "D:zpe:zpeDocument");
      properties.put(PropertyIds.BASE_TYPE_ID, "zpe:zpeDocument");
      properties.put(PropertyIds.NAME,"doc"+System.currentTimeMillis());
      ContentStream cs = null;
      Document parentDoc = rootFolder.createDocument(properties, cs, VersioningState.NONE);
      
      Map<String, Object> childProperties = new HashMap<String, Object>();
      childProperties.put(PropertyIds.OBJECT_TYPE_ID, "D:zpe:documentLog");
      childProperties.put(PropertyIds.NAME,"logdoc"+System.currentTimeMillis());
      Document childDoc = rootFolder.createDocument(childProperties, cs, VersioningState.NONE);
            
      Map<String, Object> relationProperties = new HashMap<String, Object>();
      relationProperties.put("cmis:sourceId", parentDoc.getId());
      relationProperties.put("cmis:targetId", childDoc.getId());
      relationProperties.put("cmis:objectTypeId", "R:zpe:docLogs");
      relationProperties.put("cmis:name","logid"+System.currentTimeMillis());
      session.createRelationship(relationProperties, null, null, null);




I used the CMIS workbench tool and found that when I go with your definition [zpe:documentLogs association is not listed under Relationship (cmis:relationship)] but when I add it as an aspect it gets listed under it.

Hope so that helps you.

wemu
Champ in-the-making
Champ in-the-making
Hallo

I'll give it a try!
Thanks a lot for the input! 🙂