[exo-jcr-commits] exo-jcr SVN: r782 - in jcr/branches/1.12.0-JBC/component/core/src: test/java/org/exoplatform/services/jcr/impl/storage/jbosscache and 1 other directory.
do-not-reply at jboss.org
do-not-reply at jboss.org
Thu Nov 19 11:19:28 EST 2009
Author: sergiykarpenko
Date: 2009-11-19 11:19:28 -0500 (Thu, 19 Nov 2009)
New Revision: 782
Modified:
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorage.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnection.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheWorkspaceDataContainer.java
jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/AbstractJBossCacheStorageConnectionTest.java
jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnectionTest.java
Log:
EXOJCR-246: reference support added
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorage.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorage.java 2009-11-19 15:56:16 UTC (rev 781)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorage.java 2009-11-19 16:19:28 UTC (rev 782)
@@ -44,6 +44,8 @@
public static final String LOCKS = "$LOCKS".intern();
+ public static final String REFS = "$REFS".intern();
+
public static final String ITEM_DATA = "$data".intern();
public static final String ITEM_ID = "$id".intern();
@@ -62,14 +64,18 @@
protected final Node<Serializable, Object> locksRoot;
+ protected final Node<Serializable, Object> refsRoot;
+
protected JBossCacheStorage(Node<Serializable, Object> nodesRoot, Node<Serializable, Object> propsRoot,
- Node<Serializable, Object> locksRoot)
+ Node<Serializable, Object> locksRoot, Node<Serializable, Object> refsRoot)
{
this.nodesRoot = nodesRoot;
this.propsRoot = propsRoot;
this.locksRoot = locksRoot;
+
+ this.refsRoot = refsRoot;
}
/**
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnection.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnection.java 2009-11-19 15:56:16 UTC (rev 781)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnection.java 2009-11-19 16:19:28 UTC (rev 782)
@@ -18,13 +18,17 @@
*/
package org.exoplatform.services.jcr.impl.storage.jbosscache;
+import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.datamodel.ItemData;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.lock.LockData;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
+import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -32,13 +36,17 @@
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
+import java.io.IOException;
import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.jcr.InvalidItemStateException;
import javax.jcr.ItemExistsException;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.lock.LockException;
@@ -75,11 +83,12 @@
* JBossCacheStorageConnection constructor.
*
* @param cache Cache<Serializable, Object>
+ * @param refs
*/
public JBossCacheStorageConnection(Cache<Serializable, Object> cache, Node<Serializable, Object> nodesRoot,
- Node<Serializable, Object> propsRoot, Node<Serializable, Object> locksRoot)
+ Node<Serializable, Object> propsRoot, Node<Serializable, Object> locksRoot, Node<Serializable, Object> refsRoot)
{
- super(nodesRoot, propsRoot, locksRoot);
+ super(nodesRoot, propsRoot, locksRoot, refsRoot);
this.cache = cache;
}
@@ -138,6 +147,43 @@
throw new RepositoryException("Property's parent doesn't exist " + data.getQPath().getAsString());
}
+ if (data.getType() == PropertyType.REFERENCE)
+ {
+ Fqn propUUID = makeNodeFqn(data.getIdentifier());
+
+ for (ValueData value : data.getValues())
+ {
+
+ String refNodeUUID;
+ try
+ {
+ refNodeUUID = ValueDataConvertor.readString(value);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+
+ Fqn refNode = makeNodeFqn(refNodeUUID);
+
+ // add to $REFS map
+ Node<Serializable, Object> refParent = refsRoot.getChild(refNode);
+ if (refParent == null)
+ {
+ refParent = refsRoot.addChild(refNode);
+ }
+
+ refParent.addChild(propUUID);
+ }
+
+ }
+
// add to parent's properties attr
String propName = data.getQPath().getName().getAsString();
if (parent.get(propName) == null)
@@ -162,6 +208,23 @@
{
startBatch();
+ for (InternalQName mixin : data.getMixinTypeNames())
+ {
+ if (mixin.equals(Constants.MIX_REFERENCEABLE))
+ {
+ // check and release references
+ Node<Serializable, Object> node = refsRoot.addChild(Fqn.fromElements(data.getIdentifier()));
+ if (node != null)
+ {
+ if (node.getChildrenNames().size() != 0)
+ {
+ throw new RepositoryException("Referenceable node removed but still have live references.");
+ }
+ }
+ break;
+ }
+ }
+
if (data.getParentIdentifier() != null)
{
// check if parent is cached
@@ -199,6 +262,46 @@
throw new RepositoryException("Property parent doesn't exist " + data.getQPath().getAsString());
}
+ if (data.getType() == PropertyType.REFERENCE)
+ {
+ Fqn propUUID = makeNodeFqn(data.getIdentifier());
+
+ for (ValueData value : data.getValues())
+ {
+
+ String refNodeUUID;
+ try
+ {
+ refNodeUUID = ValueDataConvertor.readString(value);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+
+ // remove property from referencedNode in $REFS map
+
+ Node<Serializable, Object> refParent = refsRoot.getChild(makeNodeFqn(refNodeUUID));
+ if (refParent != null)
+ {
+ refParent.removeChild(propUUID);
+ }
+ // check is there is no more references
+ if (refParent.getChildrenNames().size() == 0)
+ {
+ //TODO remove children
+ refsRoot.removeChild(makeNodeFqn(refNodeUUID));
+ }
+ }
+
+ }
+
// remove from parent's properties attr
// TODO validate does deleted
if (parent.remove(data.getQPath().getName().getAsString()) == null)
@@ -474,8 +577,33 @@
public List<PropertyData> getReferencesData(String nodeIdentifier) throws RepositoryException,
IllegalStateException, UnsupportedOperationException
{
- // TODO refs impl
- return new ArrayList<PropertyData>();
+ ArrayList<PropertyData> references = new ArrayList<PropertyData>();
+
+ Node<Serializable, Object> node = this.refsRoot.getChild(Fqn.fromElements(nodeIdentifier));
+ if (node != null)
+ {
+ Set<Object> props = node.getChildrenNames();
+
+ for (Object o : props)
+ {
+ String propUUID = (String)o;
+ Node<Serializable, Object> prop = propsRoot.getChild(Fqn.fromElements(propUUID));
+ if (prop == null)
+ {
+ throw new RepositoryException("FATAL Property record not found(" + propUUID
+ + "), but listed in reference properties of node " + nodeIdentifier);
+ }
+
+ PropertyData propData = (PropertyData)prop.get(ITEM_DATA);
+ if (propData == null)
+ {
+ throw new RepositoryException("FATAL Property data is null. Property UUID " + propUUID);
+ }
+
+ references.add(propData);
+ }
+ }
+ return references;
}
/**
@@ -625,13 +753,107 @@
{
startBatch();
+ Fqn propFqn = Fqn.fromElements(data.getIdentifier());
+
// update in PROPERTIES
- Node<Serializable, Object> prop = propsRoot.getChild(makePropFqn(data.getIdentifier()));
+ Node<Serializable, Object> prop = propsRoot.getChild(propFqn);
if (prop == null)
{
throw new IllegalStateException("Property was deleted " + data.getQPath().getAsString());
}
+ if (data.getType() == PropertyType.REFERENCE)
+ {
+ PropertyData propData = (PropertyData)prop.get(ITEM_DATA);
+ if (propData == null)
+ {
+ throw new RepositoryException("FATAL Property data is null. Parent " + data.getQPath().getAsString());
+ }
+
+ //get Set of old values
+ Set<String> removeSet = new HashSet<String>();
+ for (ValueData value : propData.getValues())
+ {
+ try
+ {
+ removeSet.add(ValueDataConvertor.readString(value));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ }
+
+ Set<String> addSet = new HashSet<String>();
+ // check new
+ for (ValueData value : data.getValues())
+ {
+ try
+ {
+ addSet.add(ValueDataConvertor.readString(value));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ // TODO Auto-generated catch block
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ }
+
+ String[] added = new String[addSet.size()];
+ addSet.toArray(added);
+
+ for (String id : added)
+ {
+ if (removeSet.contains(id))
+ {
+ removeSet.remove(id);
+ addSet.remove(id);
+ }
+ }
+
+ // remove references to nodes
+ for (String id : removeSet)
+ {
+ Node<Serializable, Object> node = refsRoot.getChild(Fqn.fromElements(id));
+ if (!node.removeChild(propFqn))
+ {
+ throw new RepositoryException("FATAL Reference property was not removed from REFS table of node " + id);
+ }
+
+ // check node
+ if (node.getChildrenNames().size() == 0)
+ {
+ //TODO remove children
+ refsRoot.removeChild(Fqn.fromElements(id));
+ }
+ }
+
+ // add references to nodes
+ for (String id : addSet)
+ {
+ Fqn nodeFqn = Fqn.fromElements(id);
+ Node<Serializable, Object> node = refsRoot.getChild(nodeFqn);
+
+ if (node == null)
+ {
+ node = refsRoot.addChild(nodeFqn);
+ }
+ node.addChild(propFqn);
+ }
+ }
+
+ // remove
prop.put(ITEM_DATA, data);
}
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheWorkspaceDataContainer.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheWorkspaceDataContainer.java 2009-11-19 15:56:16 UTC (rev 781)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheWorkspaceDataContainer.java 2009-11-19 16:19:28 UTC (rev 782)
@@ -74,6 +74,8 @@
private Node<Serializable, Object> locks;
+ private Node<Serializable, Object> refs;
+
/**
* JBossWorkspaceDataContainer constructor.
*
@@ -130,6 +132,7 @@
this.nodes = cacheRoot.addChild(Fqn.fromElements(JBossCacheStorage.NODES));
this.properties = cacheRoot.addChild(Fqn.fromElements(JBossCacheStorage.PROPS));
this.locks = cacheRoot.addChild(Fqn.fromElements(JBossCacheStorage.LOCKS));
+ this.refs = cacheRoot.addChild(Fqn.fromElements(JBossCacheStorage.REFS));
cache.endBatch(true);
}
@@ -179,7 +182,7 @@
// throw new RepositoryException("Container is not started");
// }
- return new JBossCacheStorageConnection(cache, nodes, properties, locks);
+ return new JBossCacheStorageConnection(cache, nodes, properties, locks, refs);
}
/**
@@ -193,7 +196,7 @@
// throw new RepositoryException("Container is not started");
// }
- return new JBossCacheStorageConnection(cache, nodes, properties, locks);
+ return new JBossCacheStorageConnection(cache, nodes, properties, locks, refs);
}
/**
Modified: jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/AbstractJBossCacheStorageConnectionTest.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/AbstractJBossCacheStorageConnectionTest.java 2009-11-19 15:56:16 UTC (rev 781)
+++ jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/AbstractJBossCacheStorageConnectionTest.java 2009-11-19 16:19:28 UTC (rev 782)
@@ -24,7 +24,6 @@
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.storage.JDBCWorkspaceDataContainerTestBase;
-import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheSPI;
@@ -57,6 +56,8 @@
protected Node<Serializable, Object> locks;
+ protected Node<Serializable, Object> refs;
+
protected String jbcConfig;
/**
@@ -84,9 +85,10 @@
nodes = cacheRoot.addChild(Fqn.fromString(JBossCacheStorage.NODES));
props = cacheRoot.addChild(Fqn.fromString(JBossCacheStorage.PROPS));
locks = cacheRoot.addChild(Fqn.fromString(JBossCacheStorage.LOCKS));
+ refs = cacheRoot.addChild(Fqn.fromString(JBossCacheStorage.REFS));
cache.endBatch(true);
// JCR connection
- conn = new JBossCacheStorageConnection(cache, nodes, props, locks);
+ conn = new JBossCacheStorageConnection(cache, nodes, props, locks, refs);
}
protected void initJBCConfig()
@@ -157,8 +159,8 @@
Constants.DEFAULT_ENCODING));
}
- protected void checkChildProp(Node<Serializable, Object> node, InternalQName propName, String propId, QPath propPath,
- Object propValue) throws UnsupportedEncodingException, IllegalStateException, IOException
+ protected void checkChildProp(Node<Serializable, Object> node, InternalQName propName, String propId,
+ QPath propPath, Object propValue) throws UnsupportedEncodingException, IllegalStateException, IOException
{
String pid = (String)node.get(propName.getAsString());
@@ -201,5 +203,5 @@
assertEquals("Node persisted version wrong", version, childNodeData.getPersistedVersion());
}
}
-
+
}
Modified: jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnectionTest.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnectionTest.java 2009-11-19 15:56:16 UTC (rev 781)
+++ jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/JBossCacheStorageConnectionTest.java 2009-11-19 16:19:28 UTC (rev 782)
@@ -24,8 +24,8 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.lock.LockData;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
@@ -33,11 +33,14 @@
import org.jboss.cache.Node;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.List;
import javax.jcr.InvalidItemStateException;
import javax.jcr.ItemExistsException;
import javax.jcr.lock.LockException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
/**
* Created by The eXo Platform SAS.
@@ -635,13 +638,13 @@
// add /jcr:system
conn.add(new TransientNodeData(Constants.JCR_SYSTEM_PATH, Constants.SYSTEM_UUID, 1, Constants.NT_UNSTRUCTURED,
new InternalQName[0], 0, Constants.ROOT_UUID, new AccessControlList()));
-
-
- try {
+
+ try
+ {
// add /jcr:system twice
conn.add(new TransientNodeData(Constants.JCR_SYSTEM_PATH, Constants.SYSTEM_UUID, 1, Constants.NT_UNSTRUCTURED,
- new InternalQName[0], 0, Constants.ROOT_UUID, new AccessControlList()));
-
+ new InternalQName[0], 0, Constants.ROOT_UUID, new AccessControlList()));
+
conn.commit();
fail("The node jcr:system should not be save");
@@ -738,4 +741,98 @@
//ok
}
}
+
+ public void testGetReferences() throws Exception
+ {
+ // add root (/)
+ conn.add(new TransientNodeData(Constants.ROOT_PATH, Constants.ROOT_UUID, 1, Constants.NT_UNSTRUCTURED,
+ new InternalQName[0], 0, null, new AccessControlList()));
+
+ // add refernceable node (/node)
+ String node1id = "1";
+ QPath node1path = QPath.parse("[]:1[]firstParent:1");
+
+ NodeData node1 =
+ new TransientNodeData(node1path, node1id, 1, Constants.NT_UNSTRUCTURED,
+ new InternalQName[]{Constants.MIX_REFERENCEABLE}, 0, Constants.ROOT_UUID, new AccessControlList());
+ conn.add(node1);
+
+ // add node2 with reference on node
+ String node2id = "2";
+ QPath node2path = QPath.parse("[]:1[]secondParent:1");
+ conn.add(new TransientNodeData(node2path, node2id, 1, Constants.NT_UNSTRUCTURED, new InternalQName[0], 0,
+ Constants.ROOT_UUID, new AccessControlList()));
+
+ String refpropid = "21";
+ TransientPropertyData prop =
+ new TransientPropertyData(QPath.makeChildPath(node2path, "[]refprop:1"), refpropid, 0, PropertyType.REFERENCE,
+ node2id, false);
+
+ prop.setValue(new TransientValueData(node1id));
+ conn.add(prop);
+
+ String node3id = "3";
+ QPath node3path = QPath.parse("[]:1[]node3:1");
+
+ NodeData node3 =
+ new TransientNodeData(node3path, node3id, 1, Constants.NT_UNSTRUCTURED,
+ new InternalQName[]{Constants.MIX_REFERENCEABLE}, 0, Constants.ROOT_UUID, new AccessControlList());
+ conn.add(node3);
+
+ // check in nodes
+ treePrint(nodes);
+
+ // get root node ([]:1)
+ Node<Serializable, Object> rootNode = nodes.getChild(Fqn.fromElements(Constants.ROOT_UUID));
+ assertNotNull("Node expected", rootNode);
+
+ // check root Node
+ checkNode(rootNode, Constants.ROOT_UUID, Constants.ROOT_PATH);
+
+ // cechk childs
+ assertEquals("Childs expected", 3, rootNode.getChildren().size());
+ checkChildNode(rootNode, node1id, node1path);
+ checkChildNode(rootNode, node2id, node2path);
+ checkChildNode(rootNode, node3id, node3path);
+
+ List<PropertyData> props = conn.getReferencesData(node1id);
+ assertEquals("References expected", 1, props.size());
+ props = conn.getReferencesData(node3id);
+ assertEquals("References expected", 0, props.size());
+
+ // try remove referenced node
+ try
+ {
+ conn.delete(node1);
+ fail();
+ }
+ catch (RepositoryException e)
+ {
+ //ok
+ }
+
+ // update reference property
+
+ TransientPropertyData updateProp =
+ new TransientPropertyData(prop.getQPath(), prop.getIdentifier(), 0, PropertyType.REFERENCE, prop
+ .getParentIdentifier(), false);
+
+ List<ValueData> list = new ArrayList<ValueData>();
+ list.add(new TransientValueData(node1id));
+ list.add(new TransientValueData(node3id));
+
+ // ValueData[]{new TransientValueData(node1id)}
+ updateProp.setValues(list);
+ conn.update(updateProp);
+
+ // check
+ props = conn.getReferencesData(node1id);
+ assertEquals("References expected", 1, props.size());
+ props = conn.getReferencesData(node3id);
+ assertEquals("References expected", 1, props.size());
+
+ conn.delete(updateProp);
+ conn.delete(node1);
+ conn.delete(node3);
+ }
}
More information about the exo-jcr-commits
mailing list