[exo-jcr-commits] exo-jcr SVN: r906 - in jcr/trunk: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core and 14 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Mon Nov 30 05:36:39 EST 2009


Author: tolusha
Date: 2009-11-30 05:36:38 -0500 (Mon, 30 Nov 2009)
New Revision: 906

Added:
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/load/perf/TestGetNodesPerf.java
Modified:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/PlainChangesLogImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/ItemImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/ItemAutocreator.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/VersionHistoryImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/UpperLowerCaseQueryTest.java
   jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/BaseStandaloneTest.java
   jcr/trunk/exo.jcr.component.ftp/src/test/java/org/exoplatform/services/ftp/BaseStandaloneTest.java
Log:
EXOJCR-280: Merge OPT branch

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -28,48 +28,72 @@
 import javax.jcr.RepositoryException;
 
 /**
- * Created by The eXo Platform SAS.
+ * Created by The eXo Platform SAS.<br/>
  * 
- * @author <a href="mailto:geaz at users.sourceforge.net">Gennady Azarenkov</a>
- * @version $Id: ItemDataConsumer.java 11907 2008-03-13 15:36:21Z ksm $
+ *          Basic (Level 1) data flow inmemory operations<br/>
  * 
- *          Basic (Level 1) data flow inmemory operations
- * 
  *          Common Rule for Read : If there is some storage in this manager � try to get the data
  *          from here first, if not found � call super.someMethod
+ *          
+ * @author <a href="mailto:geaz at users.sourceforge.net">Gennady Azarenkov</a>
+ * @version $Id$
  */
 public interface ItemDataConsumer
 {
 
    /**
-    * @param parent
-    * @param name
-    * @return data by parent and name
+    * Find Item by parent (id) and name (with path index).
+    * 
+    * @param parent NodeData
+    * @param name QPathEntry
+    * @return ItemData, data by parent and name
     * @throws RepositoryException
     */
    ItemData getItemData(NodeData parent, QPathEntry name) throws RepositoryException;
 
    /**
-    * @param identifier
-    * @return data by identifier
+    * Find Item by identifier.
+    * 
+    * @param String identifier
+    * @return ItemData, data by identifier
     */
    ItemData getItemData(String identifier) throws RepositoryException;
 
    /**
-    * @param parentIdentifier
-    * @return children data
+    * Get child Nodes of the parent node.
+    * 
+    * @param parent NodeData
+    * @return List of children Nodes
     */
    List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException;
 
    /**
-    * @param parentIdentifier
-    * @return children data
+    * Get children nodes count of the parent node. 
+    * @param parent NodeData
+    * @return int, child nodes count
     */
+   int getChildNodesCount(NodeData parent) throws RepositoryException;
+   
+   /**
+    * Get child Properties of the parent node.
+    * 
+    * @param parent NodeData
+    * @return List of children Properties
+    */
    List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException;
 
-   List<PropertyData> listChildPropertiesData(final NodeData nodeData) throws RepositoryException;
+   /**
+    * List child Properties, returned list will contains Properties without actual Values.
+    *
+    * @param parent NodeData 
+    * @return List of PropertyData 
+    * @throws RepositoryException
+    */
+   List<PropertyData> listChildPropertiesData(final NodeData parent) throws RepositoryException;
 
    /**
+    * Get Referenced properties.
+    * 
     * @param identifier
     *          - referenceable id
     * @param skipVersionStorage

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/PlainChangesLogImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/PlainChangesLogImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/PlainChangesLogImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -199,7 +199,6 @@
       in.readFully(buf);
       sessionId = new String(buf, DEFAULT_ENCODING);
 
-      items = new ArrayList<ItemState>();
       int listSize = in.readInt();
       for (int i = 0; i < listSize; i++)
          add((ItemState)in.readObject());

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/ItemImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/ItemImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/ItemImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -23,6 +23,7 @@
 import org.exoplatform.services.jcr.access.AccessManager;
 import org.exoplatform.services.jcr.access.PermissionType;
 import org.exoplatform.services.jcr.core.ExtendedPropertyType;
+import org.exoplatform.services.jcr.core.nodetype.ItemDefinitionData;
 import org.exoplatform.services.jcr.core.nodetype.NodeTypeData;
 import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
 import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionData;
@@ -97,6 +98,11 @@
     */
    protected JCRPath location;
 
+   /**
+    * Item QPath.
+    */
+   protected QPath qpath;
+
    protected SessionDataManager dataManager;
 
    protected LocationFactory locationFactory;
@@ -104,32 +110,24 @@
    protected ValueFactoryImpl valueFactory;
 
    /**
-    * Hashcode.
-    */
-   protected final int itemHashCode;
-
-   /**
-    * ItemImpl constructor.
-    * 
-    * @param data
-    *          ItemData object
-    * @param session
-    *          Session object
-    * @throws RepositoryException
-    *           if any Exception is occurred
-    */
+   * ItemImpl constructor.
+   * 
+   * @param data
+   *          ItemData object
+   * @param session
+   *          Session object
+   * @throws RepositoryException
+   *           if any Exception is occurred
+   */
    ItemImpl(ItemData data, SessionImpl session) throws RepositoryException
    {
 
       this.session = session;
       this.data = data;
-      this.location = session.getLocationFactory().createJCRPath(data.getQPath());
 
       this.dataManager = session.getTransientNodesManager();
       this.locationFactory = session.getLocationFactory();
       this.valueFactory = session.getValueFactory();
-
-      itemHashCode = (session.getWorkspace().getName() + data.getIdentifier()).hashCode();
    }
 
    protected void invalidate()
@@ -165,7 +163,7 @@
    /**
     * {@inheritDoc}
     */
-   public String getPath()
+   public String getPath() throws RepositoryException
    {
       return getLocation().getAsString(false);
    }
@@ -173,7 +171,7 @@
    /**
     * {@inheritDoc}
     */
-   public String getName()
+   public String getName() throws RepositoryException
    {
       return getLocation().getName().getAsString();
    }
@@ -239,7 +237,7 @@
     */
    public int getDepth()
    {
-      return getLocation().getDepth();
+      return qpath.getDepth();
    }
 
    /**
@@ -749,8 +747,11 @@
     * 
     * @return item JCRPath
     */
-   public JCRPath getLocation()
+   public JCRPath getLocation() throws RepositoryException
    {
+      if (this.location == null)
+         this.location = session.getLocationFactory().createJCRPath(qpath);
+
       return this.location;
    }
 
@@ -764,8 +765,35 @@
       return data.getIdentifier().equals(Constants.ROOT_UUID);
    }
 
+   /**
+    * Loads data
+    *
+    * @param data
+    *          source item data
+    * @throws RepositoryException 
+    *          if errors occurs
+    */
    abstract void loadData(ItemData data) throws RepositoryException;
 
+   /**
+    * Loads data.
+    *
+    * @param data
+    *          source item data
+    * @param itemDefinitionData
+    *          source item definition data
+    * @throws RepositoryException
+    *          if errors occurs
+    */
+   abstract void loadData(ItemData data, ItemDefinitionData itemDefinitionData) throws RepositoryException;
+
+   /**
+    * Returns Item definition data.
+    *
+    * @return
+    */
+   abstract ItemDefinitionData getItemDefinitionData();
+
    public boolean hasPermission(String action) throws RepositoryException
    {
       NodeData ndata;
@@ -804,15 +832,6 @@
       return false;
    }
 
-   /**
-    * {@inheritDoc}
-    */
-   @Override
-   public int hashCode()
-   {
-      return itemHashCode;
-   }
-
    private ValueData valueData(Value value, int type) throws RepositoryException, ValueFormatException
    {
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -24,6 +24,7 @@
 import org.exoplatform.services.jcr.access.SystemIdentity;
 import org.exoplatform.services.jcr.core.ExtendedNode;
 import org.exoplatform.services.jcr.core.nodetype.ExtendedNodeTypeManager;
+import org.exoplatform.services.jcr.core.nodetype.ItemDefinitionData;
 import org.exoplatform.services.jcr.core.nodetype.NodeDefinitionData;
 import org.exoplatform.services.jcr.core.nodetype.NodeTypeData;
 import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
@@ -137,7 +138,7 @@
     * 
     * @param data
     *          Node data
-    * @param session
+    * @param session    
     *          Session
     * @throws RepositoryException
     *           if error occurs during the Node data loading
@@ -150,6 +151,25 @@
    }
 
    /**
+    * NodeImpl constructor.
+    * 
+    * @param data
+    *          Node data
+    * @param parent
+    *          parent node data is used for simple calculation item definition
+    * @param session    
+    *          Session
+    * @throws RepositoryException
+    *           if error occurs during the Node data loading
+    */
+   public NodeImpl(NodeData data, NodeData parent, SessionImpl session) throws RepositoryException
+   {
+      super(data, session);
+      this.sysLocFactory = session.getSystemLocationFactory();
+      loadData(data, parent);
+   }
+
+   /**
     * {@inheritDoc}
     */
    public void accept(ItemVisitor visitor) throws RepositoryException
@@ -585,7 +605,7 @@
       dataManager.update(state, false);
 
       NodeTypeDataManager ntmanager = session.getWorkspace().getNodeTypesHolder();
-      ItemAutocreator itemAutocreator = new ItemAutocreator(ntmanager, valueFactory, dataManager);
+      ItemAutocreator itemAutocreator = new ItemAutocreator(ntmanager, valueFactory, dataManager, false);
 
       PlainChangesLog changes =
          itemAutocreator.makeAutoCreatedItems(nodeData(), type.getName(), dataManager, session.getUserID());
@@ -956,7 +976,7 @@
             + itemPath.getAsString(false));
       return (NodeImpl)node;
    }
-   
+
    /**
     * {@inheritDoc}
     */
@@ -1234,7 +1254,7 @@
 
       checkValid();
 
-      return dataManager.getChildNodesData(nodeData()).size() > 0;
+      return dataManager.getChildNodesCount(nodeData()) > 0;
    }
 
    /**
@@ -1357,14 +1377,100 @@
          throw new RepositoryException("ACL is NULL " + nodeData.getQPath().getAsString());
 
       this.data = nodeData;
-      this.location = session.getLocationFactory().createJCRPath(getData().getQPath());
+      this.qpath = nodeData.getQPath();
+      this.location = null;
 
       initDefinition();
    }
 
    /**
+    * Loads data.
+    *
+    * @param data
+    *          source item data for load 
+    * @param parent
+    *          parent node data is used for simple calculation item definition
+    * @throws RepositoryException 
+    *          if error occurs
+    */
+   private void loadData(ItemData data, NodeData parent) throws RepositoryException, InvalidItemStateException,
+      ConstraintViolationException
+   {
+
+      if (data == null)
+         throw new InvalidItemStateException("Data is null for " + this.getPath()
+            + " Probably was deleted by another session and can not be loaded from container ");
+
+      if (!data.isNode())
+         throw new RepositoryException("Load data failed: Node expected");
+
+      NodeData nodeData = (NodeData)data;
+
+      // TODO do we need this three checks here?
+      if (nodeData.getPrimaryTypeName() == null)
+         throw new RepositoryException("Load data: NodeData has no primaryTypeName. Null value found. "
+            + (nodeData.getQPath() != null ? nodeData.getQPath().getAsString() : "[null path node]") + " " + nodeData);
+
+      if (nodeData.getMixinTypeNames() == null)
+         throw new RepositoryException("Load data: NodeData has no mixinTypeNames. Null value found. "
+            + (nodeData.getQPath() != null ? nodeData.getQPath().getAsString() : "[null path node]"));
+
+      if (nodeData.getACL() == null)
+         throw new RepositoryException("ACL is NULL " + nodeData.getQPath().getAsString());
+
+      this.data = nodeData;
+      this.qpath = nodeData.getQPath();
+      this.location = null;
+
+      initDefinition(parent);
+   }
+
+   /**
     * {@inheritDoc}
     */
