First draft of DAO implementation for JCR.
authorBruno Sinou <bsinou@argeo.org>
Fri, 9 Apr 2010 11:26:55 +0000 (11:26 +0000)
committerBruno Sinou <bsinou@argeo.org>
Fri, 9 Apr 2010 11:26:55 +0000 (11:26 +0000)
Some methods might still be missing but commons and slc both build.

git-svn-id: https://svn.argeo.org/commons/trunk@3443 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

sandbox/runtime/org.argeo.sandbox.jackrabbit/pom.xml
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java
server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/applicationContext.xml [new file with mode: 0644]

index 0d374e966c71a03527de78a6a086648f9eeb9ae5..551da5bde3819342027844f1419a055722de3459 100644 (file)
@@ -38,6 +38,9 @@
                                                        ${basedir}/../../../server/demo;in=*;ex=pom.xml;ex=target;ex=.*,
                                                        ${basedir}/../../../server/runtime;in=*/target/classes,
                                                </argeo.osgi.bundles>
+                                               
+                                               
+                                               
                                        </systemProperties>
                                </configuration>
                        </plugin>
index f066ce8f931a46ee099a4d03354da7a818e050ca..6f282bac7177143da530bc4f55df4d5b7f0f4c4c 100644 (file)
@@ -28,7 +28,7 @@ import org.argeo.ArgeoException;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.BeanWrapperImpl;
 
-public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
+public class BeanNodeMapper implements NodeMapper {
        private final static Log log = LogFactory.getLog(BeanNodeMapper.class);
 
        private final static String NODE_VALUE = "value";
@@ -39,35 +39,64 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
 
        private Boolean versioning = false;
        private Boolean strictUuidReference = false;
+
+       // TODO define a primaryNodeType Strategy
        private String primaryNodeType = null;
 
        private ClassLoader classLoader = getClass().getClassLoader();
 
        private NodeMapperProvider nodeMapperProvider;
 
-       public void update(Node node, Object obj) {
+       /**
+        * exposed method to retrieve a bean from a node
+        */
+       public Object load(Node node) {
                try {
-                       beanToNode(createBeanWrapper(obj), node);
+                       if (nodeMapperProvider != null) {
+                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
+                               if (nodeMapper != this) {
+                                       return nodeMapper.load(node);
+                               }
+                       }
+                       return nodeToBean(node);
                } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot update node " + node + " with "
-                                       + obj, e);
+                       throw new ArgeoException("Cannot load object from node " + node, e);
                }
        }
 
