]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java
Remove log
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jackrabbit / src / main / java / org / argeo / jcr / BeanNodeMapper.java
index f066ce8f931a46ee099a4d03354da7a818e050ca..a526bcf5ec0d06ed838392baa08aabfbccd38bb1 100644 (file)
@@ -22,14 +22,12 @@ import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.BeanWrapperImpl;
 
-public class BeanNodeMapper implements NodeMapper, NodeMapperProvider {
-       private final static Log log = LogFactory.getLog(BeanNodeMapper.class);
+public class BeanNodeMapper implements NodeMapper {
+       // private final static Log log = LogFactory.getLog(BeanNodeMapper.class);
 
        private final static String NODE_VALUE = "value";
 
@@ -39,55 +37,93 @@ 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);
                        final Node node;
                        String parentPath = JcrUtils.parentPath(path);
                        // find or create parent node
                        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,162 +133,163 @@ 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);
-                       }
-               }
-
-               String clssName = node.getProperty(classProperty).getValue()
-                               .getString();
-
-               if (log.isTraceEnabled())
-                       log.debug("Map node " + node.getPath() + " to bean " + clssName);
+       /** 
+        * Transforms a node into an object of the class defined by classProperty Property
+        */
+       protected Object nodeToBean(Node node) throws RepositoryException {
 
-               BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName));
-
-               // process properties
-               PropertyIterator propIt = node.getProperties();
-               props: while (propIt.hasNext()) {
-                       Property prop = propIt.nextProperty();
-                       if (!beanWrapper.isWritableProperty(prop.getName()))
-                               continue props;
+               try {
+                       String clssName = node.getProperty(classProperty).getValue()
+                                       .getString();
+
+                       BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName));
+
+                       // process properties
+                       PropertyIterator propIt = node.getProperties();
+                       props: while (propIt.hasNext()) {
+                               Property prop = propIt.nextProperty();
+                               if (!beanWrapper.isWritableProperty(prop.getName()))
+                                       continue props;
+
+                               PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop
+                                               .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>();
+                                       Class<?> valuesClass = classFromProperty(prop);
+                                       if (valuesClass != null)
+                                               for (Value value : prop.getValues()) {
+                                                       lst.add(asObject(value, valuesClass));
+                                               }
+                                       continue props;
+                               }
 
-                       PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop
-                                       .getName());
-                       Class propClass = pd.getPropertyType();
+                               // 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);
+                       }
 
