cancel
Showing results for 
Search instead for 
Did you mean: 

apply aspect to property

sachinr_bhat
Champ in-the-making
Champ in-the-making
Hi All,

Is it possible to apply an aspect to a particular property of a content-type and not entire content-type?

Eg:BaseModel.xml

<type name="foo:baseDocument">
     <title>Base Document</title>
     <parent>cm:content</parent>
     <properties>
         <property name="foo:documentType">
                <title>document type</title>
               <type>d:text</type>
          <mandatory>false</mandatory>
          <index enabled="true">
             <atomic>false</atomic>
             <stored>false</stored>
             <tokenised>true</tokenised>
          </index>
              </property>
         <property name="foo:extraRef">
                <title>Extra Reference</title>
                <type>d:text</type>
               <mandatory>false</mandatory>
               <index enabled="true">
               <atomic>false</atomic>
               <stored>false</stored>
               <tokenised>true</tokenised>
                </index>
              </property>
I want to apply new aspect only to <foo:documentType> property and not entire content-type  <foo:baseDocument>. How to do this?

Thanks and Regards,
Sachin Bhat.
12 REPLIES 12

invictus9
Champ in-the-making
Champ in-the-making
Aspects are a collection of metadata applied as a bundle to a node in the system. An aspect is not applied to a type or a property.

Either I misunderstood your question, or you need to dig a bit further into how aspects and content types overlap.

sachinr_bhat
Champ in-the-making
Champ in-the-making
Hi Invictus,

Thanks a lot for your quick reply. You understood my question correctly sir. I went through the aspects and content-types in alfresco wiki but i nowhere got applying aspects to a particular property. That's why i asked you any feature like that is there or what?    Smiley Happy

Thanks and Regards,
Sachin Bhat.

invictus9
Champ in-the-making
Champ in-the-making
Aspects are not applied to properties; they are applied to nodes. Essentially, an aspect is a set of metadata that is (normally) optional, and can be added (and removed) after a document is created and typed.

Question: do you want the aspect to be applied only if the foo:documentType has a particular value? You can always do that in a business rule that checks for specific values and adds the aspect if the foo:documentType field meets certain criteria.

sachinr_bhat
Champ in-the-making
Champ in-the-making
Hi Invictus,

Thank you for quick reply invictus. You are absolutely right sir. Actually i wanted to do that thing only, i.e. applying aspect based on <foo:documentType> value.
i.e.
if foo:documentType = "purchase Invoice" then aspect is invoicable
if foo:documentType = "report"  then aspect is reportable    etc.

Thanks and Regards,
Sachin Bhat.

invictus9
Champ in-the-making
Champ in-the-making
Hi Invictus,

Thank you for quick reply invictus. You are absolutely right sir. Actually i wanted to do that thing only, i.e. applying aspect based on <foo:documentType> value.
i.e.
if foo:documentType = "purchase Invoice" then aspect is invoicable
if foo:documentType = "report"  then aspect is reportable    etc.

Thanks and Regards,
Sachin Bhat.

Well, this brings up an interesting point. Again, you should do some research on what content types are. If foo:documentType is being used to discriminate between different types of documents, you likely have not understood what content types do.

You may want to, instead, create content types for "purchase invoice" and for "report", making foo:baseDocument their parent. So …

<type name="foo:baseDocument">
     …
</type>
<type name="foo:purchaseinvoice">
   <title>Purchase Invoice</title>
   <parent>foo:baseDocument</parent>
   …
</type>
<type name="foo:report">
   <title>Report</title>
   <parent>foo:baseDocument</parent>
   …
</type>
This way you can test to see whether the document is of type "foo:report" or "fooSmiley Tongueurchaseinvoice". Now, you can add an aspect to just "fooSmiley Tongueurchaseinvoice" documents.

sachinr_bhat
Champ in-the-making
Champ in-the-making
Hi Invictus,

Thank you for your reply invictus. What you have said above model is the same way i have done as below.

<types>
<type name="foo:baseDocument">
           <title>Base Document</title>
      <parent>cm:content</parent>
      <properties>
         <property name="foo:documentType">
            <type>d:text</type>
         </property>
         </properties>
   </type>
        <type name="foo:pinv">
            <title>Pinv</title>
       <parent>foo:baseDocument</parent>
       <properties>
       <property name="foo:pinvSupCode">
            <type>d:text</type>
       </property>
            </properties>
   </type>
        <type name="foo:sinv">
        <title>Sinv</title>
        <parent>foo:baseDocument</parent>
        <properties>
           <property name="foo:sinvCusCode">
              <type>d:text</type>
           </property>
        </properties>
   </type>
