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 2006/11/09 10:09:25 UTC
svn commit: r472818 -
/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/
Author: angela
Date: Thu Nov 9 01:09:24 2006
New Revision: 472818
URL: http://svn.apache.org/viewvc?view=rev&rev=472818
Log:
work in progress.
- nodestates must always be connected to their cne upon creation
TODO: add some sort of caching to avoid traffic overhead
- add TODO for refresh, that currently doesn't work properly
- ItemState.refresh only takes changelog and returns the ids of the
processed states. cleanup of events is left to caller.
- move of NodeStates does not work
- PathResolver: force start to be an NodeState
- all MODIFIED status for SessionStates as well in order to make sure
that listeners are informed about external changes even if the
state is EXISTING.
next TODO: make sure, that public getChildNodeEntry/ies and hasChildNodeEntry check for validity of the connected NodeState. don't return entries, where the nodestate is (transiently) removed or stale.
Modified:
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/CachingItemStateManager.java Thu Nov 9 01:09:24 2006
@@ -188,34 +188,39 @@
* present in the cache.
*/
protected ItemState lookup(ItemId id) {
- ItemState state;
+ NodeState start;
// resolve UUID
if (id.getUUID() != null) {
- state = cache.getNodeState(id.getUUID());
- if (state == null) {
+ start = cache.getNodeState(id.getUUID());
+ if (start == null) {
// not cached
return null;
}
} else {
// start from root
try {
- state = getRootState();
+ start = getRootState();
} catch (ItemStateException e) {
- log.warn("unable to get root node state:" + e.getMessage());
+ // should never occur
+ log.error("Error while retrieving root node state:" + e.getMessage());
return null;
}
}
- // resolve relative path
- if (id.getPath() != null) {
+ if (id.getPath() == null) {
+ // path is null -> id points to a state identified by uuid
+ return start;
+ } else {
+ // resolve path part
try {
- state = PathResolver.lookup(state, id.getPath());
+ return PathResolver.lookup(start, id.getPath());
+ } catch (NoSuchItemStateException e) {
+ log.debug("exception while looking up state with id: " + id);
+ return null;
} catch (ItemStateException e) {
- log.warn("exception while looking up state with id: " + id);
+ log.debug("exception while looking up state with id: " + id);
return null;
}
}
-
- return state;
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChildNodeEntries.java Thu Nov 9 01:09:24 2006
@@ -112,14 +112,15 @@
/**
* Returns the <code>ChildNodeEntry</code> for the given
- * <code>nodeState</code>.
+ * <code>nodeState</code>. Note, that this method does not check if the
+ * given childNodeEntry (and its attached NodeState) is still valid.
*
- * @param nodeState the node state.
+ * @param childState the child node state for which a entry is searched.
* @return the <code>ChildNodeEntry</code> or <code>null</code> if there
- * is no <code>ChildNodeEntry</code> for <code>nodeState</code>.
+ * is no <code>ChildNodeEntry</code> for the given <code>NodeState</code>.
*/
- ChildNodeEntry get(NodeState nodeState) {
- Object o = nameMap.get(nodeState.getQName());
+ ChildNodeEntry get(NodeState childState) {
+ Object o = nameMap.get(childState.getQName());
if (o == null) {
// no matching child node entry
return null;
@@ -131,7 +132,7 @@
ChildNodeEntry cne = n.getChildNodeEntry();
// only check available child node entries
try {
- if (cne.isAvailable() && cne.getNodeState() == nodeState) {
+ if (cne.isAvailable() && cne.getNodeState() == childState) {
return cne;
}
} catch (ItemStateException e) {
@@ -142,7 +143,7 @@
// single child node with this name
ChildNodeEntry cne = ((LinkedEntries.LinkNode) o).getChildNodeEntry();
try {
- if (cne.isAvailable() && cne.getNodeState() == nodeState) {
+ if (cne.isAvailable() && cne.getNodeState() == childState) {
return cne;
}
} catch (ItemStateException e) {
@@ -241,7 +242,7 @@
}
} else {
// then this child node entry has never been accessed
- // before and is assumed valid
+ // before and is assumed valid // TODO: check if correct.
index--;
}
if (index == 0) {
@@ -268,9 +269,9 @@
if (uuid == null) {
throw new IllegalArgumentException();
}
- List l = get(nodeName);
- for (Iterator it = l.iterator(); it.hasNext();) {
- ChildNodeEntry cne = (ChildNodeEntry) it.next();
+ Iterator cneIter = (nodeName != null) ? get(nodeName).iterator() : iterator();
+ while (cneIter.hasNext()) {
+ ChildNodeEntry cne = (ChildNodeEntry) cneIter.next();
if (uuid.equals(cne.getUUID())) {
return cne;
}
@@ -309,9 +310,9 @@
* Adds a <code>ChildNodeEntry</code> for a child node with the given
* name and an optional <code>uuid</code>.
*
- * @param nodeName the name of the child node.
- * @param uuid the UUID of the child node if it can be identified
- * with a UUID; otherwise <code>null</code>.
+ * @param nodeName The name of the child node.
+ * @param uuid The UUID of the child node if it can be identified with a UUID;
+ * otherwise <code>null</code>.
* @return the created ChildNodeEntry.
*/
private ChildNodeEntry add(QName nodeName, String uuid) {
@@ -455,8 +456,7 @@
* <code>beforeNode</code> does not have a <code>ChildNodeEntry</code>
* in this <code>ChildNodeEntries</code>.
*/
- void reorder(NodeState insertNode, NodeState beforeNode)
- throws NoSuchItemStateException {
+ void reorder(NodeState insertNode, NodeState beforeNode) throws NoSuchItemStateException {
Object insertObj = nameMap.get(insertNode.getQName());
// the link node to move
LinkedEntries.LinkNode insertLN = getLinkNode(insertNode);
@@ -510,19 +510,23 @@
ChildNodeEntry newCne = ChildNodeReference.create(childState, nodeState.isf, nodeState.idFactory);
entries.replaceNode(ln, newCne);
} catch (NoSuchItemStateException e) {
- log.error("Internal error.", e);
+ // should never occur.
+ log.error("Internal Error: ", e);
}
}
/**
* Returns the matching <code>LinkNode</code> from a list or a single
- * <code>LinkNode</code>.
+ * <code>LinkNode</code>. Note, that in contrast to {@link #getLinkNode(ChildNodeEntry)}
+ * this method will throw <code>NoSuchItemStateException</code> if none of the
+ * entries matches either due to missing entry for given state name or due
+ * to missing availability of the <code>ChildNodeEntry</code>.
*
- * @param nodeState the <code>NodeState</code> which is the value
- * of on of the <code>LinkNode</code>s.
+ * @param nodeState the <code>NodeState</code> that is compared to the
+ * resolution of any ChildNodeEntry that matches by name.
* @return the matching <code>LinkNode</code>.
* @throws NoSuchItemStateException if none of the <code>LinkNode</code>s
- * matches.
+ * matches.
*/
private LinkedEntries.LinkNode getLinkNode(NodeState nodeState)
throws NoSuchItemStateException {
@@ -531,7 +535,7 @@
// no matching child node entry
throw new NoSuchItemStateException(nodeState.getQName().toString());
}
-
+
if (listOrLinkNode instanceof List) {
// has same name sibling
for (Iterator it = ((List) listOrLinkNode).iterator(); it.hasNext();) {
@@ -560,8 +564,10 @@
throw new NoSuchItemStateException(nodeState.getQName().toString());
}
- //---------------------------------------< unmodifiable Collection view >---
-
+ //--------------------------------------------< unmodifiable Collection >---
+ /**
+ * @see Collection#contains(Object)
+ */
public boolean contains(Object o) {
if (o instanceof ChildNodeEntry) {
// narrow down to same name sibling nodes and check list
@@ -571,6 +577,9 @@
}
}
+ /**
+ * @see Collection#containsAll(Collection)
+ */
public boolean containsAll(Collection c) {
Iterator iter = c.iterator();
while (iter.hasNext()) {
@@ -581,23 +590,38 @@
return true;
}
+ /**
+ * @see Collection#isEmpty()
+ */
public boolean isEmpty() {
return entries.isEmpty();
}
+ /**
+ * @see Collection#iterator()
+ */
public Iterator iterator() {
return UnmodifiableIterator.decorate(entries.iterator());
}
+ /**
+ * @see Collection#size()
+ */
public int size() {
return entries.size();
}
+ /**
+ * @see Collection#toArray()
+ */
public Object[] toArray() {
ChildNodeEntry[] array = new ChildNodeEntry[size()];
return toArray(array);
}
+ /**
+ * @see Collection#toArray(Object[])
+ */
public Object[] toArray(Object[] a) {
if (!a.getClass().getComponentType().isAssignableFrom(ChildNodeEntry.class)) {
throw new ArrayStoreException();
@@ -616,31 +640,61 @@
return a;
}
+ /**
+ * Throws <code>UnsupportedOperationException</code>.
+ *
+ * @see Collection#add(Object)
+ */
public boolean add(Object o) {
throw new UnsupportedOperationException();
}
+ /**
+ * Throws <code>UnsupportedOperationException</code>.
+ *
+ * @see Collection#addAll(Collection)
+ */
public boolean addAll(Collection c) {
throw new UnsupportedOperationException();
}
+ /**
+ * Throws <code>UnsupportedOperationException</code>.
+ *
+ * @see Collection#clear()
+ */
public void clear() {
throw new UnsupportedOperationException();
}
+ /**
+ * Throws <code>UnsupportedOperationException</code>.
+ *
+ * @see Collection#remove(Object)
+ */
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
+ /**
+ * Throws <code>UnsupportedOperationException</code>.
+ *
+ * @see Collection#removeAll(Collection)
+ */
public boolean removeAll(Collection c) {
throw new UnsupportedOperationException();
}
+ /**
+ * Throws <code>UnsupportedOperationException</code>.
+ *
+ * @see Collection#retainAll(Collection)
+ */
public boolean retainAll(Collection c) {
throw new UnsupportedOperationException();
}
-
+ //-------------------------------------------------< AbstractLinkedList >---
/**
* An implementation of a linked list which provides access to the internal
* LinkNode which links the entries of the list.
@@ -698,6 +752,7 @@
*
* @param value a child node entry.
* @return a wrapping {@link LinkedEntries.LinkNode}.
+ * @see AbstractLinkedList#createNode(Object)
*/
protected Node createNode(Object value) {
return new LinkNode(value);
@@ -705,6 +760,7 @@
/**
* @return a new <code>LinkNode</code>.
+ * @see AbstractLinkedList#createHeaderNode()
*/
protected Node createHeaderNode() {
return new LinkNode();
@@ -746,7 +802,7 @@
};
}
- //-----------------------------------------------------------------------
+ //----------------------------------------------------------------------
/**
* Extends the <code>AbstractLinkedList.Node</code>.
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java Thu Nov 9 01:09:24 2006
@@ -341,6 +341,7 @@
synchronized (this) {
reset();
}
+ setStatus(Status.MODIFIED);
} else if (status == Status.EXISTING_MODIFIED) {
setStatus(Status.STALE_MODIFIED);
}
@@ -445,11 +446,12 @@
* Used on the target state of a save call AFTER the changelog has been
* successfully submitted to the SPI..
*
- * @param events
* @param changeLog
+ * @return a Set of <code>ItemId</code>s in order to allow the caller to
+ * remove those events that have already been processed.
* @throws IllegalStateException if this state is a 'session' state.
*/
- abstract void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException;
+ abstract Set refresh(ChangeLog changeLog) throws IllegalStateException;
/**
* Copy all state information from overlayed state to this state
@@ -527,21 +529,6 @@
default:
String msg = "Cannot mark item state with status " + status + " modified.";
throw new IllegalStateException(msg);
- }
- }
-
- //--------------------------------------------------------------------------
- /**
- *
- * @param events
- * @param processedState
- */
- static void removeEvent(Collection events, ItemState processedState) {
- for (Iterator it = events.iterator(); it.hasNext();) {
- if (((Event)it.next()).getItemId().equals(processedState.getId())) {
- it.remove();
- break;
- }
}
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateCache.java Thu Nov 9 01:09:24 2006
@@ -87,10 +87,12 @@
private void putToCache(ItemState state) {
if (state.isNode() && (state.getStatus() == Status.EXISTING || state.getStatus() == Status.MODIFIED)) {
NodeState nodeState = (NodeState) state;
+ // NOTE: uuid is retrieved from the state and not from the NodeId.
String uuid = nodeState.getUUID();
if (uuid != null) {
uuid2NodeState.put(uuid, nodeState);
}
}
+ // TODO: add caching for other items as well
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java Thu Nov 9 01:09:24 2006
@@ -123,7 +123,6 @@
this.uuid = uuid;
this.nodeTypeName = nodeTypeName;
this.definition = definition;
- assertAvailability();
}
/**
@@ -151,7 +150,6 @@
init(wspState.getMixinTypeNames(), wspState.getChildNodeEntries(), wspState.getPropertyNames(), wspState.getNodeReferences());
}
}
- assertAvailability();
}
/**
@@ -185,17 +183,6 @@
this.references = references;
}
- private void assertAvailability() {
- // TODO: TOBEFIXED. duality of creating states via ISM or via factory may result in a cached state, that is not connected to its cne.
- if (uuid != null && parent != null) {
- // make sure this state is connected to its childNode-entry
- ChildNodeEntry cne = parent.childNodeEntries.get(name, uuid);
- if (cne != null && !cne.isAvailable()) {
- parent.childNodeEntries.replaceEntry(this);
- }
- }
- }
-
//----------------------------------------------------------< ItemState >---
/**
* Determines if this item state represents a node.
@@ -360,17 +347,17 @@
}
/**
- * Determines if there are any child node entries.
+ * Determines if there are any valid child node entries.
*
* @return <code>true</code> if there are child node entries,
- * <code>false</code> otherwise.
+ * <code>false</code> otherwise.
*/
public boolean hasChildNodeEntries() {
return containsValidChildNodeEntry(childNodeEntries);
}
/**
- * Determines if there is a <code>ChildNodeEntry</code> with the
+ * Determines if there is a valid <code>ChildNodeEntry</code> with the
* specified <code>name</code>.
*
* @param name <code>QName</code> object specifying a node name
@@ -388,7 +375,7 @@
* @param name <code>QName</code> object specifying a node name
* @param index 1-based index if there are same-name child node entries
* @return <code>true</code> if there is a <code>ChildNodeEntry</code> with
- * the specified <code>name</code> and <code>index</code>.
+ * the specified <code>name</code> and <code>index</code>.
*/
public synchronized boolean hasChildNodeEntry(QName name, int index) {
return childNodeEntries.get(name, index) != null;
@@ -409,13 +396,34 @@
/**
* Returns the <code>ChildNodeEntry</code> with the specified
+ * <code>NodeId</code> or <code>null</code> if there's no matching
+ * entry.
+ *
+ * @param nodeId the id of the child node state.
+ * @return the <code>ChildNodeEntry</code> with the specified
+ * <code>NodeId</code> or <code>null</code> if there's no matching entry.
+ */
+ public synchronized ChildNodeEntry getChildNodeEntry(NodeId nodeId) {
+ String uuid = nodeId.getUUID();
+ Path path = nodeId.getPath();
+ if (uuid != null && path == null) {
+ // retrieve child-entry by uuid
+ return childNodeEntries.get(null, uuid);
+ } else {
+ // retrieve child-entry by name and index
+ Path.PathElement nameElement = path.getNameElement();
+ return childNodeEntries.get(nameElement.getName(), nameElement.getIndex());
+ }
+ }
+
+ /**
+ * Returns the <code>ChildNodeEntry</code> with the specified
* <code>NodeState</code> or <code>null</code> if there's no matching
* entry.
*
* @param nodeState the child node state.
* @return the <code>ChildNodeEntry</code> with the specified
- * <code>NodeState</code> or <code>null</code> if there's no
- * matching entry.
+ * <code>NodeState</code> or <code>null</code> if there's no matching entry.
*/
private synchronized ChildNodeEntry getChildNodeEntry(NodeState nodeState) {
return childNodeEntries.get(nodeState);
@@ -465,7 +473,7 @@
return false;
}
} else {
- // then it must be valid
+ // then it must be valid // TODO check if this assumption is correct.
return true;
}
}
@@ -525,39 +533,26 @@
/*
* Returns the property state with the given name.
*
- * @param propertyName the name of the property state to return.
- * @throws NoSuchItemStateException if there is no property state with the
- * given name.
- * @throws ItemStateException if an error occurs while retrieving the
- * property state.
+ * @param propertyName The name of the property state to return.
+ * @throws NoSuchItemStateException If there is no (valid) property state
+ * with the given name.
+ * @throws ItemStateException If an error occurs while retrieving the
+ * property state.
*/
public synchronized PropertyState getPropertyState(QName propertyName)
- throws NoSuchItemStateException, ItemStateException {
- PropertyState propState = getAnyPropertyState(propertyName);
- if (propState.isValid()) {
- return propState;
- } else {
- throw new NoSuchItemStateException(idFactory.createPropertyId(getNodeId(), propertyName).toString());
- }
- }
+ throws NoSuchItemStateException, ItemStateException {
- /**
- * Returns the property state with the given name and also takes removed
- * property states into account.
- *
- * @param propertyName the name of the property state to return.
- * @throws NoSuchItemStateException if there is no property state with the
- * given name.
- * @throws ItemStateException if an error occurs while retrieving the
- * property state.
- */
- public synchronized PropertyState getAnyPropertyState(QName propertyName)
- throws NoSuchItemStateException, ItemStateException {
ChildPropertyEntry propEntry = (ChildPropertyEntry) properties.get(propertyName);
if (propEntry == null) {
throw new NoSuchItemStateException(idFactory.createPropertyId(getNodeId(), propertyName).toString());
+ } else {
+ PropertyState propState = propEntry.getPropertyState();
+ if (propState.isValid()) {
+ return propState;
+ } else {
+ throw new NoSuchItemStateException(idFactory.createPropertyId(getNodeId(), propertyName).toString());
+ }
}
- return propEntry.getPropertyState();
}
/**
@@ -606,8 +601,8 @@
* <code>name</code>.
*
* @param cne the <code>ChildNodeEntry</code> instance.
- * @return the index of the child node entry or <code>0</code> if it is not
- * found in this <code>NodeState</code>.
+ * @return the index of the child node entry or <code>Path.INDEX_UNDEFINED</code>
+ * if it is not found in this <code>NodeState</code>.
*/
public int getChildNodeIndex(ChildNodeEntry cne) {
List sns = childNodeEntries.get(cne.getName());
@@ -630,6 +625,7 @@
}
} else {
// cne has not been resolved yet -> increase counter.
+ // TODO: check if assuption is correct
index++;
}
}
@@ -715,13 +711,14 @@
//----------------------------------------------------< Session - State >---
/**
* {@inheritDoc}
- * @see ItemState#refresh(Collection,ChangeLog)
+ * @see ItemState#refresh(ChangeLog)
*/
- void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException {
+ Set refresh(ChangeLog changeLog) throws IllegalStateException {
// remember parent states that have need to adjust their uuid/mixintypes
// or that got a new child entry added or existing entries removed.
- HashMap modParents = new HashMap();
+ Map modParents = new HashMap();
+ Set processedIds = new HashSet();
// process deleted states from the changelog
for (Iterator it = changeLog.deletedStates(); it.hasNext();) {
@@ -742,7 +739,7 @@
}
// don't remove processed state from changelog, but from event list
// state on changelog is used for check if parent is deleted as well.
- removeEvent(events, state);
+ processedIds.add(state.getId());
}
// process added states from the changelog. since the changlog maintains
@@ -790,7 +787,7 @@
}
it.remove();
- removeEvent(events, addedState);
+ processedIds.add(addedState.getId());
} catch (ItemStateException e) {
log.error("Internal error.", e);
}
@@ -799,27 +796,50 @@
for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
ItemState modState = (ItemState) it.next();
if (modState.isNode()) {
- continue;
+ NodeState modNodeState = (NodeState) modState;
+ // handle moved nodes
+ if (isMovedState(modNodeState)) {
+ // move overlayed state as well
+ NodeState newParent = (NodeState) modState.parent.overlayedState;
+ NodeState overlayed = (NodeState) modState.overlayedState;
+ ItemId removedId = overlayed.getId();
+ try {
+ overlayed.parent.moveEntry(newParent, overlayed, modNodeState.getQName(), modNodeState.getDefinition());
+ } catch (RepositoryException e) {
+ // should never occur
+ log.error("Internal error while moving childnode entries.", e);
+ }
+ // and mark the moved state existing
+ modNodeState.setStatus(Status.EXISTING);
+ it.remove();
+
+ processedIds.add(removedId);
+ processedIds.add(modNodeState.getId());
+ } else {
+ modifiedParent((NodeState)modState, null, modParents);
+ }
+ } else {
+ // push changes down to overlayed state
+ int type = ((PropertyState) modState).getType();
+ QValue[] values = ((PropertyState) modState).getValues();
+ ((PropertyState) modState.overlayedState).init(type, values);
+
+ 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 (isUuidOrMixin(modState.getQName())) {
+ modifiedParent(modState.getParent(), modState, modParents);
+ }
+ it.remove();
+ // remove the property-modification event from the set
+ processedIds.add(modState.getId());
}
- // push changes down to overlayed state
- int type = ((PropertyState) modState).getType();
- QValue[] values = ((PropertyState) modState).getValues();
- ((PropertyState) modState.overlayedState).init(type, values);
-
- 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 (isUuidOrMixin(modState.getQName())) {
- modifiedParent(this, modState, modParents);
- }
- // remove the processed event from the set
- it.remove();
- removeEvent(events, modState);
}
- /* process all parent states that need their uuid or mixin-types being
- adjusted because that property has been added or modified */
+ /* process all parent states that are marked modified and eventually
+ need their uuid or mixin-types being adjusted because that property
+ has been added, modified or removed */
for (Iterator it = modParents.keySet().iterator(); it.hasNext();) {
NodeState parent = (NodeState) it.next();
List l = (List) modParents.get(parent);
@@ -838,6 +858,8 @@
// TODO: discard state and force reload of all data
}
}
+
+ return processedIds;
}
/**
@@ -957,6 +979,7 @@
* @see ItemState#revert(Set)
*/
void revert(Set affectedItemStates) {
+ // TODO: TOBEFIXED. revert must include an update with the latest state present on the server
checkIsSessionState();
// copy to new list, when a property is reverted it may call this node
@@ -1215,9 +1238,17 @@
throws RepositoryException {
checkIsSessionState();
+ moveEntry(newParent, childState, newName, newDefinition);
+ // mark both this and newParent modified
+ markModified();
+ childState.markModified();
+ newParent.markModified();
+ }
+
+ private void moveEntry(NodeState newParent, NodeState childState, QName newName, QNodeDefinition newDefinition) throws RepositoryException {
ChildNodeEntry oldEntry = childNodeEntries.remove(childState);
if (oldEntry != null) {
- childState.rename(newName);
+ childState.name = newName;
// re-parent target node
childState.parent = newParent;
// set definition according to new definition required by the new parent
@@ -1225,26 +1256,8 @@
// add child node entry to new parent
newParent.childNodeEntries.add(childState);
} else {
- throw new RepositoryException("Unexpected error: Child state to be renamed does not exist.");
+ throw new RepositoryException("Unexpected error: Child state to be moved does not exist.");
}
- // mark both this and newParent modified
- markModified();
- childState.markModified();
- newParent.markModified();
- }
-
- /**
- * Renames this node to <code>newName</code>.
- *
- * @param newName the new name for this node state.
- * @throws IllegalStateException if this is the root node.
- */
- private synchronized void rename(QName newName) {
- checkIsSessionState();
- if (getParent() == null) {
- throw new IllegalStateException("root node cannot be renamed");
- }
- name = newName;
}
//---------------------------------------------------------< diff methods >
@@ -1369,6 +1382,7 @@
}
} else {
// then it has never been accessed and must exist
+ // TODO: check if this assumption is correct
return true;
}
}
@@ -1449,5 +1463,8 @@
log.warn("Error while adjusting nodestate: Overlayed state is missing.");
}
}
- //------------------------------------------------------< inner classes >---
+
+ private static boolean isMovedState(NodeState modState) {
+ return modState.overlayedState.parent != modState.parent.overlayedState;
+ }
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java Thu Nov 9 01:09:24 2006
@@ -28,7 +28,7 @@
/**
* The starting point to resolve the path.
*/
- private final ItemState start;
+ private final NodeState start;
/**
* The path to resolve.
@@ -43,7 +43,7 @@
* @throws IllegalArgumentException if not normalized or starts with a
* parent ('..') path element.
*/
- private PathResolver(ItemState start, Path relPath) {
+ private PathResolver(NodeState start, Path relPath) {
if (!relPath.isNormalized() || relPath.getElement(0).denotesParent()) {
throw new IllegalArgumentException("path must be relative and must " +
"not contain parent path elements");
@@ -66,7 +66,7 @@
* or starts with a parent ('..') path
* element.
*/
- public static ItemState resolve(ItemState start, Path path)
+ public static ItemState resolve(NodeState start, Path path)
throws NoSuchItemStateException, ItemStateException {
return new PathResolver(start, path).resolve();
}
@@ -87,7 +87,7 @@
* or starts with a parent ('..') path
* element.
*/
- public static ItemState lookup(ItemState start, Path path)
+ public static ItemState lookup(NodeState start, Path path)
throws NoSuchItemStateException, ItemStateException {
return new PathResolver(start, path).lookup();
}
@@ -97,15 +97,11 @@
*
* @return the resolved item state.
* @throws NoSuchItemStateException the the item state does not exist.
- * @throws ItemStateException if an error occurs while retrieving the
- * item state.
+ * @throws ItemStateException if an error occurs while retrieving the item state.
*/
private ItemState resolve()
throws NoSuchItemStateException, ItemStateException {
- if (!start.isNode()) {
- throw new NoSuchItemStateException(path.toString());
- }
- NodeState state = (NodeState) start;
+ NodeState state = start;
for (int i = 0; i < path.getLength(); i++) {
Path.PathElement elem = path.getElement(i);
// check for root element
@@ -119,8 +115,8 @@
// first try to resolve node
if (state.hasChildNodeEntry(elem.getName(), elem.getNormalizedIndex())) {
- state = state.getChildNodeEntry(elem.getName(),
- elem.getNormalizedIndex()).getNodeState();
+ ChildNodeEntry cne = state.getChildNodeEntry(elem.getName(), elem.getNormalizedIndex());
+ state = cne.getNodeState();
} else if (elem.getIndex() == 0 // property must not have index
&& state.hasPropertyName(elem.getName())
&& i == path.getLength() - 1) { // property must be final path element
@@ -133,21 +129,18 @@
}
/**
- * Resolves the path but does not the <code>ItemState</code> if it is not
- * yet loaded.
+ * Resolves the path but does not return the <code>ItemState</code> if it
+ * has not yet been loaded.
*
* @return the resolved item state or <code>null</code> if the item is not
- * available.
+ * available.
* @throws NoSuchItemStateException the the item state does not exist.
- * @throws ItemStateException if an error occurs while retrieving the
- * item state.
+ * @throws ItemStateException if an error occurs while retrieving the
+ * item state.
*/
private ItemState lookup()
throws NoSuchItemStateException, ItemStateException {
- if (!start.isNode()) {
- throw new NoSuchItemStateException(path.toString());
- }
- NodeState state = (NodeState) start;
+ NodeState state = start;
for (int i = 0; i < path.getLength(); i++) {
Path.PathElement elem = path.getElement(i);
// first try to resolve node
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java Thu Nov 9 01:09:24 2006
@@ -35,6 +35,7 @@
import java.util.Set;
import java.util.Collection;
import java.util.Iterator;
+import java.util.HashSet;
/**
* <code>PropertyState</code> represents the state of a <code>Property</code>.
@@ -259,9 +260,10 @@
//----------------------------------------------------< Session - State >---
/**
* {@inheritDoc}
- * @see ItemState#refresh(Collection,ChangeLog)
+ * @see ItemState#refresh(ChangeLog)
*/
- void refresh(Collection events, ChangeLog changeLog) throws IllegalStateException {
+ Set refresh(ChangeLog changeLog) throws IllegalStateException {
+ Set processedIds = new HashSet(1);
for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
ItemState modState = (ItemState) it.next();
if (modState == this) {
@@ -275,9 +277,10 @@
setStatus(Status.EXISTING);
// parent must not be informed, since all properties that
// affect the parent state (uuid, mixins) are protected.
- removeEvent(events, modState);
+ processedIds.add(modState.getId());
}
}
+ return processedIds;
}
/**
@@ -313,6 +316,7 @@
* @see ItemState#revert(Set)
*/
void revert(Set affectedItemStates) {
+ // TODO: TOBEFIXED. revert must include an update with the latest state present on the server
checkIsSessionState();
switch (getStatus()) {
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/Status.java Thu Nov 9 01:09:24 2006
@@ -124,6 +124,7 @@
case EXISTING_MODIFIED: /* save, revert */
case EXISTING_REMOVED: /* revert */
case STALE_MODIFIED: /* revert */
+ case MODIFIED:
isValid = true;
break;
/* REMOVED, STALE_DESTROYED -> false */
@@ -142,9 +143,11 @@
case REMOVED:
isValid = (oldStatus == NEW || oldStatus == EXISTING || oldStatus == EXISTING_REMOVED);
break;
- /* default:
- NEW cannot change state to NEW -> false
- MODIFIED never applicable to session state -> false */
+ case MODIFIED:
+ isValid = (oldStatus == EXISTING);
+ break;
+ /* default:
+ NEW cannot change state to NEW -> false */
}
}
return isValid;
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientISFactory.java Thu Nov 9 01:09:24 2006
@@ -24,6 +24,7 @@
import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.PropertyId;
import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.jcr2spi.state.entry.ChildNodeEntry;
/**
* <code>TransientISFactory</code>...
@@ -33,14 +34,14 @@
private static Logger log = LoggerFactory.getLogger(TransientISFactory.class);
private final IdFactory idFactory;
- private final ItemStateManager parent;
+ private final ItemStateManager workspaceItemStateMgr;
private ItemStateCache cache;
private ItemStateCreationListener listener;
- TransientISFactory(IdFactory idFactory, ItemStateManager parent) {
+ TransientISFactory(IdFactory idFactory, ItemStateManager workspaceItemStateMgr) {
this.idFactory = idFactory;
- this.parent = parent;
+ this.workspaceItemStateMgr = workspaceItemStateMgr;
}
//------------------------------------------< TransientItemStateFactory >---
@@ -99,7 +100,7 @@
*/
public NodeState createRootState(ItemStateManager ism) throws ItemStateException {
// retrieve state to overlay
- NodeState overlayedState = (NodeState) parent.getRootState();
+ NodeState overlayedState = (NodeState) workspaceItemStateMgr.getRootState();
NodeState nodeState = new NodeState(overlayedState, null, Status.EXISTING, this, idFactory);
nodeState.addListener(cache);
@@ -117,17 +118,27 @@
NodeState nodeState = cache.getNodeState(nodeId);
if (nodeState == null) {
// retrieve state to overlay
- NodeState overlayedState = (NodeState) parent.getItemState(nodeId);
+ NodeState overlayedState = (NodeState) workspaceItemStateMgr.getItemState(nodeId);
NodeState overlayedParent = overlayedState.getParent();
- NodeState parentState = null;
- if (overlayedParent != null) {
+ if (overlayedParent == null) {
+ // special case root state
+ return createRootState(ism);
+ }
+
+ NodeState parentState = (NodeState) overlayedParent.getSessionState();
+ if (parentState == null) {
parentState = (NodeState) ism.getItemState(overlayedParent.getId());
}
- nodeState = new NodeState(overlayedState, parentState, Status.EXISTING, this, idFactory);
- nodeState.addListener(cache);
- cache.created(nodeState);
+ ChildNodeEntry cne = parentState.getChildNodeEntry(nodeId);
+ if (cne != null) {
+ nodeState = cne.getNodeState();
+ nodeState.addListener(cache);
+ cache.created(nodeState);
+ } else {
+ throw new NoSuchItemStateException("No such item " + nodeId.toString());
+ }
}
return nodeState;
}
@@ -142,7 +153,7 @@
NodeState nodeState = cache.getNodeState(nodeId);
if (nodeState == null) {
// retrieve state to overlay
- NodeState overlayedState = (NodeState) parent.getItemState(nodeId);
+ NodeState overlayedState = (NodeState) workspaceItemStateMgr.getItemState(nodeId);
nodeState = new NodeState(overlayedState, parentState, Status.EXISTING, this, idFactory);
nodeState.addListener(cache);
@@ -162,7 +173,7 @@
PropertyState propState = cache.getPropertyState(propertyId);
if (propState == null) {
// retrieve state to overlay
- PropertyState overlayedState = (PropertyState) parent.getItemState(propertyId);
+ PropertyState overlayedState = (PropertyState) workspaceItemStateMgr.getItemState(propertyId);
propState = new PropertyState(overlayedState, parentState, Status.EXISTING, this, idFactory);
propState.addListener(cache);
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java Thu Nov 9 01:09:24 2006
@@ -309,6 +309,10 @@
break;
case Status.STALE_MODIFIED:
// state is now stale. keep in modified. wait until refreshed
+ case Status.MODIFIED:
+ // MODIFIED is only possible on EXISTING states -> thus, there
+ // must not be any transient modifications for that state.
+ // we ignore it.
break;
default:
log.error("ItemState has invalid status: " + state.getStatus());
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java Thu Nov 9 01:09:24 2006
@@ -73,7 +73,8 @@
*/
public NodeState createRootState(ItemStateManager ism) throws ItemStateException {
try {
- return createNodeState(service.getRootId(sessionInfo), ism);
+ NodeInfo info = service.getNodeInfo(sessionInfo, service.getRootId(sessionInfo));
+ return createNodeState(info, null);
} catch (RepositoryException e) {
throw new ItemStateException("Internal error while building root state.");
}
@@ -90,15 +91,13 @@
throws NoSuchItemStateException, ItemStateException {
try {
NodeInfo info = service.getNodeInfo(sessionInfo, nodeId);
-
- // get parent
- NodeId parentId = (info.getParentId() != null) ? info.getParentId() : null;
- NodeState parent = (parentId != null) ? (NodeState) ism.getItemState(parentId) : null;
-
- if (parent != null) {
- return parent.getChildNodeEntry(info.getQName(), info.getIndex()).getNodeState();
+ NodeId parentId = info.getParentId();
+ if (parentId != null) {
+ NodeState parent = (NodeState) ism.getItemState(parentId);
+ return parent.getChildNodeEntry(nodeId).getNodeState();
} else {
- return createNodeState(info, parent);
+ // special case for root state
+ return createNodeState(info, null);
}
} catch (ItemNotFoundException e) {
throw new NoSuchItemStateException(e.getMessage(), e);
@@ -129,8 +128,8 @@
/**
* Creates the node with information retrieved from <code>info</code>.
*
- * @param info the <code>NodeInfo</code> to use to create the
- * <code>NodeState</code>.
+ * @param info the <code>NodeInfo</code> to use to create the
+ * <code>NodeState</code>.
* @param parent the parent <code>NodeState</code>.
* @return the new <code>NodeState</code>.
*/
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java?view=diff&rev=472818&r1=472817&r2=472818
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java Thu Nov 9 01:09:24 2006
@@ -21,6 +21,7 @@
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.spi.EventIterator;
+import org.apache.jackrabbit.spi.ItemId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -73,7 +74,14 @@
// that have been persisted now: NEW-states will be connected to their
// overlayed state, EXISTING_REMOVED states will be definitely removed,
// EXISTING_MODIFIED states are merged with their workspace-state.
- changeLog.getTarget().refresh(evs, changeLog);
+ Set processedIds = changeLog.getTarget().refresh(changeLog);
+ for (Iterator it = evs.iterator(); it.hasNext();) {
+ ItemId evId = ((Event)it.next()).getItemId();
+ if (processedIds.contains(evId)) {
+ it.remove();
+ }
+ }
+
// all events not covered by the changelog must not be handled on the
// session-states -> treat the same way as events returned by
// workspace operations.