-                       // primitive list
-                       if (propClass != null && List.class.isAssignableFrom(propClass)) {
-                               List<Object> lst = new ArrayList<Object>();
-                               Class<?> valuesClass = classFromProperty(prop);
-                               if (valuesClass != null)
-                                       for (Value value : prop.getValues()) {
-                                               lst.add(asObject(value, valuesClass));
+                       // process children nodes
+                       NodeIterator nodeIt = node.getNodes();
+                       nodes: while (nodeIt.hasNext()) {
+                               Node childNode = nodeIt.nextNode();
+                               String name = childNode.getName();
+                               if (!beanWrapper.isWritableProperty(name))
+                                       continue nodes;
+
+                               PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name);
+                               Class propClass = pd.getPropertyType();
+
+                               // objects list
+                               if (propClass != null && List.class.isAssignableFrom(propClass)) {
+                                       String lstClass = childNode.getProperty(classProperty)
+                                                       .getString();
+                                       List<Object> lst;
+                                       try {
+                                               lst = (List<Object>) loadClass(lstClass).newInstance();
+                                       } catch (Exception e) {
+                                               lst = new ArrayList<Object>();
                                        }
-                               continue props;
-                       }
 
-                       Object value = asObject(prop.getValue(), pd.getPropertyType());
-                       if (value != null)
-                               beanWrapper.setPropertyValue(prop.getName(), value);
-               }
+                                       NodeIterator valuesIt = childNode.getNodes();
+                                       while (valuesIt.hasNext()) {
+                                               Node lstValueNode = valuesIt.nextNode();
+                                               Object lstValue = nodeToBean(lstValueNode);
+                                               lst.add(lstValue);
+                                       }
 
-               // process children nodes
-               NodeIterator nodeIt = node.getNodes();
-               nodes: while (nodeIt.hasNext()) {
-                       Node childNode = nodeIt.nextNode();
-                       String name = childNode.getName();
-                       if (!beanWrapper.isWritableProperty(name))
-                               continue nodes;
-
-                       PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name);
-                       Class propClass = pd.getPropertyType();
-
-                       // objects list
-                       if (propClass != null && List.class.isAssignableFrom(propClass)) {
-                               String lstClass = childNode.getProperty(classProperty)
-                                               .getString();
-                               List<Object> lst;
-                               try {
-                                       lst = (List<Object>) loadClass(lstClass).newInstance();
-                               } catch (Exception e) {
-                                       lst = new ArrayList<Object>();
+                                       beanWrapper.setPropertyValue(name, lst);
+                                       continue nodes;
                                }
 
-                               NodeIterator valuesIt = childNode.getNodes();
-                               while (valuesIt.hasNext()) {
-                                       Node lstValueNode = valuesIt.nextNode();
-                                       Object lstValue = nodeToBean(lstValueNode);
-                                       lst.add(lstValue);
-                               }
+                               // objects map
+                               if (propClass != null && Map.class.isAssignableFrom(propClass)) {
+                                       String mapClass = childNode.getProperty(classProperty)
+                                                       .getString();
+                                       Map<Object, Object> map;
+                                       try {
+                                               map = (Map<Object, Object>) loadClass(mapClass)
+                                                               .newInstance();
+                                       } catch (Exception e) {
+                                               map = new HashMap<Object, Object>();
+                                       }
 
-                               beanWrapper.setPropertyValue(name, lst);
-                               continue nodes;
-                       }
+                                       // properties
+                                       PropertyIterator keysPropIt = childNode.getProperties();
+                                       keyProps: while (keysPropIt.hasNext()) {
+                                               Property keyProp = keysPropIt.nextProperty();
+                                               // FIXME: use property editor
+                                               String key = keyProp.getName();
+                                               if (classProperty.equals(key))
+                                                       continue keyProps;
+
+                                               Class keyPropClass = classFromProperty(keyProp);
+                                               if (keyPropClass != null) {
+                                                       Object mapValue = asObject(keyProp.getValue(),
+                                                                       keyPropClass);
+                                                       map.put(key, mapValue);
+                                               }
+                                       }
 
-                       // objects map
-                       if (propClass != null && Map.class.isAssignableFrom(propClass)) {
-                               String mapClass = childNode.getProperty(classProperty)
-                                               .getString();
-                               Map<Object, Object> map;
-                               try {
-                                       map = (Map<Object, Object>) loadClass(mapClass)
-                                                       .newInstance();
-                               } catch (Exception e) {
-                                       map = new HashMap<Object, Object>();
-                               }
+                                       // node
+                                       NodeIterator keysIt = childNode.getNodes();
+                                       while (keysIt.hasNext()) {
+                                               Node mapValueNode = keysIt.nextNode();
+                                               // FIXME: use property editor
+                                               Object key = mapValueNode.getName();
+
+                                               Object mapValue = nodeToBean(mapValueNode);
 
-                               // properties
-                               PropertyIterator keysPropIt = childNode.getProperties();
-                               keyProps: while (keysPropIt.hasNext()) {
-                                       Property keyProp = keysPropIt.nextProperty();
-                                       // FIXME: use property editor
-                                       String key = keyProp.getName();
-                                       if (classProperty.equals(key))
-                                               continue keyProps;
-
-                                       Class keyPropClass = classFromProperty(keyProp);
-                                       if (keyPropClass != null) {
-                                               Object mapValue = asObject(keyProp.getValue(),
-                                                               keyPropClass);
                                                map.put(key, mapValue);
                                        }
+                                       beanWrapper.setPropertyValue(name, map);
+                                       continue nodes;
                                }
 
-                               // node
-                               NodeIterator keysIt = childNode.getNodes();
-                               while (keysIt.hasNext()) {
-                                       Node mapValueNode = keysIt.nextNode();
-                                       // FIXME: use property editor
-                                       Object key = mapValueNode.getName();
-
-                                       Object mapValue = nodeToBean(mapValueNode);
+                               // default
+                               Object value = nodeToBean(childNode);
+                               beanWrapper.setPropertyValue(name, value);
 
-                                       map.put(key, mapValue);
-                               }
-                               beanWrapper.setPropertyValue(name, map);
-                               continue nodes;
                        }
-
-                       // default
-                       Object value = nodeToBean(childNode);
-                       beanWrapper.setPropertyValue(name, value);
-
+                       return beanWrapper.getWrappedInstance();
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot map node " + node, e);
                }
-               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;
+       }
 }