</types>
<aspects>
<aspect name="foo:pInvoice">
               <title>pinvoicable</title>
               <parent>foo:commonAspect1</parent>
               <properties>
             <property name="foo:pSupCode">
                <title>Supplier code</title>
                <type>d:text</type>
             </property>
                    </properties>
          </aspect>
         
          <aspect name="foo:sInvoice">
                    <title>sinvoicable</title>
                    <parent>foo:commonAspect1</parent>
                    <properties>
                  <property name="foo:sCusCode">
                     <title>Customer Code</title>
                     <type>d:text</type>
                  </property>
                         </properties>
          </aspect>
         
          <aspect name="foo:brcptInvoice">
                    <title>brcptvoicable</title>
                    <parent>foo:commonAspect1</parent>
                    <properties>
                  <property name="foo:brBankAccRef">
                     <title>Bank Ref</title>
                     <type>d:text</type>
                  </property>
                         </properties>
          </aspect>
</aspects>


Now i am having combobox displaying all the content-types as below:

<field id="foo:documentType" template="core.field.combo" default="cm:content">
            <params>
               <plugins>jibe.plugins.comboSelectLast</plugins>
               <width>150</width>
               <comboModel>jibe.Cache.contentTypes</comboModel>
               </params>
            <validation-rules>
               <rule id="mandatory" />
            </validation-rules>
              </field>

what i wanted to do is : when i change the content-type of  a document from the original content-type while processing, it sholud reload with new metadata by applying aspect and with new content-type. For eg: for fooSmiley Tongueinv(combobox selection) –> content-type=fooSmiley Tongueinv and aspect=fooSmiley TongueInvoice". How to do this?  Please explain me invictus whether i should use NodeService Api or how to go next?

Thanks and Regards,
Sachin Bhat.

invictus9
Champ in-the-making
Champ in-the-making
The first thing is to make those aspects part of the type. For that, you provide a list of mandatory aspects.

<type name="foo:pinv">
   …
   <mandatory-aspects>
      <aspect>foo:pInvoice</aspect>
   </mandatory-aspects>
That will apply the aspect fooSmiley TongueInvoice whenever you specialize the type to fooSmiley Tongueinv. You can also do it programmatically, or do it from the Alfresco user interface (not that I recommend this).

You can Run Action on a document with one of the actions being "Specialize Type". This allows you to select a subtype of the current document type. In your model, you create the document as foo:baseDocument, and then specialize it as, let's say, fooSmiley Tongueinv. If you have mandatory aspects set, then those aspects will be added, and you will be asked to enter those fields. If you don't have mandatory aspects set, you can do another Run Action and select "Add aspect", and add the aspects that you want.

sachinr_bhat
Champ in-the-making
Champ in-the-making
Hi Invictus,

I can't change the nodetype because i can change from foo:basedocument to fooSmiley Tongueinv for the first time as you said because subtype. Later if i want to change from fooSmiley Tongueinv to foo:sinv it is not possible because foo:sinv is subtype of foo:baseDocument and not fooSmiley Tongueinv. To solve this problem what i have done is: i am having foo:documentType property inside foo:baseDocuemnt content-type. Hence fooDocumentType property is inheriting to all other documents. Based on the foo:documentType property value i am applying aspect without changing nodetype. Hence Nodetype is foo:baseDocument only and applying aspect to it based on value of foo:documenttype.  The value is taking from combobox like fooSmiley Tongueinv or foo:sinv etc.

The code is as below: In the below method based on the foo:documentType value i am calling methods(enablePinv, enableSinv etc) for applying aspect.
BrowsingBean.java

