You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2005/06/01 16:51:23 UTC

svn commit: r179383 - in /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: PathMap.java lock/LockInfo.java lock/LockManagerImpl.java lock/LockToken.java lock/PathMap.java

Author: dpfister
Date: Wed Jun  1 07:51:23 2005
New Revision: 179383

URL: http://svn.apache.org/viewcvs?rev=179383&view=rev
Log:
Moved PathMap to core package

Added:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PathMap.java   (with props)
Removed:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/PathMap.java
Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockInfo.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockToken.java

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PathMap.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PathMap.java?rev=179383&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PathMap.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PathMap.java Wed Jun  1 07:51:23 2005
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Generic path map that associates information with the individual path elements
+ * of a path.
+ */
+public class PathMap {
+
+    /**
+     * Root element
+     */
+    private final Child root = new Child(Path.ROOT.getNameElement());
+
+    /**
+     * Map a path to a child. If <code>exact</code> is <code>false</code>,
+     * returns the last available item along the path that is stored in the map.
+     * @param path path to map
+     * @param exact flag indicating whether an exact match is required
+     * @return child, maybe <code>null</code> if <code>exact</code> is
+     *         <code>true</code>
+     */
+    public Child map(Path path, boolean exact) {
+        Path.PathElement[] elements = path.getElements();
+        Child current = root;
+
+        for (int i = 1; i < elements.length; i++) {
+            Child next = current.getChild(elements[i], false);
+            if (next == null) {
+                if (exact) {
+                    return null;
+                }
+                break;
+            }
+            current = next;
+        }
+        return current;
+    }
+
+    /**
+     * Create a child given by its path. The path map will create any necessary
+     * intermediate children.
+     * @param path path to child
+     * @param obj object to store at destination
+     */
+    public Child put(Path path, Object obj) {
+        Child child = put(path);
+        child.obj = obj;
+        return child;
+    }
+
+    /**
+     * Create an empty child given by its path.
+     * @param path path to child
+     */
+    public Child put(Path path) {
+        Path.PathElement[] elements = path.getElements();
+        Child current = root;
+
+        for (int i = 1; i < elements.length; i++) {
+            current = current.getChild(elements[i], true);
+        }
+        return current;
+    }
+
+    /**
+     * Ressurrect a child previously removed, given by its path and the
+     * child structure. If an item at path already exists, nothing happens.
+     * @param path new path to child
+     * @param zombie previously removed child object to store at destination
+     */
+    public void resurrect(Path path, Child zombie) {
+        Path.PathElement[] elements = path.getElements();
+        Path.PathElement name = path.getNameElement();
+        Child parent = root;
+
+        if (map(path, true) == null) {
+            for (int i = 1; i < elements.length - 1; i++) {
+                parent = parent.getChild(elements[i], true);
+            }
+            parent.setChild(name, zombie);
+        }
+    }
+
+    /**
+     * Traverse the path map and call back requester.
+     * @param includeEmpty if <code>true</code> invoke call back on every child
+     *                     regardless, whether the associated object is empty
+     *                     or not; otherwise call back on non-empty children
+     *                     only
+     */
+    public void traverse(ChildVisitor visitor, boolean includeEmpty) {
+        root.traverse(visitor, includeEmpty);
+    }
+
+    /**
+     * Internal class holding the object associated with a certain
+     * path element.
+     */
+    public static class Child {
+
+        /**
+         * Parent child
+         */
+        private Child parent;
+
+        /**
+         * Map of immediate children of this child.
+         */
+        private Map children;
+
+        /**
+         * Number of non-null children
+         */
+        private int childrenCount;
+
+        /**
+         * Object associated with this child
+         */
+        private Object obj;
+
+        /**
+         * QName associated with this child
+         */
+        private QName name;
+
+        /**
+         * index associated with this child
+         */
+        private int index;
+
+        /**
+         * Create a new instance of this class with a path element.
+         * @param element path element of this child
+         */
+        Child(Path.PathElement element) {
+            this.name = element.getName();
+            this.index = element.getIndex();
+        }
+
+        /**
+         * Create a new instance of this class.
+         */
+        Child() {
+        }
+
+        /**
+         * Insert an empty child. Will shift all children having an index
+         * greater than or equal to the child inserted to the right.
+         * @param element child's path element
+         */
+        public void insertChild(Path.PathElement element) {
+            int index = getOneBasedIndex(element) - 1;
+            if (children != null) {
+                ArrayList list = (ArrayList) children.get(element.getName());
+                if (list != null && list.size() > index) {
+                    for (int i = index; i < list.size(); i++) {
+                        Child child = (Child) list.get(i);
+                        if (child != null) {
+                            child.index++;
+                        }
+                    }
+                    list.add(index, null);
+                }
+            }
+        }
+
+        /**
+         * Remove a child. Will shift all children having an index greater than
+         * the child removed to the left.
+         * @param element child's path element
+         * @return removed child, may be <code>null</code>
+         */
+        public Child removeChild(Path.PathElement element) {
+            int index = getOneBasedIndex(element) - 1;
+            if (children != null) {
+                ArrayList list = (ArrayList) children.get(element.getName());
+                if (list != null && list.size() > index) {
+                    for (int i = index + 1; i < list.size(); i++) {
+                        Child child = (Child) list.get(i);
+                        if (child != null) {
+                            child.index--;
+                        }
+                    }
+                    Child child = (Child) list.remove(index);
+                    if (child != null) {
+                        child.parent = null;
+                        childrenCount--;
+                    }
+                    if (obj == null && childrenCount == 0) {
+                        remove();
+                    }
+                    return child;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Return a child matching a path element. If a child does not exist
+         * at that position and <code>create</code> is <code>true</code> a
+         * new child will be created.
+         * @param element child's path element
+         * @param create flag indicating whether this child should be
+         *        created if not available
+         */
+        private Child getChild(Path.PathElement element, boolean create) {
+            int index = getOneBasedIndex(element) - 1;
+            Child child = null;
+
+            if (children != null) {
+                ArrayList list = (ArrayList) children.get(element.getName());
+                if (list != null && list.size() > index) {
+                    child = (Child) list.get(index);
+                }
+            }
+            if (child == null && create) {
+                child = new Child();
+                setChild(element, child);
+            }
+            return child;
+        }
+
+        /**
+         * Add a child.
+         * @param element child's path element
+         * @param child child to add
+         */
+        private void setChild(Path.PathElement element, Child child) {
+            int index = getOneBasedIndex(element) - 1;
+            if (children == null) {
+                children = new HashMap();
+            }
+            ArrayList list = (ArrayList) children.get(element.getName());
+            if (list == null) {
+                list = new ArrayList();
+                children.put(element.getName(), list);
+            }
+            while (list.size() < index) {
+                list.add(null);
+            }
+            if (list.size() == index) {
+                list.add(child);
+            } else {
+                list.set(index, child);
+            }
+
+            child.parent = this;
+            child.name = element.getName();
+            child.index = element.getIndex();
+
+            childrenCount++;
+        }
+
+        /**
+         * Remove this child. Delegates the call to the parent item.
+         */
+        public void remove() {
+            if (parent != null) {
+                parent.removeChild(getPathElement());
+            }
+        }
+
+        /**
+         * Return the object associated with this child
+         * @return object associated with this child
+         */
+        public Object get() {
+            return obj;
+        }
+
+        /**
+         * Set the object associated with this child
+         * @param obj object associated with this child
+         */
+        public void set(Object obj) {
+            this.obj = obj;
+
+            if (obj == null && childrenCount == 0) {
+                remove();
+            }
+        }
+
+        /**
+         * Return the name of this child
+         * @return name
+         */
+        public QName getName() {
+            return name;
+        }
+
+        /**
+         * Return the index of this child
+         * @return index
+         */
+        public int getIndex() {
+            return index;
+        }
+
+        /**
+         * Return a path element pointing to this child
+         * @return path element
+         */
+        public Path.PathElement getPathElement() {
+            return Path.create(name, index).getNameElement();
+        }
+
+        /**
+         * Return the path of this element.
+         * @return path
+         * @throws MalformedPathException if building the path fails
+         */
+        public Path getPath() throws MalformedPathException {
+            if (parent == null) {
+                return Path.ROOT;
+            }
+
+            Path.PathBuilder builder = new Path.PathBuilder();
+            getPath(builder);
+            return builder.getPath();
+        }
+
+        /**
+         * Internal implementation of {@link #getPath()} that populates entries
+         * in a builder. On exit, <code>builder</code> contains the path
+         * of this element
+         */
+        private void getPath(Path.PathBuilder builder) {
+            if (parent == null) {
+                builder.addRoot();
+                return;
+            }
+            parent.getPath(builder);
+            if (index == 0 || index == 1) {
+                builder.addLast(name);
+            } else {
+                builder.addLast(name, index);
+            }
+        }
+
+        /**
+         * Checks whether this child has the specified path. Introduced to
+         * avoid catching a <code>MalformedPathException</code> for simple
+         * path comparisons.
+         * @param path path to compare to
+         * @return <code>true</code> if this child has the path
+         *         <code>path</code>, <code>false</code> otherwise
+         */
+        public boolean hasPath(Path path) {
+            return hasPath(path.getElements(), path.getLength());
+        }
+
+        /**
+         * Checks whether this child has the specified path, given by
+         * path elements.
+         * @param elements path elements to compare to
+         * @param len number of elements to compare to
+         * @return <code>true</code> if this child has the path given;
+         *         otherwise <code>false</code>
+         */
+        private boolean hasPath(Path.PathElement[] elements, int len) {
+            if (getPathElement().equals(elements[len - 1])) {
+                if (parent != null) {
+                    return parent.hasPath(elements, len - 1);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Return 1-based index of a path element.
+         */
+        private static int getOneBasedIndex(Path.PathElement element) {
+            int index = element.getIndex();
+            if (index == 0) {
+                return 1;
+            } else {
+                return index;
+            }
+        }
+
+        /**
+         * Recursively invoked traversal method.
+         * @param visitor visitor to invoke
+         * @param includeEmpty if <code>true</code> invoke call back on every
+         *        child regardless, whether the associated object is empty
+         *        or not; otherwise call back on non-empty children only
+         */
+        public void traverse(ChildVisitor visitor, boolean includeEmpty) {
+            if (children != null) {
+                Iterator iter = children.values().iterator();
+                while (iter.hasNext()) {
+                    ArrayList list = (ArrayList) iter.next();
+                    for (int i = 0; i < list.size(); i++) {
+                        Child child = (Child) list.get(i);
+                        if (child != null) {
+                            child.traverse(visitor, includeEmpty);
+                        }
+                    }
+                }
+            }
+            if (includeEmpty || obj != null) {
+                visitor.childVisited(this);
+            }
+        }
+
+        /**
+         * Return the depth of this child. Defined to be <code>0</code> for the
+         * root node and <code>n + 1</code> for some child if the depth of its
+         * parent is <code>n</code>.
+         */
+        public int getDepth() {
+            if (parent != null) {
+                return parent.getDepth() + 1;
+            }
+            return 0;
+        }
+
+        /**
+         * Return a flag indicating whether the specified node is a
+         * child of this node.
+         * @param other node to check
+         */
+        public boolean isAncestorOf(Child other) {
+            Child parent = other.parent;
+            while (parent != null) {
+                if (parent == this) {
+                    return true;
+                }
+                parent = parent.parent;
+            }
+            return false;
+        }
+
+        /**
+         * Return the parent of this child
+         * @return parent or <code>null</code> if this is the root node
+         */
+        public Child getParent() {
+            return parent;
+        }
+    }
+
+    /**
+     * Child visitor used in {@link PathMap#traverse}
+     */
+    public interface ChildVisitor {
+
+        /**
+         * Invoked for every child visited on a tree traversal
+         * @param child child visited
+         */
+        void childVisited(Child child);
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/PathMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockInfo.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockInfo.java?rev=179383&r1=179382&r2=179383&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockInfo.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockInfo.java Wed Jun  1 07:51:23 2005
@@ -27,7 +27,7 @@
 
 /**
  * Contains information about a lock and gets placed inside the child
- * information of a {@link PathMap}.
+ * information of a {@link org.apache.jackrabbit.core.PathMap}.
  */
 class LockInfo implements SessionListener {
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=179383&r1=179382&r2=179383&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Wed Jun  1 07:51:23 2005
@@ -24,6 +24,7 @@
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.MalformedPathException;
+import org.apache.jackrabbit.core.PathMap;
 import org.apache.jackrabbit.core.observation.SynchronousEventListener;
 import org.apache.jackrabbit.core.observation.EventImpl;
 import org.apache.log4j.Logger;

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockToken.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockToken.java?rev=179383&r1=179382&r2=179383&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockToken.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/lock/LockToken.java Wed Jun  1 07:51:23 2005
@@ -93,7 +93,10 @@
             }
         }
 
-        int rem = 37 - (result % 37);
+        int rem = result % 37;
+        if (rem != 0) {
+            rem = 37 - rem;
+        }
         if (rem >= 0 && rem <= 9) {
             return (char) ('0' + rem);
         } else if (rem >= 10 && rem <= 35) {