-       public String storagePath(Object obj) {
-               String clss = obj.getClass().getName();
-               StringBuffer buf = new StringBuffer("/objects/");
-               StringTokenizer st = new StringTokenizer(clss, ".");
-               while (st.hasMoreTokens()) {
-                       buf.append(st.nextToken()).append('/');
+       /** Update an existing node with an object */
+       public void update(Node node, Object obj) {
+               try {
+                       if (nodeMapperProvider != null) {
+
+                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
+                               if (nodeMapper != this) {
+                                       nodeMapper.update(node, obj);
+                               } else
+                                       beanToNode(createBeanWrapper(obj), node);
+                       } else
+                               beanToNode(createBeanWrapper(obj), node);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot update node " + node + " with "
+                                       + obj, e);
                }
-               buf.append(obj.toString());
-               return buf.toString();
        }
 
+       /**
+        * if no storage path is given; we use canonical path
+        * 
+        * @see this.storagePath()
+        */
        public Node save(Session session, Object obj) {
                return save(session, storagePath(obj), obj);
        }
+
+       /**
+        * Create a new node to store an object. If the parentNode doesn't exist, it
+        * is created
+        * 
+        * the primaryNodeType may be initialized before
+        */
        public Node save(Session session, String path, Object obj) {
                try {
                        BeanWrapper beanWrapper = createBeanWrapper(obj);
@@ -77,17 +106,28 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                        Node parentNode;
                        if (session.itemExists(path))
                                parentNode = (Node) session.getItem(parentPath);
-                       else
+                       else {
                                parentNode = JcrUtils.mkdirs(session, parentPath, null,
                                                versioning);
+                       }
                        // create node
+
                        if (primaryNodeType != null)
                                node = parentNode.addNode(JcrUtils.lastPathElement(path),
                                                primaryNodeType);
                        else
                                node = parentNode.addNode(JcrUtils.lastPathElement(path));
 
-                       beanToNode(beanWrapper, node);
+                       // Check specific cases
+                       if (nodeMapperProvider != null) {
+
+                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
+                               if (nodeMapper != this) {
+                                       nodeMapper.update(node, obj);
+                                       return node;
+                               }
+                       }
+                       update(node, obj);
                        return node;
                } catch (ArgeoException e) {
                        throw e;
@@ -97,30 +137,30 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                }
        }
 
-       public Object load(Node node) {
-               try {
-                       return nodeToBean(node);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot load object from node " + node, e);
+       /**
+        * Parse the FQN of a class to string with '/' delimiters Prefix the
+        * returned string with "/objects/"
+        */
+       public String storagePath(Object obj) {
+               String clss = obj.getClass().getName();
+               StringBuffer buf = new StringBuffer("/objects/");
+               StringTokenizer st = new StringTokenizer(clss, ".");
+               while (st.hasMoreTokens()) {
+                       buf.append(st.nextToken()).append('/');
                }
+               buf.append(obj.toString());
+               return buf.toString();
        }
 
        @SuppressWarnings("unchecked")
-       /** Transforms an object into a node*/
-       public Object nodeToBean(Node node) throws RepositoryException {
-               if (nodeMapperProvider != null) {
-                       NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
-                       if (nodeMapper != null) {
-                               return nodeMapper.load(node);
-                       }
-               }
+       /** 
+        * Transforms a node into an object of the class defined by classProperty Property
+        */
+       protected Object nodeToBean(Node node) throws RepositoryException {
 
                String clssName = node.getProperty(classProperty).getValue()
                                .getString();
 
-               if (log.isTraceEnabled())
-                       log.debug("Map node " + node.getPath() + " to bean " + clssName);
-
                BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName));
 
                // process properties
@@ -134,6 +174,7 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                                        .getName());
                        Class propClass = pd.getPropertyType();
 
+                       // Process case of List and its derived classes
                        // primitive list
                        if (propClass != null && List.class.isAssignableFrom(propClass)) {
                                List<Object> lst = new ArrayList<Object>();
@@ -145,6 +186,8 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                                continue props;
                        }
 
+                       // Case of other type of property accepted by jcr
+                       // Long, Double, String, Binary, Date, Boolean, Name
                        Object value = asObject(prop.getValue(), pd.getPropertyType());
                        if (value != null)
                                beanWrapper.setPropertyValue(prop.getName(), value);
@@ -235,24 +278,18 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                return beanWrapper.getWrappedInstance();
        }
 
+       /**
+        * Transforms an object to the specified jcr Node in order to persist it.
+        * 
+        * @param beanWrapper
+        * @param node
+        * @throws RepositoryException
+        */
        protected void beanToNode(BeanWrapper beanWrapper, Node node)
                        throws RepositoryException {
-
-               if (nodeMapperProvider != null) {
-                       NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
-                       if (nodeMapper != null) {
-                               nodeMapper.update(node, beanWrapper.getWrappedInstance());
-                               return;
-                       }
-               }
-
-               if (log.isTraceEnabled())
-                       log.debug("Map bean to node " + node.getPath());
-
                properties: for (PropertyDescriptor pd : beanWrapper
                                .getPropertyDescriptors()) {
                        String name = pd.getName();
-
                        if (!beanWrapper.isReadableProperty(name))
                                continue properties;// skip
 
@@ -282,6 +319,7 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                                continue properties;
                        }
 
+                       // Some bean reference other classes. We must deal with this case
                        if (value instanceof Class<?>) {
                                node.setProperty(name, ((Class<?>) value).getName());
                                continue properties;
@@ -325,6 +363,14 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                }
        }
 
+       /**
+        * Process specific case of list
+        * 
+        * @param node
+        * @param name
+        * @param lst
+        * @throws RepositoryException
+        */
        protected void addList(Node node, String name, List<?> lst)
                        throws RepositoryException {
                if (node.hasNode(name)) {// update
@@ -363,6 +409,14 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                }
        }
 
+       /**
+        * Process specific case of maps.
+        * 
+        * @param node
+        * @param name
+        * @param map
+        * @throws RepositoryException
+        */
        protected void addMap(Node node, String name, Map<?, ?> map)
                        throws RepositoryException {
                if (node.hasNode(name)) {// update
@@ -508,11 +562,6 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                }
        }
 
-       /** Returns itself. */
-       public NodeMapper findNodeMapper(Node node) {
-               return this;
-       }
-
        protected String propertyName(String name) {
                return name;
        }
@@ -545,4 +594,11 @@ public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
                this.nodeMapperProvider = nodeMapperProvider;
        }
 
