Return-Path: X-Original-To: apmail-jackrabbit-commits-archive@www.apache.org Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id DA2A37EBD for ; Tue, 13 Dec 2011 19:14:04 +0000 (UTC) Received: (qmail 70291 invoked by uid 500); 13 Dec 2011 19:14:02 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 70255 invoked by uid 500); 13 Dec 2011 19:14:02 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 70228 invoked by uid 99); 13 Dec 2011 19:14:02 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Dec 2011 19:14:02 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Dec 2011 19:13:59 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id F112C238889B; Tue, 13 Dec 2011 19:13:38 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1213877 - in /jackrabbit/sandbox/jackrabbit-mk: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ jackrabbit-spi2microkernel/ Date: Tue, 13 Dec 2011 19:13:38 -0000 To: commits@jackrabbit.apache.org From: mduerig@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111213191338.F112C238889B@eris.apache.org> 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 entries = new HashMap(); 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 childNodeInfos = factory.getItemStateFactory().getChildNodeInfos(id); + NodeId nodeId = parent.getWorkspaceId(); + Iterator childNodeInfos = factory.getItemStateFactory().getChildNodeInfos(nodeId); update(childNodeInfos); } @@ -158,26 +128,13 @@ final class ChildNodeEntries { */ synchronized void update(Iterator 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 iterator() { - List l = new ArrayList(entries.size()); - for (Iterator 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 not filter out - * removed {@code NodeEntry}s. - * - * @param nodeName the child node name. - * @return same name sibling nodes with the given {@code nodeName}. - */ - public List get(Name nodeName) { - return entriesByName.getList(nodeName); + // avoid concurrent modification exception + return new ArrayList(entries.values()).iterator(); } - /** - * Returns the {@code NodeEntry} with the given - * {@code nodeName} and {@code index}. Note, that this method - * does not 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}.
- * Note the following special cases: - *
    - *
  1. If an entry with the given index already exists, the the new sibling - * is inserted before.
  2. - *
  3. If the given index is bigger that the last entry in the siblings list, - * intermediate entries will be created.
  4. - *
- * - * @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 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 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 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 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(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(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 { - - 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> snsMap = new HashMap>(); - private final Map nameMap = new HashMap(); - - /** - * 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 get(Name name) { - LinkedEntries.LinkNode val = nameMap.get(name); - if (val != null) { - return Collections.singletonList(val.getNodeEntry()); - } else { - List l = snsMap.get(name); - if (l != null) { - List nodeEntries = new ArrayList(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 getList(Name name) { - List nodeEntries = get(name); - if (nodeEntries == null) { - return Collections.emptyList(); - } else { - return Collections.unmodifiableList(new ArrayList(nodeEntries)); - } - } - - public NodeEntry getNodeEntry(Name name, int index) { - List 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 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 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 l; - if (single != null) { - l = new ArrayList(); - 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 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 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 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 siblings = entry.childNodeEntries.get(name); + List 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 siblings = entry.childNodeEntries.get(name); + List 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 namedEntries = childNodeEntries.get(nodeName); + List 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 entries = childNodeEntries.get(nodeName); + List 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 getNodeEntries(Name nodeName) throws RepositoryException { - List namedEntries = getCompleteChildNodeEntries().get(nodeName); + List 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 childInfos) { + public void setNodeEntries(Iterator 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 sns = new ArrayList(childNodeEntries.get(cne.getName())); + List sns = new ArrayList(); + sns.add(childNodeEntries.get(cne.getName())); if (wspIndex) { List 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 + + 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 + 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 - - org.apache.jackrabbit.test.api.observation.NodeReorderTest#testNodeReorder - org.apache.jackrabbit.test.api.observation.AddEventListenerTest#testNodeType org.apache.jackrabbit.test.api.observation.AddEventListenerTest#testUUID