jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r906574 - in /jackrabbit/trunk: jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/
Date Thu, 04 Feb 2010 17:28:05 GMT
Author: mduerig
Date: Thu Feb  4 17:28:05 2010
New Revision: 906574

URL: http://svn.apache.org/viewvc?rev=906574&view=rev
Log:
JCR-2486: Promote ItemInfo builder classes from GetItemsTest to top level classes

Added:
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ItemInfoStore.java
  (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoBuilder.java
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java?rev=906574&r1=906573&r2=906574&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
(original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
Thu Feb  4 17:28:05 2010
@@ -65,6 +65,8 @@
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Subscription;
 import org.apache.jackrabbit.spi.commons.AbstractReadableRepositoryService;
+import org.apache.jackrabbit.spi.commons.ItemInfoBuilder;
+import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.NodeInfoBuilder;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 
 /**
@@ -75,6 +77,7 @@
 public abstract class AbstractJCR2SPITest extends TestCase implements RepositoryService {
     private static final String DEFAULT_WSP = "default";
 
+    protected ItemInfoStore itemInfoStore;
     protected RepositoryService repositoryService;
     protected RepositoryConfig config;
     protected Repository repository;
@@ -82,11 +85,30 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
+
+        itemInfoStore = new ItemInfoStore();
+        ItemInfoBuilder.Listener listener = new ItemInfoBuilder.Listener() {
+            public void createPropertyInfo(PropertyInfo propertyInfo) {
+                itemInfoStore.addItemInfo(propertyInfo);
+            }
+
+            public void createNodeInfo(NodeInfo nodeInfo) {
+                itemInfoStore.addItemInfo(nodeInfo);
+            }
+
+            public void createChildInfos(NodeId id, Iterator<ChildInfo> childInfos)
{
+                itemInfoStore.setChildInfos(id, childInfos);
+            }
+        };
+
+        initInfosStore(ItemInfoBuilder.nodeInfoBuilder(listener));
         repositoryService = getRepositoryService();
         config = getRepositoryConfig();
         repository = getRepository();
     }
 
+    protected abstract void initInfosStore(NodeInfoBuilder builder) throws RepositoryException;
+
     protected RepositoryService getRepositoryService() throws RepositoryException, ParseException
{
         return new AbstractReadableRepositoryService(getDescriptors(), getNameSpaces(), getCndReader(),
                 getWspNames(), DEFAULT_WSP) {

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java?rev=906574&r1=906573&r2=906574&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java
(original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java
Thu Feb  4 17:28:05 2010
@@ -16,87 +16,72 @@
  */
 package org.apache.jackrabbit.jcr2spi;
 
-import java.util.ArrayList;
 import java.util.Iterator;
-import java.util.List;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Item;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.commons.collections.Predicate;
-import org.apache.commons.collections.Transformer;
 import org.apache.commons.collections.functors.NotPredicate;
-import org.apache.commons.collections.iterators.EmptyIterator;
 import org.apache.commons.collections.iterators.FilterIterator;
 import org.apache.commons.collections.iterators.IteratorChain;
-import org.apache.commons.collections.iterators.TransformIterator;
 import org.apache.jackrabbit.spi.ChildInfo;
 import org.apache.jackrabbit.spi.ItemInfo;
-import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.NodeInfo;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.PropertyId;
 import org.apache.jackrabbit.spi.PropertyInfo;
 import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.RepositoryService;
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Path.Element;
-import org.apache.jackrabbit.spi.commons.ChildInfoImpl;
-import org.apache.jackrabbit.spi.commons.NodeInfoImpl;
-import org.apache.jackrabbit.spi.commons.PropertyInfoImpl;
-import org.apache.jackrabbit.spi.commons.identifier.IdFactoryImpl;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
-import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.NodeInfoBuilder;
 
 /**
  * Test cases for {@link RepositoryService#getItemInfos(SessionInfo, NodeId)}. Specifically
  * for JCR-1797.
  */
 public class GetItemsTest extends AbstractJCR2SPITest {
-    private List<ItemInfo> itemInfos;
     private Session session;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        itemInfos = new ArrayList<ItemInfo>();
+        session = repository.login("default");
+    }
 
+    @Override
+    protected void initInfosStore(NodeInfoBuilder builder) throws RepositoryException {
         // build up a hierarchy of items
-        new NodeInfoBuilder()
+        builder
             .createNodeInfo("node1")
-                .createNodeInfo("node11").build(itemInfos)
-                .createNodeInfo("node12").build(itemInfos)
-                .createNodeInfo("node13").build(itemInfos)
-                .createPropertyInfo("property11", "value11").build(itemInfos)
-                .createPropertyInfo("property12", "value12").build(itemInfos)
-            .build(itemInfos)
+                .createNodeInfo("node11").build()
+                .createNodeInfo("node12").build()
+                .createNodeInfo("node13").build()
+                .createPropertyInfo("property11", "value11").build()
+                .createPropertyInfo("property12", "value12").build()
+            .build()
             .createNodeInfo("node2")
                 .createNodeInfo("node21")
                     .createNodeInfo("node211")
                         .createNodeInfo("node2111")
                             .createNodeInfo("node21111")
                                 .createNodeInfo("node211111")
-                                    .createNodeInfo("node2111111").build(itemInfos)
-                                .build(itemInfos)
-                            .build(itemInfos)
-                        .build(itemInfos)
-                    .build(itemInfos)
-                .build(itemInfos)
-            .build(itemInfos)
-            .createNodeInfo("node3").build(itemInfos)
-            .build(itemInfos);
-
-        session = repository.login("default");
+                                    .createNodeInfo("node2111111").build()
+                                .build()
+                            .build()
+                        .build()
+                    .build()
+                .build()
+            .build()
+            .createNodeInfo("node3").build()
+            .build();
     }
 
     @Override
@@ -127,8 +112,8 @@
             @SuppressWarnings("unchecked")
             public Iterator<ItemInfo> iterator() {
                 return new IteratorChain(
-                        new FilterIterator(itemInfos.iterator(), isRoot),
-                        new FilterIterator(itemInfos.iterator(), NotPredicate.getInstance(isRoot)));
+                        new FilterIterator(itemInfoStore.getItemInfos(), isRoot),
+                        new FilterIterator(itemInfoStore.getItemInfos(), NotPredicate.getInstance(isRoot)));
             }
         };
 