+       public String getPrimaryNodeType() {
+               return this.primaryNodeType;
+       }
+
+       public String getClassProperty() {
+               return this.classProperty;
+       }
 }
index ddbb7c71f006c5f4d60fd5572fde53aef4a75340..c0276ae023d8c9a2e4e9bd7711665680ef267fd8 100644 (file)
@@ -70,6 +70,12 @@ public class JcrUtils {
 
        }
 
+       public static String hostAsPath(String host) {
+               // TODO : inverse order of the elements (to have org/argeo/test IO
+               // test/argeo/org
+               return host.replace('.', '/');
+       }
+
        public static String lastPathElement(String path) {
                if (path.charAt(path.length() - 1) == '/')
                        throw new ArgeoException("Path " + path + " cannot end with '/'");
@@ -134,6 +140,8 @@ public class JcrUtils {
 
                // Then output the properties
                PropertyIterator properties = node.getProperties();
+               //log.debug("Property are : ");
+               
                while (properties.hasNext()) {
                        Property property = properties.nextProperty();
                        if (property.getDefinition().isMultiple()) {
index df0ff3f3f0f8ac9cc575f2e590def0e192088eb6..2b816c35d9275bfb6f76e493475a10bf8a7d59cd 100644 (file)
@@ -9,4 +9,6 @@ public interface NodeMapper {
        public void update(Node node, Object obj);
 
        public Node save(Session session, String path, Object obj);
+       
+       public void setNodeMapperProvider(NodeMapperProvider nmp);
 }
index 1d3c11b2058bd31d1fe8170cc6eabf29e4aedeb9..316a877f6ad3e6df82f97172b3f8b77f6751e027 100644 (file)
@@ -4,6 +4,10 @@ import javax.jcr.Node;
 
 /** Provides a node mapper relevant for this node. */
 public interface NodeMapperProvider {
-       /** @return the node mapper or null if no relvant node mapper cna be found. */
+
+       /** 
+        * Node Mapper is chosen regarding the Jcr path of the node parameter 
+        * @param Node node
+        * @return the node mapper or null if no relevant node mapper can be found. */
        public NodeMapper findNodeMapper(Node node);
 }
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki b/server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki
new file mode 100644 (file)
index 0000000..1a27383
--- /dev/null
@@ -0,0 +1,9 @@
+= Titre =\r
+\r
+ == Sous Titre ==\r
+\r
+* point1\r
+* point2\r
+\r
+ Code (il suffit de mettre un espace en début de ligne\r
\ No newline at end of file
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/applicationContext.xml b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/applicationContext.xml
new file mode 100644 (file)
index 0000000..78a34af
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+       <bean\r
+               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\r
+               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />\r
+               <property name="ignoreUnresolvablePlaceholders" value="true" />\r
+       </bean>\r
+\r
+       <bean id="nodeMapperProvider" class="org.argeo.slc.jcr.dao.SlcNodeMapperProvider"\r
+               init-method="init">\r
+               <property name="defaultNodeMapper" ref="nodeMapper" />\r
+               <property name="treeTestResultNodeMapper" ref="treeTestResultNodeMapper" />\r
+       </bean>\r
+\r
+       <bean id="nodeMapper" class="org.argeo.jcr.BeanNodeMapper">\r
+       </bean>\r
+\r
+       <bean id="treeTestResultNodeMapper" class="org.argeo.slc.jcr.dao.TreeTestResultNodeMapper">\r
+       </bean>\r
+\r
+       <bean id="argeo.jcr.session.inMemory" factory-bean="argeo.jcr.repository.inMemory"\r
+               factory-method="login" destroy-method="logout">\r
+               <constructor-arg>\r
+                       <bean class="javax.jcr.SimpleCredentials">\r
+                               <constructor-arg value="demo" />\r
+                               <constructor-arg value="demo" />\r
+                       </bean>\r
+               </constructor-arg>\r
+       </bean>\r
+\r
+       <bean id="argeo.jcr.repository.inMemory" class="org.argeo.server.jackrabbit.JackrabbitContainer">\r
+               <property name="homeDirectory" value="${java.io.tmpdir}/jackrabbit-slc-unit" />\r
+               <property name="configuration"\r
+                       value="classpath:/org/argeo/server/jackrabbit/repository-inMemory.xml" />\r
+       </bean>\r
+\r
+</beans>
\ No newline at end of file