From: Bruno Sinou Date: Fri, 9 Apr 2010 11:26:55 +0000 (+0000) Subject: First draft of DAO implementation for JCR. X-Git-Tag: argeo-commons-2.1.30~1634 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=4dd49d63209bb5997109ed3fe100d76679f7694b;p=lgpl%2Fargeo-commons.git First draft of DAO implementation for JCR. 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 --- diff --git a/sandbox/runtime/org.argeo.sandbox.jackrabbit/pom.xml b/sandbox/runtime/org.argeo.sandbox.jackrabbit/pom.xml index 0d374e966..551da5bde 100644 --- a/sandbox/runtime/org.argeo.sandbox.jackrabbit/pom.xml +++ b/sandbox/runtime/org.argeo.sandbox.jackrabbit/pom.xml @@ -38,6 +38,9 @@ ${basedir}/../../../server/demo;in=*;ex=pom.xml;ex=target;ex=.*, ${basedir}/../../../server/runtime;in=*/target/classes, + + + diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java index f066ce8f9..6f282bac7 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java @@ -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 lst = new ArrayList(); @@ -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; + } } diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java index ddbb7c71f..c0276ae02 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java @@ -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()) { diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java index df0ff3f3f..2b816c35d 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java @@ -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); } diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java index 1d3c11b20..316a877f6 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java @@ -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 index 000000000..1a273832c --- /dev/null +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki @@ -0,0 +1,9 @@ += Titre = + + == Sous Titre == + +* point1 +* point2 + + Code (il suffit de mettre un espace en début de ligne + \ 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 index 000000000..78a34af4d --- /dev/null +++ b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/applicationContext.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file