@Progress(message = "progress.repo.reloadNode", cancelable = false)
   @RemoteMethod(name = "repo.document.reloadNode")
   public void reloadNode(Context context) {
      DocumentNode node = new DocumentNode((String) context.get("nodeId"));
      //NodeRef nodeRef = node.getNodeRef();
      String docType = (String)context.getArg("foo:documentType");
      System.out.println("document type:"+docType);
      node.setProperties(context.getRequestMap());
      context.setNode(node);
      modelsManager.replaceEntry(node);
      
      if("foo:pinv".equals(docType)){
         node.enablePinv(docType);
      }else if("foo:brcpt".equals(docType)){
         node.enableBrcpt(docType);
      }else if("foo:sinv".equals(docType)){
         node.enableSinv(docType);
      }else if("foo:batchPinv".equals(docType)){
         node.enableBatchPinv(docType);
      }
      context.setProducedResponse(Context.RESULT_SUCCESS);
   }

DocumentNode.java

       final QName PINVOICE = QName.createQName("foo:pInvoice", serviceRegistry.getNamespaceService());
   final QName SINVOICE = QName.createQName("foo:sInvoice", serviceRegistry.getNamespaceService());
   final QName DOCTYPE = QName.createQName("foo:documentType", serviceRegistry.getNamespaceService());

       public void enablePinv(String docType) {
      NodeService nodeService = serviceRegistry.getNodeService();
      nodeService.setProperty(nodeRef, DOCTYPE, docType);
      Serializable value = nodeService.getProperty(nodeRef, DOCTYPE);
      QName changedValue = nodeService.getType(nodeRef);
      System.out.println("enablePinv(DOCTYPE):"+value.toString());
      System.out.println("enablePinv(getTYPE):"+changedValue.toString());
      Set<QName> aspects = nodeService.getAspects(this.nodeRef);
      for (QName aspect : aspects) {
         nodeService.removeAspect(nodeRef, aspect);
      }
      nodeService.addAspect(nodeRef, PINVOICE, null);
   }
   
   public void enableSinv(String docType) {
      NodeService nodeService = serviceRegistry.getNodeService();
      nodeService.setProperty(nodeRef, DOCTYPE, docType);
      Serializable value = nodeService.getProperty(nodeRef, DOCTYPE);
      QName changedValue = nodeService.getType(nodeRef);
      System.out.println("enableSinv(DOCTYPE):"+value.toString());
      System.out.println("enableSinv(getTYPE):"+changedValue.toString());
      Set<QName> aspects = nodeService.getAspects(nodeRef);
      for (QName aspect : aspects) {
         nodeService.removeAspect(nodeRef, aspect);
      }
      nodeService.addAspect(nodeRef, SINVOICE, null);
   }

When i changing from foo:baseDocument to fooSmiley Tongueinv, it is applying pinv aspect and reloading with new metadata and everything is working fine. But when i change from fooSmiley Tongueinv to foo:sinv in combobox it is giving error as "invalid NodeRef exception". I am not changing nodetype here but still why error is coming?  Below is the error:

10:47:26,250 User:admin ERROR [reponse.provider.ErrorResponseProvider] Node does
not exist: [\"workspace://SpacesStore/20f98594-9277-4722-85a4-60e843bc24ff\
org.alfresco.service.cmr.repository.InvalidNodeRefException: Node does not exist
: [\"workspace://SpacesStore/20f98594-9277-4722-85a4-60e843bc24ff\
        at org.alfresco.repo.node.db.DbNodeServiceImpl.getNodePairNotNull(DbNode
ServiceImpl.java:158)
        at org.alfresco.repo.node.db.DbNodeServiceImpl.hasAspect(DbNodeServiceIm

How to solve this invictus?

Thanks and Regards,
Sachin Bhat.

invictus9
Champ in-the-making
Champ in-the-making
You are much deeper into the code than I ever got. All I can offer you at this point is some well-meaning, yet naive, questions.

1) You are stripping ALL of the aspects from the node before you attempt to apply the new node. This is NOT advised, as there are many aspects that might be applied in the course of the documents adventuring which are quite benign and irrelevant to your operation here. Just check to see if the aspects that you really wish to control are present.

2) On a related note, is there harm in leaving the old aspects present? You might add a check before adding an aspect to see if it is already present; either delete it at that time or just overwrite the values.

3) Just to be clear, then, you have a document which is polymorphous? It changes from type to type as circumstances dictate? And the sequence of changes is not linear, nor can it be made linear?

4) I have no advice to give concerning the Alfresco user interface. I have written some web scripts to provide a brand new user interface that accesses the Alfresco repository, but have not used anything in the Alfresco web explorer that is not out of the box. My one question is: what node is the error message referring to? Is it the noderef for the document you are trying to change? Have you tried to run this under the Java debugger?