You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/10/14 09:48:24 UTC
svn commit: r704361 [3/5] - in /jackrabbit/trunk:
jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/
jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/
jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/o...
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Move.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Move.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Move.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Move.java Tue Oct 14 00:48:22 2008
@@ -16,26 +16,26 @@
*/
package org.apache.jackrabbit.jcr2spi.operation;
-import org.apache.jackrabbit.jcr2spi.util.LogUtil;
import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
import org.apache.jackrabbit.jcr2spi.state.NodeState;
-import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.jcr2spi.util.LogUtil;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
-import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import javax.jcr.RepositoryException;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemExistsException;
-import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.ItemNotFoundException;
-import javax.jcr.version.VersionException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.lock.LockException;
+import javax.jcr.version.VersionException;
/**
* <code>Move</code>...
@@ -54,7 +54,8 @@
private final boolean sessionMove;
- private Move(NodeState srcNodeState, NodeState srcParentState, NodeState destParentState, Name destName, boolean sessionMove) {
+ private Move(NodeState srcNodeState, NodeState srcParentState, NodeState destParentState, Name destName, boolean sessionMove)
+ throws RepositoryException {
this.srcId = (NodeId) srcNodeState.getId();
this.destParentId = destParentState.getNodeId();
@@ -77,6 +78,7 @@
* @param visitor
*/
public void accept(OperationVisitor visitor) throws LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -87,22 +89,39 @@
*
* @see Operation#persisted()
*/
- public void persisted() {
+ public void persisted() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
if (sessionMove) {
- throw new UnsupportedOperationException("persisted() not implemented for transient modification.");
+ srcState.getNodeEntry().complete(this);
+ } else {
+ // non-recursive invalidation
+ try {
+ srcState.getNodeEntry().move(destName, destParentState.getNodeEntry(), false);
+ // TODO: TOBEFIXED. moved state ev. got a new definition.
+ } catch (RepositoryException e) {
+ // should not occure
+ log.error("Internal error", e);
+ srcParentState.getHierarchyEntry().invalidate(false);
+ destParentState.getHierarchyEntry().invalidate(false);
+ srcState.getHierarchyEntry().invalidate(false);
+ }
}
- // non-recursive invalidation
- try {
- srcState.getNodeEntry().move(destName, destParentState.getNodeEntry(), false);
- // TODO: TOBEFIXED. moved state ev. got a new definition.
- } catch (RepositoryException e) {
- // should not occure
- log.error("Internal error", e);
- srcParentState.getHierarchyEntry().invalidate(false);
- destParentState.getHierarchyEntry().invalidate(false);
- srcState.getHierarchyEntry().invalidate(false);
+ }
+
+ /**
+ * @see Operation#undo()
+ */
+ public void undo() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ if (sessionMove) {
+ status = STATUS_UNDO;
+ srcState.getHierarchyEntry().complete(this);
+ } else {
+ super.undo();
}
}
+
//----------------------------------------< Access Operation Parameters >---
public NodeId getSourceId() {
return srcId;
@@ -161,24 +180,28 @@
NodeState destParentState = getNodeState(destPath.getAncestor(1), hierMgr, resolver);
Name destName = destElement.getName();
- // for session-move perform a lazy check for existing items at destination.
- // since the hierarchy may not be complete it is possible that an conflict
- // is only detected upon saving the 'move'.
- NodeEntry destEntry = (NodeEntry) destParentState.getHierarchyEntry();
- if (destEntry.hasPropertyEntry(destName) && sessionMove) {
- throw new ItemExistsException("Move destination already exists (Property).");
- }
- // force childnodeentries list to be present before the move is executed
- // on the hierarchy entry.
- if (destEntry.hasNodeEntry(destName)) {
- NodeEntry existing = destEntry.getNodeEntry(destName, Path.INDEX_DEFAULT);
- if (existing != null && sessionMove) {
- try {
- if (!existing.getNodeState().getDefinition().allowsSameNameSiblings()) {
- throw new ItemExistsException("Node existing at move destination does not allow same name siblings.");
+ if (sessionMove) {
+ NodeEntry destEntry = (NodeEntry) destParentState.getHierarchyEntry();
+ if (destEntry.hasPropertyEntry(destName)) {
+ // TODO: remove for 283
+ throw new ItemExistsException("Move destination already exists (Property).");
+ }
+
+ // force childnodeentries list to be present before the move is executed
+ // on the hierarchy entry.
+ assertChildNodeEntries(srcParentState);
+ assertChildNodeEntries(destParentState);
+
+ if (destEntry.hasNodeEntry(destName)) {
+ NodeEntry existing = destEntry.getNodeEntry(destName, Path.INDEX_DEFAULT);
+ if (existing != null && sessionMove) {
+ try {
+ if (!existing.getNodeState().getDefinition().allowsSameNameSiblings()) {
+ throw new ItemExistsException("Node existing at move destination does not allow same name siblings.");
+ }
+ } catch (ItemNotFoundException e) {
+ // existing apparent not valid any more -> probably no conflict
}
- } catch (ItemNotFoundException e) {
- // existing apparent not valid any more -> probably no conflict
}
}
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Operation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Operation.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Operation.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Operation.java Tue Oct 14 00:48:22 2008
@@ -32,6 +32,10 @@
*/
public interface Operation {
+ int STATUS_PENDING = 0;
+ int STATUS_PERSISTED = 1;
+ int STATUS_UNDO = 2;
+
/**
* Returns the name of <code>this</code> operation.
*
@@ -56,6 +60,22 @@
/**
* Informs this Operation that it has been successfully executed.
+ *
+ * @throws RepositoryException
+ */
+ public void persisted() throws RepositoryException;
+
+ /**
+ * Revert changes made by this operation.
+ *
+ * @throws RepositoryException
+ */
+ public void undo() throws RepositoryException;
+
+ /**
+ * Returns the status of this operation.
+ *
+ * @return status of this operation.
*/
- public void persisted();
+ public int getStatus();
}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java Tue Oct 14 00:48:22 2008
@@ -19,6 +19,8 @@
import org.apache.jackrabbit.jcr2spi.state.ItemState;
import org.apache.jackrabbit.jcr2spi.state.NodeState;
import org.apache.jackrabbit.spi.ItemId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
@@ -30,11 +32,13 @@
*/
public class Remove extends AbstractOperation {
+ private static Logger log = LoggerFactory.getLogger(Remove.class);
+
private ItemId removeId;
protected ItemState removeState;
protected NodeState parent;
- protected Remove(ItemState removeState, NodeState parent) {
+ protected Remove(ItemState removeState, NodeState parent) throws RepositoryException {
this.removeId = removeState.getId();
this.removeState = removeState;
this.parent = parent;
@@ -48,20 +52,30 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws AccessDeniedException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
/**
- * Throws UnsupportedOperationException
- *
* @see Operation#persisted()
*/
- public void persisted() {
- throw new UnsupportedOperationException("persisted() not implemented for transient modification.");
+ public void persisted() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
+ parent.getHierarchyEntry().complete(this);
+ }
+
+ /**
+ * @see Operation#undo()
+ */
+ public void undo() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_UNDO;
+ parent.getHierarchyEntry().complete(this);
}
//----------------------------------------< Access Operation Parameters >---
- public ItemId getRemoveId() {
+ public ItemId getRemoveId() throws RepositoryException {
return removeId;
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveLabel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveLabel.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveLabel.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveLabel.java Tue Oct 14 00:48:22 2008
@@ -16,22 +16,22 @@
*/
package org.apache.jackrabbit.jcr2spi.operation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.jcr2spi.state.NodeState;
import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import javax.jcr.RepositoryException;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.version.VersionException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.version.VersionException;
/**
* <code>RemoveLabel</code>...
@@ -63,7 +63,8 @@
* @throws UnsupportedRepositoryOperationException
* @throws VersionException
*/
- public void accept(OperationVisitor visitor) throws RepositoryException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException {
+ public void accept(OperationVisitor visitor) throws RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -73,7 +74,8 @@
*
* @see Operation#persisted()
*/
- public void persisted() {
+ public void persisted() throws RepositoryException {
+ status = STATUS_PERSISTED;
try {
NodeEntry vhEntry = (NodeEntry) versionHistoryState.getHierarchyEntry();
NodeEntry lnEntry = vhEntry.getNodeEntry(NameConstants.JCR_VERSIONLABELS, Path.INDEX_DEFAULT);
@@ -86,11 +88,11 @@
}
//----------------------------------------< Access Operation Parameters >---
- public NodeId getVersionHistoryId() {
+ public NodeId getVersionHistoryId() throws RepositoryException {
return versionHistoryState.getNodeEntry().getWorkspaceId();
}
- public NodeId getVersionId() {
+ public NodeId getVersionId() throws RepositoryException {
return versionState.getNodeEntry().getWorkspaceId();
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveVersion.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveVersion.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveVersion.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/RemoveVersion.java Tue Oct 14 00:48:22 2008
@@ -40,12 +40,13 @@
private NodeEntry versionableEntry = null;
- protected RemoveVersion(ItemState removeState, NodeState parent, VersionManager mgr) {
+ protected RemoveVersion(ItemState removeState, NodeState parent, VersionManager mgr)
+ throws RepositoryException {
super(removeState, parent);
try {
versionableEntry = mgr.getVersionableNodeEntry((NodeState) removeState);
} catch (RepositoryException e) {
- log.warn("Internal error", e);
+ log.warn("Failed to retrieve the hierarchy entry of the versionable node.", e);
}
}
@@ -54,6 +55,7 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws AccessDeniedException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -64,6 +66,8 @@
* @see Operation#persisted()
*/
public void persisted() {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
// invaliate the versionable node as well (version related properties)
if (versionableEntry != null) {
Iterator propEntries = versionableEntry.getPropertyEntries();
@@ -80,12 +84,13 @@
}
//----------------------------------------< Access Operation Parameters >---
- public ItemId getRemoveId() {
+ public ItemId getRemoveId() throws RepositoryException {
return removeState.getWorkspaceId();
}
//------------------------------------------------------------< Factory >---
- public static Operation create(NodeState versionState, NodeState vhState, VersionManager mgr) {
+ public static Operation create(NodeState versionState, NodeState vhState, VersionManager mgr)
+ throws RepositoryException {
RemoveVersion rm = new RemoveVersion(versionState, vhState, mgr);
return rm;
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ReorderNodes.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ReorderNodes.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ReorderNodes.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ReorderNodes.java Tue Oct 14 00:48:22 2008
@@ -40,7 +40,8 @@
private final NodeState insert;
private final NodeState before;
- private ReorderNodes(NodeState parentState, NodeState insert, NodeState before) {
+ private ReorderNodes(NodeState parentState, NodeState insert, NodeState before)
+ throws RepositoryException {
this.parentState = parentState;
this.insert = insert;
this.before = before;
@@ -58,6 +59,7 @@
* @param visitor
*/
public void accept(OperationVisitor visitor) throws ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -66,9 +68,21 @@
*
* @see Operation#persisted()
*/
- public void persisted() {
- throw new UnsupportedOperationException("persisted() not implemented for transient modification.");
+ public void persisted() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
+ insert.getHierarchyEntry().complete(this);
}
+
+ /**
+ * @see Operation#undo()
+ */
+ public void undo() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_UNDO;
+ insert.getHierarchyEntry().complete(this);
+ }
+
//----------------------------------------< Access Operation Parameters >---
public NodeId getParentId() {
@@ -99,6 +113,9 @@
public static Operation create(NodeState parentState, Path.Element srcName,
Path.Element beforeName) throws ItemNotFoundException, RepositoryException {
+ // make sure the parent hierarchy entry has its child entries loaded
+ assertChildNodeEntries(parentState);
+
NodeState insert = parentState.getChildNodeState(srcName.getName(), srcName.getNormalizedIndex());
NodeState before = (beforeName == null) ? null : parentState.getChildNodeState(beforeName.getName(), beforeName.getNormalizedIndex());
return new ReorderNodes(parentState, insert, before);
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ResolveMergeConflict.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ResolveMergeConflict.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ResolveMergeConflict.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/ResolveMergeConflict.java Tue Oct 14 00:48:22 2008
@@ -16,18 +16,18 @@
*/
package org.apache.jackrabbit.jcr2spi.operation;
-import org.apache.jackrabbit.jcr2spi.state.NodeState;
-import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
import org.apache.jackrabbit.spi.NodeId;
-import javax.jcr.RepositoryException;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.version.VersionException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.version.VersionException;
import java.util.Iterator;
/**
@@ -55,6 +55,7 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws RepositoryException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -65,6 +66,8 @@
* @see Operation#persisted()
*/
public void persisted() {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
// non-recursive invalidation BUT including all properties
Iterator propEntries = ((NodeEntry) nodeState.getHierarchyEntry()).getPropertyEntries();
while (propEntries.hasNext()) {
@@ -74,7 +77,7 @@
nodeState.getHierarchyEntry().invalidate(false);
}
//----------------------------------------< Access Operation Parameters >---
- public NodeId getNodeId() {
+ public NodeId getNodeId() throws RepositoryException {
return nodeState.getNodeEntry().getWorkspaceId();
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Restore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Restore.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Restore.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Restore.java Tue Oct 14 00:48:22 2008
@@ -55,6 +55,7 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws PathNotFoundException, ItemExistsException, VersionException, ConstraintViolationException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -66,6 +67,8 @@
* @see Operation#persisted()
*/
public void persisted() {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
NodeEntry entry;
if (nodeState == null || removeExisting) {
// invalidate the complete tree
@@ -88,7 +91,7 @@
*
* @return
*/
- public NodeId getNodeId() {
+ public NodeId getNodeId() throws RepositoryException {
return (nodeState == null) ? null : nodeState.getNodeEntry().getWorkspaceId();
}
@@ -103,7 +106,7 @@
return relQPath;
}
- public NodeId[] getVersionIds() {
+ public NodeId[] getVersionIds() throws RepositoryException {
NodeId[] versionIds = new NodeId[versionStates.length];
for (int i = 0; i < versionStates.length; i++) {
versionIds[i] = versionStates[i].getNodeEntry().getWorkspaceId();
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetMixin.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetMixin.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetMixin.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetMixin.java Tue Oct 14 00:48:22 2008
@@ -36,7 +36,7 @@
private final NodeState nodeState;
private final Name[] mixinNames;
- private SetMixin(NodeState nodeState, Name[] mixinNames) {
+ private SetMixin(NodeState nodeState, Name[] mixinNames) throws RepositoryException {
this.nodeState = nodeState;
this.nodeId = nodeState.getNodeId();
this.mixinNames = mixinNames;
@@ -59,16 +59,26 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws AccessDeniedException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
/**
- * Throws UnsupportedOperationException
- *
* @see Operation#persisted()
*/
- public void persisted() {
- throw new UnsupportedOperationException("persisted() not implemented for transient modification.");
+ public void persisted() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
+ nodeState.getHierarchyEntry().complete(this);
+ }
+
+ /**
+ * @see Operation#undo()
+ */
+ public void undo() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_UNDO;
+ nodeState.getHierarchyEntry().complete(this);
}
//----------------------------------------< Access Operation Parameters >---
@@ -86,7 +96,11 @@
//------------------------------------------------------------< Factory >---
- public static Operation create(NodeState nodeState, Name[] mixinNames) {
+ public static Operation create(NodeState nodeState, Name[] mixinNames)
+ throws RepositoryException {
+ if (nodeState == null || mixinNames == null) {
+ throw new IllegalArgumentException();
+ }
SetMixin sm = new SetMixin(nodeState, mixinNames);
return sm;
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPropertyValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPropertyValue.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPropertyValue.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPropertyValue.java Tue Oct 14 00:48:22 2008
@@ -41,7 +41,8 @@
private final QValue[] values;
private final int valueType;
- private SetPropertyValue(PropertyState propertyState, int valueType, QValue[] values) {
+ private SetPropertyValue(PropertyState propertyState, int valueType, QValue[] values)
+ throws RepositoryException {
this.propertyState = propertyState;
propertyId = (PropertyId) propertyState.getId();
@@ -58,16 +59,26 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws ValueFormatException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
/**
- * Throws UnsupportedOperationException
- *
* @see Operation#persisted()
*/
- public void persisted() {
- throw new UnsupportedOperationException("persisted() not implemented for transient modification.");
+ public void persisted() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
+ propertyState.getHierarchyEntry().complete(this);
+ }
+
+ /**
+ * @see Operation#undo()
+ */
+ public void undo() throws RepositoryException {
+ assert status == STATUS_PENDING;
+ status = STATUS_UNDO;
+ propertyState.getHierarchyEntry().complete(this);
}
//----------------------------------------< Access Operation Parameters >---
@@ -93,7 +104,7 @@
//------------------------------------------------------------< Factory >---
public static Operation create(PropertyState propState, QValue[] qValues,
- int valueType) {
+ int valueType) throws RepositoryException {
// compact array (purge null entries)
List list = new ArrayList();
for (int i = 0; i < qValues.length; i++) {
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Update.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Update.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Update.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Update.java Tue Oct 14 00:48:22 2008
@@ -19,13 +19,13 @@
import org.apache.jackrabbit.jcr2spi.state.NodeState;
import org.apache.jackrabbit.spi.NodeId;
-import javax.jcr.RepositoryException;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.version.VersionException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.version.VersionException;
/**
* <code>Update</code>...
@@ -47,6 +47,7 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws RepositoryException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -57,11 +58,13 @@
* @see Operation#persisted()
*/
public void persisted() {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
nodeState.getHierarchyEntry().invalidate(true);
}
//----------------------------------------< Access Operation Parameters >---
- public NodeId getNodeId() {
+ public NodeId getNodeId() throws RepositoryException {
return nodeState.getNodeEntry().getWorkspaceId();
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/WorkspaceImport.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/WorkspaceImport.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/WorkspaceImport.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/WorkspaceImport.java Tue Oct 14 00:48:22 2008
@@ -55,6 +55,7 @@
* @see Operation#accept(OperationVisitor)
*/
public void accept(OperationVisitor visitor) throws RepositoryException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException {
+ assert status == STATUS_PENDING;
visitor.visit(this);
}
@@ -65,6 +66,8 @@
* @see Operation#persisted()
*/
public void persisted() {
+ assert status == STATUS_PENDING;
+ status = STATUS_PERSISTED;
NodeEntry entry;
if (uuidBehaviour == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING ||
uuidBehaviour == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING) {
@@ -82,7 +85,7 @@
}
//----------------------------------------< Access Operation Parameters >---
- public NodeId getNodeId() {
+ public NodeId getNodeId() throws RepositoryException {
return nodeState.getNodeId();
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java Tue Oct 14 00:48:22 2008
@@ -17,22 +17,18 @@
package org.apache.jackrabbit.jcr2spi.state;
import org.apache.jackrabbit.jcr2spi.operation.Operation;
-import org.apache.jackrabbit.jcr2spi.operation.AddNode;
-import org.apache.jackrabbit.jcr2spi.operation.AddProperty;
import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
-import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.InvalidItemStateException;
import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
import java.util.Iterator;
import java.util.Set;
-import java.util.LinkedHashSet;
-import java.util.HashSet;
-import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
/**
* Registers changes made to states and references and consolidates
@@ -50,101 +46,129 @@
* in this changelog.
*/
private final ItemState target;
- /**
- * Added states
- */
- private final Set addedStates = new LinkedHashSet();
-
- /**
- * Modified states
- */
- private final Set modifiedStates = new LinkedHashSet();
-
- /**
- * Deleted states
- */
- private final Set deletedStates = new LinkedHashSet();
/**
* Set of operations
*/
- private Set operations = new LinkedHashSet();
+ private final Set operations;
+
+ private final Set affectedStates;
/**
+ * Create a new change log and populates it with operations and states
+ * that are within the scope of this change set.
*
* @param target
+ * @param operations
+ * @param affectedStates
+ * @throws InvalidItemStateException
+ * @throws ConstraintViolationException
*/
- ChangeLog(ItemState target) {
+ ChangeLog(ItemState target, Set operations, Set affectedStates)
+ throws InvalidItemStateException, ConstraintViolationException {
this.target = target;
+ this.operations = operations;
+ this.affectedStates = affectedStates;
}
//-----------------------------------------------< Inform the ChangeLog >---
/**
- * Add the given operation to the list of operations to be recorded within
- * the current update cycle of this ChangeLog.
- *
- * @param operation
- */
- public void addOperation(Operation operation) {
- operations.add(operation);
- }
-
- /**
- * A state has been added
- *
- * @param state state that has been added
- */
- public void added(ItemState state) {
- addedStates.add(state);
- }
-
- /**
- * A state has been modified. If the state is not a new state
- * (not in the collection of added ones), then add
- * it to the modified states collection.
- *
- * @param state state that has been modified
- */
- public void modified(ItemState state) {
- if (!addedStates.contains(state)) {
- modifiedStates.add(state);
+ * Call this method when this change log has been sucessfully persisted.
+ * This implementation will call {@link Operation#persisted() on the
+ * individual operations followed by setting all remaining modified
+ * states to EXISTING.
+ */
+ public void persisted() throws RepositoryException {
+ List changedMixins = new ArrayList();
+ Operation[] ops = (Operation[]) operations.toArray(new Operation[operations.size()]);
+ for (int i = 0; i < ops.length; i++) {
+ ops[i].persisted();
+ if (ops[i] instanceof SetMixin) {
+ changedMixins.add(((SetMixin) ops[i]).getNodeState());
+ }
}
- }
-
- /**
- * A state has been deleted. If the state is not a new state
- * (not in the collection of added ones), then remove
- * it from the modified states collection and add it to the
- * deleted states collection.
- *
- * @param state state that has been deleted
- */
- public void deleted(ItemState state) {
- if (!addedStates.remove(state)) {
- modifiedStates.remove(state);
- deletedStates.add(state);
+ // process all remaining states that were not covered by the
+ // operation persistence.
+ for (Iterator it = affectedStates.iterator(); it.hasNext();) {
+ ItemState state = (ItemState) it.next();
+ HierarchyEntry he = state.getHierarchyEntry();
+
+ switch (state.getStatus()) {
+ case Status.EXISTING_MODIFIED:
+ state.setStatus(Status.EXISTING);
+ if (state.isNode() && changedMixins.contains(state)) {
+ // mixin changed for a node -> force reloading upon next
+ // access in order to be aware of modified uniqueID.
+ he.invalidate(false);
+ }
+ break;
+ case Status.EXISTING_REMOVED:
+ he.remove();
+ break;
+ case Status.NEW:
+ // illegal. should not get here.
+ log.error("ChangeLog still contains NEW state: " + state.getName());
+ state.setStatus(Status.EXISTING);
+ break;
+ case Status.MODIFIED:
+ case Status._UNDEFINED_:
+ case Status.STALE_DESTROYED:
+ case Status.STALE_MODIFIED:
+ // illegal.
+ log.error("ChangeLog contains state (" + state.getName() + ") with illegal status " + Status.getName(state.getStatus()));
+ break;
+ case Status.EXISTING:
+ if (state.isNode() && changedMixins.contains(state)) {
+ // mixin changed for a node -> force reloading upon next
+ // access in order to be aware of modified uniqueID.
+ he.invalidate(false);
+ }
+ // otherwise: ignore. operations already have been completed
+ break;
+ case Status.INVALIDATED:
+ case Status.REMOVED:
+ // ignore. operations already have been completed
+ break;
+ }
}
}
/**
- * Call this method when this change log has been sucessfully persisted.
- * This implementation will call {@link ItemState#persisted(ChangeLog)
- * ItemState.refresh(this)} on the target item of this change log.
- */
- public void persisted() {
- target.persisted(this);
- }
-
- /**
* Revert the changes listed within this changelog
*/
public void undo() throws RepositoryException {
- // TODO: check if states are reverted in the correct order
- Iterator[] its = new Iterator[] {addedStates(), deletedStates(), modifiedStates()};
- IteratorChain chain = new IteratorChain(its);
- while (chain.hasNext()) {
- ItemState state = (ItemState) chain.next();
- state.getHierarchyEntry().revert();
+ Operation[] ops = (Operation[]) operations.toArray(new Operation[operations.size()]);
+ for (int i = ops.length - 1; i >= 0; i--) {
+ ops[i].undo();
+ }
+
+ // process all remaining states that were not covered by the
+ // operation undo.
+ for (Iterator it = affectedStates.iterator(); it.hasNext();) {
+ ItemState state = (ItemState) it.next();
+ switch (state.getStatus()) {
+ case Status.EXISTING_MODIFIED:
+ case Status.EXISTING_REMOVED:
+ case Status.STALE_MODIFIED:
+ case Status.STALE_DESTROYED:
+ state.getHierarchyEntry().revert();
+ break;
+ case Status.NEW:
+ // illegal. should not get here.
+ log.error("ChangeLog still contains NEW state: " + state.getName());
+ state.getHierarchyEntry().revert();
+ break;
+ case Status.MODIFIED:
+ case Status._UNDEFINED_:
+ // illegal.
+ log.error("ChangeLog contains state (" + state.getName() + ") with illegal status " + Status.getName(state.getStatus()));
+ break;
+ case Status.EXISTING:
+ case Status.REMOVED:
+ case Status.INVALIDATED:
+ // ignore already processed
+ break;
+ }
}
}
//----------------------< Retrieve information present in the ChangeLog >---
@@ -156,264 +180,33 @@
}
/**
- * @return <code>true</code> if this changelog is empty.
+ * @return true if no <code>operations</code> are present.
*/
public boolean isEmpty() {
return operations.isEmpty();
}
/**
- * @return an iterator over all operations.
+ * @return set of operations.
*/
- public Iterator getOperations() {
- return operations.iterator();
+ public Set getOperations() {
+ return operations;
}
/**
- * Return an iterator over all added states.
- *
- * @return iterator over all added states.
- */
- public Iterator addedStates() {
- return addedStates.iterator();
- }
-
- /**
- * Return an iterator over all modified states.
- *
- * @return iterator over all modified states.
+ * @return set of the affected states.
*/
- public Iterator modifiedStates() {
- return modifiedStates.iterator();
- }
-
- /**
- * Return an iterator over all deleted states.
- *
- * @return iterator over all deleted states.
- */
- public Iterator deletedStates() {
- return deletedStates.iterator();
- }
-
- /**
- * Returns true, if this change log contains the given <code>ItemState</code>
- * in the set of transiently removed states.
- *
- * @param state
- * @return
- */
- public boolean containsDeletedState(ItemState state) {
- return deletedStates.contains(state);
- }
-
- /**
- * Removes the subset of this changelog represented by the given
- * <code>ChangeLog</code> from this changelog.
- *
- * @param subChangeLog remove all entries (states, operations) present in
- * the given changelog from this changelog.
- */
- public void removeAll(ChangeLog subChangeLog) {
- addedStates.removeAll(subChangeLog.addedStates);
- modifiedStates.removeAll(subChangeLog.modifiedStates);
- deletedStates.removeAll(subChangeLog.deletedStates);
-
- operations.removeAll(subChangeLog.operations);
- }
-
- /**
- * Adjust this ChangeLog according to the status change with the given
- * ItemState:
- * Remove all entries and operation related to the given ItemState, that
- * are not used any more (respecting the status change).
- *
- * @param state
- */
- public void statusChanged(ItemState state, int previousStatus) {
- switch (state.getStatus()) {
- case (Status.EXISTING):
- switch (previousStatus) {
- case Status.EXISTING_MODIFIED:
- // was modified and is now refreshed
- modifiedStates.remove(state);
- break;
- case Status.EXISTING_REMOVED:
- // was removed and is now refreshed
- deletedStates.remove(state);
- break;
- case Status.STALE_MODIFIED:
- // was modified and state and is now refreshed
- modifiedStates.remove(state);
- break;
- case Status.NEW:
- // was new and has been saved now
- addedStates.remove(state);
- break;
- }
- // TODO: check if correct: changelog gets cleared any way -> no need to remove operations
- break;
- case Status.EXISTING_MODIFIED:
- modified(state);
- break;
- case (Status.EXISTING_REMOVED):
- deleted(state);
- // removeAffectedOperations(state);
- break;
- case (Status.REMOVED):
- switch (previousStatus) {
- case Status.EXISTING_REMOVED:
- // was removed and is now saved
- deletedStates.remove(state);
- removeAffectedOperations(state);
- break;
- case Status.NEW:
- newStateRemoved(state);
- break;
- }
- break;
- }
- }
-
- private void newStateRemoved(ItemState state) {
- NodeEntry parentEntry = state.getHierarchyEntry().getParent();
- if (!parentEntry.isAvailable() || Status.isTerminal(parentEntry.getStatus())) {
- return; // TODO: check if correct
- }
- // was new and now removed again
- addedStates.remove(state);
-
- // remove any operations performed on the removed state
- removeAffectedOperations(state);
-
- /* remove the add-operation as well:
- since the affected state of an 'ADD' operation is the parent instead
- of the added-state, the set of operations need to be searched for the
- parent state && the proper operation type.
- SET_MIXIN is considered as a special case of adding a property
- */
- NodeState parent;
- try {
- parent = parentEntry.getNodeState();
- } catch (RepositoryException e) {
- // should never occur
- log.error("Internal error:", e);
- return;
- }
- for (Iterator it = operations.iterator(); it.hasNext();) {
- Operation op = (Operation) it.next();
- if (op instanceof AddNode) {
- AddNode operation = (AddNode) op;
- if (operation.getParentState() == parent
- && operation.getNodeName().equals(state.getName())) {
- // TODO: this will not work for name name siblings!
- it.remove();
- break;
- }
- } else if (op instanceof AddProperty) {
- AddProperty operation = (AddProperty) op;
- if (operation.getParentState() == parent
- && operation.getPropertyName().equals(state.getName())) {
- it.remove();
- break;
- }
- } else if (op instanceof SetMixin &&
- NameConstants.JCR_MIXINTYPES.equals(state.getName()) &&
- ((SetMixin)op).getNodeState() == parent) {
- it.remove();
- break;
- }
- }
- }
-
- private void removeAffectedOperations(ItemState state) {
- for (Iterator it = operations.iterator(); it.hasNext();) {
- Operation op = (Operation) it.next();
- if (op.getAffectedItemStates().contains(state)) {
- it.remove();
- }
- }
- }
-
- /**
- * Make sure that this ChangeLog is totally 'self-contained'
- * and independant; items within the scope of this update operation
- * must not have 'external' dependencies;
- * (e.g. moving a node requires that the target node including both
- * old and new parents are saved)
- */
- public void checkIsSelfContained() throws ConstraintViolationException {
- Set affectedStates = new HashSet();
- affectedStates.addAll(modifiedStates);
- affectedStates.addAll(deletedStates);
- affectedStates.addAll(addedStates);
-
- // check if the affected states listed by the operations are all
- // listed in the modified,deleted or added states collected by this
- // changelog.
- Iterator it = getOperations();
- while (it.hasNext()) {
- Operation op = (Operation) it.next();
- Collection opStates = op.getAffectedItemStates();
- if (!affectedStates.containsAll(opStates)) {
- // need to save the parent as well
- String msg = "ChangeLog is not self contained.";
- throw new ConstraintViolationException(msg);
- }
- }
- }
-
- /**
- * Populates this <code>ChangeLog</code> with operations that are within the
- * scope of this change set.
- *
- * @param operations an Iterator of <code>Operation</code>s which are the
- * candidates to be included in this <code>ChangeLog</code>.
- */
- public void collectOperations(Iterator operations) {
- Set affectedStates = new HashSet();
- affectedStates.addAll(addedStates);
- affectedStates.addAll(deletedStates);
- affectedStates.addAll(modifiedStates);
- while (operations.hasNext()) {
- Operation op = (Operation) operations.next();
- Iterator states = op.getAffectedItemStates().iterator();
- while (states.hasNext()) {
- ItemState state = (ItemState) states.next();
- if (affectedStates.contains(state)) {
- addOperation(op);
- break;
- }
- }
- }
+ public Set getAffectedStates() {
+ return affectedStates;
}
/**
* Reset this change log, removing all members inside the
* maps we built.
*/
- public void reset() {
- addedStates.clear();
- modifiedStates.clear();
- deletedStates.clear();
+ void reset() {
+ affectedStates.clear();
// also clear all operations
operations.clear();
}
-
- //-------------------------------------------------------------< Object >---
- /**
- * Returns a string representation of this change log for diagnostic
- * purposes.
- *
- * @return a string representation of this change log
- */
- public String toString() {
- StringBuffer buf = new StringBuffer();
- buf.append("{");
- buf.append("#addedStates=").append(addedStates.size());
- buf.append(", #modifiedStates=").append(modifiedStates.size());
- buf.append(", #deletedStates=").append(deletedStates.size());
- buf.append("}");
- return buf.toString();
- }
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java Tue Oct 14 00:48:22 2008
@@ -16,25 +16,22 @@
*/
package org.apache.jackrabbit.jcr2spi.state;
-import org.apache.jackrabbit.util.WeakIdentityCollection;
-import org.apache.jackrabbit.spi.ItemId;
-import org.apache.jackrabbit.spi.NodeId;
-import org.apache.jackrabbit.spi.PropertyId;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
-import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProvider;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.util.WeakIdentityCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jcr.RepositoryException;
-import javax.jcr.ItemNotFoundException;
import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
import java.util.Collection;
-import java.util.Iterator;
import java.util.Collections;
+import java.util.Iterator;
/**
* <code>ItemState</code> represents the state of an <code>Item</code>.
@@ -108,10 +105,6 @@
this.hierarchyEntry = entry;
this.isf = isf;
this.definitionProvider = definitionProvider;
-
- if (!entry.isAvailable()) {
- entry.setItemState(this);
- }
}
/**
@@ -144,17 +137,13 @@
}
/**
- * Returns <code>true</code> if this item state is valid, that is its status
- * is one of:
- * <ul>
- * <li>{@link Status#EXISTING}</li>
- * <li>{@link Status#EXISTING_MODIFIED}</li>
- * <li>{@link Status#NEW}</li>
- * </ul>
+ * Returns <code>true</code> if this item state is valid and can be accessed.
* @return
+ * @see Status#isValid(int)
+ * @see Status#isStale(int)
*/
public boolean isValid() {
- return Status.isValid(getStatus());
+ return Status.isValid(getStatus()) || Status.isStale(getStatus());
}
/**
@@ -183,7 +172,7 @@
*
* @return the identifier of this item state..
*/
- public abstract ItemId getId();
+ public abstract ItemId getId() throws RepositoryException;
/**
* Utility method:
@@ -192,7 +181,7 @@
*
* @return the identifier of this item state..
*/
- public abstract ItemId getWorkspaceId();
+ public abstract ItemId getWorkspaceId() throws RepositoryException;
/**
* Utility method:
@@ -239,7 +228,7 @@
return;
}
- if (Status.isTerminal(oldStatus)) {
+ if (oldStatus == Status.REMOVED) {
throw new IllegalStateException("State is already in terminal status " + Status.getName(oldStatus));
}
if (Status.isValidStatusChange(oldStatus, newStatus)) {
@@ -319,55 +308,6 @@
}
/**
- * Used on the target state of a save call AFTER the changelog has been
- * successfully submitted to the SPI..
- *
- * @param changeLog
- * @throws IllegalStateException if this state is a 'workspace' state.
- */
- abstract void persisted(ChangeLog changeLog) throws IllegalStateException;
-
- /**
- * Retrieved a fresh ItemState from the persistent layer and merge its
- * data with this state in order to reload it. In case of a NEW state retrieving
- * the state from the persistent layer is only possible if the state has
- * been persisted.
- *
- * @param keepChanges
- */
- public void reload(boolean keepChanges) {
- ItemId id = getWorkspaceId();
- ItemState tmp;
- try {
- if (isNode()) {
- tmp = isf.createNodeState((NodeId) id, (NodeEntry) getHierarchyEntry());
- } else {
- tmp = isf.createPropertyState((PropertyId) id, (PropertyEntry) getHierarchyEntry());
- }
- } catch (ItemNotFoundException e) {
- // TODO: deal with moved items separately
- // remove hierarchyEntry (including all children and set
- // state-status to REMOVED (or STALE_DESTROYED)
- log.debug("Item '" + id + "' cannot be found on the persistent layer -> remove.");
- getHierarchyEntry().remove();
- return;
- } catch (RepositoryException e) {
- // TODO: rather throw? remove from parent?
- log.warn("Exception while reloading item state: " + e);
- log.debug("Stacktrace: ", e);
- return;
- }
-
- boolean modified = merge(tmp, keepChanges);
- if (status == Status.NEW || status == Status.INVALIDATED) {
- setStatus(Status.EXISTING);
- } else if (modified) {
- // start notification by marking this state modified.
- setStatus(Status.MODIFIED);
- }
- }
-
- /**
* Marks this item state as modified.
*/
void markModified() throws InvalidItemStateException {
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java Tue Oct 14 00:48:22 2008
@@ -16,31 +16,25 @@
*/
package org.apache.jackrabbit.jcr2spi.state;
-import org.apache.commons.collections.iterators.IteratorChain;
import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
-import org.apache.jackrabbit.jcr2spi.util.StateUtility;
import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProvider;
+import org.apache.jackrabbit.jcr2spi.util.StateUtility;
+import org.apache.jackrabbit.spi.ItemId;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.NodeId;
-import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.NodeInfo;
import org.apache.jackrabbit.spi.PropertyId;
import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.NodeInfo;
import org.apache.jackrabbit.spi.QValue;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import javax.jcr.RepositoryException;
import javax.jcr.ItemNotFoundException;
-import java.util.ArrayList;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import javax.jcr.RepositoryException;
import java.util.Arrays;
+import java.util.List;
/**
* <code>NodeState</code> represents the state of a <code>Node</code>.
@@ -113,7 +107,7 @@
* {@inheritDoc}
* @see ItemState#getId()
*/
- public ItemId getId() {
+ public ItemId getId() throws RepositoryException {
return getNodeId();
}
@@ -121,7 +115,7 @@
* {@inheritDoc}
* @see ItemState#getWorkspaceId()
*/
- public ItemId getWorkspaceId() {
+ public ItemId getWorkspaceId() throws RepositoryException {
return getNodeEntry().getWorkspaceId();
}
@@ -177,125 +171,6 @@
return false;
}
- /**
- * {@inheritDoc}
- * @see ItemState#persisted(ChangeLog)
- */
- void persisted(ChangeLog changeLog) throws IllegalStateException {
- // remember parent states that have need to adjust their uniqueID/mixintypes
- // or that got a new child entry added or existing entries removed.
- Map modParents = new HashMap();
-
- // process deleted states from the changelog
- for (Iterator it = changeLog.deletedStates(); it.hasNext();) {
- ItemState delState = (ItemState) it.next();
- if (Status.isTerminal(delState.getStatus())) {
- log.debug("Removal of State " + delState + " has already been completed.");
- continue;
- }
- delState.getHierarchyEntry().remove();
-
- // adjust parent states unless the parent is removed as well
- if (delState.getHierarchyEntry().getParent().isAvailable()) {
- try {
- NodeState parent = delState.getParent();
- if (!changeLog.containsDeletedState(parent)) {
- modifiedParent(parent, delState, modParents);
- }
- } catch (RepositoryException e) {
- // ignore. if parent state cannot be retrieved for whatever
- // reason, it doesn't need to be adjusted
- }
- }
- }
-
- // process added states from the changelog. since the changlog maintains
- // LinkedHashSet for its entries, the iterator will not return a added
- // entry before its NEW parent.
- for (Iterator it = changeLog.addedStates(); it.hasNext();) {
- ItemState addedState = (ItemState) it.next();
- NodeState parent;
- try {
- parent = addedState.getParent();
- } catch (RepositoryException e) {
- // TODO: handle properly
- log.error("Internal error:", e.getMessage());
- continue;
- }
- // if parent is modified -> remember for final status reset
- if (parent.getStatus() == Status.EXISTING_MODIFIED) {
- modifiedParent(parent, addedState, modParents);
- }
- if (addedState.getStatus() == Status.EXISTING) {
- log.debug("Adding new state " + addedState + " has already been completed.");
- } else {
- // connect the new state to its overlayed state (including update
- // via merging in order to be aware of autocreated values,
- // changed definition etc.
- addedState.reload(false);
- }
- }
-
- for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
- ItemState modState = (ItemState) it.next();
- if (modState.getStatus() == Status.EXISTING) {
- log.debug("Modified state has already been processed");
- continue;
- }
- if (modState.isNode()) {
- if (StateUtility.isMovedState((NodeState) modState)) {
- // and mark the moved state existing
- modState.setStatus(Status.EXISTING);
- } else {
- // remember state as modified only for later processing
- if (!modParents.containsKey(modState)) {
- modParents.put(modState, new ArrayList(2));
- }
- }
- } else {
- // peristed prop-state has status EXISTING now
- modState.setStatus(Status.EXISTING);
-
- // if property state defines a modified jcr:mixinTypes the parent
- // is listed as modified state and needs to be processed at the end.
- if (NameConstants.JCR_MIXINTYPES.equals(modState.getName())) {
- try {
- modifiedParent(modState.getParent(), modState, modParents);
- } catch (RepositoryException e) {
- // should never occur. since parent must be available otherwise
- // the mixin could not been added/removed.
- log.warn("Internal error:", e.getMessage());
- }
- }
- }
- }
-
- /* process all parent states that are marked modified and eventually
- need their uniqueID or mixin-types being adjusted because that property
- has been added, modified or removed */
- for (Iterator it = modParents.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- NodeState parent = (NodeState) entry.getKey();
- List l = (List) entry.getValue();
- adjustNodeState(parent, (PropertyState[]) l.toArray(new PropertyState[l.size()]));
- }
-
- /* finally check if all entries in the changelog have been processed
- and eventually force a reload in order not to have any states with
- wrong transient status floating around. */
- Iterator[] its = new Iterator[] {changeLog.addedStates(), changeLog.deletedStates(), changeLog.modifiedStates()};
- IteratorChain chain = new IteratorChain(its);
- while (chain.hasNext()) {
- ItemState state = (ItemState) chain.next();
- if (!(state.getStatus() == Status.EXISTING ||
- state.getStatus() == Status.REMOVED ||
- state.getStatus() == Status.INVALIDATED)) {
- log.info("State " + state + " with Status " + Status.getName(state.getStatus()) + " has not been processed upon ChangeLog.persisted => invalidate");
- state.setStatus(Status.EXISTING);
- }
- }
- }
-
//----------------------------------------------------------< NodeState >---
/**
* @return The <code>NodeEntry</code> associated with this state.
@@ -309,7 +184,7 @@
*
* @return the id of this node state.
*/
- public NodeId getNodeId() {
+ public NodeId getNodeId() throws RepositoryException {
return getNodeEntry().getId();
}
@@ -349,7 +224,6 @@
}
/**
- * TODO improve
* Used by NodeEntryImpl and NodeState only
*
* @param mixinTypeNames
@@ -573,51 +447,10 @@
before. The effective NT must be evaluated as if it had been
evaluated upon creating the workspace state.
*/
- def = definitionProvider.getQNodeDefinition(getParent().getNodeTypeNames(), getName(), getNodeTypeName(), getNodeEntry().getWorkspaceId());
+ NodeState parent = getParent();
+ NodeId wspId = (NodeId) getWorkspaceId();
+ def = definitionProvider.getQNodeDefinition(getParent().getNodeTypeNames(), getName(), getNodeTypeName(), wspId);
}
return def;
}
- /**
- *
- * @param childState
- * @param modParents
- */
- private static void modifiedParent(NodeState parent, ItemState childState, Map modParents) {
- List l;
- if (modParents.containsKey(parent)) {
- l = (List) modParents.get(parent);
- } else {
- l = new ArrayList(2);
- modParents.put(parent, l);
- }
- if (childState != null && !childState.isNode() && StateUtility.isUuidOrMixin(childState.getName())) {
- l.add(childState);
- }
- }
-
- /**
- *
- * @param parent
- * @param props
- */
- private static void adjustNodeState(NodeState parent, PropertyState[] props) {
- for (int i = 0; i < props.length; i++) {
- PropertyState propState = props[i];
- if (NameConstants.JCR_UUID.equals(propState.getName())) {
- if (propState.getStatus() == Status.REMOVED) {
- parent.getNodeEntry().setUniqueID(null);
- } else {
- // retrieve uuid from persistent layer
- propState.reload(false);
- }
- } else if (NameConstants.JCR_MIXINTYPES.equals(propState.getName())) {
- Name[] mixins = StateUtility.getMixinNames(propState);
- parent.setMixinTypeNames(mixins);
- } // else: ignore.
- }
-
- // set parent status to 'existing'
- parent.setStatus(Status.EXISTING);
- parent.reload(false);
- }
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java?rev=704361&r1=704360&r2=704361&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java Tue Oct 14 00:48:22 2008
@@ -30,7 +30,6 @@
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.ConstraintViolationException;
-import java.util.Iterator;
/**
* <code>PropertyState</code> represents the state of a <code>Property</code>.
@@ -50,14 +49,15 @@
private final boolean multiValued;
/**
- *
+ * Value(s) and type of an existing property that has been transiently
+ * modified.
*/
- private TransientData transientData;
+ private PropertyData transientData;
/**
- *
+ * Original value(s) and type of an existing or a new property.
*/
- private PropertyInfo pInfo;
+ private PropertyData data;
/**
* Create a NEW PropertyState
@@ -69,12 +69,13 @@
*/
protected PropertyState(PropertyEntry entry, ItemStateFactory isf,
QPropertyDefinition definition,
- ItemDefinitionProvider definitionProvider) {
+ ItemDefinitionProvider definitionProvider,
+ QValue[] values, int propertyType)
+ throws ConstraintViolationException, RepositoryException {
super(Status.NEW, entry, isf, definitionProvider);
this.multiValued = definition.isMultiple();
this.definition = definition;
- this.transientData = null; // TODO: maybe type/values should be passed to constructor
- this.pInfo = null;
+ setValues(values, propertyType);
}
/**
@@ -90,8 +91,8 @@
ItemDefinitionProvider definitionProvider) {
super(entry, isf, definitionProvider);
this.multiValued = pInfo.isMultiValued();
+ this.data = new PropertyData(pInfo);
this.transientData = null;
- this.pInfo = pInfo;
}
//----------------------------------------------------------< ItemState >---
@@ -109,7 +110,7 @@
* {@inheritDoc}
* @see ItemState#getId()
*/
- public ItemId getId() {
+ public ItemId getId() throws RepositoryException {
return ((PropertyEntry) getHierarchyEntry()).getId();
}
@@ -117,15 +118,15 @@
* {@inheritDoc}
* @see ItemState#getWorkspaceId()
*/
- public ItemId getWorkspaceId() {
+ public ItemId getWorkspaceId() throws RepositoryException {
return ((PropertyEntry) getHierarchyEntry()).getWorkspaceId();
}
/**
- * If <code>keepChanges</code> is true, this method does nothing and returns
- * false. Otherwise type and values of the other property state are compared
- * to this state. If they differ, they will be copied to this state and
- * this method returns true.
+ * If <code>keepChanges</code> is true, this method only compares the existing
+ * values with the values from 'another' and returns true, if the underlying
+ * persistent state is different to the stored persistent values. Otherwise
+ * the transient changes will be discarded.
*
* @see ItemState#merge(ItemState, boolean)
*/
@@ -136,14 +137,21 @@
if (another.isNode()) {
throw new IllegalArgumentException("Attempt to merge property state with node state.");
}
- boolean modified = diff(this, (PropertyState) another);
- this.pInfo = ((PropertyState) another).pInfo;
- if (!keepChanges && transientData != null) {
- modified = true;
+ // calculate if the persistent values of this state differ from the
+ // other state.
+ boolean diff = diff(data, ((PropertyState) another).data);
+ // reset the pInfo to point to the pInfo of another state.
+ this.data = ((PropertyState) another).data;
+ // if transient changes should be preserved OR if there are not
+ // transient changes, simply return diff to indicate if this state
+ // was internally changed.
+ if (keepChanges || transientData == null) {
+ return diff;
+ } else {
transientData.discardValues();
transientData = null;
+ return true;
}
- return modified;
}
/**
@@ -163,26 +171,6 @@
}
}
-
- /**
- * {@inheritDoc}
- * @see ItemState#persisted(ChangeLog)
- */
- void persisted(ChangeLog changeLog)
- throws IllegalStateException {
- for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
- ItemState modState = (ItemState) it.next();
- if (modState == this) {
- /*
- NOTE: Property can only be the changelog target, if it was
- existing and has been modified. removal, add and implicit modification
- of protected properties must be persisted by save on parent.
- */
- setStatus(Status.EXISTING);
- }
- }
- }
-
//------------------------------------------------------< PropertyState >---
/**
* Returns the type of the property value(s).
@@ -194,7 +182,7 @@
* type if the latter is {@link PropertyType#UNDEFINED}.
*/
public int getType() {
- return (transientData == null) ? pInfo.getType() : transientData.type;
+ return (transientData == null) ? data.type : transientData.type;
}
/**
@@ -236,8 +224,8 @@
* @return the value(s) of this property.
*/
public QValue[] getValues() {
- // if transientData are null the pInfo MUST be present (ev. add check)
- return (transientData == null) ? pInfo.getValues() : transientData.values;
+ // if transientData are null the data MUST be present (ev. add check)
+ return (transientData == null) ? data.values : transientData.values;
}
/**
@@ -264,12 +252,20 @@
* @param values the new values
*/
void setValues(QValue[] values, int type) throws RepositoryException {
- if (transientData == null) {
- transientData = new TransientData(type, values);
+ if (getStatus() == Status.NEW) {
+ if (data == null) {
+ data = new PropertyData(type, values);
+ } else {
+ data.setValues(type, values);
+ }
} else {
- transientData.setValues(type, values);
+ if (transientData == null) {
+ transientData = new PropertyData(type, values);
+ } else {
+ transientData.setValues(type, values);
+ }
+ markModified();
}
- markModified();
}
//------------------------------------------------------------< private >---
@@ -317,14 +313,14 @@
* @return if the 2 <code>PropertyState</code>s are different in terms of
* type and/or values.
*/
- private static boolean diff(PropertyState p1, PropertyState p2) {
+ private static boolean diff(PropertyData p1, PropertyData p2) {
// compare type
- if (p1.getType() != p2.getType()) {
+ if (p1.type != p2.type) {
return true;
}
- QValue[] vs1 = p1.getValues();
- QValue[] vs2 = p2.getValues();
+ QValue[] vs1 = p1.values;
+ QValue[] vs2 = p2.values;
if (vs1.length != vs2.length) {
return true;
} else {
@@ -341,18 +337,23 @@
//--------------------------------------------------------< inner class >---
/**
- * Inner class storing transient property values an their type.
+ * Inner class storing property values an their type.
*/
- private class TransientData {
+ private class PropertyData {
private int type;
private QValue[] values;
- private TransientData(int type, QValue[] values) throws RepositoryException {
+ private PropertyData(PropertyInfo pInfo) {
+ this.type = pInfo.getType();
+ this.values = pInfo.getValues();
+ }
+
+ private PropertyData(int type, QValue[] values) throws ConstraintViolationException, RepositoryException {
setValues(type, values);
}
- private void setValues(int type, QValue[] values) throws RepositoryException {
+ private void setValues(int type, QValue[] values) throws ConstraintViolationException, RepositoryException {
// make sure the arguements are consistent and do not violate the
// given property definition.
validate(values, type, getDefinition());