You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2011/12/13 20:13:38 UTC
svn commit: r1213877 - in /jackrabbit/sandbox/jackrabbit-mk:
jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/
jackrabbit-spi2microkernel/
Author: mduerig
Date: Tue Dec 13 19:13:38 2011
New Revision: 1213877
URL: http://svn.apache.org/viewvc?rev=1213877&view=rev
Log:
Microkernel based Jackrabbit prototype (WIP)
- remove support for orderable child nodes
- remove support for same name siblings
Modified:
jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntries.java
jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntry.java
jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/pom.xml
Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntries.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntries.java?rev=1213877&r1=1213876&r2=1213877&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntries.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntries.java Tue Dec 13 19:13:38 2011
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.jcr2spi.hierarchy;
-import org.apache.commons.collections.list.AbstractLinkedList;
import org.apache.jackrabbit.jcr2spi.state.Status;
import org.apache.jackrabbit.spi.ChildInfo;
import org.apache.jackrabbit.spi.Name;
@@ -26,16 +25,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.RepositoryException;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
-import java.util.NoSuchElementException;
/**
* {@code ChildNodeEntries} represents a collection of {@code NodeEntry}s that
@@ -47,14 +40,9 @@ final class ChildNodeEntries {
private boolean complete;
/**
- * Linked list of {@link NodeEntry} instances.
- */
- private final LinkedEntries entries = new LinkedEntries();
-
- /**
* Map used for lookup by name.
*/
- private final NameMap entriesByName = new NameMap();
+ private final Map<Name, NodeEntry> entries = new HashMap<Name, NodeEntry>();
private final NodeEntry parent;
private final EntryFactory factory;
@@ -79,40 +67,22 @@ final class ChildNodeEntries {
if (childNodeInfos != null) {
while (childNodeInfos.hasNext()) {
ChildInfo ci = childNodeInfos.next();
+ if (ci.getIndex() > Path.INDEX_DEFAULT) {
+ IllegalArgumentException e = new IllegalArgumentException("Invalid index: " + ci.getIndex());
+ log.error(e.getMessage(), e);
+ throw e;
+ }
NodeEntry entry = factory.createNodeEntry(parent, ci.getName(), ci.getUniqueID());
- add(entry, ci.getIndex());
+ add(entry);
}
complete = true;
- } else {
+ }
+ else {
complete = false;
}
}
/**
- * @param childEntry
- * @return The node entry that directly follows the given {@code childEntry}
- * or {@code null} if the given {@code childEntry} has no successor
- * or was not found in this {@code ChildNodeEntries}.
- */
- NodeEntry getNext(NodeEntry childEntry) {
- LinkedEntries.LinkNode ln = entries.getLinkNode(childEntry);
- LinkedEntries.LinkNode nextLn = ln == null ? null : ln.getNextLinkNode();
- return nextLn == null ? null : nextLn.getNodeEntry();
- }
-
- /**
- * @param childEntry
- * @return The node entry that directly precedes the given {@code childEntry}
- * or {@code null} if the given {@code childEntry} is the first
- * or was not found in this {@code ChildNodeEntries}.
- */
- NodeEntry getPrevious(NodeEntry childEntry) {
- LinkedEntries.LinkNode ln = entries.getLinkNode(childEntry);
- LinkedEntries.LinkNode prevLn = ln == null ? null : ln.getPreviousLinkNode();
- return prevLn == null ? null : prevLn.getNodeEntry();
- }
-
- /**
* @return {@code true} if this {@code ChildNodeEntries} have
* been updated or completely loaded without being invalidated in the
* mean time.
@@ -134,8 +104,8 @@ final class ChildNodeEntries {
return;
}
- NodeId id = parent.getWorkspaceId();
- Iterator<ChildInfo> childNodeInfos = factory.getItemStateFactory().getChildNodeInfos(id);
+ NodeId nodeId = parent.getWorkspaceId();
+ Iterator<ChildInfo> childNodeInfos = factory.getItemStateFactory().getChildNodeInfos(nodeId);
update(childNodeInfos);
}
@@ -158,26 +128,13 @@ final class ChildNodeEntries {
*/
synchronized void update(Iterator<ChildInfo> childNodeInfos) {
// insert missing entries and reorder all if necessary.
- LinkedEntries.LinkNode prevLN = null;
while (childNodeInfos.hasNext()) {
- ChildInfo ci = childNodeInfos.next();
- LinkedEntries.LinkNode ln = entriesByName.getLinkNode(ci.getName(), ci.getIndex(), ci.getUniqueID());
- if (ln == null) {
+ ChildInfo info = childNodeInfos.next();
+ if (entries.get(info.getName()) == null) {
// add missing at the correct position.
- NodeEntry entry = factory.createNodeEntry(parent, ci.getName(), ci.getUniqueID());
- ln = internalAddAfter(entry, ci.getIndex(), prevLN);
- } else if (prevLN != null) {
- // assert correct order of existing
- if (prevLN == ln) {
- // there was an existing entry but it's the same as the one
- // created/retrieved before. getting here indicates that
- // the SPI implementation provided invalid childNodeInfos.
- log.error("ChildInfo iterator contains multiple entries with the same name|index or uniqueID -> ignore ChildNodeInfo.");
- } else {
- reorderAfter(ln, prevLN);
- }
+ NodeEntry entry = factory.createNodeEntry(parent, info.getName(), info.getUniqueID());
+ add(entry);
}
- prevLN = ln;
}
// finally reset the status
complete = true;
@@ -190,42 +147,12 @@ final class ChildNodeEntries {
* @return Iterator over all NodeEntry object
*/
public Iterator<NodeEntry> iterator() {
- List<NodeEntry> l = new ArrayList<NodeEntry>(entries.size());
- for (Iterator<LinkedEntries.LinkNode> it = entries.linkNodeIterator(); it.hasNext();) {
- l.add(it.next().getNodeEntry());
- }
- return Collections.unmodifiableList(l).iterator();
- }
-
- /**
- * Returns a {@code List} of {@code NodeEntry}s for the
- * given {@code nodeName}. This method does <b>not</b> filter out
- * removed {@code NodeEntry}s.
- *
- * @param nodeName the child node name.
- * @return same name sibling nodes with the given {@code nodeName}.
- */
- public List<NodeEntry> get(Name nodeName) {
- return entriesByName.getList(nodeName);
+ // avoid concurrent modification exception
+ return new ArrayList<NodeEntry>(entries.values()).iterator();
}
- /**
- * Returns the {@code NodeEntry} with the given
- * {@code nodeName} and {@code index}. Note, that this method
- * does <b>not</b> filter out removed {@code NodeEntry}s.
- *
- * @param nodeName name of the child node entry.
- * @param index the index of the child node entry.
- * @return the {@code NodeEntry} or {@code null} if there
- * is no such {@code NodeEntry}.
- */
- public NodeEntry get(Name nodeName, int index) {
- if (index < Path.INDEX_DEFAULT) {
- IllegalArgumentException e = new IllegalArgumentException("index is 1-based");
- log.error(e.getMessage(), e);
- throw e;
- }
- return entriesByName.getNodeEntry(nodeName, index);
+ public NodeEntry get(Name nodeName) {
+ return entries.get(nodeName);
}
/**
@@ -243,709 +170,30 @@ final class ChildNodeEntries {
log.error(e.getMessage(), e);
throw e;
}
- for (NodeEntry cne : get(nodeName)) {
- if (uniqueID.equals(cne.getUniqueID())) {
- return cne;
- }
- }
- return null;
- }
-
- /**
- * Adds a {@code NodeEntry} to the end of the list. Same as
- * {@link #add(NodeEntry, int)}, where the index is {@link Path#INDEX_UNDEFINED}.
- *
- * @param cne the {@code NodeEntry} to add.
- */
- public synchronized void add(NodeEntry cne) {
- internalAdd(cne, Path.INDEX_UNDEFINED);
- }
-
- /**
- * Adds a {@code NodeEntry}.<br>
- * Note the following special cases:
- * <ol>
- * <li>If an entry with the given index already exists, the the new sibling
- * is inserted before.</li>
- * <li>If the given index is bigger that the last entry in the siblings list,
- * intermediate entries will be created.</li>
- * </ol>
- *
- * @param cne the {@code NodeEntry} to add.
- */
- public synchronized void add(NodeEntry cne, int index) {
- if (index < Path.INDEX_UNDEFINED) {
- IllegalArgumentException e = new IllegalArgumentException("Invalid index" + index);
- log.error(e.getMessage(), e);
- throw e;
- }
- internalAdd(cne, index);
- }
-
- /**
- * Adds a the new {@code NodeEntry} before {@code beforeEntry}.
- *
- * @param entry
- * @param index
- * @param beforeEntry
- */
- public synchronized void add(NodeEntry entry, int index, NodeEntry beforeEntry) {
- if (beforeEntry != null) {
- // the link node where the new entry is ordered before
- LinkedEntries.LinkNode beforeLN = entries.getLinkNode(beforeEntry);
- if (beforeLN == null) {
- throw new NoSuchElementException();
- }
- LinkedEntries.LinkNode insertLN = internalAdd(entry, index);
- reorder(entry.getName(), insertLN, beforeLN);
- } else {
- // 'before' is null -> simply append new entry at the end
- add(entry);
- }
- }
-
- /**
- *
- * @param entry
- * @param index
- * @return the {@code LinkNode} belonging to the added entry.
- */
- private LinkedEntries.LinkNode internalAdd(NodeEntry entry, int index) {
- Name nodeName = entry.getName();
-
- // retrieve ev. sibling node with same index. if index is 'undefined'
- // the existing entry is always null and no reordering occurs.
- LinkedEntries.LinkNode existing = null;
- if (index >= Path.INDEX_DEFAULT) {
- existing = entriesByName.getLinkNode(nodeName, index);
- }
- // in case index greater than default -> create intermediate entries.
- // TODO: in case of orderable node the order in the 'linked-entries' must be respected.
- for (int i = Path.INDEX_DEFAULT; i < index; i++) {
- LinkedEntries.LinkNode previous = entriesByName.getLinkNode(nodeName, i);
- if (previous == null) {
- NodeEntry sibling = factory.createNodeEntry(parent, nodeName, null);
- internalAdd(sibling, i);
- }
- }
-
- // add new entry
- LinkedEntries.LinkNode ln = entries.add(entry, index);
- entriesByName.put(nodeName, index, ln);
-
- // reorder the child entries if, the new entry must be inserted rather
- // than appended at the end of the list.
- if (existing != null) {
- reorder(nodeName, ln, existing);
- }
- return ln;
+ NodeEntry nodeEntry = entries.get(nodeName);
+ return nodeEntry != null && uniqueID.equals(nodeEntry.getUniqueID())
+ ? nodeEntry
+ : null;
}
/**
- * Add the specified new entry after the specified {@code insertAfter}.
+ * Adds a {@code NodeEntry} to the end of the list. Same as
*
- * @param newEntry
- * @param index
- * @param insertAfter
- * @return the {@code LinkNode} associated with the {@code newEntry}.
+ * @param nodeEntry the {@code NodeEntry} to add.
*/
- private LinkedEntries.LinkNode internalAddAfter(NodeEntry newEntry, int index, LinkedEntries.LinkNode insertAfter) {
- LinkedEntries.LinkNode ln = entries.addAfter(newEntry, index, insertAfter);
- entriesByName.put(newEntry.getName(), index, ln);
- return ln;
+ public synchronized void add(NodeEntry nodeEntry) {
+ entries.put(nodeEntry.getName(), nodeEntry);
}
/**
* Removes the child node entry referring to the node state.
*
- * @param childEntry the entry to be removed.
+ * @param nodeEntry the entry to be removed.
* @return the removed entry or {@code null} if there is no such entry.
*/
- public synchronized NodeEntry remove(NodeEntry childEntry) {
- LinkedEntries.LinkNode ln = entries.removeNodeEntry(childEntry);
- if (ln != null) {
- entriesByName.remove(childEntry.getName(), ln);
- return childEntry;
- } else {
- return null;
- }
- }
-
- /**
- * Reorders an existing {@code NodeEntry} before another
- * {@code NodeEntry}. If {@code beforeEntry} is
- * {@code null} {@code insertEntry} is moved to the end of the
- * child node entries.
- *
- * @param insertEntry the NodeEntry to move.
- * @param beforeEntry the NodeEntry where {@code insertEntry} is
- * reordered to.
- * @return the NodeEntry that followed the 'insertEntry' before the reordering.
- * @throws NoSuchElementException if {@code insertEntry} or
- * {@code beforeEntry} does not have a {@code NodeEntry}
- * in this {@code ChildNodeEntries}.
- */
- public synchronized NodeEntry reorder(NodeEntry insertEntry, NodeEntry beforeEntry) {
- // the link node to move
- LinkedEntries.LinkNode insertLN = entries.getLinkNode(insertEntry);
- if (insertLN == null) {
- throw new NoSuchElementException();
- }
- // the link node where insertLN is ordered before
- LinkedEntries.LinkNode beforeLN = beforeEntry != null ? entries.getLinkNode(beforeEntry) : null;
- if (beforeEntry != null && beforeLN == null) {
- throw new NoSuchElementException();
- }
-
- NodeEntry previousBefore = insertLN.getNextLinkNode().getNodeEntry();
- if (previousBefore != beforeEntry) {
- reorder(insertEntry.getName(), insertLN, beforeLN);
- }
- return previousBefore;
- }
-
- /**
- * Reorders an existing {@code NodeEntry} after another
- * {@code NodeEntry}. If {@code afterEntry} is
- * {@code null} {@code insertEntry} is moved to the beginning of
- * the child node entries.
- *
- * @param insertEntry the NodeEntry to move.
- * @param afterEntry the NodeEntry where {@code insertEntry} is
- * reordered behind.
- * @throws NoSuchElementException if {@code insertEntry} or
- * {@code afterEntry} does not have a {@code NodeEntry}
- * in this {@code ChildNodeEntries}.
- */
- public void reorderAfter(NodeEntry insertEntry, NodeEntry afterEntry) {
- // the link node to move
- LinkedEntries.LinkNode insertLN = entries.getLinkNode(insertEntry);
- if (insertLN == null) {
- throw new NoSuchElementException();
- }
- // the link node where insertLN is ordered before
- LinkedEntries.LinkNode afterLN = afterEntry != null ? entries.getLinkNode(afterEntry) : null;
- if (afterEntry != null && afterLN == null) {
- throw new NoSuchElementException();
- }
-
- LinkedEntries.LinkNode previousLN = insertLN.getPreviousLinkNode();
- if (previousLN != afterLN) {
- reorderAfter(insertLN, afterLN);
- } // else: already in correct position. nothing to do
- }
-
- /**
- *
- * @param insertName
- * @param insert
- * @param beforeLN
- */
- private void reorder(Name insertName, LinkedEntries.LinkNode insert, LinkedEntries.LinkNode beforeLN) {
- // reorder named map
- if (entriesByName.containsSiblings(insertName)) {
- int position;
- if (beforeLN == null) {
- // reorder to the end -> use illegal position as marker
- position = - 1;
- } else {
- // count all SNS-entries that are before 'beforeLN' in order to
- // determine the new position of the reordered node regarding
- // his siblings.
- position = 0;
- for (Iterator<LinkedEntries.LinkNode> it = entries.linkNodeIterator(); it.hasNext(); ) {
- LinkedEntries.LinkNode ln = it.next();
- if (ln == beforeLN) {
- break;
- } else if (ln != insert && insertName.equals(ln.name)) {
- position++;
- } // else: ln == insertLN OR no SNS -> not relevant for position count
- }
- }
- entriesByName.reorder(insertName, insert, position);
- }
- // reorder in linked list
- entries.reorderNode(insert, beforeLN);
- }
-
- /**
- *
- * @param insertLN
- * @param afterLN
- */
- private void reorderAfter(LinkedEntries.LinkNode insertLN, LinkedEntries.LinkNode afterLN) {
- // the link node to move
- if (insertLN == null) {
- throw new NoSuchElementException();
- }
- // the link node where insertLN is ordered after
- if (afterLN == null) {
- // move to first position
- afterLN = entries.getHeader();
- }
-
- LinkedEntries.LinkNode currentAfter = afterLN.getNextLinkNode();
- if (currentAfter == insertLN) {
- log.debug("Already ordered behind 'afterEntry'.");
- // nothing to do
- } else {
- // reorder named map
- Name insertName = insertLN.name;
- if (entriesByName.containsSiblings(insertName)) {
- int position;
- if (afterLN == entries.getHeader()) {
- // move to the beginning
- position = 0;
- } else {
- // count all SNS-entries that are before 'afterLN' in order to
- // determine the new position of the reordered node regarding
- // his siblings.
- position = 0;
- for (Iterator<LinkedEntries.LinkNode> it = entries.linkNodeIterator(); it.hasNext(); ) {
- LinkedEntries.LinkNode ln = it.next();
- if (insertName.equals(ln.name) && ln != insertLN) {
- position++;
- }
- if (ln == afterLN) {
- break;
- }
- }
- }
- entriesByName.reorder(insertName, insertLN, position);
- }
- // reorder in linked list
- entries.reorderNode(insertLN, currentAfter);
- }
- }
-
- //-------------------------------------------------< AbstractLinkedList >---
-
- /**
- * An implementation of a linked list which provides access to the internal
- * LinkNode which links the entries of the list.
- */
- private final class LinkedEntries extends AbstractLinkedList {
-
- LinkedEntries() {
- init();
- }
-
- /**
- * Returns the matching {@code LinkNode} from a list or a single
- * {@code LinkNode}. This method will return {@code null}
- * if none of the entries matches either due to missing entry for given
- * state name or due to missing availability of the {@code NodeEntry}.
- *
- * @param nodeEntry the {@code NodeEntry} that is compared to the
- * resolution of any {@code NodeEntry} that matches by name.
- * @return the matching {@code LinkNode} or {@code null}
- */
- private LinkedEntries.LinkNode getLinkNode(NodeEntry nodeEntry) {
- for (Iterator<LinkedEntries.LinkNode> it = linkNodeIterator(); it.hasNext();) {
- LinkedEntries.LinkNode ln = it.next();
- if (ln.getNodeEntry() == nodeEntry) {
- return ln;
- }
- }
- // not found
- return null;
- }
-
- private LinkedEntries.LinkNode getHeader() {
- return (LinkedEntries.LinkNode) header;
- }
-
- /**
- * Adds a child node entry at the end of this list.
- *
- * @param cne the child node entry to add.
- * @param index
- * @return the LinkNode which refers to the added {@code NodeEntry}.
- */
- LinkedEntries.LinkNode add(NodeEntry cne, int index) {
- LinkedEntries.LinkNode ln = new LinkedEntries.LinkNode(cne, index);
- addNode(ln, header);
- return ln;
- }
-
- /**
- * Adds the given child node entry to this list after the specified
- * {@code entry} or at the beginning if {@code entry} is
- * {@code null}.
- *
- * @param cne the child node entry to add.
- * @param index
- * @param insertAfter after which to insert the new entry
- * @return the LinkNode which refers to the added {@code NodeEntry}.
- */
- LinkedEntries.LinkNode addAfter(NodeEntry cne, int index, LinkedEntries.LinkNode insertAfter) {
- LinkedEntries.LinkNode newNode;
- if (insertAfter == null) {
- // insert at the beginning
- newNode = new LinkedEntries.LinkNode(cne, index);
- addNode(newNode, header);
- } else if (insertAfter.getNextLinkNode() == null) {
- newNode = add(cne, index);
- } else {
- newNode = new LinkedEntries.LinkNode(cne, index);
- addNode(newNode, insertAfter.getNextLinkNode());
- }
- return newNode;
- }
-
- /**
- * Remove the LinkEntry the contains the given NodeEntry as value.
- *
- * @param cne NodeEntry to be removed.
- * @return LinkedEntries.LinkNode that has been removed.
- */
- LinkedEntries.LinkNode removeNodeEntry(NodeEntry cne) {
- LinkedEntries.LinkNode ln = getLinkNode(cne);
- if (ln != null) {
- ln.remove();
- }
- return ln;
- }
-
- /**
- * Reorders an existing {@code LinkNode} before another existing
- * {@code LinkNode}. If {@code before} is {@code null}
- * the {@code insert} node is moved to the end of the list.
- *
- * @param insert the node to reorder.
- * @param before the node where to reorder node {@code insert}.
- */
- void reorderNode(LinkedEntries.LinkNode insert, LinkedEntries.LinkNode before) {
- removeNode(insert);
- if (before == null) {
- addNode(insert, header);
- } else {
- addNode(insert, before);
- }
- }
-
- /**
- * Create a new {@code LinkNode} for a given {@link NodeEntry}
- * {@code value}.
- *
- * @param value a child node entry.
- * @return a wrapping {@link LinkedEntries.LinkNode}.
- */
- @Override
- protected Node createNode(Object value) {
- return new LinkedEntries.LinkNode(value, Path.INDEX_DEFAULT);
- }
-
- @Override
- protected Node createHeaderNode() {
- return new LinkedEntries.LinkNode();
- }
-
- /**
- * @return iterator over all LinkNode entries in this list.
- */
- private Iterator<LinkedEntries.LinkNode> linkNodeIterator() {
- return new LinkNodeIterator();
- }
-
- //----------------------------------------------------------------------
- /**
- * Extends the {@code AbstractLinkedList.Node}.
- */
- private final class LinkNode extends Node {
-
- private final Name name;
-
- protected LinkNode() {
- name = null;
- }
-
- protected LinkNode(Object value, int index) {
- // add soft reference from linkNode to the NodeEntry (value)
- // unless the entry is a SNSibling. TODO: review again.
- super(index > Path.INDEX_DEFAULT ? value : new SoftReference<Object>(value));
- name = ((NodeEntry) value).getName();
- }
-
- @Override
- protected void setValue(Object value) {
- UnsupportedOperationException e = new UnsupportedOperationException("remove");
- log.error(e.getMessage(), e);
- throw e;
- }
-
- @Override
- protected Object getValue() {
- Object val = super.getValue();
- NodeEntry ne;
- if (val == null) {
- ne = null;
- } else if (val instanceof Reference<?>) {
- ne = (NodeEntry) ((Reference<?>) val).get();
- } else {
- ne = (NodeEntry) val;
- }
- // if the nodeEntry has been g-collected in the mean time
- // create a new NodeEntry in order to avoid returning null.
- if (ne == null && this != header) {
- ne = factory.createNodeEntry(parent, name, null);
- super.setValue(new SoftReference<NodeEntry>(ne));
- }
- return ne;
- }
-
- /**
- * @return the wrapped {@code NodeEntry}.
- */
- public NodeEntry getNodeEntry() {
- return (NodeEntry) getValue();
- }
-
- /**
- * Removes this {@code LinkNode} from the linked list.
- */
- public void remove() {
- removeNode(this);
- }
-
- /**
- * @return the next LinkNode.
- */
- public LinkedEntries.LinkNode getNextLinkNode() {
- return (LinkedEntries.LinkNode) getNextNode();
- }
-
- /**
- * @return the next LinkNode.
- */
- public LinkedEntries.LinkNode getPreviousLinkNode() {
- return (LinkedEntries.LinkNode) getPreviousNode();
- }
- }
-
- //----------------------------------------------------------------------
- private class LinkNodeIterator implements Iterator<LinkedEntries.LinkNode> {
-
- private LinkedEntries.LinkNode next = ((LinkedEntries.LinkNode) header).getNextLinkNode();
- private final int expectedModCount = modCount;
-
- @Override
- public boolean hasNext() {
- checkModCount();
- return next != header;
- }
-
- @Override
- public LinkedEntries.LinkNode next() {
- checkModCount();
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- LinkedEntries.LinkNode n = next;
- next = next.getNextLinkNode();
- return n;
- }
-
- @Override
- public void remove() {
- UnsupportedOperationException e = new UnsupportedOperationException("remove");
- log.error(e.getMessage(), e);
- throw e;
- }
-
- private void checkModCount() {
- if (expectedModCount != modCount) {
- throw new ConcurrentModificationException();
- }
- }
- }
+ public synchronized NodeEntry remove(NodeEntry nodeEntry) {
+ return entries.remove(nodeEntry.getName());
}
-
-
- //--------------------------------------------------------------------------
-
- /**
- * Mapping of Name to LinkNode OR List of LinkNode(s) in case of SNSiblings.
- */
- private static class NameMap {
-
- private final Map<Name, List<LinkedEntries.LinkNode>> snsMap = new HashMap<Name, List<LinkedEntries.LinkNode>>();
- private final Map<Name, LinkedEntries.LinkNode> nameMap = new HashMap<Name, LinkedEntries.LinkNode>();
-
- /**
- * Return true if more than one NodeEntry with the given name exists.
- *
- * @param name
- * @return true if more than one NodeEntry with the given name exists.
- */
- public boolean containsSiblings(Name name) {
- return snsMap.containsKey(name);
- }
-
- /**
- * Returns a single {@code NodeEntry} or an unmodifiable
- * {@code List} of NodeEntry objects.
- *
- *
- * @param name
- * @return a single {@code NodeEntry} or a {@code List} of
- * NodeEntry objects.
- */
- private List<NodeEntry> get(Name name) {
- LinkedEntries.LinkNode val = nameMap.get(name);
- if (val != null) {
- return Collections.singletonList(val.getNodeEntry());
- } else {
- List<LinkedEntries.LinkNode> l = snsMap.get(name);
- if (l != null) {
- List<NodeEntry> nodeEntries = new ArrayList<NodeEntry>(l.size());
- for (LinkedEntries.LinkNode ln : l) {
- nodeEntries.add(ln.getNodeEntry());
- }
- return nodeEntries;
- }
- }
- return null;
- }
-
- /**
- * Returns a unmodifiable List of NodeEntry objects even if the name map
- * only contains a single entry for the given name. If no matching entry
- * exists for the given {@code Name} an empty list is returned.
- *
- * @param name
- * @return list of entries or an empty list.
- */
- public List<NodeEntry> getList(Name name) {
- List<NodeEntry> nodeEntries = get(name);
- if (nodeEntries == null) {
- return Collections.emptyList();
- } else {
- return Collections.unmodifiableList(new ArrayList<NodeEntry>(nodeEntries));
- }
- }
-
- public NodeEntry getNodeEntry(Name name, int index) {
- List<NodeEntry> obj = get(name);
- return obj == null
- ? null
- : findMatchingEntry(obj, index);
- }
-
- public LinkedEntries.LinkNode getLinkNode(Name name, int index) {
- if (index < Path.INDEX_DEFAULT) {
- IllegalArgumentException e = new IllegalArgumentException("Illegal index " + index);
- log.error(e.getMessage(), e);
- throw e;
- }
-
- LinkedEntries.LinkNode val = nameMap.get(name);
- if (val != null) {
- return index == Path.INDEX_DEFAULT ? val : null;
- } else {
- // look in snsMap
- List<LinkedEntries.LinkNode> l = snsMap.get(name);
- int pos = index - 1; // Index of NodeEntry is 1-based
- return l != null && pos < l.size() ? l.get(pos) : null;
- }
- }
-
- public LinkedEntries.LinkNode getLinkNode(Name name, int index, String uniqueID) {
- if (uniqueID != null) {
- // -> try if any entry matches.
- // if none matches it be might that entry doesn't have uniqueID
- // set yet -> search without uniqueID
- LinkedEntries.LinkNode val = nameMap.get(name);
- if (val != null) {
- if (uniqueID.equals(val.getNodeEntry().getUniqueID())) {
- return val;
- }
- } else {
- // look in snsMap
- List<LinkedEntries.LinkNode> l = snsMap.get(name);
- if (l != null) {
- for (LinkedEntries.LinkNode ln : l) {
- if (uniqueID.equals(ln.getNodeEntry().getUniqueID())) {
- return ln;
- }
- }
- }
- }
- }
- // no uniqueID passed or not match.
- // try to load the child entry by name and index.
- return getLinkNode(name, index);
- }
-
- public void put(Name name, int index, LinkedEntries.LinkNode value) {
- // if 'nameMap' already contains a single entry -> move it to snsMap
- LinkedEntries.LinkNode single = nameMap.remove(name);
- List<LinkedEntries.LinkNode> l;
- if (single != null) {
- l = new ArrayList<LinkedEntries.LinkNode>();
- l.add(single);
- snsMap.put(name, l);
- } else {
- // if 'snsMap' already contains list
- l = snsMap.get(name);
- }
-
- if (l == null) {
- // no same name siblings -> simply put to the name map.
- nameMap.put(name, value);
- } else {
- // sibling(s) already present -> insert into the list
- int position = index - 1;
- if (position < 0 || position > l.size()) {
- l.add(value); // invalid position -> append at the end.
- } else {
- l.add(position, value); // insert with the correct index.
- }
- }
- }
-
- public LinkedEntries.LinkNode remove(Name name, LinkedEntries.LinkNode value) {
- LinkedEntries.LinkNode rm = nameMap.remove(name);
- if (rm == null) {
- List<LinkedEntries.LinkNode> l = snsMap.get(name);
- if (l != null && l.remove(value)) {
- rm = value;
- }
- }
- return rm;
- }
-
- public void reorder(Name name, LinkedEntries.LinkNode insertValue, int position) {
- List<LinkedEntries.LinkNode> sns = snsMap.get(name);
- if (sns == null) {
- // no same name siblings -> no special handling required
- return;
- }
- // reorder sns in the name-list
- sns.remove(insertValue);
- if (position < 0 || position > sns.size()) {
- // simply move to end of list
- sns.add(insertValue);
- } else {
- sns.add(position, insertValue);
- }
- }
-
- /**
- *
- * @param siblings
- * @param index
- * @return matching entry or {@code null}.
- */
- private static NodeEntry findMatchingEntry(List<NodeEntry> siblings, int index) {
- // shortcut if index can never match
- if (index > siblings.size()) {
- return null;
- } else {
- return siblings.get(index - 1);
- }
- }
- }
}
Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntry.java?rev=1213877&r1=1213876&r2=1213877&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntry.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntry.java Tue Dec 13 19:13:38 2011
@@ -55,6 +55,7 @@ import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -358,7 +359,7 @@ public class NodeEntry extends Hierarchy
* @return the index of this child node entry to support same-name siblings.
* If the index of this entry cannot be determined
* {@link org.apache.jackrabbit.spi.Path#INDEX_UNDEFINED} is returned.
- * @throws InvalidItemStateException
+ * @throws javax.jcr.InvalidItemStateException
* @throws RepositoryException
*/
public int getIndex() throws RepositoryException {
@@ -384,7 +385,7 @@ public class NodeEntry extends Hierarchy
*
* @param path
* @return the entry at the given path.
- * @throws PathNotFoundException
+ * @throws javax.jcr.PathNotFoundException
* @throws RepositoryException
*/
public NodeEntry getDeepNodeEntry(Path path) throws RepositoryException {
@@ -418,7 +419,7 @@ public class NodeEntry extends Hierarchy
// -> check for moved child entry in node-attic
// -> check if child points to a removed/moved sns
- List<NodeEntry> siblings = entry.childNodeEntries.get(name);
+ List<NodeEntry> siblings = Collections.singletonList(entry.childNodeEntries.get(name));
if (entry.containsAtticChild(siblings, name, index)) {
throw new PathNotFoundException(factory.saveGetJCRPath(path));
}
@@ -501,7 +502,7 @@ public class NodeEntry extends Hierarchy
}
// -> check for moved child entry in node-attic
// -> check if child points to a removed/moved sns
- List<NodeEntry> siblings = entry.childNodeEntries.get(name);
+ List<NodeEntry> siblings = Collections.singletonList(entry.childNodeEntries.get(name));
if (entry.containsAtticChild(siblings, name, index)) {
throw new PathNotFoundException(factory.saveGetJCRPath(path));
}
@@ -592,7 +593,7 @@ public class NodeEntry extends Hierarchy
* the specified {@code nodeName}.
*/
public synchronized boolean hasNodeEntry(Name nodeName) {
- List<NodeEntry> namedEntries = childNodeEntries.get(nodeName);
+ List<NodeEntry> namedEntries = Collections.singletonList(childNodeEntries.get(nodeName));
return !namedEntries.isEmpty() && EntryValidation.containsValidNodeEntry(namedEntries.iterator());
}
@@ -643,7 +644,7 @@ public class NodeEntry extends Hierarchy
* @throws RepositoryException If an unexpected error occurs.
*/
public NodeEntry getNodeEntry(Name nodeName, int index, boolean loadIfNotFound) throws RepositoryException {
- List<NodeEntry> entries = childNodeEntries.get(nodeName);
+ List<NodeEntry> entries = Collections.singletonList(childNodeEntries.get(nodeName));
NodeEntry cne = null;
if (entries.size() >= index) {
// position of entry might differ from index-1 if a SNS with lower
@@ -698,7 +699,7 @@ public class NodeEntry extends Hierarchy
* @throws RepositoryException If an unexpected error occurs.
*/
public synchronized List<NodeEntry> getNodeEntries(Name nodeName) throws RepositoryException {
- List<NodeEntry> namedEntries = getCompleteChildNodeEntries().get(nodeName);
+ List<NodeEntry> namedEntries = Collections.singletonList(getCompleteChildNodeEntries().get(nodeName));
if (namedEntries.isEmpty()) {
return Collections.emptyList();
} else {
@@ -720,7 +721,7 @@ public class NodeEntry extends Hierarchy
*
* @param childInfos
*/
- public void setNodeEntries(Iterator<ChildInfo> childInfos) {
+ public void setNodeEntries(Iterator<ChildInfo> childInfos) throws UnsupportedRepositoryOperationException {
if (childNodeAttic.isEmpty()) {
childNodeEntries.update(childInfos);
} else {
@@ -745,7 +746,9 @@ public class NodeEntry extends Hierarchy
* @param uniqueID
* @return the {@code NodeEntry}.
*/
- public NodeEntry getOrAddNodeEntry(Name nodeName, int index, String uniqueID) {
+ public NodeEntry getOrAddNodeEntry(Name nodeName, int index, String uniqueID)
+ throws UnsupportedRepositoryOperationException {
+
NodeEntry ne = lookupNodeEntry(uniqueID, nodeName, index);
if (ne == null) {
ne = internalAddNodeEntry(nodeName, uniqueID, index);
@@ -764,7 +767,8 @@ public class NodeEntry extends Hierarchy
* @param definition
* @return
*/
- public NodeEntry addNewNodeEntry(Name nodeName, String uniqueID, Name primaryNodeType, QNodeDefinition definition) {
+ public NodeEntry addNewNodeEntry(Name nodeName, String uniqueID, Name primaryNodeType, QNodeDefinition definition)
+ throws UnsupportedRepositoryOperationException {
NodeEntry entry = internalAddNodeEntry(nodeName, uniqueID, Path.INDEX_UNDEFINED);
NodeState state = getItemStateFactory().createNewNodeState(entry, primaryNodeType, definition);
@@ -942,14 +946,7 @@ public class NodeEntry extends Hierarchy
* @throws RepositoryException If an unexpected error occurs.
*/
public void orderBefore(NodeEntry beforeEntry) throws RepositoryException {
- if (Status.NEW == getStatus()) {
- // new states get remove upon revert
- parent.childNodeEntries.reorder(this, beforeEntry);
- } else {
- createRevertInfo();
- // now reorder child entries on parent
- parent.childNodeEntries.reorder(this, beforeEntry);
- }
+ throw new UnsupportedRepositoryOperationException("orderBefore");
}
/**
@@ -1067,8 +1064,14 @@ public class NodeEntry extends Hierarchy
* @return the added entry.
*/
private NodeEntry internalAddNodeEntry(Name nodeName, String uniqueID, int index) {
+ if (index > Path.INDEX_DEFAULT) {
+ IllegalArgumentException e = new IllegalArgumentException("Invalid index: " + index);
+ log.error(e.getMessage(), e);
+ throw e;
+ }
+
NodeEntry entry = factory.createNodeEntry(this, nodeName, uniqueID);
- childNodeEntries.add(entry, index);
+ childNodeEntries.add(entry);
return entry;
}
@@ -1213,6 +1216,12 @@ public class NodeEntry extends Hierarchy
}
private NodeEntry lookupNodeEntry(String uniqueChildId, Name childName, int index) {
+ if (index > Path.INDEX_DEFAULT) {
+ IllegalArgumentException e = new IllegalArgumentException("Invalid index: " + index);
+ log.error(e.getMessage(), e);
+ throw e;
+ }
+
NodeEntry child = null;
if (uniqueChildId != null) {
child = childNodeAttic.get(uniqueChildId);
@@ -1223,7 +1232,7 @@ public class NodeEntry extends Hierarchy
if (child == null) {
child = childNodeAttic.get(childName, index);
if (child == null && childNodeEntries != null) {
- child = childNodeEntries.get(childName, index);
+ child = childNodeEntries.get(childName);
}
}
return child;
@@ -1335,7 +1344,8 @@ public class NodeEntry extends Hierarchy
* this {@code NodeEntry}.
*/
private int getChildIndex(NodeEntry cne, boolean wspIndex) throws RepositoryException {
- List<NodeEntry> sns = new ArrayList<NodeEntry>(childNodeEntries.get(cne.getName()));
+ List<NodeEntry> sns = new ArrayList<NodeEntry>();
+ sns.add(childNodeEntries.get(cne.getName()));
if (wspIndex) {
List<NodeEntry> atticSiblings = childNodeAttic.get(cne.getName());
@@ -1648,7 +1658,7 @@ public class NodeEntry extends Hierarchy
// now restore moved entry with the old name and index and re-add
// it to its original parent
name = revertInfo.oldName;
- parent.childNodeEntries.add(this, revertInfo.oldIndex, revertInfo.oldSuccessor);
+ parent.childNodeEntries.add(this);
}
private static Name[] getMixinNames(PropertyState propertyState) {
@@ -1677,15 +1687,11 @@ public class NodeEntry extends Hierarchy
private final NodeEntry oldParent;
private final Name oldName;
private final int oldIndex;
- private final NodeEntry oldSuccessor;
- private final NodeEntry oldPredecessor;
private RevertInfo() throws RepositoryException {
oldParent = parent;
oldName = name;
oldIndex = getIndex();
- oldSuccessor = parent.childNodeEntries.getNext(NodeEntry.this);
- oldPredecessor = parent.childNodeEntries.getPrevious(NodeEntry.this);
}
private boolean isMoved() {
@@ -1695,8 +1701,6 @@ public class NodeEntry extends Hierarchy
private void dispose(boolean persisted) {
if (!persisted) {
NodeEntry ne = NodeEntry.this;
- ChildNodeEntries parentCNEs = parent.childNodeEntries;
- parentCNEs.reorderAfter(ne, revertInfo.oldPredecessor);
try {
if (oldIndex != ne.getIndex()) {
// TODO: fix
Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/pom.xml?rev=1213877&r1=1213876&r2=1213877&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/pom.xml (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/pom.xml Tue Dec 13 19:13:38 2011
@@ -281,6 +281,13 @@
org.apache.jackrabbit.test.api.NodeTest#testRefreshInvalidItemStateException
org.apache.jackrabbit.test.api.NodeTest#testSaveOnNewNodeRepositoryException
+ <!-- Not supported reorder -->
+ org.apache.jackrabbit.test.api.observation.NodeReorderTest#testNodeReorder
+ org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest#testOrderBeforePlaceAtEndParentSave
+ org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest#testOrderBeforePlaceAtEndSessionSave
+ org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest#testOrderBeforeSecondToFirstParentSave
+ org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest#testOrderBeforeSecondToFirstSessionSave
+
<!-- fixme: Microkernel indexer does not properly handler multi valued properties -->
org.apache.jackrabbit.test.api.GetWeakReferencesTest#testMultiValues
org.apache.jackrabbit.test.api.GetWeakReferencesTest#testMultiValuesWithName
@@ -290,9 +297,6 @@
org.apache.jackrabbit.test.api.observation.NodeMovedTest#testMoveNode
org.apache.jackrabbit.test.api.observation.NodeMovedTest#testMoveWithRemove
- <!-- fixme: reorder is not yet implemented -->
- org.apache.jackrabbit.test.api.observation.NodeReorderTest#testNodeReorder
-
<!-- fixme: filtering by uuid, nodetype is not yet implemented -->
org.apache.jackrabbit.test.api.observation.AddEventListenerTest#testNodeType
org.apache.jackrabbit.test.api.observation.AddEventListenerTest#testUUID