We are calling "Mapping strategy" the algorithm used by the Persistence Manager to map a bean into JCR nodes and/or properties.
In order to explain the basic mapping strategies, we will use the following simple object model :
This object model could be too simple for real applications and it is used here just to simplify the description of the different mapping strategies.
Based on that object model, we can define the following java classes :
public class Page { String path; PageInfo pageInfo; Collection paragraphs; /* Add here the getter and setter methods */ public void addParagraph(Paragraph paragraph) { if (paragraphs == null) { paragraphs = new ArrayList(); } paragraphs.add(paragraph); } } public class PageInfo { String path; String title; String description; /* Add here the getter and setter methods */ } public class Paragraph { private String path; private String text; /* Add here the getter and setter methods */ }
When you decide to map a bean class, you have to create a new class descriptor entry in the Persistence Manager descriptor file.
Here are the class-descriptors required to map the classes Page, PageInfo and Paragraph :
<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Page" jcrNodeType="graffito:page"> <field-descriptor fieldName="path" path="true" /> <bean-descriptor fieldName="pageInfo" jcrName="pageInfo" /> <collection-descriptor fieldName="paragraphs" jcrName="paragraphs" elementClassName="org.apache.portals.graffito.jcr.testmodel.Paragraph" /> </class-descriptor> <class-descriptor className="org.apache.portals.graffito.jcr.testmodel.PageInfo" jcrNodeType="graffito:PageInfo"> <field-descriptor fieldName="path" path="true" /> <field-descriptor fieldName="title" jcrName="graffito:title"/> <field-descriptor fieldName="description" jcrName="graffito:description"/> </class-descriptor> <class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Paragraph" jcrNodeType="graffito:paragraph"> <field-descriptor fieldName="path" path="true" /> <field-descriptor fieldName="text" jcrName="graffito:text"/> </class-descriptor>
We will explain in more details each descriptors in the following sections (Mapping Atomic Fields,Mapping Bean Fields and Mapping Collection Fields. If the page is stored on the path "/mysite/mypage1" and contains 2 paragraphs, here is the resulting jcr structure :
/mysite/page1 /mysite/page1/pageInfo graffito:title = "This is my page title" graffito:description = "This is my page description" /mysite/page1/paragraphs /mysite/page1/paragraphs/paragraph1 graffito:text = "This is the content of para1" /mysite/page1/paragraphs/paragraph2 graffito:text = ""This is the content of para2"
It is possible to have another kind of jcr structure by using other mapping strategies. You can see the section "Advance Mapping strategies" to get more information on that.
Now, let's go back to the class-descriptor.
<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Paragraph" jcrNodeType="nt:unstructured"> <field-descriptor fieldName="path" path="true" /> <field-descriptor fieldName="text" jcrName="graffito:text"/> </class-descriptor>
This class descriptor maps the class "org.apache.portals.graffito.jcr.testmodel.Paragraph" to the JCR type "nt:unstructured". Each field-descriptors maps one bean attribute to a JCR property. You can find more information on the field-descriptors in the page Mapping Atomic fields.
It is also possible to map a bean class to a specific JCR node type. The following class-descriptor map the class "org.apache.portals.graffito.jcr.testmodel.Paragraph" to the node type "graffito:paragraph".
<class-descriptor className="org.apache.portals.graffito.jcr.testmodel.Paragraph" jcrNodeType="graffito:paragraph"> <field-descriptor fieldName="path" path="true" /> <field-descriptor fieldName="text" jcrName="graffito:text"/> </class-descriptor>
In order to use correclty our example class with Jackrabbit, you should add the following node type definition in its custom_nodetypes.xml file or import the node type definition with the Jackrabbit API
<nodeType name="graffito:paragraph" isMixin="false" hasOrderableChildNodes="false" primaryItemName=""> <supertypes> <supertype>mix:versionable</supertype> <supertype>nt:base</supertype> </supertypes> <propertyDefinition name="*" requiredType="undefined" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="false" multiple="false" /> <propertyDefinition name="graffito:text" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="false" multiple="false" /> </nodeType>
Of course, node types "Graffito:Page" and "Graffito:PageInfo" are alse required. We are currently building a node type management tools which can import the node types from the class-descriptors.