@@ -155,8 +140,8 @@
             @SuppressWarnings("unchecked")
             public Iterator<ItemInfo> iterator() {
                 return new IteratorChain(
-                        new FilterIterator(itemInfos.iterator(), isTarget),
-                        new FilterIterator(itemInfos.iterator(), NotPredicate.getInstance(isTarget)));
+                        new FilterIterator(itemInfoStore.getItemInfos(), isTarget),
+                        new FilterIterator(itemInfoStore.getItemInfos(), NotPredicate.getInstance(isTarget)));
             }
         };
 
@@ -234,162 +219,4 @@
         public Iterator<ItemInfo> iterator();
     }
 
-    /**
-     * todo: we might want to grow this in a full blown helper class
-     */
-    class NodeInfoBuilder {
-        private final NodeInfoBuilder parent;
-        private final String name;
-
-        protected boolean stale;
-        private final List<ItemInfo> itemInfos = new ArrayList<ItemInfo>();
-        private NodeInfo nodeInfo;
-
-        public NodeInfoBuilder() {
-            this(null, null);
-        }
-
-        public NodeInfoBuilder(NodeInfoBuilder nodeInfoBuilder, String name) {
-            super();
-            parent = nodeInfoBuilder;
-            this.name = name;
-        }
-
-        public PropertyInfoBuilder createPropertyInfo(String name, String value) {
-            return new PropertyInfoBuilder(this, name, value);
-        }
-
-        public NodeInfoBuilder createNodeInfo(String name) {
-            return new NodeInfoBuilder(this, name);
-        }
-
-        @SuppressWarnings("unchecked")
-        public NodeInfoBuilder build(List<ItemInfo> infos) throws RepositoryException
{
-            if (stale) {
-                throw new IllegalStateException("Builder is stale");
-            }
-            else {
-                stale = true;
-
-                NodeId id = getId();
-                Path path = id.getPath();
-
-                Iterator<ItemInfo> propertyIds = new TransformIterator(new FilterIterator(itemInfos.iterator(),
-                        new Predicate() {
-                            public boolean evaluate(Object object) {
-                                return object instanceof PropertyInfo;
-                            }
-                        }),
-                        new Transformer() {
-                            public Object transform(Object input) {
-                                PropertyInfo info = (PropertyInfo) input;
-                                return info.getId();
-                            }});
-
-                Iterator<ItemInfo> childInfos = new TransformIterator(itemInfos.iterator(),
new Transformer(){
-                    public Object transform(Object input) {
-                        ItemInfo info = (ItemInfo) input;
-                        Name name = info.getPath().getNameElement().getName();
-                        return new ChildInfoImpl(name, null, Path.INDEX_DEFAULT);
-                    }});
-
-                nodeInfo = new NodeInfoImpl(path, id, Path.INDEX_DEFAULT, NameConstants.NT_UNSTRUCTURED,
-                        Name.EMPTY_ARRAY, EmptyIterator.INSTANCE, propertyIds, childInfos);
-
-                if (infos != null) {
-                    infos.add(nodeInfo);
-                }
-
-                if (parent == null) {
-                    return this;
-                }
-                else {
-                    parent.addNodeInfo(nodeInfo);
-                    return parent;
-                }
-            }
-        }
-
-        public NodeInfo getNodeInfo() throws RepositoryException {
-            if (!stale) {
-                build(null);
-            }
-            return nodeInfo;
-        }
-
-        NodeInfoBuilder addPropertyInfo(PropertyInfo propertyInfo) {
-            itemInfos.add(propertyInfo);
-            return this;
-        }
-
-        NodeInfoBuilder addNodeInfo(NodeInfo nodeInfo) {
-            itemInfos.add(nodeInfo);
-            return this;
-        }
-
-        NodeId getId() throws RepositoryException {
-            return IdFactoryImpl.getInstance().createNodeId((String) null, getPath());
-        }
-
-        Path getPath() throws RepositoryException {
-            if (parent == null) {
-                return PathFactoryImpl.getInstance().getRootPath();
-            }
-            else {
-                Name name = NameFactoryImpl.getInstance().create(Name.NS_DEFAULT_URI, this.name);
-                return PathFactoryImpl.getInstance().create(parent.getPath(), name, true);
-            }
-        }
-
-    }
-
-    /**
-     * todo: we might want to grow this in a full blown helper class
-     */
-    class PropertyInfoBuilder {
-        private final NodeInfoBuilder parent;
-        private final String name;
-        private final String value;
-
-        private boolean stale;
-        private PropertyInfo propertyInfo;
-
-        public PropertyInfoBuilder(NodeInfoBuilder nodeInfoBuilder, String name, String value)
{
-            super();
-            parent = nodeInfoBuilder;
-            this.name = name;
-            this.value = value;
-        }
-
-        public NodeInfoBuilder build(List<ItemInfo> infos) throws RepositoryException
{
-            if (parent == null) {
-                return null;
-            }
-
-            if (stale) {
-                throw new IllegalStateException("Builder is stale");
-            }
-            else {
-                stale = true;
-
-                NodeId parentId = parent.getId();
-                Name propertyName = NameFactoryImpl.getInstance().create(Name.NS_DEFAULT_URI,
this.name);
-                Path path = PathFactoryImpl.getInstance().create(parentId.getPath(), propertyName,
true);
-                PropertyId id = IdFactoryImpl.getInstance().createPropertyId(parentId, propertyName);
-                QValue qvalue = QValueFactoryImpl.getInstance().create(value, PropertyType.STRING);
-                propertyInfo = new PropertyInfoImpl(path, id, PropertyType.STRING, false,
new QValue[] { qvalue });
-
-                if (infos != null) {
-                    infos.add(propertyInfo);
-                }
-                return parent.addPropertyInfo(propertyInfo);
-            }
-        }
-
-        public PropertyInfo getPropertyInfo() {
-            return propertyInfo;
-        }
-
-    }
-
 }

Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ItemInfoStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ItemInfoStore.java?rev=906574&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ItemInfoStore.java
(added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ItemInfoStore.java
Thu Feb  4 17:28:05 2010
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jcr2spi;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.ItemNotFoundException;
+
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.jackrabbit.spi.ChildInfo;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.ItemInfo;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.NodeInfo;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.RepositoryService;
+
+/**
+ * In memory store for {@link ItemInfo}s.
+ */
+public class ItemInfoStore {
+    private final Map<ItemId, ItemInfo>infos = new HashMap<ItemId, ItemInfo>();
+    private final Map<ItemId, Collection<ItemInfo>> batches = new HashMap<ItemId,
Collection<ItemInfo>>();
+    private final Map<ItemId, Collection<ChildInfo>> childInfos = new HashMap<ItemId,
Collection<ChildInfo>>();
+
+    /**
+     * Retrieve an item by its <code>id</code>.
+     * @param id
+     * @return
+     * @throws ItemNotFoundException  if no such item exists
+     */
+    public ItemInfo getItemInfo(ItemId id) throws ItemNotFoundException {
+        ItemInfo itemInfo = infos.get(id);
+
+        return itemInfo == null
+            ? ItemInfoStore.<ItemInfo>notFound(id)
+            : itemInfo;
+    }
+
+    /**
+     * Retrieve an iterator over all items
+     * @return
+     */
+    public Iterator<ItemInfo> getItemInfos() {
+        return infos.values().iterator();
+    }
+
+    /**
+     * Retrieve a node by its <code>id</code>.
+     *
+     * @param id
+     * @return
+     * @throws ItemNotFoundException  if no such node exists
+     */
+    public NodeInfo getNodeInfo(NodeId id) throws ItemNotFoundException {
+        ItemInfo itemInfo = getItemInfo(id);
+
+        return itemInfo.denotesNode()
+            ? (NodeInfo) itemInfo
+            : ItemInfoStore.<NodeInfo>notFound(id);
+    }
+
+    /**
+     * Retrieve a property by its <code>id</code>.
+     *
+     * @param id
+     * @return
+     * @throws ItemNotFoundException  if no such property exists
+     */
+    public PropertyInfo getPropertyInfo(PropertyId id) throws ItemNotFoundException {
+        ItemInfo itemInfo = getItemInfo(id);
+
+        return itemInfo.denotesNode()
+            ? ItemInfoStore.<PropertyInfo>notFound(id)
+            : (PropertyInfo) itemInfo;
+    }
+
+    /**
+     * Retrieve all items of a batch
+     * @see RepositoryService#getItemInfos(org.apache.jackrabbit.spi.SessionInfo, NodeId)
+     *
+     * @param id
+     * @return
+     */
+    public Iterator<? extends ItemInfo> getBatch(ItemId id) {
+        Iterable<ItemInfo> batch = batches.get(id);
+
+        return batch == null
+            ? ItemInfoStore.<ItemInfo>empty()
+            : batch.iterator();
+    }
+
+    /**
+     * Retrieve the {@link ChildInfo}s of a node
+     *
+     * @param id
+     * @return
+     * @throws ItemNotFoundException  if no such node exists
+     */
+    public Iterator<ChildInfo> getChildInfos(NodeId id) throws ItemNotFoundException
{
+        Iterable<ChildInfo> childs = childInfos.get(id);
+
+        return childs == null
+            ? ItemInfoStore.<Iterator<ChildInfo>>notFound(id)
+            : childs.iterator();
+    }
+
+    /**
+     * Add an {@link ItemInfo}
+     *
+     * @param info
+     */
+    public void addItemInfo(ItemInfo info) {
+        infos.put(info.getId(), info);
+    }
+
+    /**
+     * Add a {@link ItemInfo} to a batch
+     *
+     * @param id
+     * @param info
+     */
+    public void updateBatch(ItemId id, ItemInfo info) {
+        if (!batches.containsKey(id)) {
+            batches.put(id, new ArrayList<ItemInfo>());
+        }
+
+        batches.get(id).add(info);
+    }
+
+    /**
+     * Add a {@link ChildInfo} to a node
+     * @param id
+     * @param info
+     */
+    public void updateChilds(ItemId id, ChildInfo info) {
+        if (!childInfos.containsKey(id)) {
+            childInfos.put(id, new ArrayList<ChildInfo>());
+        }
+
+        childInfos.get(id).add(info);
+    }
+
+    /**
+     * Set the {@link ChildInfo}s of a node
+     *
+     * @param id
+     * @param infos
+     */
+    public void setChildInfos(NodeId id, Iterator<ChildInfo> infos) {
+        childInfos.put(id, toList(infos));
+    }
+
+    // -----------------------------------------------------< private >---
+
+    private static <T> T notFound(ItemId itemId) throws ItemNotFoundException {
+        throw new ItemNotFoundException(itemId.toString());
+    }
+
+    private static <T> List<T> toList(Iterator<T> infos) {
+        List<T> list = new ArrayList<T>();
+
+        while (infos.hasNext()) {
+            list.add(infos.next());
+        }
+        return list;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Iterator<T> empty() {
+        return EmptyIterator.INSTANCE;
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ItemInfoStore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoBuilder.java?rev=906574&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoBuilder.java
(added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoBuilder.java
Thu Feb  4 17:28:05 2010
@@ -0,0 +1,662 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.spi.commons;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.FilterIterator;
+import org.apache.commons.collections.iterators.TransformIterator;
+import org.apache.jackrabbit.spi.ChildInfo;
+import org.apache.jackrabbit.spi.ItemInfo;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.NodeInfo;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.commons.identifier.IdFactoryImpl;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+
+/**
+ * Utility class providing a {@link NodeInfoBuilder} for building {@link NodeInfo}.
+ * Example usage:
+ * <pre>
+ * ItemInfoBuilder.nodeInfoBuilder()
+ *     .createNodeInfo("node1")
+ *         .createPropertyInfo("prop1", "value1").build()
+ *         .createPropertyInfo("prop2")
+ *             .addValue(1.2)
+ *             .addValue(2.3)
+ *         .build()
+ *     .build()
+ *     .createNodeInfo("node2")
+ *         .setPrimaryType(NameConstants.NT_BASE)
+ *         .addMixin(NameConstants.MIX_LOCKABLE)
+ *         .createPropertyInfo("prop3")
+ *             .setType(PropertyType.BINARY)
+ *         .build()
+ *     .build()
+ * .build();
+ * </pre>
+ */
+public final class ItemInfoBuilder {
+
+    private ItemInfoBuilder() {
+        super();
+    }
+
+    /**
+     * Same as <code>nodeInfoBuilder("", listener)</code>
+     * @param listener
+     * @return
+     */
+    public static NodeInfoBuilder nodeInfoBuilder(Listener listener) {
+        return nodeInfoBuilder("", listener);
+    }
+
+    /**
+     * Same as <code>nodeInfoBuilder("", null)</code>
+     * @return
+     */
+    public static NodeInfoBuilder nodeInfoBuilder() {
+        return nodeInfoBuilder("", null);
+    }
+
+    /**
+     * Same as <code>nodeInfoBuilder(name, null)</code>
+     * @param name
+     * @return
+     */
+    public static NodeInfoBuilder nodeInfoBuilder(String name) {
+        return nodeInfoBuilder(name, null);
+    }
+
+    /**
+     * Return a {@link NodeInfoBuilder} for a node with a given <code>name</code>.
+     * @param name  Name of the node
+     * @param listener  {@link Listener} to receive notifications about {@link NodeInfo}s,
+     *                  {@link PropertyInfo}s and {@link ChildInfo}s built.
+     * @return
+     */
+    public static NodeInfoBuilder nodeInfoBuilder(String name, Listener listener) {
+        return new NodeInfoBuilder(null, name, listener);
+    }
+
+    /**
+     * A listener for receiving notifications about items built by the builders in this class.
+     */
+    public interface Listener {
+
+        /**
+         * Notification that a new {@link NodeInfo} has been built.
+         * @param nodeInfo
+         */
+        void createNodeInfo(NodeInfo nodeInfo);
+
+        /**
+         * Notification that new {@link ChildInfo}s have been built.
+         * @param id  Id of the parent to which the <code>childInfos</code> belong
+         * @param childInfos
+         */
+        void createChildInfos(NodeId id, Iterator<ChildInfo> childInfos);
+
+        /**
+         * Notification that a new {@link PropertyInfo} has been bult.
+         * @param propertyInfo
+         */
+        void createPropertyInfo(PropertyInfo propertyInfo);
+    }
+
+    /**
+     * Builder for {@link NodeInfo}s. Use one of the {@link ItemInfoBuilder#nodeInfoBuilder()}
+     * methods to create instances of this class.
+     */
+    public static class NodeInfoBuilder {
+        private final NodeInfoBuilder parent;
+        private final String name;
+        private final Listener listener;
+
+        private int index = Path.INDEX_DEFAULT;
+        private Name primaryTypeName = NameConstants.NT_UNSTRUCTURED;
+        private final List<Name> mixins = new ArrayList<Name>();
+        private boolean includeChildInfos = true;
+
+        private boolean stale;
+        private final List<ItemInfo> itemInfos = new ArrayList<ItemInfo>();
+        private NodeInfo nodeInfo;
+
+        private NodeInfoBuilder(NodeInfoBuilder nodeInfoBuilder, String name, Listener listener)
{
+            super();
+            parent = nodeInfoBuilder;
+            this.name = name;
+            this.listener = listener;
+        }
+
+        /**
+         * Create a new child {@link PropertyInfo} with a given <code>name</code>
and a given
+         * <code>value</code> of type <code>String</code> on this
{@link NodeInfo}.
+         *
+         * @param name
+         * @param value
+         * @return  <code>this</code>
+         * @throws RepositoryException
+         */
+        public PropertyInfoBuilder createPropertyInfo(String name, String value) throws RepositoryException
{
+            PropertyInfoBuilder pBuilder = new PropertyInfoBuilder(this, name, listener);
+            pBuilder.addValue(value);
+            return  pBuilder;
+        }
+
+        /**
+         * Create a new child {@link PropertyInfo} with a given
+         * <code>name</code> on this {@link NodeInfo}.
+         *
+         * @param name
+         * @return  <code>this</code>
+         */
+        public PropertyInfoBuilder createPropertyInfo(String name) {
+            PropertyInfoBuilder pBuilder = new PropertyInfoBuilder(this, name, listener);
+            return  pBuilder;
+        }
+
+        /**
+         * Create a new child {@link NodeInfo} on this NodeInfo with a given <code>name</code>.
+         * @param name
+         * @return  <code>this</code>
+         */
+        public NodeInfoBuilder createNodeInfo(String name) {
+            return new NodeInfoBuilder(this, name, listener);
+        }
+
+        /**
+         * Set the index.
+         * @see NodeInfo#getIndex()
+         *
+         * @param index
+         * @return
+         */
+        public NodeInfoBuilder setIndex(int index) {
+            this.index = index;
+            return this;
+        }
+
+        /**
+         * Set the name of the primary type.
+         * @param name
+         * @see NodeInfo#getNodetype()
+         *
+         * @return
+         */
+        public NodeInfoBuilder setPrimaryType(Name name) {
+            primaryTypeName = name;
+            return this;
+        }
+
+        /**
+         * Add a mixin type
+         * @see NodeInfo#getMixins()
+         *
+         * @param name
+         * @return
+         */
+        public NodeInfoBuilder addMixin(Name name) {
+            mixins.add(name);
+            return this;
+        }
+
+        /**
+         * Whether the {@link ChildInfo}s should be included or not.
+         * @see NodeInfo#getChildInfos()
+         *
+         * @param include
+         * @return
+         */
+        public NodeInfoBuilder includeChildInfos(boolean include) {
+            includeChildInfos = include;
+            return this;
+        }
+
+        /**
+         * Build the {@link NodeInfo}. If a {@link Listener} is associated with this
+         * instance, then its {@link Listener#createChildInfos(NodeId, Iterator)} and
+         * its {@link Listener#createNodeInfo(NodeInfo)} methods are called.
+         *
+         * @return the parent builder of this builder
+         * @throws RepositoryException
+         * @throws IllegalStateException  if build has been called before
+         */
+        public NodeInfoBuilder build() throws RepositoryException {
+            if (stale) {
+                throw new IllegalStateException("Builder is stale");
+            }
+            else {
+                stale = true;
+                NodeId id = getId();
+
+                nodeInfo = new NodeInfoImpl(id.getPath(), id, index, primaryTypeName,
+                        mixins.toArray(new Name[mixins.size()]), EmptyIterator.INSTANCE,
+                        getPropertyIds(), includeChildInfos ? getChildInfos() : null);
+
+                if (listener != null) {
+                    listener.createNodeInfo(nodeInfo);
+                    listener.createChildInfos(id, getChildInfos());
+                }
+
+                if (parent == null) {
+                    return this;
+                }
+                else {
+                    parent.addNodeInfo(nodeInfo);
+                    return parent;
+                }
+            }
+        }
+
+        /**
+         * Returns the {@link NodeInfo} which has been built by this builder.
+         *
+         * @return
+         * @throws IllegalStateException  if {@link #build()} has not been called before.
+         */
+        public NodeInfo getNodeInfo() {
+            if (!stale) {
+                throw new IllegalStateException("NodeInfo not built yet");
+            }
+            return nodeInfo;
+        }
+
+        /**
+         * Add a {@link PropertyInfo}
+         *
+         * @param propertyInfo
+         * @return <code>this</code>
+         */
+        public NodeInfoBuilder addPropertyInfo(PropertyInfo propertyInfo) {
+            itemInfos.add(propertyInfo);
+            return this;
+        }
+
+        /**
+         * Add a {@link NodeInfo}
+         *
+         * @param nodeInfo
+         * @return <code>this</code>
+         */
+        public NodeInfoBuilder addNodeInfo(NodeInfo nodeInfo) {
+            itemInfos.add(nodeInfo);
+            return this;
+        }
+
+        private NodeId getId() throws RepositoryException {
+            return IdFactoryImpl.getInstance().createNodeId((String) null, getPath());
+        }
+
+        private Path getPath() throws RepositoryException {
+            if (parent == null) {
+                return PathFactoryImpl.getInstance().getRootPath();
+            }
+            else {
+                Name name = NameFactoryImpl.getInstance().create(Name.NS_DEFAULT_URI, this.name);
+                return PathFactoryImpl.getInstance().create(parent.getPath(), name, true);
+            }
+        }
+
+        private Iterator<ChildInfo> getChildInfos() {
+            return map(itemInfos.iterator(),
+                    new Function<ItemInfo, ChildInfo>(){
+                        public ChildInfo apply(ItemInfo info) {
+                            Name name = info.getPath().getNameElement().getName();
+                            return new ChildInfoImpl(name, null, Path.INDEX_DEFAULT);
+                        }
+                    });
+        }
+
+        private Iterator<PropertyId> getPropertyIds() {
+            return map(filter(itemInfos.iterator(),
+                    new Predicate<ItemInfo>(){
+                        public boolean evaluate(ItemInfo info) {
+                            return !info.denotesNode();
+                        }
+                    }),
+                    new Function<ItemInfo, PropertyId>(){
+                        public PropertyId apply(ItemInfo info) {
+                            return (PropertyId) info.getId();
+                        }
+                    });
+        }
+
+    }
+
+    /**
+     * Builder for {@link PropertyInfo}s. Use {@link NodeInfoBuilder#createPropertyInfo(String)}
+     * to create an instance of this class.
+     */
+    public static class PropertyInfoBuilder {
+        private final NodeInfoBuilder parent;
+        private final String name;
+        private final Listener listener;
+
+        private final List<QValue> values = new ArrayList<QValue>();
+        private int type = PropertyType.UNDEFINED;
+        private boolean isMultivalued = true;
+
+        private boolean stale;
+        private PropertyInfo propertyInfo;
+
+        private PropertyInfoBuilder(NodeInfoBuilder nodeInfoBuilder, String name, Listener
listener) {
+            super();
+            parent = nodeInfoBuilder;
+            this.name = name;
+            this.listener = listener;
+        }
+
+        /**
+         * Set the <code>{@link PropertyType type}</code> of this property
+         *
+         * @param type
+         * @return <code>this</code>
+         * @throws IllegalStateException  if a property of a different type has been added
before.
+         */
+        public PropertyInfoBuilder setType(int type) {
+            if (values.size() > 0 && type != values.get(0).getType()) {
+                throw new IllegalStateException("Type mismatch. " +
+                        "Required " + PropertyType.nameFromValue(values.get(0).getType())
+
+                        "found " + PropertyType.nameFromValue(type));
+            }
+
+            this.type = type;
+            return this;
+        }
+
+        /**
+         * Add a <code>value</code> to this property. Sets this property to single
valued if
+         * this is the first value. Otherwise sets this property to multi-valued.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(QValue value) {
+            int actualType = value.getType();
+            if (type != PropertyType.UNDEFINED && type != actualType) {
+                throw new IllegalStateException("Type mismatch. " +
+                        "Required " + PropertyType.nameFromValue(type) +
+                        " found " + PropertyType.nameFromValue(value.getType()));
+            }
+
+            values.add(value);
+            type = actualType;
+            isMultivalued = values.size() != 1;
+            return this;
+        }
+
+        /**
+         * Add a {@link PropertyType#STRING} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(String value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value, PropertyType.STRING));
+        }
+
+        /**
+         * Add a {@link PropertyType#DATE} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(Calendar  value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#DOUBLE} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(double value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#LONG} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(long value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#BOOLEAN} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(boolean value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#NAME} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(Name value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#PATH} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(Path value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#DECIMAL} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(BigDecimal  value) throws RepositoryException
{
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#URI} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(URI value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#BINARY} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(byte[] value) throws RepositoryException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#BINARY} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(InputStream value) throws RepositoryException,
IOException {
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Add a {@link PropertyType#BINARY} value to this property.
+         *
+         * @param value
+         * @return <code>this</code>
+         * @throws RepositoryException
+         * @throws IllegalStateException  if the type of the value does not match the type
of this property
+         */
+        public PropertyInfoBuilder addValue(File value) throws RepositoryException, IOException
{
+            return addValue(QValueFactoryImpl.getInstance().create(value));
+        }
+
+        /**
+         * Set this property to multi-values.
+         *
+         * @param on
+         * @return <code>this</code>
+         * @throws IllegalStateException if this property does not contain exactly on value
+         */
+        public PropertyInfoBuilder setMultivalued(boolean on) {
+            if (!on && values.size() != 1) {
+                throw new IllegalStateException(
+                        "Cannot create single valued property when multiple values are present");
+            }
+            isMultivalued = true;
+            return this;
+        }
+
+        /**
+         * Build the {@link PropertyInfo}. If a {@link Listener} is associated with this
+         * instance, then its {@link Listener#createPropertyInfo(PropertyInfo)} methods
+         * is called.
+         *
+         * @return the parent builder of this builder
+         * @throws RepositoryException
+         * @throws IllegalStateException  if build has been called before
+         * @throws IllegalStateException  if the type is not set
+         */
+        public NodeInfoBuilder build() throws RepositoryException {
+            if (stale) {
+                throw new IllegalStateException("Builder is stale");
+            }
+            else if (type == PropertyType.UNDEFINED) {
+                throw new IllegalStateException("Type not set");
+            }
+            else {
+                stale = true;
+
+                NodeId parentId = parent.getId();
+                Name propertyName = NameFactoryImpl.getInstance().create(Name.NS_DEFAULT_URI,
this.name);
+                Path path = PathFactoryImpl.getInstance().create(parentId.getPath(), propertyName,
true);
+                PropertyId id = IdFactoryImpl.getInstance().createPropertyId(parentId, propertyName);
+
+                propertyInfo = new PropertyInfoImpl(path, id, type, isMultivalued,
+                        values.toArray(new QValue[values.size()]));
+
+                if (listener != null) {
+                    listener.createPropertyInfo(propertyInfo);
+                }
+                return parent.addPropertyInfo(propertyInfo);
+            }
+        }
+
+        /**
+         * Returns the {@link PropertyInfo} which has been built by this builder.
+         *
+         * @return
+         * @throws IllegalStateException  if {@link #build()} has not been called before.
+         */
+        public PropertyInfo getPropertyInfo() {
+            if (!stale) {
+                throw new IllegalStateException("PropertyInfo not built yet");
+            }
+            return propertyInfo;
+        }
+
+    }
+
+    // -----------------------------------------------------< private >---
+
+    private interface Predicate<T> {
+        public boolean evaluate(T value);
+    }
+
+    private interface Function<S, T> {
+        public T apply(S s);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <S, T> Iterator<T> map(Iterator<S> source, final Function<S,
T> f) {
+        return new TransformIterator(source, new Transformer() {
+            public Object transform(Object o) {
+                return f.apply((S) o);
+            }
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Iterator<T> filter(Iterator<T> source, final Predicate<T>
predicate) {
+        return new FilterIterator(source, new org.apache.commons.collections.Predicate()
{
+            public boolean evaluate(Object object) {
+                return predicate.evaluate((T) object);
+            }
+        });
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message