+   @Override
+   public void loadData(ItemData data, ItemDefinitionData itemDefinitionData) throws RepositoryException,
+      InvalidItemStateException, ConstraintViolationException
+   {
+
+      if (data == null)
+         throw new InvalidItemStateException("Data is null for " + this.getPath()
+            + " Probably was deleted by another session and can not be loaded from container ");
+
+      if (!data.isNode())
+         throw new RepositoryException("Load data failed: Node expected");
+
+      NodeData nodeData = (NodeData)data;
+
+      // TODO do we need this three checks here?
+      if (nodeData.getPrimaryTypeName() == null)
+         throw new RepositoryException("Load data: NodeData has no primaryTypeName. Null value found. "
+            + (nodeData.getQPath() != null ? nodeData.getQPath().getAsString() : "[null path node]") + " " + nodeData);
+
+      if (nodeData.getMixinTypeNames() == null)
+         throw new RepositoryException("Load data: NodeData has no mixinTypeNames. Null value found. "
+            + (nodeData.getQPath() != null ? nodeData.getQPath().getAsString() : "[null path node]"));
+
+      if (nodeData.getACL() == null)
+         throw new RepositoryException("ACL is NULL " + nodeData.getQPath().getAsString());
+
+      this.data = nodeData;
+      this.location = null;
+      this.qpath = nodeData.getQPath();
+      this.definition = (NodeDefinitionData)itemDefinitionData;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ItemDefinitionData getItemDefinitionData()
+   {
+      return definition;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public Lock lock(boolean isDeep, boolean isSessionScoped) throws UnsupportedRepositoryOperationException,
       LockException, AccessDeniedException, RepositoryException
    {
@@ -2488,16 +2594,92 @@
 
    // ----------------------------- ExtendedNode -----------------------------
 
-   private int getNextChildOrderNum(List<NodeData> siblings)
+   private int getNextChildOrderNum() throws RepositoryException
    {
-      int max = -1;
+      //      int max = -1;
+      //      for (NodeData sibling : siblings)
+      //      {
+      //         int cur = sibling.getOrderNumber();
+      //         if (cur > max)
+      //            max = cur;
+      //      }
+      //      return ++max;
+
+      //return siblings.size();
+
+      return dataManager.getChildNodesCount(nodeData());
+   }
+
+   private int getNextChildIndex(InternalQName nameToAdd, NodeData parentNode) throws RepositoryException,
+      ItemExistsException
+   {
+
+      NodeDefinitionData def =
+         session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(nameToAdd, parentNode.getPrimaryTypeName(),
+            parentNode.getMixinTypeNames());
+
+      boolean allowSns = def.isAllowsSameNameSiblings();
+
+      int ind = 1;
+
+      NodeData sibling = (NodeData)dataManager.getItemData(parentNode, new QPathEntry(nameToAdd, ind));
+      while (sibling != null)
+      {
+         if (allowSns)
+         {
+            ind++;
+            sibling = (NodeData)dataManager.getItemData(parentNode, new QPathEntry(nameToAdd, ind));
+         }
+         else
+         {
+            throw new ItemExistsException("The node " + nameToAdd + " already exists in " + getPath()
+               + " and same name sibling is not allowed ");
+         }
+      };
+
+      return ind;
+
+      //      int ind = 0;
+      //      for (NodeData sibling : siblings)
+      //      {
+      //         if (sibling.getQPath().getName().equals(nameToAdd))
+      //         {
+      //            if (allowSns)
+      //               ind++;
+      //            else
+      //               throw new ItemExistsException("The node " + nameToAdd + " already exists in " + getPath()
+      //                  + " and same name sibling is not allowed ");
+      //         }
+      //      }
+      //      return ind + 1;
+
+   }
+
+   // old impl
+   @Deprecated
+   private int getNextChildIndex(InternalQName nameToAdd, List<NodeData> siblings, NodeData parentNode)
+      throws RepositoryException, ItemExistsException
+   {
+
+      int ind = 0;
       for (NodeData sibling : siblings)
       {
-         int cur = sibling.getOrderNumber();
-         if (cur > max)
-            max = cur;
+         if (sibling.getQPath().getName().equals(nameToAdd))
+         {
+            NodeDefinitionData def =
+               session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(nameToAdd,
+                  parentNode.getPrimaryTypeName(), parentNode.getMixinTypeNames());
+            if (LOG.isDebugEnabled())
+               LOG.debug("Calculate index for " + nameToAdd + " " + sibling.getQPath().getAsString());
+
+            if (def.isAllowsSameNameSiblings())
+               ind++;
+            else
+               throw new ItemExistsException("The node " + nameToAdd + " already exists in " + getPath()
+                  + " and same name sibling is not allowed ");
+         }
       }
-      return ++max;
+      return ind + 1;
    }
 
    private NodeImpl doAddNode(NodeImpl parentNode, InternalQName name, InternalQName primaryTypeName)
@@ -2510,9 +2692,9 @@
       InternalQName[] mixinTypeNames = new InternalQName[0];
       String identifier = IdGenerator.generate();
 
-      List<NodeData> siblings = dataManager.getChildNodesData(parentNode.nodeData());
-      int orderNum = parentNode.getNextChildOrderNum(siblings);
-      int index = parentNode.getNextChildIndex(name, siblings, parentNode.nodeData());
+      //List<NodeData> siblings = dataManager.getChildNodesData(parentNode.nodeData());
+      int orderNum = parentNode.getNextChildOrderNum();
+      int index = parentNode.getNextChildIndex(name, parentNode.nodeData());
 
       QPath path = QPath.makeChildPath(parentNode.getInternalPath(), name, index);
 
@@ -2528,7 +2710,7 @@
       NodeImpl node = (NodeImpl)dataManager.update(state, true);
 
       NodeTypeDataManager ntmanager = session.getWorkspace().getNodeTypesHolder();
-      ItemAutocreator itemAutocreator = new ItemAutocreator(ntmanager, valueFactory, dataManager);
+      ItemAutocreator itemAutocreator = new ItemAutocreator(ntmanager, valueFactory, dataManager, true);
 
       PlainChangesLog changes =
          itemAutocreator.makeAutoCreatedItems(node.nodeData(), primaryTypeName, dataManager, session.getUserID());
@@ -2546,35 +2728,8 @@
       session.getActionHandler().postAddNode(node);
 
       return node;
-
    }
 
-   private int getNextChildIndex(InternalQName nameToAdd, List<NodeData> siblings, NodeData parentNode)
-      throws RepositoryException, ItemExistsException
-   {
-
-      int ind = 0;
-      for (NodeData sibling : siblings)
-      {
-         if (sibling.getQPath().getName().equals(nameToAdd))
-         {
-            NodeDefinitionData def =
-               session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(nameToAdd,
-                  parentNode.getPrimaryTypeName(), parentNode.getMixinTypeNames());
-            if (LOG.isDebugEnabled())
-               LOG.debug("Calculate index for " + nameToAdd + " " + sibling.getQPath().getAsString());
-
-            if (def.isAllowsSameNameSiblings())
-               ind++;
-            else
-               throw new ItemExistsException("The node " + nameToAdd + " already exists in " + getPath()
-                  + " and same name sibling is not allowed ");
-         }
-      }
-      return ind + 1;
-
-   }
-
    private int getOrderNumber()
    {
       return nodeData().getOrderNumber();
@@ -2636,6 +2791,33 @@
          throw new ConstraintViolationException("Node definition not found for " + getPath());
    }
 
+   /**
+    * Init NodeDefinition.
+    * 
+    * @throws RepositoryException
+    *           if error occurs
+    * @throws ConstraintViolationException
+    *           if definition not found
+    */
+   private void initDefinition(NodeData parent) throws RepositoryException, ConstraintViolationException
+   {
+
+      if (this.isRoot())
+      { // root - no parent
+         this.definition =
+            new NodeDefinitionData(null, null, true, true, OnParentVersionAction.ABORT, true,
+               new InternalQName[]{Constants.NT_BASE}, null, false);
+         return;
+      }
+
+      this.definition =
+         session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(getInternalName(),
+            parent.getPrimaryTypeName(), parent.getMixinTypeNames());
+
+      if (definition == null)
+         throw new ConstraintViolationException("Node definition not found for " + getPath());
+   }
+
    private void removeMergeFailed(Version version, PlainChangesLog changesLog) throws RepositoryException
    {
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -19,6 +19,7 @@
 package org.exoplatform.services.jcr.impl.core;
 
 import org.exoplatform.services.jcr.core.nodetype.ExtendedNodeTypeManager;
+import org.exoplatform.services.jcr.core.nodetype.ItemDefinitionData;
 import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionData;
 import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionDatas;
 import org.exoplatform.services.jcr.datamodel.InternalQName;
@@ -93,14 +94,42 @@
       this.propertyData = (TransientPropertyData)data;
       this.type = propertyData.getType();
 
-      this.location = session.getLocationFactory().createJCRPath(getData().getQPath());
-      this.propertyDef = null;
+      this.qpath = data.getQPath();
+      this.location = null;
+
       initDefinitions(this.propertyData.isMultiValued());
    }
 
    /**
     * {@inheritDoc}
     */
+   void loadData(ItemData data, ItemDefinitionData itemDefinitionData) throws RepositoryException,
+      ConstraintViolationException
+   {
+
+      if (!(data instanceof TransientPropertyData))
+         throw new RepositoryException("Load data: TransientPropertyData is expected, but have " + data);
+
+      this.data = data;
+      this.propertyData = (TransientPropertyData)data;
+      this.type = propertyData.getType();
+
+      this.location = null;
+      this.qpath = data.getQPath();
+      this.propertyDef = (PropertyDefinitionData)itemDefinitionData;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ItemDefinitionData getItemDefinitionData()
+   {
+      return propertyDef;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public Value getValue() throws ValueFormatException, RepositoryException
    {
 
@@ -526,9 +555,10 @@
     */
    public String dump()
    {
-      String vals = "Property " + getPath() + " values: ";
+      String vals = "Property ";
       try
       {
+         vals = getPath() + " values: ";
          for (int i = 0; i < getValueArray().length; i++)
          {
             vals += new String(((BaseValue)getValueArray()[i]).getInternalData().getAsByteArray()) + ";";
@@ -564,19 +594,4 @@
       return false;
    }
 
-   /**
-    * {@inheritDoc}
-    */
-   @Override
-   public int hashCode()
-   {
-      try
-      {
-         return getLocation().getAsString(false).hashCode();
-      }
-      catch (Exception e)
-      {
-         return super.hashCode();
-      }
-   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -466,18 +466,12 @@
    public boolean isNew(String identifier)
    {
 
-      List<ItemState> states = changesLog.getItemStates(identifier);
-      ItemState lastState = states.size() > 0 ? states.get(states.size() - 1) : null;
+      ItemState lastState = changesLog.getItemState(identifier);
 
       if (lastState == null || lastState.isDeleted())
          return false;
 
-      for (ItemState state : states)
-      {
-         if (state.isAdded())
-            return true;
-      }
-      return false;
+      return changesLog.getItemState(identifier, ItemState.ADDED) != null;
    }
 
    /**
@@ -534,7 +528,8 @@
          // [PN] 21.12.07 use item data
          NodeData parent = (NodeData)getItemData(data.getParentIdentifier());
          // skip not permitted
-         if (accessManager.hasPermission(parent.getACL(), PermissionType.READ, session.getUserState().getIdentity()))
+         if (accessManager.hasPermission(parent.getACL(), new String[]{PermissionType.READ}, session.getUserState()
+            .getIdentity()))
          {
             PropertyImpl item = null;
             ItemState state = changesLog.getItemState(identifier);
@@ -583,11 +578,12 @@
 
          for (NodeData data : nodeDatas)
          {
-            NodeImpl item = itemFactory.createNode(data);
+            NodeImpl item = itemFactory.createNode(data, parent);
 
             session.getActionHandler().postRead(item);
 
-            if (accessManager.hasPermission(data.getACL(), PermissionType.READ, session.getUserState().getIdentity()))
+            if (accessManager.hasPermission(data.getACL(), new String[]{PermissionType.READ}, session.getUserState()
+               .getIdentity()))
             {
                if (pool)
                   item = (NodeImpl)itemsPool.get(item);
@@ -633,7 +629,8 @@
          {
             ItemImpl item = itemFactory.createItem(data);
             session.getActionHandler().postRead(item);
-            if (accessManager.hasPermission(parent.getACL(), PermissionType.READ, session.getUserState().getIdentity()))
+            if (accessManager.hasPermission(parent.getACL(), new String[]{PermissionType.READ}, session.getUserState()
+               .getIdentity()))
             {
                if (pool)
                   item = itemsPool.get(item);
@@ -674,6 +671,22 @@
    /**
     * {@inheritDoc}
     */
+   public int getChildNodesCount(NodeData parent) throws RepositoryException
+   {
+      int childsCount =
+         changesLog.getChildNodesCount(parent.getIdentifier()) + transactionableManager.getChildNodesCount(parent);
+      if (childsCount < 0)
+      {
+         throw new InvalidItemStateException("Node's child nodes were changed in another Session "
+            + parent.getQPath().getAsString());
+      }
+
+      return childsCount;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException
    {
       long start = 0;
@@ -1264,8 +1277,8 @@
          // Remove propery or node
          if (changedItem.isDeleted())
          {
-            if (!accessManager.hasPermission(parent.getACL(), PermissionType.REMOVE, session.getUserState()
-               .getIdentity()))
+            if (!accessManager.hasPermission(parent.getACL(), new String[]{PermissionType.REMOVE}, session
+               .getUserState().getIdentity()))
                throw new AccessDeniedException("Access denied: REMOVE "
                   + changedItem.getData().getQPath().getAsString() + " for: " + session.getUserID() + " item owner "
                   + parent.getACL().getOwner());
@@ -1275,8 +1288,8 @@
             // add node
             if (changedItem.isAdded())
             {
-               if (!accessManager.hasPermission(parent.getACL(), PermissionType.ADD_NODE, session.getUserState()
-                  .getIdentity()))
+               if (!accessManager.hasPermission(parent.getACL(), new String[]{PermissionType.ADD_NODE}, session
+                  .getUserState().getIdentity()))
                {
                   throw new AccessDeniedException("Access denied: ADD_NODE "
                      + changedItem.getData().getQPath().getAsString() + " for: " + session.getUserID() + " item owner "
@@ -1287,8 +1300,8 @@
          else if (changedItem.isAdded() || changedItem.isUpdated())
          {
             // add or update property
-            if (!accessManager.hasPermission(parent.getACL(), PermissionType.SET_PROPERTY, session.getUserState()
-               .getIdentity()))
+            if (!accessManager.hasPermission(parent.getACL(), new String[]{PermissionType.SET_PROPERTY}, session
+               .getUserState().getIdentity()))
                throw new AccessDeniedException("Access denied: SET_PROPERTY "
                   + changedItem.getData().getQPath().getAsString() + " for: " + session.getUserID() + " item owner "
                   + parent.getACL().getOwner());
@@ -1647,10 +1660,6 @@
             {
                ret.add(childNode);
 
-               if (log.isDebugEnabled())
-                  log.debug("Traverse transient (N) " + childNode.getData().getQPath().getAsString() + " "
-                     + ItemState.nameFromValue(childNode.getState()));
-
                if (deep)
                   traverseTransientDescendants(childNode.getData(), deep, action, ret);
             }
@@ -1661,17 +1670,14 @@
             for (ItemState childProp : childProps)
             {
                ret.add(childProp);
-
-               if (log.isDebugEnabled())
-                  log.debug("Traverse transient  (P) " + childProp.getData().getQPath().getAsString());
             }
          }
       }
    }
 
    /**
-    * Pool for touched items.
-    */
+   * Pool for touched items.
+   */
    protected final class ItemReferencePool
    {
 
@@ -1723,7 +1729,7 @@
          }
          else
          {
-            item.loadData(newItem.getData());
+            item.loadData(newItem.getData(), newItem.getItemDefinitionData());
             return item;
          }
       }
@@ -1833,12 +1839,19 @@
       String dump()
       {
          String str = "Items Pool: \n";
-         for (ItemImpl item : items.values())
+         try
          {
-            str +=
-               (item.isNode() ? "Node\t\t" : "Property\t") + "\t" + item.isValid() + "\t" + item.isNew() + "\t"
-                  + item.getInternalIdentifier() + "\t" + item.getPath() + "\n";
+            for (ItemImpl item : items.values())
+            {
+               str +=
+                  (item.isNode() ? "Node\t\t" : "Property\t") + "\t" + item.isValid() + "\t" + item.isNew() + "\t"
+                     + item.getInternalIdentifier() + "\t" + item.getPath() + "\n";
+            }
          }
+         catch (Exception e)
+         {
+            e.printStackTrace();
+         }
 
          return str;
       }
@@ -1874,10 +1887,26 @@
             return node;
       }
 
+      private NodeImpl createNode(NodeData data, NodeData parent) throws RepositoryException
+      {
+         NodeImpl node = new NodeImpl(data, parent, session);
+         if (data.getPrimaryTypeName().equals(Constants.NT_VERSION))
+         {
+            return new VersionImpl(data, session);
+         }
+         else if (data.getPrimaryTypeName().equals(Constants.NT_VERSIONHISTORY))
+         {
+            return new VersionHistoryImpl(data, session);
+         }
+         else
+            return node;
+      }
+
       private PropertyImpl createProperty(ItemData data) throws RepositoryException
       {
          return new PropertyImpl(data, session);
       }
+
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/ItemAutocreator.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/ItemAutocreator.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/ItemAutocreator.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -69,16 +69,19 @@
 
    private final ValueFactory valueFactory;
 
+   private final boolean avoidCheckExistedChildItems;
+
    /**
     * @param nodeTypeDataManager
     */
    public ItemAutocreator(NodeTypeDataManager nodeTypeDataManager, ValueFactory valueFactory,
-      ItemDataConsumer dataConsumer)
+      ItemDataConsumer dataConsumer, boolean avoidCheckExistedChildItems)
    {
       super();
       this.nodeTypeDataManager = nodeTypeDataManager;
       this.valueFactory = valueFactory;
       this.dataConsumer = dataConsumer;
+      this.avoidCheckExistedChildItems = avoidCheckExistedChildItems;
    }
 
    public PlainChangesLog makeAutoCreatedItems(final NodeData parent, final InternalQName nodeTypeName,
@@ -113,7 +116,9 @@
       {
          if (ndef.isAutoCreated())
          {
-            final ItemData pdata = targetDataManager.getItemData(parent, new QPathEntry(ndef.getName(), 0));
+            final ItemData pdata =
+               avoidCheckExistedChildItems ? null : targetDataManager.getItemData(parent, new QPathEntry(
+                  ndef.getName(), 0));
             if (pdata == null && !addedNodes.contains(ndef.getName()) || pdata != null && !pdata.isNode())
             {
 
@@ -156,7 +161,9 @@
          if (pdef.isAutoCreated())
          {
 
-            final ItemData pdata = targetDataManager.getItemData(parent, new QPathEntry(pdef.getName(), 0));
+            final ItemData pdata =
+               avoidCheckExistedChildItems ? null : targetDataManager.getItemData(parent, new QPathEntry(
+                  pdef.getName(), 0));
             if (pdata == null && !addedProperties.contains(pdef.getName()) || pdata != null && pdata.isNode())
             {
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -638,7 +638,7 @@
       final boolean recipientsMixVersionable = isNodeType(Constants.MIX_VERSIONABLE, recipienAllNodeTypeNames);
       final boolean ancestorIsMixVersionable = isNodeType(Constants.MIX_VERSIONABLE, ancestorAllNodeTypeNames);
 
-      ItemAutocreator itemAutocreator = new ItemAutocreator(this, valueFactory, dataManager);
+      ItemAutocreator itemAutocreator = new ItemAutocreator(this, valueFactory, dataManager, false);
       if (recipientsMixVersionable && !ancestorIsMixVersionable)
       {
 
@@ -838,7 +838,8 @@
 
       volatileNodeTypeDataManager.registerVolatileNodeTypes(volatileNodeTypes);
 
-      ItemAutocreator itemAutocreator = new ItemAutocreator(volatileNodeTypeDataManager, valueFactory, dataManager);
+      ItemAutocreator itemAutocreator =
+         new ItemAutocreator(volatileNodeTypeDataManager, valueFactory, dataManager, false);
 
       final Set<String> nodes = this.indexSearcherHolder.getNodesByNodeType(recipientDefinition.getName());
       // check add mix:versionable super

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -16,7 +16,6 @@
  */
 package org.exoplatform.services.jcr.impl.core.query;
 
-
 import java.text.NumberFormat;
 
 import javax.jcr.ItemExistsException;
@@ -56,298 +55,302 @@
 /**
  * Provides the default implementation for a JCR query.
  */
-public class QueryImpl extends AbstractQueryImpl {
+public class QueryImpl extends AbstractQueryImpl
+{
 
-    /**
-     * The logger instance for this class
-     */
-    private static final Logger log = LoggerFactory.getLogger(QueryImpl.class);
+   /**
+    * The logger instance for this class
+    */
+   private static final Logger log = LoggerFactory.getLogger(QueryImpl.class);
 
-    /**
-     * A string constant representing the JCR-SQL2 query language.
-     *
-     * @since JCR 2.0
-     * TODO: REMOVE WHEN JSR 283 IS FINAL!!
-     */
-    public static final String JCR_SQL2 = "JCR-SQL2";
+   /**
+    * A string constant representing the JCR-SQL2 query language.
+    *
+    * @since JCR 2.0
+    * TODO: REMOVE WHEN JSR 283 IS FINAL!!
+    */
+   public static final String JCR_SQL2 = "JCR-SQL2";
 
-    /**
-     * A string constant representing the JCR-JQOM query language.
-     *
-     * @since JCR 2.0
-     * TODO: REMOVE WHEN JSR 283 IS FINAL!!
-     */
-    public static final String JCR_JQOM = "JCR-JQOM";
+   /**
+    * A string constant representing the JCR-JQOM query language.
+    *
+    * @since JCR 2.0
+    * TODO: REMOVE WHEN JSR 283 IS FINAL!!
+    */
+   public static final String JCR_JQOM = "JCR-JQOM";
 
-    /**
-     * The session of the user executing this query
-     */
-    protected SessionImpl session;
+   /**
+    * The session of the user executing this query
+    */
+   protected SessionImpl session;
 
-    /**
-     * The query statement
-     */
-    protected String statement;
+   /**
+    * The query statement
+    */
+   protected String statement;
 
-    /**
-     * The syntax of the query statement
-     */
-    protected String language;
+   /**
+    * The syntax of the query statement
+    */
+   protected String language;
 
-    /**
-     * The actual query implementation that can be executed
-     */
-    protected ExecutableQuery query;
+   /**
+    * The actual query implementation that can be executed
+    */
+   protected ExecutableQuery query;
 
-    /**
-     * The node where this query is persisted. Only set when this is a persisted
-     * query.
-     */
-    protected Node node;
+   /**
+    * The node where this query is persisted. Only set when this is a persisted
+    * query.
+    */
+   protected Node node;
 
-    /**
-     * The query handler for this query.
-     */
-    protected QueryHandler handler;
+   /**
+    * The query handler for this query.
+    */
+   protected QueryHandler handler;
 
-    /**
-     * Flag indicating whether this query is initialized.
-     */
-    private boolean initialized = false;
+   /**
+    * Flag indicating whether this query is initialized.
+    */
+   private boolean initialized = false;
 
-    /**
-     * The maximum result size
-     */
-    private long limit;
+   /**
+    * The maximum result size
+    */
+   private long limit;
 
-    /**
-     * The offset in the total result set
-     */
-    private long offset;
+   /**
+    * The offset in the total result set
+    */
+   private long offset;
 
-    /**
-     * @inheritDoc
-     */
-    public void init(SessionImpl session,
-                     SessionDataManager itemMgr,
-                     QueryHandler handler,
-                     String statement,
-                     String language) throws InvalidQueryException {
-        checkNotInitialized();
-        this.session = session;
-        this.statement = statement;
-        this.language = language;
-        this.handler = handler;
-        this.query = handler.createExecutableQuery(session, itemMgr, statement, language);
-        setInitialized();
-    }
+   /**
+    * @inheritDoc
+    */
+   public void init(SessionImpl session, SessionDataManager itemMgr, QueryHandler handler, String statement,
+      String language) throws InvalidQueryException
+   {
+      checkNotInitialized();
+      this.session = session;
+      this.statement = statement;
+      this.language = language;
+      this.handler = handler;
+      this.query = handler.createExecutableQuery(session, itemMgr, statement, language);
+      setInitialized();
+   }
 
-    /**
-     * @inheritDoc
-     */
-    public void init(SessionImpl session,
-                     SessionDataManager itemMgr,
-                     QueryHandler handler,
-                     Node node)
-            throws InvalidQueryException, RepositoryException {
-        checkNotInitialized();
-        this.session = session;
-        this.node = node;
-        this.handler = handler;
+   /**
+    * @inheritDoc
+    */
+   public void init(SessionImpl session, SessionDataManager itemMgr, QueryHandler handler, Node node)
+      throws InvalidQueryException, RepositoryException
+   {
+      checkNotInitialized();
+      this.session = session;
+      this.node = node;
+      this.handler = handler;
 
-        if (!((ExtendedNode)node).isNodeType(Constants.NT_QUERY)){
-            throw new InvalidQueryException("node is not of type nt:query");
-        }
-        statement = node.getProperty("jcr:statement").getString();
-        language = node.getProperty("jcr:language").getString();
-        query = handler.createExecutableQuery(session, itemMgr, statement, language);
-        setInitialized();
-    }
+      if (!((ExtendedNode)node).isNodeType(Constants.NT_QUERY))
+      {
+         throw new InvalidQueryException("node is not of type nt:query");
+      }
+      statement = node.getProperty("jcr:statement").getString();
+      language = node.getProperty("jcr:language").getString();
+      query = handler.createExecutableQuery(session, itemMgr, statement, language);
+      setInitialized();
+   }
 
-//    /**
-//     * @inheritDoc
-//     * <p/>
-//     * Throws an {@link UnsupportedOperationException}.
-//     */
-//    public void init(SessionImpl session,
-//                     Sess itemMgr,
-//                     QueryHandler handler,
-//                     QueryObjectModelTree qomTree,
-//                     String language)
-//            throws InvalidQueryException, RepositoryException {
-//        throw new UnsupportedOperationException("not a prepared query");
-//    }
+   //    /**
+   //     * @inheritDoc
+   //     * <p/>
+   //     * Throws an {@link UnsupportedOperationException}.
+   //     */
+   //    public void init(SessionImpl session,
+   //                     Sess itemMgr,
+   //                     QueryHandler handler,
+   //                     QueryObjectModelTree qomTree,
+   //                     String language)
+   //            throws InvalidQueryException, RepositoryException {
+   //        throw new UnsupportedOperationException("not a prepared query");
+   //    }
 
-    /**
-     * This method simply forwards the <code>execute</code> call to the
-     * {@link ExecutableQuery} object returned by
-     * {@link QueryHandler#createExecutableQuery}.
-     * {@inheritDoc}
-     */
-    public QueryResult execute() throws RepositoryException {
-        checkInitialized();
-        long time = System.currentTimeMillis();
-        QueryResult result = query.execute(offset, limit);
-        if (log.isDebugEnabled()) {
-            time = System.currentTimeMillis() - time;
-            NumberFormat format = NumberFormat.getNumberInstance();
-            format.setMinimumFractionDigits(2);
-            format.setMaximumFractionDigits(2);
-            String seconds = format.format((double) time / 1000);
-            log.debug("executed in " + seconds + " s. (" + statement + ")");
-        }
-        return result;
-    }
+   /**
+    * This method simply forwards the <code>execute</code> call to the
+    * {@link ExecutableQuery} object returned by
+    * {@link QueryHandler#createExecutableQuery}.
+    * {@inheritDoc}
+    */
+   public QueryResult execute() throws RepositoryException
+   {
+      checkInitialized();
+      long time = System.currentTimeMillis();
+      QueryResult result = query.execute(offset, limit);
+      if (log.isDebugEnabled())
+      {
+         time = System.currentTimeMillis() - time;
+         NumberFormat format = NumberFormat.getNumberInstance();
+         format.setMinimumFractionDigits(2);
+         format.setMaximumFractionDigits(2);
+         String seconds = format.format((double)time / 1000);
+         log.debug("executed in " + seconds + " s. (" + statement + ")");
+      }
+      return result;
+   }
 
-    /**
-     * {@inheritDoc}
-     */
-    public String getStatement() {
-        checkInitialized();
-        return statement;
-    }
+   /**
+    * {@inheritDoc}
+    */
+   public String getStatement()
+   {
+      checkInitialized();
+      return statement;
+   }
 
-    /**
-     * {@inheritDoc}
-     */
-    public String getLanguage() {
-        checkInitialized();
-        return language;
-    }
+   /**
+    * {@inheritDoc}
+    */
+   public String getLanguage()
+   {
+      checkInitialized();
+      return language;
+   }
 
-    /**
-     * {@inheritDoc}
-     */
-    public String getStoredQueryPath()
-            throws ItemNotFoundException, RepositoryException {
-        checkInitialized();
-        if (node == null) {
-            throw new ItemNotFoundException("not a persistent query");
-        }
-        return node.getPath();
-    }
+   /**
+    * {@inheritDoc}
+    */
+   public String getStoredQueryPath() throws ItemNotFoundException, RepositoryException
+   {
+      checkInitialized();
+      if (node == null)
+      {
+         throw new ItemNotFoundException("not a persistent query");
+      }
+      return node.getPath();
+   }
 
-    /**
-     * {@inheritDoc}
-     */
-    public Node storeAsNode(String absPath)
-            throws ItemExistsException,
-            PathNotFoundException,
-            VersionException,
-            ConstraintViolationException,
-            LockException,
-            UnsupportedRepositoryOperationException,
-            RepositoryException {
+   /**
+    * {@inheritDoc}
+    */
+   public Node storeAsNode(String absPath) throws ItemExistsException, PathNotFoundException, VersionException,
+      ConstraintViolationException, LockException, UnsupportedRepositoryOperationException, RepositoryException
+   {
 
-       checkInitialized();
-       JCRPath path = session.getLocationFactory().parseAbsPath(absPath);
-       QPath qpath = path.getInternalPath();
-       NodeImpl parent = (NodeImpl)session.getTransientNodesManager().getItem(qpath.makeParentPath(), false);
-       if (parent == null)
-          throw new PathNotFoundException("Parent not found for " + path.getAsString(false));
+      checkInitialized();
+      JCRPath path = session.getLocationFactory().parseAbsPath(absPath);
+      QPath qpath = path.getInternalPath();
+      NodeImpl parent = (NodeImpl)session.getTransientNodesManager().getItem(qpath.makeParentPath(), false);
+      if (parent == null)
+         throw new PathNotFoundException("Parent not found for " + path.getAsString(false));
 
-       // validate as on parent child node
-       parent.validateChildNode(qpath.getName(), Constants.NT_QUERY);
+      // validate as on parent child node
+      parent.validateChildNode(qpath.getName(), Constants.NT_QUERY);
 
-       NodeData queryData =
-          TransientNodeData.createNodeData((NodeData)parent.getData(), qpath.getName(), Constants.NT_QUERY);
-       NodeImpl queryNode =
-          (NodeImpl)session.getTransientNodesManager().update(ItemState.createAddedState(queryData), false);
+      NodeData queryData =
+         TransientNodeData.createNodeData((NodeData)parent.getData(), qpath.getName(), Constants.NT_QUERY);
+      NodeImpl queryNode =
+         (NodeImpl)session.getTransientNodesManager().update(ItemState.createAddedState(queryData), false);
 
-       NodeTypeDataManager ntmanager = session.getWorkspace().getNodeTypesHolder();
+      NodeTypeDataManager ntmanager = session.getWorkspace().getNodeTypesHolder();
 
-       ItemAutocreator itemAutocreator = new ItemAutocreator(ntmanager, session.getValueFactory(),session.getTransientNodesManager());
+      ItemAutocreator itemAutocreator =
+         new ItemAutocreator(ntmanager, session.getValueFactory(), session.getTransientNodesManager(), false);
 
-       PlainChangesLog changes =
-          itemAutocreator.makeAutoCreatedItems((NodeData)queryNode.getData(),  Constants.NT_QUERY, session
-             .getTransientNodesManager(), session.getUserID());
+      PlainChangesLog changes =
+         itemAutocreator.makeAutoCreatedItems((NodeData)queryNode.getData(), Constants.NT_QUERY, session
+            .getTransientNodesManager(), session.getUserID());
 
-       for (ItemState autoCreatedState : changes.getAllStates())
-       {
-          session.getTransientNodesManager().update(autoCreatedState, false);
-       }
-       // queryNode.addAutoCreatedItems(Constants.NT_QUERY);
-       // set properties
-       TransientValueData value = new TransientValueData(language);
-       TransientPropertyData jcrLanguage =
-          TransientPropertyData.createPropertyData(queryData, Constants.JCR_LANGUAGE, PropertyType.STRING, false, value);
-       session.getTransientNodesManager().update(ItemState.createAddedState(jcrLanguage), false);
+      for (ItemState autoCreatedState : changes.getAllStates())
+      {
+         session.getTransientNodesManager().update(autoCreatedState, false);
+      }
+      // queryNode.addAutoCreatedItems(Constants.NT_QUERY);
+      // set properties
+      TransientValueData value = new TransientValueData(language);
+      TransientPropertyData jcrLanguage =
+         TransientPropertyData.createPropertyData(queryData, Constants.JCR_LANGUAGE, PropertyType.STRING, false, value);
+      session.getTransientNodesManager().update(ItemState.createAddedState(jcrLanguage), false);
 
-       value = new TransientValueData(statement);
-       TransientPropertyData jcrStatement =
-          TransientPropertyData
-             .createPropertyData(queryData, Constants.JCR_STATEMENT, PropertyType.STRING, false, value);
-       session.getTransientNodesManager().update(ItemState.createAddedState(jcrStatement), false);
+      value = new TransientValueData(statement);
+      TransientPropertyData jcrStatement =
+         TransientPropertyData
+            .createPropertyData(queryData, Constants.JCR_STATEMENT, PropertyType.STRING, false, value);
+      session.getTransientNodesManager().update(ItemState.createAddedState(jcrStatement), false);
 
-       // NOTE: for save stored node need save() on parent or on session (6.6.10
-       // The Query Object)
-       node = queryNode;
-       return node;
-    }
+      // NOTE: for save stored node need save() on parent or on session (6.6.10
+      // The Query Object)
+      node = queryNode;
+      return node;
+   }
 
-    /**
-     * Binds the given <code>value</code> to the variable named
-     * <code>varName</code>.
-     *
-     * @param varName name of variable in query
-     * @param value   value to bind
-     * @throws IllegalArgumentException      if <code>varName</code> is not a
-     *                                       valid variable in this query.
-     * @throws javax.jcr.RepositoryException if an error occurs.
-     */
-    public void bindValue(String varName, Value value)
-            throws IllegalArgumentException, RepositoryException {
-        checkInitialized();
-        query.bindValue(session.getLocationFactory().parseJCRName(varName).getInternalName(), value);
-    }
+   /**
+    * Binds the given <code>value</code> to the variable named
+    * <code>varName</code>.
+    *
+    * @param varName name of variable in query
+    * @param value   value to bind
+    * @throws IllegalArgumentException      if <code>varName</code> is not a
+    *                                       valid variable in this query.
+    * @throws javax.jcr.RepositoryException if an error occurs.
+    */
+   public void bindValue(String varName, Value value) throws IllegalArgumentException, RepositoryException
+   {
+      checkInitialized();
+      query.bindValue(session.getLocationFactory().parseJCRName(varName).getInternalName(), value);
+   }
 
-    /**
-     * Sets the maximum size of the result set.
-     *
-     * @param limit new maximum size of the result set
-     */
-    public void setLimit(long limit) {
-        this.limit = limit;
-    }
+   /**
+    * Sets the maximum size of the result set.
+    *
+    * @param limit new maximum size of the result set
+    */
+   public void setLimit(long limit)
+   {
+      this.limit = limit;
+   }
 
-    /**
-     * Sets the start offset of the result set.
-     *
-     * @param offset new start offset of the result set
-     */
-    public void setOffset(long offset) {
-        this.offset = offset;
-    }
+   /**
+    * Sets the start offset of the result set.
+    *
+    * @param offset new start offset of the result set
+    */
+   public void setOffset(long offset)
+   {
+      this.offset = offset;
+   }
 
-    //-----------------------------< internal >---------------------------------
+   //-----------------------------< internal >---------------------------------
 
-    /**
-     * Sets the initialized flag.
-     */
-    protected void setInitialized() {
-        initialized = true;
-    }
+   /**
+    * Sets the initialized flag.
+    */
+   protected void setInitialized()
+   {
+      initialized = true;
+   }
 
-    /**
-     * Checks if this query is not yet initialized and throws an
-     * <code>IllegalStateException</code> if it is already initialized.
-     */
-    protected void checkNotInitialized() {
-        if (initialized) {
-            throw new IllegalStateException("already initialized");
-        }
-    }
+   /**
+    * Checks if this query is not yet initialized and throws an
+    * <code>IllegalStateException</code> if it is already initialized.
+    */
+   protected void checkNotInitialized()
+   {
+      if (initialized)
+      {
+         throw new IllegalStateException("already initialized");
+      }
+   }
 
-    /**
-     * Checks if this query is initialized and throws an
-     * <code>IllegalStateException</code> if it is not yet initialized.
-     */
-    protected void checkInitialized() {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-    }
+   /**
+    * Checks if this query is initialized and throws an
+    * <code>IllegalStateException</code> if it is not yet initialized.
+    */
+   protected void checkInitialized()
+   {
+      if (!initialized)
+      {
+         throw new IllegalStateException("not initialized");
+      }
+   }
 
-  
 }
-

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/VersionHistoryImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/VersionHistoryImpl.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/VersionHistoryImpl.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -629,7 +629,7 @@
 
    }
 
-   public boolean isVersionBelongToThis(Version version)
+   public boolean isVersionBelongToThis(Version version) throws RepositoryException
    {
       return ((VersionImpl)version).getLocation().isDescendantOf(getLocation(), false);
    }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -18,6 +18,12 @@
  */
 package org.exoplatform.services.jcr.impl.dataflow.persistent;
 
+import java.util.Calendar;
+import java.util.List;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.RepositoryException;
+
 import org.exoplatform.services.jcr.access.AccessControlList;
 import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
 import org.exoplatform.services.jcr.dataflow.SharedDataManager;
@@ -28,12 +34,6 @@
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 
-import java.util.Calendar;
-import java.util.List;
-
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.RepositoryException;
-
 /**
  * Created by The eXo Platform SAS. Data Manager supported ACL Inheritance
  * 
@@ -124,6 +124,9 @@
       return node;
    }
 
+   /**
+    * {@inheritDoc}
+    */
    // ------------ ItemDataConsumer impl ------------
 
    public List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException
@@ -133,29 +136,52 @@
          initACL(parent, node);
       return nodes;
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public int getChildNodesCount(final NodeData parent) throws RepositoryException 
+   {
+      return persistentManager.getChildNodesCount(parent);
+   }
 
+   /**
+    * {@inheritDoc}
+    */
    public ItemData getItemData(NodeData parent, QPathEntry name) throws RepositoryException
    {
       final ItemData item = persistentManager.getItemData(parent, name);
       return item != null && item.isNode() ? initACL(parent, (NodeData)item) : item;
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public ItemData getItemData(String identifier) throws RepositoryException
    {
       final ItemData item = persistentManager.getItemData(identifier);
       return item != null && item.isNode() ? initACL(null, (NodeData)item) : item;
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException
    {
       return persistentManager.getChildPropertiesData(parent);
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException
    {
       return persistentManager.listChildPropertiesData(parent);
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public List<PropertyData> getReferencesData(String identifier, boolean skipVersionStorage)
       throws RepositoryException
    {
@@ -164,12 +190,18 @@
 
    // ------------ SharedDataManager ----------------------
 
+   /**
+    * {@inheritDoc}
+    */
    public void save(ItemStateChangesLog changes) throws InvalidItemStateException, UnsupportedOperationException,
       RepositoryException
    {
       persistentManager.save(changes);
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public Calendar getCurrentTime()
    {
       return persistentManager.getCurrentTime();

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -369,6 +369,18 @@
       }
    }
 
+   public int getChildNodesCount(NodeData parent) throws RepositoryException
+   {
+      if (cache.isEnabled())
+      {
+         List<NodeData> childNodes = cache.getChildNodes(parent);
+         if (childNodes != null)
+            return childNodes.size();
+      }
+
+      return super.getChildNodesCount(parent);
+   }
+
    /**
     * Get child PropertyData.
     * 
@@ -453,7 +465,7 @@
       }
       return propertiesList;
    }
-
+   
    /**
     * {@inheritDoc}
     */

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -18,6 +18,12 @@
  */
 package org.exoplatform.services.jcr.impl.dataflow.persistent;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.RepositoryException;
+
 import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
 import org.exoplatform.services.jcr.dataflow.CompositeChangesLog;
 import org.exoplatform.services.jcr.dataflow.DataManager;
@@ -36,12 +42,6 @@
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.RepositoryException;
-
 /**
  * Created by The eXo Platform SAS. Responsible for: *redirecting repository operations if item is
  * descendant of /jcr:system/jcr:versionStorage *adding version history for newly added/assigned
@@ -72,11 +72,8 @@
       this.versionDataManager = (ACLInheritanceSupportedWorkspaceDataManager)systemDataManager;
    }
 
-   /*
-    * (non-Javadoc)
-    * 
-    * @see org.exoplatform.services.jcr.impl.core.WorkspaceDataManager#getChildNodes(org.exoplatform.services
-    *      .jcr.datamodel.NodeData)
+   /**
+    * {@inheritDoc}
     */
    @Override
    public List<NodeData> getChildNodesData(final NodeData nodeData) throws RepositoryException
@@ -87,12 +84,22 @@
       }
       return super.getChildNodesData(nodeData);
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int getChildNodesCount(final NodeData parent) throws RepositoryException 
+   {
+      if (isSystemDescendant(parent.getQPath()) && !this.equals(versionDataManager))
+      {
+         return versionDataManager.getChildNodesCount(parent);
+      }
+      return super.getChildNodesCount(parent);
+   }   
 
-   /*
-    * (non-Javadoc)
-    * 
-    * @see org.exoplatform.services.jcr.impl.core.WorkspaceDataManager#getChildProperties(org.exoplatform
-    *      .services.jcr.datamodel.NodeData)
+   /**
+    * {@inheritDoc}
     */
    @Override
    public List<PropertyData> getChildPropertiesData(final NodeData nodeData) throws RepositoryException
@@ -104,6 +111,10 @@
       return super.getChildPropertiesData(nodeData);
    }
 
+   /**
+    * {@inheritDoc}
+    */
+   @Override
    public List<PropertyData> listChildPropertiesData(final NodeData nodeData) throws RepositoryException
    {
       if (isSystemDescendant(nodeData.getQPath()) && !this.equals(versionDataManager))
@@ -113,6 +124,10 @@
       return super.listChildPropertiesData(nodeData);
    }
 
+   /**
+    * {@inheritDoc}
+    */
+   @Override
    public ItemData getItemData(NodeData parentData, QPathEntry name) throws RepositoryException
    {
       if (parentData != null)
@@ -127,8 +142,9 @@
    }
 
    /**
-    * @see org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager#getItemData(java.lang.String)
+    * {@inheritDoc}
     */
+   @Override
    public ItemData getItemData(String identifier) throws RepositoryException
    {
       // from cache at first

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -290,6 +290,22 @@
          con.close();
       }
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public int getChildNodesCount(NodeData parent) throws RepositoryException
+   {
+      final WorkspaceStorageConnection con = dataContainer.openConnection();
+      try
+      {
+         return con.getChildNodesCount(parent);
+      }
+      finally
+      {
+         con.close();
+      }
+   }   
 
    /**
     * {@inheritDoc}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -97,6 +97,9 @@
       storageDataManager.save(newLog);
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public ItemData getItemData(NodeData parentData, QPathEntry name) throws RepositoryException
    {
       return copyItemData(storageDataManager.getItemData(parentData, name));
@@ -117,6 +120,14 @@
    {
       return copyNodes(storageDataManager.getChildNodesData(parent));
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public int getChildNodesCount(final NodeData parent) throws RepositoryException 
+   {
+      return storageDataManager.getChildNodesCount(parent);
+   }   
 
    /**
     * {@inheritDoc}
@@ -126,6 +137,9 @@
       return copyProperties(storageDataManager.getChildPropertiesData(parent));
    }
 
+   /**
+    * {@inheritDoc}
+    */
    public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException
    {
       return copyPropertiesWithoutValues(storageDataManager.listChildPropertiesData(parent));

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/SessionChangesLog.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -26,6 +26,7 @@
 import org.exoplatform.services.jcr.datamodel.NodeData;
 import org.exoplatform.services.jcr.datamodel.QPath;
 import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.Constants;
 import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
 
 import java.util.ArrayList;
@@ -50,6 +51,22 @@
    protected Map<Object, ItemState> index = new HashMap<Object, ItemState>();
 
    /**
+    * ItemState index storage. Used to store last nodes states. 
+    */
+   protected Map<String, Map<String, ItemState>> lastChildNodeStates = new HashMap<String, Map<String, ItemState>>();
+
+   /**
+    * ItemState index storage. Used to store last properties states.  
+    */
+   protected Map<String, Map<String, ItemState>> lastChildPropertyStates =
+      new HashMap<String, Map<String, ItemState>>();
+
+   /**
+    * Stores persisted child nodes count.  
+    */
+   protected Map<String, int[]> childNodesCount = new HashMap<String, int[]>();
+
+   /**
     * Create empty ChangesLog.
     * 
     * @param sessionId
@@ -70,52 +87,45 @@
       super(items, sessionId);
 
       for (ItemState change : items)
-      {
-         index.put(change.getData().getIdentifier(), change);
-         index.put(change.getData().getQPath(), change);
-      }
+         addItem(change);
    }
 
-   /*
-    * (non-Javadoc)
-    * @see
-    * org.exoplatform.services.jcr.dataflow.PlainChangesLog#add(org.exoplatform.services.jcr.dataflow
-    * .ItemState)
+   /**
+    * {@inheritDoc}
     */
    @Override
    public PlainChangesLog add(ItemState change)
    {
       super.add(change);
-      index.put(change.getData().getIdentifier(), change);
-      index.put(change.getData().getQPath(), change);
+      addItem(change);
+
       return this;
    }
 
-   /*
-    * (non-Javadoc)
-    * @see org.exoplatform.services.jcr.dataflow.PlainChangesLog#addAll(java.util.List)
+   /**
+    * {@inheritDoc}
     */
    @Override
    public PlainChangesLog addAll(List<ItemState> changes)
    {
       super.addAll(changes);
       for (ItemState change : changes)
-      {
-         index.put(change.getData().getIdentifier(), change);
-         index.put(change.getData().getQPath(), change);
-      }
+         addItem(change);
+
       return this;
    }
 
-   /*
-    * (non-Javadoc)
-    * @see org.exoplatform.services.jcr.dataflow.PlainChangesLog#clear()
+   /**
+    * {@inheritDoc}
     */
    @Override
    public void clear()
    {
       super.clear();
       index.clear();
+      lastChildNodeStates.clear();
+      lastChildPropertyStates.clear();
+      childNodesCount.clear();
    }
 
    /**
@@ -126,24 +136,51 @@
     */
    public void remove(QPath rootPath)
    {
-      List<ItemState> removedList = new ArrayList<ItemState>();
+      for (int i = items.size() - 1; i >= 0; i--)
+      {
+         ItemState item = items.get(i);
 
-      for (ItemState item : items)
-      {
          QPath qPath = item.getData().getQPath();
          if (qPath.isDescendantOf(rootPath) || item.getAncestorToSave().isDescendantOf(rootPath)
             || item.getAncestorToSave().equals(rootPath) || qPath.equals(rootPath))
          {
-            removedList.add(item);
+            items.remove(i);
+            index.remove(item.getData().getIdentifier());
+            index.remove(item.getData().getQPath());
+            index.remove(new ParentIDQPathBasedKey(item));
+            index.remove(new IDStateBasedKey(item.getData().getIdentifier(), item.getState()));
+            childNodesCount.remove(item.getData().getIdentifier());
+            lastChildNodeStates.remove(item.getData().getIdentifier());
+            lastChildPropertyStates.remove(item.getData().getIdentifier());
+
+            if (item.isNode() && item.isPersisted())
+            {
+               int childCount[] = childNodesCount.get(item.getData().getParentIdentifier());
+               if (childCount != null)
+               {
+                  if (item.isDeleted())
+                     ++childCount[0];
+                  else if (item.isAdded())
+                     --childCount[0];
+
+                  childNodesCount.put(item.getData().getParentIdentifier(), childCount);
+               }
+            }
+
+            if (item.getData().isNode())
+            {
+               Map<String, ItemState> children = lastChildNodeStates.get(item.getData().getParentIdentifier());
+               if (children != null)
+                  children.remove(item.getData().getIdentifier());
+            }
+            else
+            {
+               Map<String, ItemState> children = lastChildPropertyStates.get(item.getData().getParentIdentifier());
+               if (children != null)
+                  children.remove(item.getData().getIdentifier());
+            }
          }
       }
-
-      for (ItemState item : removedList)
-      {
-         items.remove(item);
-         index.remove(item.getData().getIdentifier());
-         index.remove(item.getData().getQPath());
-      }
    }
 
    /**
@@ -215,9 +252,11 @@
       return list;
    }
 
-   /*
-    * (non-Javadoc)
-    * @see org.exoplatform.services.jcr.dataflow.ItemDataChangesLog#getItemStates(java.lang.String)
+   /**
+    * Gets items by identifier.
+    *
+    * @param itemIdentifier
+    * @return
     */
    public List<ItemState> getItemStates(String itemIdentifier)
    {
@@ -242,8 +281,18 @@
    public PlainChangesLog pushLog(QPath rootPath)
    {
       PlainChangesLog cLog = new PlainChangesLogImpl(sessionId);
-      cLog.addAll(getDescendantsChanges(rootPath));
-      remove(rootPath);
+
+      if (rootPath.equals(Constants.ROOT_PATH))
+      {
+         cLog.addAll(items);
+         clear();
+      }
+      else
+      {
+         cLog.addAll(getDescendantsChanges(rootPath));
+         remove(rootPath);
+      }
+
       return cLog;
    }
 
@@ -257,15 +306,7 @@
     */
    public ItemState getItemState(NodeData parentData, QPathEntry name) throws IllegalPathException
    {
-      List<ItemState> allStates = getAllStates();
-      for (int i = allStates.size() - 1; i >= 0; i--)
-      {
-         ItemState state = allStates.get(i);
-         if (state.getData().getParentIdentifier().equals(parentData.getIdentifier())
-            && state.getData().getQPath().getEntries()[state.getData().getQPath().getEntries().length - 1].isSame(name))
-            return state;
-      }
-      return null;
+      return index.get(new ParentIDQPathBasedKey(parentData.getIdentifier(), name));
    }
 
    /**
@@ -295,6 +336,20 @@
    }
 
    /**
+    * Get ItemState by identifier and state.
+    * 
+    * NOTE: Uses index HashMap.
+    * 
+    * @param itemIdentifier
+    * @param sate
+    * @return
+    */
+   public ItemState getItemState(String itemIdentifier, int state)
+   {
+      return index.get(new IDStateBasedKey(itemIdentifier, state));
+   }
+
+   /**
     * Collect changes of all item direct childs (only). Including the item itself.
     * 
     * @param rootIdentifier
@@ -312,6 +367,12 @@
       return list;
    }
 
+   public int getChildNodesCount(String rootIdentifier)
+   {
+      int[] childCount = childNodesCount.get(rootIdentifier);
+      return childCount == null ? 0 : childCount[0];
+   }
+
    /**
     * Collect last in ChangesLog order item child changes.
     * 
@@ -323,17 +384,11 @@
     */
    public Collection<ItemState> getLastChildrenStates(ItemData rootData, boolean forNodes)
    {
-      HashMap<String, ItemState> children = new HashMap<String, ItemState>();
-      List<ItemState> changes = getChildrenChanges(rootData.getIdentifier());
-      for (ItemState child : changes)
-      {
-         ItemData data = child.getData();
-         // add state to result
-         if (data.isNode() == forNodes && !data.equals(rootData))
-            children.put(data.getIdentifier(), child);
+      Map<String, ItemState> children =
+         forNodes ? lastChildNodeStates.get(rootData.getIdentifier()) : lastChildPropertyStates.get(rootData
+            .getIdentifier());
 
-      }
-      return children.values();
+      return children == null ? new ArrayList<ItemState>() : children.values();
    }
 
    /**
@@ -528,4 +583,214 @@
       }
       return null;
    }
+
+   /**
+    * Adds item to the changes log.
+    * 
+    * @param item
+    *          the item
+    */
+   private void addItem(ItemState item)
+   {
+      index.put(item.getData().getIdentifier(), item);
+      index.put(item.getData().getQPath(), item);
+      index.put(new ParentIDQPathBasedKey(item), item);
+      index.put(new IDStateBasedKey(item.getData().getIdentifier(), item.getState()), item);
+
+      if (item.getData().isNode())
+      {
+         Map<String, ItemState> children = lastChildNodeStates.get(item.getData().getParentIdentifier());
+         if (children == null)
+         {
+            children = new HashMap<String, ItemState>();
+            lastChildNodeStates.put(item.getData().getParentIdentifier(), children);
+         }
+         children.put(item.getData().getIdentifier(), item);
+      }
+      else
+      {
+         Map<String, ItemState> children = lastChildPropertyStates.get(item.getData().getParentIdentifier());
+         if (children == null)
+         {
+            children = new HashMap<String, ItemState>();
+            lastChildPropertyStates.put(item.getData().getParentIdentifier(), children);
+         }
+         children.put(item.getData().getIdentifier(), item);
+      }
+
+      if (item.isNode() && item.isPersisted())
+      {
+         int[] childCount = childNodesCount.get(item.getData().getParentIdentifier());
+         if (childCount == null)
+            childCount = new int[1];
+
+         if (item.isDeleted())
+            --childCount[0];
+         else if (item.isAdded())
+            ++childCount[0];
+
+         childNodesCount.put(item.getData().getParentIdentifier(), childCount);
+      }
+   }
+
+   /**
+    * This class is used as a key for index map.
+    */
+   private class IDStateBasedKey
+   {
+
+      /**
+       * Item identifier.
+       */
+      private final String identifier;
+
+      /**
+       * Item state.
+       */
+      private final int state;
+
+      /**
+       * KeyUUIDState  constructor.
+       *
+       * @param identifier
+       *          item identifier
+       * @param state
+       *          item state
+       */
+      IDStateBasedKey(String identifier, int state)
+      {
+         this.identifier = identifier;
+         this.state = state;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode()
+      {
+         final int prime = 31;
+         int result = 1;
+         result = prime * result + identifier.hashCode();
+         result = prime * result + state;
+
+         return result;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj)
+      {
+         if (this == obj)
+            return true;
+         if (obj == null)
+            return false;
+         if (getClass() != obj.getClass())
+            return false;
+         IDStateBasedKey other = (IDStateBasedKey)obj;
+
+         if (identifier == null)
+         {
+            if (other.identifier != null)
+               return false;
+         }
+         else if (!identifier.equals(other.identifier))
+            return false;
+         if (state != other.state)
+            return false;
+         return true;
+      }
+   }
+
+   /**
+    * This class is used as a key for index map.
+    */
+   private class ParentIDQPathBasedKey
+   {
+      /**
+       * Item name.
+       */
+      private final QPathEntry name;
+
+      /**
+       * Parent identifier.
+       */
+      private final String parentIdentifier;
+
+      /**
+       * KeyParentUUIDQPath  constructor.
+       *
+       * @param item
+       *          the item
+       */
+      ParentIDQPathBasedKey(ItemState item)
+      {
+         this.name = item.getData().getQPath().getEntries()[item.getData().getQPath().getEntries().length - 1];
+         this.parentIdentifier = item.getData().getParentIdentifier();
+      }
+
+      /**
+       * KeyParentUUIDQPath  constructor.
+       *
+       * @param parentIdentifier
+       *          the parent identifier
+       * @param name
+       *          item name
+       */
+      ParentIDQPathBasedKey(String parentIdentifier, QPathEntry name)
+      {
+         this.name = name;
+         this.parentIdentifier = parentIdentifier;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode()
+      {
+         final int prime = 31;
+         int result = 1;
+         result = prime * result + name.getName().hashCode();
+         result = prime * result + name.getNamespace().hashCode();
+         result = prime * result + name.getIndex();
+         result = prime * result + parentIdentifier.hashCode();
+
+         return result;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj)
+      {
+         if (this == obj)
+            return true;
+         if (obj == null)
+            return false;
+         if (getClass() != obj.getClass())
+            return false;
+         ParentIDQPathBasedKey other = (ParentIDQPathBasedKey)obj;
+
+         if (name == null)
+         {
+            if (other.name != null)
+               return false;
+         }
+         else if (!name.getName().equals(other.name.getName())
+            || !name.getNamespace().equals(other.name.getNamespace()) || name.getIndex() != other.name.getIndex())
+            return false;
+         if (parentIdentifier == null)
+         {
+            if (other.parentIdentifier != null)
+               return false;
+         }
+         else if (!parentIdentifier.equals(other.parentIdentifier))
+            return false;
+         return true;
+      }
+   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -94,6 +94,45 @@
    /**
     * {@inheritDoc}
     */
+   public int getChildNodesCount(final NodeData parent) throws RepositoryException
+   {
+      if (txStarted())
+      {
+         int txChildsCount = 0;
+         for (ItemState change : transactionLog.getAllStates())
+         {
+            if (change.isNode() && change.isPersisted()
+               && change.getData().getParentIdentifier().equals(parent.getIdentifier()))
+            {
+               if (change.isDeleted())
+               {
+                  txChildsCount--;
+               }
+               else if (change.isAdded())
+               {
+                  txChildsCount++;
+               }
+            }
+         }
+
+         final int childsCount = storageDataManager.getChildNodesCount(parent) + txChildsCount;
+         if (childsCount < 0)
+         {
+            throw new InvalidItemStateException("Node's child nodes were changed in another Transaction "
+               + parent.getQPath().getAsString());
+         }
+         
+         return childsCount;
+      }
+      else
+      {
+         return storageDataManager.getChildNodesCount(parent);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException
    {
       List<PropertyData> props = storageDataManager.getChildPropertiesData(parent);

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -126,6 +126,11 @@
     * FIND_NODES_BY_PARENTID.
     */
    protected String FIND_NODES_BY_PARENTID;
+   
+   /**
+    * FIND_NODES_COUNT_BY_PARENTID.
+    */
+   protected String FIND_NODES_COUNT_BY_PARENTID;
 
    /**
     * FIND_PROPERTIES_BY_PARENTID.

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -600,6 +600,29 @@
          throw new RepositoryException(e);
       }
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public int getChildNodesCount(NodeData parent) throws RepositoryException {
+      checkIfOpened();
+      try
+      {
+         ResultSet count = findChildNodesCountByParentIdentifier(getInternalId(parent.getIdentifier()));
+         if (count.next()) 
+         {
+            return count.getInt(1);
+         }
+         else
+         {
+            throw new RepositoryException("FATAL No resulton childNodes count for " + parent.getQPath().getAsString());
+         }
+      }
+      catch (SQLException e)
+      {
+         throw new RepositoryException(e);
+      }
+   }   
 
    /**
     * {@inheritDoc}
@@ -1871,6 +1894,8 @@
    protected abstract ResultSet findItemByName(String parentId, String name, int index) throws SQLException;
 
    protected abstract ResultSet findChildNodesByParentIdentifier(String parentIdentifier) throws SQLException;
+   
+   protected abstract ResultSet findChildNodesCountByParentIdentifier(String parentIdentifier) throws SQLException;
 
    protected abstract ResultSet findChildPropertiesByParentIdentifier(String parentIdentifier) throws SQLException;
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBMultiDbJDBCConnection.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -74,6 +74,7 @@
          "select V.DATA" + " from JCR_MITEM I, JCR_MVALUE V"
             + " where I.PARENT_ID=? and I.I_CLASS=2 and I.NAME=? and I.ID=V.PROPERTY_ID order by V.ORDER_NUM";
       FIND_NODES_BY_PARENTID = "select * from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=1" + " order by N_ORDER_NUM";
+      FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=1";
       FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where PARENT_ID=? and I_CLASS=2" + " order by ID";
    }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/HSQLDBSingleDbJDBCConnection.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -81,6 +81,8 @@
             + " where I.PARENT_ID=? and I.I_CLASS=2 and I.CONTAINER_NAME=? and I.NAME=? and I.ID=V.PROPERTY_ID order by V.ORDER_NUM";
       FIND_NODES_BY_PARENTID =
          "select * from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?" + " order by N_ORDER_NUM";
+      FIND_NODES_COUNT_BY_PARENTID =
+         "select count(ID) from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=1 and CONTAINER_NAME=?";
       FIND_PROPERTIES_BY_PARENTID =
          "select * from JCR_SITEM" + " where PARENT_ID=? and I_CLASS=2 and CONTAINER_NAME=?" + " order by ID";
    }
@@ -135,7 +137,23 @@
       findNodesByParentId.setString(2, containerName);
       return findNodesByParentId.executeQuery();
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected ResultSet findChildNodesCountByParentIdentifier(String parentCid) throws SQLException
+   {
+      if (findNodesCountByParentId == null)
+         findNodesCountByParentId = dbConnection.prepareStatement(FIND_NODES_COUNT_BY_PARENTID);
+      else
+         findNodesCountByParentId.clearParameters();
 
+      findNodesCountByParentId.setString(1, parentCid);
+      findNodesCountByParentId.setString(2, containerName);
+      return findNodesCountByParentId.executeQuery();
+   }
+
    /**
     * {@inheritDoc}
     */

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -77,6 +77,8 @@
    protected PreparedStatement findValueByPropertyIdOrderNumber;
 
    protected PreparedStatement findNodesByParentId;
+   
+   protected PreparedStatement findNodesCountByParentId;
 
    protected PreparedStatement findPropertiesByParentId;
 
@@ -185,6 +187,8 @@
       FIND_VALUE_BY_PROPERTYID_OREDERNUMB = "select DATA from JCR_MVALUE where PROPERTY_ID=? and ORDER_NUM=?";
 
       FIND_NODES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?" + " order by N_ORDER_NUM";
+      
+      FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?";
 
       FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=2 and PARENT_ID=?" + " order by ID";
 
@@ -428,6 +432,21 @@
     * {@inheritDoc}
     */
    @Override
+   protected ResultSet findChildNodesCountByParentIdentifier(String parentIdentifier) throws SQLException
+   {
+      if (findNodesCountByParentId == null)
+         findNodesCountByParentId = dbConnection.prepareStatement(FIND_NODES_COUNT_BY_PARENTID);
+      else
+         findNodesCountByParentId.clearParameters();
+
+      findNodesCountByParentId.setString(1, parentIdentifier);
+      return findNodesCountByParentId.executeQuery();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
    protected ResultSet findChildPropertiesByParentIdentifier(String parentIdentifier) throws SQLException
    {
       if (findPropertiesByParentId == null)

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -75,6 +75,8 @@
 
    protected PreparedStatement findNodesByParentId;
 
+   protected PreparedStatement findNodesCountByParentId;
+
    protected PreparedStatement findPropertiesByParentId;
 
    protected PreparedStatement insertItem;
@@ -193,6 +195,9 @@
       FIND_NODES_BY_PARENTID =
          "select * from JCR_SITEM" + " where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?" + " order by N_ORDER_NUM";
 
+      FIND_NODES_COUNT_BY_PARENTID =
+         "select count(ID) from JCR_SITEM" + " where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?";
+
       FIND_PROPERTIES_BY_PARENTID =
          "select * from JCR_SITEM" + " where I_CLASS=2 and CONTAINER_NAME=? and PARENT_ID=?" + " order by ID";
 
@@ -339,6 +344,22 @@
     * {@inheritDoc}
     */
    @Override
+   protected ResultSet findChildNodesCountByParentIdentifier(String parentCid) throws SQLException
+   {
+      if (findNodesCountByParentId == null)
+         findNodesCountByParentId = dbConnection.prepareStatement(FIND_NODES_COUNT_BY_PARENTID);
+      else
+         findNodesCountByParentId.clearParameters();
+
+      findNodesCountByParentId.setString(1, containerName);
+      findNodesCountByParentId.setString(2, parentCid);
+      return findNodesCountByParentId.executeQuery();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
    protected ResultSet findChildPropertiesByParentIdentifier(String parentCid) throws SQLException
    {
       if (findPropertiesByParentId == null)

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -93,6 +93,15 @@
     *           if connection is closed
     */
    List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException, IllegalStateException;
+   
+   /**
+    * Reads count of <code>parent<code/> child nodes.
+    *
+    * @param parent NodeData
+    * @return long, childs count
+    * @throws RepositoryException if error occurs
+    */
+   int getChildNodesCount(NodeData parent) throws RepositoryException;
 
    /**
     * Reads <code>List</code> of <code>PropertyData</code> from the storage using item's parent

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -387,7 +387,7 @@
       return testFile;
    }
 
-   protected void checkMixins(String[] mixins, NodeImpl node)
+   protected void checkMixins(String[] mixins, NodeImpl node) throws RepositoryException
    {
       try
       {

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/UpperLowerCaseQueryTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/UpperLowerCaseQueryTest.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/UpperLowerCaseQueryTest.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -16,9 +16,9 @@
  */
 package org.exoplatform.services.jcr.api.core.query;
 
-
-
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Random;
 import java.util.Set;
 
@@ -32,295 +32,276 @@
  * fn:upper-case() in XPath, LOWER() and UPPER() in SQL and UpperCase and
  * LowerCase in JQOM.
  */
-public class UpperLowerCaseQueryTest extends AbstractQueryTest  {
+public class UpperLowerCaseQueryTest extends AbstractQueryTest
+{
 
-//    /**
-//     * Maps operator strings to QueryObjectModelConstants.
-//     */
-//    private static final Map OPERATORS = new HashMap();
-//
-//    static {
-//        OPERATORS.put("=", new Integer(OPERATOR_EQUAL_TO));
-//        OPERATORS.put(">", new Integer(OPERATOR_GREATER_THAN));
-//        OPERATORS.put(">=", new Integer(OPERATOR_GREATER_THAN_OR_EQUAL_TO));
-//        OPERATORS.put("<", new Integer(OPERATOR_LESS_THAN));
-//        OPERATORS.put("<=", new Integer(OPERATOR_LESS_THAN_OR_EQUAL_TO));
-//        OPERATORS.put("like", new Integer(OPERATOR_LIKE));
-//        OPERATORS.put("!=", new Integer(OPERATOR_NOT_EQUAL_TO));
-//    }
+   //    /**
+   //     * Maps operator strings to QueryObjectModelConstants.
+   //     */
+   //    private static final Map OPERATORS = new HashMap();
+   //
+   //    static {
+   //        OPERATORS.put("=", new Integer(OPERATOR_EQUAL_TO));
+   //        OPERATORS.put(">", new Integer(OPERATOR_GREATER_THAN));
+   //        OPERATORS.put(">=", new Integer(OPERATOR_GREATER_THAN_OR_EQUAL_TO));
+   //        OPERATORS.put("<", new Integer(OPERATOR_LESS_THAN));
+   //        OPERATORS.put("<=", new Integer(OPERATOR_LESS_THAN_OR_EQUAL_TO));
+   //        OPERATORS.put("like", new Integer(OPERATOR_LIKE));
+   //        OPERATORS.put("!=", new Integer(OPERATOR_NOT_EQUAL_TO));
+   //    }
 
-    public void testEqualsGeneralComparison() throws RepositoryException {
-        check(new String[]{"foo", "Foo", "fOO", "FOO", "fooBar", "fo", "fooo"},
-                "=",
-                "foo",
-                new boolean[]{true, true, true, true, false, false, false});
-        check(new String[]{"foo"}, "=", "", new boolean[]{false});
-        check(new String[]{""}, "=", "", new boolean[]{true});
-    }
+   public void testEqualsGeneralComparison() throws RepositoryException
+   {
+      check(new String[]{"foo", "Foo", "fOO", "FOO", "fooBar", "fo", "fooo"}, "=", "foo", new boolean[]{true, true,
+         true, true, false, false, false});
+      check(new String[]{"foo"}, "=", "", new boolean[]{false});
+      check(new String[]{""}, "=", "", new boolean[]{true});
+   }
 
-    public void testGreaterThanGeneralComparison() throws RepositoryException {
-        // check edges
-        check(new String[]{"foo", "FOO", "FoO", "fOo", "FON", "fon", "fo", "FO"},
-                ">",
-                "foo",
-                new boolean[]{false, false, false, false, false, false, false, false});
-        check(new String[]{"foo ", "FOOa", "FoOO", "fOo1", "FOp", "foP", "fp", "g", "G"},
-                ">",
-                "foo",
-                new boolean[]{true, true, true, true, true, true, true, true, true});
-        // check combinations
-        check(new String[]{"foo", "fooo", "FooO", "fo", "FON", "fon"},
-                ">",
-                "foo",
-                new boolean[]{false, true, true, false, false, false});
-    }
+   public void testGreaterThanGeneralComparison() throws RepositoryException
+   {
+      // check edges
+      check(new String[]{"foo", "FOO", "FoO", "fOo", "FON", "fon", "fo", "FO"}, ">", "foo", new boolean[]{false, false,
+         false, false, false, false, false, false});
+      check(new String[]{"foo ", "FOOa", "FoOO", "fOo1", "FOp", "foP", "fp", "g", "G"}, ">", "foo", new boolean[]{true,
+         true, true, true, true, true, true, true, true});
+      // check combinations
+      check(new String[]{"foo", "fooo", "FooO", "fo", "FON", "fon"}, ">", "foo", new boolean[]{false, true, true,
+         false, false, false});
+   }
 
-    public void testLessThanGeneralComparison() throws RepositoryException {
-        // check edges
-        check(new String[]{"foo", "FOO", "FoO", "fOo", "foOo", "foo ", "fooa", "fop"},
-                "<",
-                "foo",
-                new boolean[]{false, false, false, false, false, false, false, false});
-        check(new String[]{"fo", "FOn", "FoN", "fO", "FO1", "fn", "fN", "E", "e"},
-                "<",
-                "foo",
-                new boolean[]{true, true, true, true, true, true, true, true, true});
-        // check combinations
-        check(new String[]{"foo", "fooo", "FooO", "fo", "FON", "fon"},
-                "<",
-                "foo",
-                new boolean[]{false, false, false, true, true, true});
-    }
+   public void testLessThanGeneralComparison() throws RepositoryException
+   {
+      // check edges
+      check(new String[]{"foo", "FOO", "FoO", "fOo", "foOo", "foo ", "fooa", "fop"}, "<", "foo", new boolean[]{false,
+         false, false, false, false, false, false, false});
+      check(new String[]{"fo", "FOn", "FoN", "fO", "FO1", "fn", "fN", "E", "e"}, "<", "foo", new boolean[]{true, true,
+         true, true, true, true, true, true, true});
+      // check combinations
+      check(new String[]{"foo", "fooo", "FooO", "fo", "FON", "fon"}, "<", "foo", new boolean[]{false, false, false,
+         true, true, true});
+   }
 
-    public void testGreaterEqualsGeneralComparison() throws RepositoryException {
-        // check edges
-        check(new String[]{"fo", "FO", "Fon", "fONo", "FON", "fO", "fo", "FO"},
-                ">=",
-                "foo",
-                new boolean[]{false, false, false, false, false, false, false, false});
-        check(new String[]{"foo", "FoO", "FoOO", "fOo1", "FOp", "foP", "fp", "g", "G"},
-                ">=",
-                "foo",
-                new boolean[]{true, true, true, true, true, true, true, true, true});
-        // check combinations
-        check(new String[]{"foo", "fooo", "FOo", "fo", "FON", "fon"},
-                ">=",
-                "foo",
-                new boolean[]{true, true, true, false, false, false});
-    }
+   public void testGreaterEqualsGeneralComparison() throws RepositoryException
+   {
+      // check edges
+      check(new String[]{"fo", "FO", "Fon", "fONo", "FON", "fO", "fo", "FO"}, ">=", "foo", new boolean[]{false, false,
+         false, false, false, false, false, false});
+      check(new String[]{"foo", "FoO", "FoOO", "fOo1", "FOp", "foP", "fp", "g", "G"}, ">=", "foo", new boolean[]{true,
+         true, true, true, true, true, true, true, true});
+      // check combinations
+      check(new String[]{"foo", "fooo", "FOo", "fo", "FON", "fon"}, ">=", "foo", new boolean[]{true, true, true, false,
+         false, false});
+   }
 
-    public void testLessEqualsGeneralComparison() throws RepositoryException {
-        // check edges
-        check(new String[]{"fooo", "FOoo", "Fop", "fOpo", "FOP", "fOo ", "fp", "G"},
-                "<=",
-                "foo",
-                new boolean[]{false, false, false, false, false, false, false, false});
-        check(new String[]{"foo", "FoO", "Foo", "fOn", "FO", "fo", "f", "E", "e"},
-                "<=",
-                "foo",
-                new boolean[]{true, true, true, true, true, true, true, true, true});
-        // check combinations
-        check(new String[]{"foo", "fo", "FOo", "fop", "FOP", "fooo"},
-                "<=",
-                "foo",
-                new boolean[]{true, true, true, false, false, false});
-    }
+   public void testLessEqualsGeneralComparison() throws RepositoryException
+   {
+      // check edges
+      check(new String[]{"fooo", "FOoo", "Fop", "fOpo", "FOP", "fOo ", "fp", "G"}, "<=", "foo", new boolean[]{false,
+         false, false, false, false, false, false, false});
+      check(new String[]{"foo", "FoO", "Foo", "fOn", "FO", "fo", "f", "E", "e"}, "<=", "foo", new boolean[]{true, true,
+         true, true, true, true, true, true, true});
+      // check combinations
+      check(new String[]{"foo", "fo", "FOo", "fop", "FOP", "fooo"}, "<=", "foo", new boolean[]{true, true, true, false,
+         false, false});
+   }
 
-    public void testNotEqualsGeneralComparison() throws RepositoryException {
-        // check edges
-        check(new String[]{"fooo", "FOoo", "Fop", "fOpo", "FOP", "fOo ", "fp", "G", ""},
-                "!=",
-                "foo",
-                new boolean[]{true, true, true, true, true, true, true, true, true});
-        check(new String[]{"foo", "FoO", "Foo", "foO", "FOO"},
-                "!=",
-                "foo",
-                new boolean[]{false, false, false, false, false});
-        // check combinations
-        check(new String[]{"foo", "fo", "FOo", "fop", "FOP", "fooo"},
-                "!=",
-                "foo",
-                new boolean[]{false, true, false, true, true, true});
-    }
+   public void testNotEqualsGeneralComparison() throws RepositoryException
+   {
+      // check edges
+      check(new String[]{"fooo", "FOoo", "Fop", "fOpo", "FOP", "fOo ", "fp", "G", ""}, "!=", "foo", new boolean[]{true,
+         true, true, true, true, true, true, true, true});
+      check(new String[]{"foo", "FoO", "Foo", "foO", "FOO"}, "!=", "foo", new boolean[]{false, false, false, false,
+         false});
+      // check combinations
+      check(new String[]{"foo", "fo", "FOo", "fop", "FOP", "fooo"}, "!=", "foo", new boolean[]{false, true, false,
+         true, true, true});
+   }
 
-    public void testLikeComparison() throws RepositoryException {
-        check(new String[]{"foo", "Foo", "fOO", "FO "},
-                "like",
-                "fo_",
-                new boolean[]{true, true, true, true});
-        check(new String[]{"foo", "Foo", "fOO", "FOO"},
-                "like",
-                "f_o",
-                new boolean[]{true, true, true, true});
-        check(new String[]{"foo", "Foo", "fOO", " OO"},
-                "like",
-                "_oo",
-                new boolean[]{true, true, true, true});
-        check(new String[]{"foo", "Foa", "fOO", "FO", "foRm", "fPo", "fno", "FPo", "Fno"},
-                "like",
-                "fo%",
-                new boolean[]{true, true, true, true, true, false, false, false, false});
-    }
+   public void testLikeComparison() throws RepositoryException
+   {
+      check(new String[]{"foo", "Foo", "fOO", "FO "}, "like", "fo_", new boolean[]{true, true, true, true});
+      check(new String[]{"foo", "Foo", "fOO", "FOO"}, "like", "f_o", new boolean[]{true, true, true, true});
+      check(new String[]{"foo", "Foo", "fOO", " OO"}, "like", "_oo", new boolean[]{true, true, true, true});
+      check(new String[]{"foo", "Foa", "fOO", "FO", "foRm", "fPo", "fno", "FPo", "Fno"}, "like", "fo%", new boolean[]{
+         true, true, true, true, true, false, false, false, false});
+   }
 
-    public void testLikeComparisonRandom() throws RepositoryException {
-        String abcd = "abcd";
-        Random random = new Random();
-        for (int i = 0; i < 50; i++) {
-            String pattern = "";
-            pattern += getRandomChar(abcd, random);
-            pattern += getRandomChar(abcd, random);
+   public void testLikeComparisonRandom() throws RepositoryException
+   {
+      String abcd = "abcd";
+      Random random = new Random();
+      for (int i = 0; i < 50; i++)
+      {
+         String pattern = "";
+         pattern += getRandomChar(abcd, random);
+         pattern += getRandomChar(abcd, random);
 
-            // create 10 random values with 4 characters
-            String[] values = new String[10];
-            boolean[] matches = new boolean[10];
-            for (int n = 0; n < 10; n++) {
-                // at least the first character always matches
-                String value = String.valueOf(pattern.charAt(0));
-                for (int r = 1; r < 4; r++) {
-                    char c = getRandomChar(abcd, random);
-                    if (random.nextBoolean()) {
-                        c = Character.toUpperCase(c);
-                    }
-                    value += c;
-                }
-                matches[n] = value.toLowerCase().startsWith(pattern);
-                values[n] = value;
+         // create 10 random values with 4 characters
+         String[] values = new String[10];
+         boolean[] matches = new boolean[10];
+         for (int n = 0; n < 10; n++)
+         {
+            // at least the first character always matches
+            String value = String.valueOf(pattern.charAt(0));
+            for (int r = 1; r < 4; r++)
+            {
+               char c = getRandomChar(abcd, random);
+               if (random.nextBoolean())
+               {
+                  c = Character.toUpperCase(c);
+               }
+               value += c;
             }
-            pattern += "%";
-            check(values, "like", pattern, matches);
-        }
-    }
+            matches[n] = value.toLowerCase().startsWith(pattern);
+            values[n] = value;
+         }
+         pattern += "%";
+         check(values, "like", pattern, matches);
+      }
+   }
 
-    public void testRangeWithEmptyString() throws RepositoryException {
-        check(new String[]{" ", "a", "A", "1", "3", "!", "@"},
-                ">",
-                "",
-                new boolean[]{true, true, true, true, true, true, true});
-        check(new String[]{"", "a", "A", "1", "3", "!", "@"},
-                ">=",
-                "",
-                new boolean[]{true, true, true, true, true, true, true});
-        check(new String[]{"", "a", "A", "1", "3", "!", "@"},
-                "<",
-                "",
-                new boolean[]{false, false, false, false, false, false, false});
-        check(new String[]{"", "a", "A", "1", "3", "!", "@"},
-                "<=",
-                "",
-                new boolean[]{true, false, false, false, false, false, false});
-    }
+   public void testRangeWithEmptyString() throws RepositoryException
+   {
+      check(new String[]{" ", "a", "A", "1", "3", "!", "@"}, ">", "", new boolean[]{true, true, true, true, true, true,
+         true});
+      check(new String[]{"", "a", "A", "1", "3", "!", "@"}, ">=", "", new boolean[]{true, true, true, true, true, true,
+         true});
+      check(new String[]{"", "a", "A", "1", "3", "!", "@"}, "<", "", new boolean[]{false, false, false, false, false,
+         false, false});
+      check(new String[]{"", "a", "A", "1", "3", "!", "@"}, "<=", "", new boolean[]{true, false, false, false, false,
+         false, false});
+   }
 
-    public void testInvalidQuery() throws RepositoryException {
-        try {
-            executeXPathQuery("//*[fn:lower-case(@foo) = 123]", new Node[]{});
-            fail("must throw InvalidQueryException");
-        } catch (InvalidQueryException e) {
-            // correct
-        }
+   public void testInvalidQuery() throws RepositoryException
+   {
+      try
+      {
+         executeXPathQuery("//*[fn:lower-case(@foo) = 123]", new Node[]{});
+         fail("must throw InvalidQueryException");
+      }
+      catch (InvalidQueryException e)
+      {
+         // correct
+      }
 
-        try {
-            executeSQLQuery("select * from nt:base where LOWER(foo) = 123", new Node[]{});
-            fail("must throw InvalidQueryException");
-        } catch (InvalidQueryException e) {
-            // correct
-        }
-    }
+      try
+      {
+         executeSQLQuery("select * from nt:base where LOWER(foo) = 123", new Node[]{});
+         fail("must throw InvalidQueryException");
+      }
+      catch (InvalidQueryException e)
+      {
+         // correct
+      }
+   }
 
-    public void testWrongCaseNeverMatches() throws RepositoryException {
-        Node n = testRootNode.addNode("node");
-        n.setProperty("foo", "Bar");
-        testRootNode.save();
-        executeXPathQuery(testPath + "/*[jcr:like(fn:lower-case(@foo), 'BA%')]", new Node[]{});
-    }
+   public void testWrongCaseNeverMatches() throws RepositoryException
+   {
+      Node n = testRootNode.addNode("node");
+      n.setProperty("foo", "Bar");
+      testRootNode.save();
+      executeXPathQuery(testPath + "/*[jcr:like(fn:lower-case(@foo), 'BA%')]", new Node[]{});
+   }
 
-    //----------------------------< internal >----------------------------------
+   //----------------------------< internal >----------------------------------
 
-    private void check(String[] values, String operation, String queryTerm, boolean[] matches)
-            throws RepositoryException {
-        if (values.length != matches.length) {
-            throw new IllegalArgumentException("values and matches must have same length");
-        }
-        // create log message
-        StringBuffer logMsg = new StringBuffer();
-        logMsg.append("queryTerm: ").append(queryTerm);
-        logMsg.append(" values: ");
-        String separator = "";
-        for (int i = 0; i < values.length; i++) {
-            logMsg.append(separator);
-            separator = ", ";
-            if (matches[i]) {
-                logMsg.append("+");
-            } else {
-                logMsg.append("-");
-            }
-            logMsg.append(values[i]);
-        }
-        log.println(logMsg.toString());
-        for (NodeIterator it = testRootNode.getNodes(); it.hasNext();) {
-            it.nextNode().remove();
-        }
-        Set matchingNodes = new HashSet();
-        for (int i = 0; i < values.length; i++) {
-            Node n = testRootNode.addNode("node" + i);
-            n.setProperty(propertyName1, values[i]);
-            if (matches[i]) {
-                matchingNodes.add(n);
-            }
-        }
-        testRootNode.save();
+   private void check(String[] values, String operation, String queryTerm, boolean[] matches)
+      throws RepositoryException
+   {
+      if (values.length != matches.length)
+      {
+         throw new IllegalArgumentException("values and matches must have same length");
+      }
+      // create log message
+      StringBuffer logMsg = new StringBuffer();
+      logMsg.append("queryTerm: ").append(queryTerm);
+      logMsg.append(" values: ");
+      String separator = "";
+      for (int i = 0; i < values.length; i++)
+      {
+         logMsg.append(separator);
+         separator = ", ";
+         if (matches[i])
+         {
+            logMsg.append("+");
+         }
+         else
+         {
+            logMsg.append("-");
+         }
+         logMsg.append(values[i]);
+      }
+      log.println(logMsg.toString());
+      for (NodeIterator it = testRootNode.getNodes(); it.hasNext();)
+      {
+         it.nextNode().remove();
+      }
+      List matchingNodes = new ArrayList();
+      for (int i = 0; i < values.length; i++)
+      {
+         Node n = testRootNode.addNode("node" + i);
+         n.setProperty(propertyName1, values[i]);
+         if (matches[i])
+         {
+            matchingNodes.add(n);
+         }
+      }
+      testRootNode.save();
 
-        Node[] nodes = (Node[]) matchingNodes.toArray(new Node[matchingNodes.size()]);
-        String sqlOperation = operation;
-        if (operation.equals("!=")) {
-            sqlOperation = "<>";
-        }
+      Node[] nodes = (Node[])matchingNodes.toArray(new Node[matchingNodes.size()]);
+      String sqlOperation = operation;
+      if (operation.equals("!="))
+      {
+         sqlOperation = "<>";
+      }
 
-        // run queries with lower-case
-        String xpath = testPath;
-        if (operation.equals("like")) {
-            xpath += "/*[jcr:like(fn:lower-case(@" + propertyName1 +
-                    "), '" + queryTerm.toLowerCase() + "')]";
-        } else {
-            xpath += "/*[fn:lower-case(@" + propertyName1 +
-                    ") " + operation + " '" + queryTerm.toLowerCase() + "']";
-        }
-        executeXPathQuery(xpath, nodes);
+      // run queries with lower-case
+      String xpath = testPath;
+      if (operation.equals("like"))
+      {
+         xpath += "/*[jcr:like(fn:lower-case(@" + propertyName1 + "), '" + queryTerm.toLowerCase() + "')]";
+      }
+      else
+      {
+         xpath += "/*[fn:lower-case(@" + propertyName1 + ") " + operation + " '" + queryTerm.toLowerCase() + "']";
+      }
+      executeXPathQuery(xpath, nodes);
 
-        String sql = "select * from nt:base where jcr:path like '" +
-                testRoot + "/%' and LOWER(" + propertyName1 + ") " +
-                sqlOperation + " '" + queryTerm.toLowerCase() + "'";
-        executeSQLQuery(sql, nodes);
+      String sql =
+         "select * from nt:base where jcr:path like '" + testRoot + "/%' and LOWER(" + propertyName1 + ") "
+            + sqlOperation + " '" + queryTerm.toLowerCase() + "'";
+      executeSQLQuery(sql, nodes);
 
+      // run queries with upper-case
+      xpath = testPath;
+      if (operation.equals("like"))
+      {
+         xpath += "/*[jcr:like(fn:upper-case(@" + propertyName1 + "), '" + queryTerm.toUpperCase() + "')]";
+      }
+      else
+      {
+         xpath += "/*[fn:upper-case(@" + propertyName1 + ") " + operation + " '" + queryTerm.toUpperCase() + "']";
+      }
+      executeXPathQuery(xpath, nodes);
 
+      sql =
+         "select * from nt:base where jcr:path like '" + testRoot + "/%' and UPPER(" + propertyName1 + ") "
+            + sqlOperation + " '" + queryTerm.toUpperCase() + "'";
+      executeSQLQuery(sql, nodes);
 
-        // run queries with upper-case
-        xpath = testPath;
-        if (operation.equals("like")) {
-            xpath += "/*[jcr:like(fn:upper-case(@" + propertyName1 +
-                    "), '" + queryTerm.toUpperCase() + "')]";
-        } else {
-            xpath += "/*[fn:upper-case(@" + propertyName1 +
-                    ") " + operation + " '" + queryTerm.toUpperCase() + "']";
-        }
-        executeXPathQuery(xpath, nodes);
+   }
 
-        sql = "select * from nt:base where jcr:path like '" +
-                testRoot + "/%' and UPPER(" + propertyName1 + ") " +
-                sqlOperation + " '" + queryTerm.toUpperCase() + "'";
-        executeSQLQuery(sql, nodes);
+   private char getRandomChar(String pool, Random random)
+   {
+      return pool.charAt(random.nextInt(pool.length()));
+   }
 
-
-    }
-
-    private char getRandomChar(String pool, Random random) {
-        return pool.charAt(random.nextInt(pool.length()));
-    }
-
-//    protected static int getOperatorForString(String operator) {
-//        Integer i = (Integer) OPERATORS.get(operator);
-//        if (i == null) {
-//            throw new IllegalArgumentException("unknown operator: " + operator);
-//        }
-//        return i.intValue();
-//    }
+   //    protected static int getOperatorForString(String operator) {
+   //        Integer i = (Integer) OPERATORS.get(operator);
+   //        if (i == null) {
+   //            throw new IllegalArgumentException("unknown operator: " + operator);
+   //        }
+   //        return i.intValue();
+   //    }
 }

Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+import org.exoplatform.services.jcr.JcrImplBaseTest;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * <br/>Date: 13.11.2009
+ *
+ * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a> 
+ * @version $Id$
+ */
+public class TestNodeOrder extends JcrImplBaseTest
+{
+
+   public void testOrder() throws Exception
+   {
+      Node testNode = root.addNode("testNode");
+      session.save();
+      testNode.addNode("z");
+      session.save();
+      testNode.addNode("a");
+      session.save();
+      testNode.addNode("b");
+      session.save();
+      testNode.addNode("c");
+
+      // check
+      NodeIterator nodes = testNode.getNodes();
+      assertEquals(4, nodes.getSize());
+
+      int order = 0;
+      for (; nodes.hasNext();)
+      {
+         NodeImpl n = (NodeImpl)nodes.nextNode();
+         int orderNumb = ((NodeData)n.getData()).getOrderNumber();
+         log.info(orderNumb + ": " + n.getPath());
+
+         assertEquals(order++, orderNumb);
+      }
+   }
+
+   public void testOrderInSession() throws Exception
+   {
+      Node testNode = root.addNode("testNode");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("a");
+      testNode.addNode("z");
+      testNode.addNode("a");
+
+      // check
+      NodeIterator nodes = testNode.getNodes();
+      assertEquals(4, nodes.getSize());
+
+      int order = 0;
+      for (; nodes.hasNext();)
+      {
+         NodeImpl n = (NodeImpl)nodes.nextNode();
+         int orderNumb = ((NodeData)n.getData()).getOrderNumber();
+         log.info(orderNumb + ": " + n.getPath());
+
+         assertEquals(order++, orderNumb);
+      }
+   }
+
+   public void testOrderCombined() throws Exception
+   {
+      Node testNode = root.addNode("testNode");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("a");
+      testNode.addNode("z");
+      testNode.addNode("a");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("y");
+      session.save();
+
+      testNode.addNode("c");
+      testNode.addNode("a");
+      session.save();
+
+      // check
+      NodeIterator nodes = testNode.getNodes();
+      assertEquals(8, nodes.getSize());
+
+      int order = 0;
+      for (; nodes.hasNext();)
+      {
+         NodeImpl n = (NodeImpl)nodes.nextNode();
+         int orderNumb = ((NodeData)n.getData()).getOrderNumber();
+         log.info(orderNumb + ": " + n.getPath());
+
+         assertEquals(order++, orderNumb);
+      }
+   }
+
+   public void testOrderWithRefreshDiscard() throws Exception
+   {
+      Node testNode = root.addNode("testNode");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("a");
+      testNode.addNode("z");
+      testNode.addNode("a");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("y");
+      root.refresh(false); // discard added a and y
+
+      testNode.addNode("c");
+      testNode.addNode("a");
+      session.save();
+
+      // check
+      NodeIterator nodes = testNode.getNodes();
+      assertEquals(6, nodes.getSize());
+
+      int order = 0;
+      for (; nodes.hasNext();)
+      {
+         NodeImpl n = (NodeImpl)nodes.nextNode();
+         int orderNumb = ((NodeData)n.getData()).getOrderNumber();
+         log.info(orderNumb + ": " + n.getPath());
+
+         assertEquals(order++, orderNumb);
+      }
+   }
+
+   public void testOrderWithInvalidation() throws Exception
+   {
+      Node testNode = root.addNode("testNode");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("a");
+      testNode.addNode("z");
+      testNode.addNode("a");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("y");
+
+      // add some in another session
+      Session another = repository.login(credentials, root.getSession().getWorkspace().getName());
+      Node anotherTest = another.getRootNode().getNode("testNode");
+      another.save();
+      anotherTest.addNode("a");
+      anotherTest.addNode("y");
+      another.save();
+      another.logout();
+
+      try
+      {
+         session.save();
+         fail("Nodes already added in another session, ItemExistsException should be thrown");
+      }
+      catch (ItemExistsException e)
+      {
+         // ok
+         root.refresh(false); // discard a and y
+      }
+
+      testNode.addNode("c");
+      testNode.addNode("a");
+      session.save();
+
+      // check
+      NodeIterator nodes = testNode.getNodes();
+      assertEquals(8, nodes.getSize());
+
+      int order = 0;
+      for (; nodes.hasNext();)
+      {
+         NodeImpl n = (NodeImpl)nodes.nextNode();
+         int orderNumb = ((NodeData)n.getData()).getOrderNumber();
+         log.info(orderNumb + ": " + n.getPath());
+
+         assertEquals(order++, orderNumb);
+      }
+   }
+   
+   public void testOrderWithRefreshKeep() throws Exception
+   {
+      Node testNode = root.addNode("testNode");
+      session.save();
+
+      testNode.addNode("a");
+      testNode.addNode("a");
+      testNode.addNode("z");
+      testNode.addNode("a");
+      session.save();
+
+      // add some in another session
+      Session another = repository.login(credentials, root.getSession().getWorkspace().getName());
+      Node anotherTest = another.getRootNode().getNode("testNode");
+      another.save();
+      anotherTest.addNode("a");
+      anotherTest.addNode("y");
+      another.save();
+      another.logout();
+
+      //root.refresh(true); // refresh to see another Session
+      testNode.addNode("a");
+      testNode.addNode("y");
+      session.save();
+
+      // check
+      NodeIterator nodes = testNode.getNodes();
+      assertEquals(8, nodes.getSize());
+
+      int order = 0;
+      for (; nodes.hasNext();)
+      {
+         NodeImpl n = (NodeImpl)nodes.nextNode();
+         int orderNumb = ((NodeData)n.getData()).getOrderNumber();
+         log.info(orderNumb + ": " + n.getPath());
+
+         assertEquals(order++, orderNumb);
+      }
+   }
+
+}


Property changes on: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/TestNodeOrder.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/load/perf/TestGetNodesPerf.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/load/perf/TestGetNodesPerf.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/load/perf/TestGetNodesPerf.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2003-2009 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.load.perf;
+
+import org.exoplatform.services.jcr.JcrAPIBaseTest;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * <br/>Date: 2009
+ *
+ * @author <a href="mailto:anatoliy.bazko at exoplatform.com.ua">Anatoliy Bazko</a> 
+ * @version $Id$
+ */
+public class TestGetNodesPerf extends JcrAPIBaseTest
+{
+   private static final String testName = "testRoot";
+
+   private static final int sessionCount = 10;
+
+   private static final int tryCount = 5;
+
+   private Session[] sessions = new Session[sessionCount];
+
+   private GetNodesThread[] threads = new GetNodesThread[sessionCount];
+
+   public void testGetNodes() throws Exception
+   {
+      for (int i = 0; i < sessionCount; i++)
+      {
+         sessions[i] = (SessionImpl)repository.login(credentials, "ws");
+      }
+
+      Node testRoot = session.getRootNode().addNode(testName);
+      session.save();
+
+      log.info("adding...");
+      int nodesCount = 50000;
+      for (int i = 0; i < nodesCount; i++)
+      {
+         testRoot.addNode("_" + i + "_node");
+      }
+      log.info("saving...");
+      session.save();
+
+      log.info("waiting for 10 seconds...");
+      Thread.sleep(10000);
+
+      System.gc();
+      Runtime rt = Runtime.getRuntime();
+      long usedMemory = rt.totalMemory() - rt.freeMemory();
+
+      log.info("getting nodes...");
+      for (int k = 0; k < tryCount; k++)
+      {
+         for (int i = 0; i < sessionCount; i++)
+         {
+            threads[i] = new GetNodesThread(sessions[i]);
+            threads[i].start();
+         }
+
+         outer : while (true)
+         {
+            for (int i = 0; i < sessionCount; i++)
+            {
+               if (threads[i].isAlive())
+               {
+                  Thread.sleep(1000);
+                  continue outer;
+               }
+            }
+
+            break;
+         }
+
+         log.info("waiting for 10 seconds...");
+         Thread.sleep(10000);
+      }
+      log.info("Memory used: " + (rt.totalMemory() - rt.freeMemory() - usedMemory) / 1024 / 1024 + "Mb");
+   }
+
+   private class GetNodesThread extends Thread
+   {
+      private final Session curSession;
+
+      private NodeIterator nodes;
+
+      GetNodesThread(Session session)
+      {
+         this.curSession = session;
+      }
+
+      @Override
+      public void run()
+      {
+         try
+         {
+            Node testRoot = curSession.getRootNode().getNode(testName);
+
+            long startTime = System.currentTimeMillis();
+            nodes = testRoot.getNodes();
+            log.info("Total time: " + (System.currentTimeMillis() - startTime) + "ms");
+
+         }
+         catch (Exception e)
+         {
+            e.printStackTrace();
+         }
+      }
+   }
+}


Property changes on: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/load/perf/TestGetNodesPerf.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/BaseStandaloneTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/BaseStandaloneTest.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/BaseStandaloneTest.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -388,7 +388,7 @@
       return testFile;
    }
 
-   protected void checkMixins(String[] mixins, NodeImpl node)
+   protected void checkMixins(String[] mixins, NodeImpl node) throws RepositoryException
    {
       try
       {

Modified: jcr/trunk/exo.jcr.component.ftp/src/test/java/org/exoplatform/services/ftp/BaseStandaloneTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.ftp/src/test/java/org/exoplatform/services/ftp/BaseStandaloneTest.java	2009-11-29 20:16:22 UTC (rev 905)
+++ jcr/trunk/exo.jcr.component.ftp/src/test/java/org/exoplatform/services/ftp/BaseStandaloneTest.java	2009-11-30 10:36:38 UTC (rev 906)
@@ -343,7 +343,7 @@
       return testFile;
    }
 
-   protected void checkMixins(String[] mixins, NodeImpl node)
+   protected void checkMixins(String[] mixins, NodeImpl node) throws RepositoryException
    {
       try
       {



More information about the exo-jcr-commits mailing list