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

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Feb 22 09:52:14 EST 2011


Author: sergiykarpenko
Date: 2011-02-22 09:52:13 -0500 (Tue, 22 Feb 2011)
New Revision: 4006

Added:
   jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml
Modified:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java
Log:
EXOJCR-1207: Export/Import child nodes version history into single xml with parent version history

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -22,6 +22,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.Map;
 
 import javax.jcr.InvalidSerializedDataException;
@@ -62,7 +63,7 @@
     * @throws RepositoryException if any repository errors occurs
     */
    Node getNodeByIdentifier(String identifier) throws ItemNotFoundException, RepositoryException;
-   
+
    /**
     * Deserialize an XML document and adds the resulting item subtree as a child of the node at
     * parentAbsPath.
@@ -86,6 +87,60 @@
       InvalidSerializedDataException, RepositoryException;
 
    /**
+    * Serializes the node (and if <code>noRecurse</code> is <code>false</code>,
+    * the whole subtree) at <code>absPath</code> into a series of SAX events by
+    * calling the methods of the supplied <code>org.xml.sax.ContentHandler</code>.
+    * The resulting XML is in the document view form. Note that <code>absPath</code>
+    * must be the path of a node, not a property.
+    * <p>
+    * If <code>skipBinary</code> is true then any properties of <code>PropertyType.BINARY</code> will be
+    * serialized as if they are empty. That is, the existence of the property
+    * will be serialized, but its content will not appear in the serialized
+    * output (the value of the attribute will be empty). If <code>skipBinary</code> is false
+    * then the actual value(s) of each <code>BINARY</code> property is recorded using Base64
+    * encoding.
+    * <p>
+    * If <code>noRecurse</code> is true then only the node at
+    * <code>absPath</code> and its properties, but not its child nodes, are
+    * serialized. If <code>noRecurse</code> is <code>false</code> then the entire subtree
+    * rooted at <code>absPath</code> is serialized.
+    * <p>
+    * If the user lacks read access to some subsection of the specified tree,
+    * that section simply does not get serialized, since, from the user's
+    * point of view, it is not there.
+    * <p>
+    * The serialized output will reflect the state of the current workspace as
+    * modified by the state of this <code>Session</code>. This means that
+    * pending changes (regardless of whether they are valid according to
+    * node type constraints) and the current session-mapping of namespaces
+    * are reflected in the output.
+    * <p>
+    * A <code>PathNotFoundException</code> is thrown if no node exists at <code>absPath</code>.
+    * <p>
+    * A <code>SAXException</code> is thrown if an error occurs while feeding events to the
+    * <code>ContentHandler</code>.
+    *
+    * @param absPath The path of the root of the subtree to be serialized.
+    * This must be the path to a node, not a property
+    * @param contentHandler The  <code>org.xml.sax.ContentHandler</code> to
+    * which the SAX events representing the XML serialization of the subtree
+    * will be output.
+    * @param skipBinary A <code>boolean</code> governing whether binary
+    * properties are to be serialized.
+    * @param noRecurse A <code>boolean</code> governing whether the subtree at
+    * absPath is to be recursed.
+    * @param exportChildVersionHisotry A <code>boolean</code> governing whether child nodes 
+    * version histories must be included into resulting xml. 
+    * 
+    * @throws PathNotFoundException if no node exists at <code>absPath</code>.
+    * @throws org.xml.sax.SAXException if an error occurs while feeding events to the
+    * <code>org.xml.sax.ContentHandler</code>.
+    * @throws RepositoryException if another error occurs.
+    */
+   void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse,
+      boolean exportChildVersionHisotry) throws IOException, PathNotFoundException, RepositoryException;
+
+   /**
     * Registers session listener.
     * 
     * @param listener

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -579,6 +579,11 @@
    public static final String SV_NODE = "node";
 
    /**
+    * SV_VERSION_HISTORY.
+    */
+   public static final String SV_VERSION_HISTORY = "versionhistory";
+
+   /**
     * SV_PROPERTY.
     */
    public static final String SV_PROPERTY = "property";
@@ -614,6 +619,11 @@
    public static final InternalQName SV_NODE_NAME = new InternalQName(NS_SV_URI, SV_NODE);
 
    /**
+    * sv:versionhistory internal name.
+    */
+   public static final InternalQName SV_VERSION_HISTORY_NAME = new InternalQName(NS_SV_URI, SV_VERSION_HISTORY);
+
+   /**
     * sv:property internal name.
     */
    public static final InternalQName SV_PROPERTY_NAME = new InternalQName(NS_SV_URI, SV_PROPERTY);
@@ -677,7 +687,7 @@
     * eXo JCR default Strings encoding.
     */
    public static final String DEFAULT_ENCODING = "UTF-8";
-   
+
    /**
     * System identifier for remote workspace initializer changes.
     */

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -409,8 +409,8 @@
    /**
     * {@inheritDoc}
     */
-   public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse)
-      throws IOException, PathNotFoundException, RepositoryException
+   public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse,
+      boolean exportChildVersionHisotry) throws IOException, PathNotFoundException, RepositoryException
    {
       checkLive();
 
@@ -426,7 +426,8 @@
       {
          BaseXmlExporter exporter =
             new ExportImportFactory().getExportVisitor(XmlMapping.SYSVIEW, out, skipBinary, noRecurse,
-               getTransientNodesManager(), repository.getNamespaceRegistry(), valueFactoryImpl);
+               exportChildVersionHisotry, getTransientNodesManager(), repository.getNamespaceRegistry(),
+               valueFactoryImpl);
 
          JCRPath srcNodePath = getLocationFactory().parseAbsPath(absPath);
          ItemData srcItemData = dataManager.getItemData(srcNodePath.getInternalPath());
@@ -446,9 +447,19 @@
       {
          throw new IOException(e.getLocalizedMessage());
       }
+
    }
 
    /**
+    * {@inheritDoc}
+    */
+   public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse)
+      throws IOException, PathNotFoundException, RepositoryException
+   {
+      exportSystemView(absPath, out, skipBinary, noRecurse, false);
+   }
+
+   /**
     * @return Returns the accessManager.
     */
    public AccessManager getAccessManager()

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -112,7 +112,33 @@
       ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory)
       throws NamespaceException, RepositoryException, IOException
    {
+      return getExportVisitor(type, stream, skipBinary, noRecurse, false, dataManager, namespaceRegistry,
+         systemValueFactory);
+   }
 
+   /**
+    * Create export visitor for given type of view.\
+    * 
+    * @param type - 6.4 XML Mappings
+    * @param stream - output result stream
+    * @param skipBinary- If skipBinary is true then any properties of
+    *          PropertyType.BINARY will be serialized as if they are empty.
+    * @param noRecurse- if noRecurse is false, the whole subtree are serialized
+    * @param exportChildVersionHistory - does versioned child nodes version history must be exported
+    *          (works ONLY with system view).
+    * @param dataManager - ItemDataConsumer
+    * @param namespaceRegistry - NamespaceRegistry
+    * @param systemValueFactory - default value factory
+    * @return - visitor BaseXmlExporter.
+    * @throws NamespaceException
+    * @throws RepositoryException
+    * @throws IOException
+    */
+   public BaseXmlExporter getExportVisitor(XmlMapping type, OutputStream stream, boolean skipBinary, boolean noRecurse,
+      boolean exportChildVersionHistory, ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry,
+      ValueFactoryImpl systemValueFactory) throws NamespaceException, RepositoryException, IOException
+   {
+
       XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
       XMLStreamWriter streamWriter;
       try
@@ -127,7 +153,7 @@
       if (type == XmlMapping.SYSVIEW)
       {
          return new SystemViewStreamExporter(streamWriter, dataManager, namespaceRegistry, systemValueFactory,
-            skipBinary, noRecurse);
+            skipBinary, noRecurse, exportChildVersionHistory);
       }
       else if (type == XmlMapping.DOCVIEW)
       {

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -49,7 +49,7 @@
       NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse)
       throws NamespaceException, RepositoryException
    {
-      super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse);
+      super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, false);
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -38,14 +38,22 @@
 
    protected final XMLStreamWriter writer;
 
+   protected final boolean exportChildVersionHistory;
+
    public StreamExporter(XMLStreamWriter writer, ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry,
       ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse) throws NamespaceException,
       RepositoryException
    {
+      this(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, false);
+   }
 
+   public StreamExporter(XMLStreamWriter writer, ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry,
+      ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse, boolean exportChildVersionHistory)
+      throws NamespaceException, RepositoryException
+   {
       super(dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, noRecurse ? 1 : -1);
       this.writer = writer;
-
+      this.exportChildVersionHistory = exportChildVersionHistory;
    }
 
    @Override

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -21,14 +21,17 @@
 import org.apache.ws.commons.util.Base64;
 import org.exoplatform.services.jcr.core.ExtendedPropertyType;
 import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
+import org.exoplatform.services.jcr.datamodel.ItemType;
 import org.exoplatform.services.jcr.datamodel.NodeData;
 import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
 import org.exoplatform.services.jcr.datamodel.ValueData;
 import org.exoplatform.services.jcr.impl.Constants;
 import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.jcr.NamespaceException;
@@ -47,6 +50,8 @@
 
    private static final int BUFFER_SIZE = 3 * 1024 * 3;
 
+   private static final List<String> exportedVersionHistories = new ArrayList<String>();
+
    /**
     * @param writer
     * @param session
@@ -59,9 +64,17 @@
       NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse)
       throws NamespaceException, RepositoryException
    {
-      super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse);
+      this(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, false);
    }
 
+   public SystemViewStreamExporter(XMLStreamWriter writer, ItemDataConsumer dataManager,
+      NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse,
+      boolean exportChildVersionHistory) throws NamespaceException, RepositoryException
+   {
+      super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse,
+         exportChildVersionHistory);
+   }
+
    /*
     * (non-Javadoc)
     * @see
@@ -145,6 +158,40 @@
    {
       try
       {
+         if (exportChildVersionHistory && node.getPrimaryTypeName().equals(Constants.NT_VERSIONEDCHILD))
+         {
+            try
+            {
+               PropertyData childVersionHistory =
+                  ((PropertyData)dataManager.getItemData(node, new QPathEntry(Constants.JCR_CHILDVERSIONHISTORY, 1),
+                     ItemType.PROPERTY));
+               String childVersionHistoryId =
+                  getValueAsStringForExport(childVersionHistory.getValues().get(0), childVersionHistory.getType());
+
+               //check does this child version history was already exported
+               if (!exportedVersionHistories.contains(childVersionHistoryId))
+               {
+
+                  writer.writeStartElement(Constants.NS_SV_PREFIX, Constants.SV_VERSION_HISTORY, getSvNamespaceUri());
+                  writer.writeAttribute(Constants.NS_SV_PREFIX, getSvNamespaceUri(), Constants.SV_NAME,
+                     childVersionHistoryId);
+
+                  NodeData versionStorage = (NodeData)dataManager.getItemData(Constants.VERSIONSTORAGE_UUID);
+                  NodeData childVersionNodeData =
+                     (NodeData)dataManager.getItemData(versionStorage, new QPathEntry("", childVersionHistoryId, 1),
+                        ItemType.NODE);
+                  childVersionNodeData.accept(this);
+
+                  writer.writeEndElement();
+                  exportedVersionHistories.add(childVersionHistoryId);
+               }
+            }
+            catch (IOException e)
+            {
+               throw new RepositoryException("Can't export versioned child version history: " + e.getMessage(), e);
+            }
+         }
+
          writer.writeEndElement();
       }
       catch (XMLStreamException e)

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -35,6 +35,8 @@
     */
    public String RESPECT_PROPERTY_DEFINITIONS_CONSTRAINTS = "respectPropertyDefinitionsConstraints";
 
+   public final String LIST_OF_IMPORTED_VERSION_HISTORIES = "importedSubversions";
+
    /**
     * Receive notification of character data.
     * 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -18,21 +18,6 @@
  */
 package org.exoplatform.services.jcr.impl.xml.importing;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-
 import org.exoplatform.services.jcr.access.AccessManager;
 import org.exoplatform.services.jcr.core.ExtendedPropertyType;
 import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
@@ -42,8 +27,10 @@
 import org.exoplatform.services.jcr.datamodel.IllegalNameException;
 import org.exoplatform.services.jcr.datamodel.IllegalPathException;
 import org.exoplatform.services.jcr.datamodel.InternalQName;
+import org.exoplatform.services.jcr.datamodel.ItemType;
 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.datamodel.ValueData;
 import org.exoplatform.services.jcr.impl.Constants;
 import org.exoplatform.services.jcr.impl.core.JCRName;
@@ -51,6 +38,7 @@
 import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
 import org.exoplatform.services.jcr.impl.core.value.BaseValue;
 import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
+import org.exoplatform.services.jcr.impl.dataflow.ItemDataRemoveVisitor;
 import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
 import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
 import org.exoplatform.services.jcr.impl.xml.DecodedValue;
@@ -62,6 +50,21 @@
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.security.ConversationState;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
 /**
  * Created by The eXo Platform SAS.
  * 
@@ -171,6 +174,11 @@
          DecodedValue curPropValue = propertyInfo.getValues().get(propertyInfo.getValues().size() - 1);
          curPropValue.setComplete(true);
       }
+      else if (Constants.SV_VERSION_HISTORY_NAME.equals(elementName))
+      {
+         // remove version storage node from tree
+         tree.pop();
+      }
       else
       {
          throw new RepositoryException("invalid element in system view xml document: " + localName);
@@ -260,6 +268,36 @@
          propertyInfo.getValues().add(new DecodedValue());
 
       }
+      else if (Constants.SV_VERSION_HISTORY_NAME.equals(elementName))
+      {
+         String svName = getAttribute(atts, Constants.SV_NAME_NAME);
+         if (svName == null)
+         {
+            throw new RepositoryException("Missing mandatory sv:name attribute of element sv:versionhistory");
+         }
+
+         NodeData versionStorage = (NodeData)this.dataConsumer.getItemData(Constants.VERSIONSTORAGE_UUID);
+
+         NodeData versionHistory =
+            (NodeData)dataConsumer.getItemData(versionStorage, new QPathEntry("", svName, 1), ItemType.NODE);
+
+         if (versionHistory != null)
+         {
+            RemoveVisitor rv = new RemoveVisitor();
+            rv.visit(versionHistory);
+            changesLog.addAll(rv.getRemovedStates());
+         }
+         tree.push(versionStorage);
+
+         List<String> list = (List<String>)context.get(ContentImporter.LIST_OF_IMPORTED_VERSION_HISTORIES);
+         if (list == null)
+         {
+            list = new ArrayList<String>();
+         }
+         list.add(svName);
+         context.put(ContentImporter.LIST_OF_IMPORTED_VERSION_HISTORIES, list);
+
+      }
       else
       {
          throw new RepositoryException("Unknown element " + elementName.getAsString());
@@ -687,4 +725,25 @@
       JCRName jname = locationFactory.createJCRName(name);
       return attributes.get(jname.getAsString());
    }
+
+   protected class RemoveVisitor extends ItemDataRemoveVisitor
+   {
+      /**
+       * Default constructor.
+       * 
+       * @throws RepositoryException - exception.
+       */
+      RemoveVisitor() throws RepositoryException
+      {
+         super(dataConsumer, null, nodeTypeDataManager, accessManager, userState);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      protected void validateReferential(NodeData node) throws RepositoryException
+      {
+         // no REFERENCE validation here
+      }
+   };
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -23,23 +23,31 @@
 import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
 import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
 import org.exoplatform.services.jcr.datamodel.Identifier;
+import org.exoplatform.services.jcr.datamodel.ItemType;
 import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
 import org.exoplatform.services.jcr.datamodel.ValueData;
 import org.exoplatform.services.jcr.impl.Constants;
 import org.exoplatform.services.jcr.impl.core.NodeImpl;
 import org.exoplatform.services.jcr.impl.core.PropertyImpl;
+import org.exoplatform.services.jcr.impl.core.SessionDataManager;
 import org.exoplatform.services.jcr.impl.core.SessionImpl;
 import org.exoplatform.services.jcr.impl.dataflow.ItemDataRemoveVisitor;
 import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
 import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
+import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
 import org.exoplatform.services.jcr.impl.xml.ItemDataKeeperAdapter;
+import org.exoplatform.services.jcr.impl.xml.importing.ContentImporter;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -144,7 +152,7 @@
       {
          uuid = versionableNode.getUUID();
          path = versionableNode.getVersionHistory().getParent().getPath();
-         LOG.info("Started: Import version history for node wiht path=" + path + " and UUID=" + uuid);
+         LOG.info("Started: Import version history for node with path=" + path + " and UUID=" + uuid);
 
          NodeData versionable = (NodeData)versionableNode.getData();
          // ----- VERSIONABLE properties -----
@@ -176,32 +184,43 @@
          changesLog.add(ItemState.createAddedState(bv));
          changesLog.add(ItemState.createAddedState(pd));
          // remove version properties to avoid referential integrety check
-         PlainChangesLog changesLogDeltete = new PlainChangesLogImpl();
+         PlainChangesLog changesLogDelete = new PlainChangesLogImpl();
 
-         changesLogDeltete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
+         changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
             .getProperty("jcr:versionHistory")).getData()));
-         changesLogDeltete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
+         changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
             .getProperty("jcr:baseVersion")).getData()));
-         changesLogDeltete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
+         changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
             .getProperty("jcr:predecessors")).getData()));
-         dataKeeper.save(changesLogDeltete);
+         dataKeeper.save(changesLogDelete);
          // remove version history
          dataKeeper.save(changesLog);
          userSession.save();
+
          // import new version history
-         userSession.getWorkspace().importXML(path, versionHistoryStream, 0);
+         Map<String, Object> context = new HashMap<String, Object>();
+         //context.put("versionablenode", versionableNode);
+         context.put(ContentImporter.RESPECT_PROPERTY_DEFINITIONS_CONSTRAINTS, true);
+         userSession.getWorkspace().importXML(path, versionHistoryStream, 0, context);
          userSession.save();
 
-         LOG.info("Completed: Import version history for node wiht path=" + path + " and UUID=" + uuid);
+         LOG.info("Completed: Import version history for node with path=" + path + " and UUID=" + uuid);
+
+         // fetch list of imported child nodes versions
+         List<String> versionUuids = (List<String>)context.get(ContentImporter.LIST_OF_IMPORTED_VERSION_HISTORIES);
+         if (versionUuids != null && !versionUuids.isEmpty())
+         {
+            updateVersionedChildNodes(versionUuids);
+         }
       }
       catch (RepositoryException exception)
       {
-         LOG.error("Failed: Import version history for node wiht path=" + path + " and UUID=" + uuid, exception);
+         LOG.error("Failed: Import version history for node with path=" + path + " and UUID=" + uuid, exception);
          throw new RepositoryException(exception);
       }
       catch (IOException exception)
       {
-         LOG.error("Failed: Import version history for node wiht path=" + path + " and UUID=" + uuid, exception);
+         LOG.error("Failed: Import version history for node with path=" + path + " and UUID=" + uuid, exception);
          IOException newException = new IOException();
          newException.initCause(exception);
          throw newException;
@@ -209,6 +228,120 @@
    }
 
    /**
+    * Update child nodes that owns versions from versionUuids list. 
+    * 
+    * @param versionUuids - list of version histories uuids.
+    * @throws RepositoryException
+    * @throws IOException
+    */
+   private void updateVersionedChildNodes(List<String> versionUuids) throws RepositoryException, IOException
+   {
+      SessionDataManager dataManager = userSession.getTransientNodesManager();
+
+      NodeData versionStorage = (NodeData)dataManager.getItemData(Constants.VERSIONSTORAGE_UUID);
+
+      for (String versionUuid : versionUuids)
+      {
+         NodeData versionHistoryData =
+            (NodeData)dataManager.getItemData(versionStorage, new QPathEntry("", versionUuid, 1), ItemType.NODE);
+
+         PropertyData versionableUuidProp =
+            (PropertyData)dataManager.getItemData(versionHistoryData, new QPathEntry(Constants.JCR_VERSIONABLEUUID, 1),
+               ItemType.PROPERTY);
+
+         String versionableUuid = ValueDataConvertor.readString(versionableUuidProp.getValues().get(0));
+
+         // fetch child versionable node
+
+         NodeData versionedChild = (NodeData)dataManager.getItemData(versionableUuid);
+
+         if (versionedChild != null && versionedChild.getQPath().isDescendantOf(versionableNode.getData().getQPath()))
+         {
+            // find latest version
+            String latestVersionUuid = null;
+            for (int versionNumber = 1;; versionNumber++)
+            {
+               NodeData nodeData =
+                  (NodeData)dataManager.getItemData(versionHistoryData, new QPathEntry("", Integer
+                     .toString(versionNumber), 1), ItemType.NODE);
+
+               if (nodeData == null)
+               {
+                  break;
+               }
+               else
+               {
+                  latestVersionUuid = nodeData.getIdentifier();
+               }
+            }
+
+            if (latestVersionUuid == null)
+            {
+               // fetch root version
+               NodeData rootVersion =
+                  (NodeData)dataManager.getItemData(versionHistoryData, new QPathEntry(Constants.JCR_ROOTVERSION, 1),
+                     ItemType.NODE);
+               latestVersionUuid = rootVersion.getIdentifier();
+            }
+
+            PropertyData propVersionHistory =
+               (PropertyData)dataManager.getItemData(versionedChild, new QPathEntry(Constants.JCR_VERSIONHISTORY, 1),
+                  ItemType.PROPERTY);
+            String prevVerHistoryId = ValueDataConvertor.readString(propVersionHistory.getValues().get(0));
+
+            PropertyData propBaseVersion =
+               (PropertyData)dataManager.getItemData(versionedChild, new QPathEntry(Constants.JCR_BASEVERSION, 1),
+                  ItemType.PROPERTY);
+
+            PropertyData propPredecessors =
+               (PropertyData)dataManager.getItemData(versionedChild, new QPathEntry(Constants.JCR_PREDECESSORS, 1),
+                  ItemType.PROPERTY);
+
+            TransientPropertyData newVersionHistoryProp =
+               TransientPropertyData.createPropertyData(versionedChild, Constants.JCR_VERSIONHISTORY,
+                  PropertyType.REFERENCE, false, new TransientValueData(new Identifier(versionUuid)));
+
+            // jcr:baseVersion
+            TransientPropertyData newBaseVersionProp =
+               TransientPropertyData.createPropertyData(versionedChild, Constants.JCR_BASEVERSION,
+                  PropertyType.REFERENCE, false, new TransientValueData(new Identifier(latestVersionUuid)));
+
+            // jcr:predecessors
+            List<ValueData> predecessorValues = new ArrayList<ValueData>();
+            predecessorValues.add(new TransientValueData(new Identifier(latestVersionUuid)));
+            TransientPropertyData newPredecessorsProp =
+               TransientPropertyData.createPropertyData(versionedChild, Constants.JCR_PREDECESSORS,
+                  PropertyType.REFERENCE, true, predecessorValues);
+
+            //remove previous version of childnode nad update properties
+            NodeData prevVersionHistory = (NodeData)dataManager.getItemData(prevVerHistoryId);
+
+            PlainChangesLogImpl changesLog = new PlainChangesLogImpl();
+            if (!prevVerHistoryId.equals(versionUuid))
+            {
+               RemoveVisitor rv = new RemoveVisitor();
+               rv.visit(prevVersionHistory);
+               changesLog.addAll(rv.getRemovedStates());
+            }
+            changesLog.add(ItemState.createAddedState(newVersionHistoryProp));
+            changesLog.add(ItemState.createAddedState(newBaseVersionProp));
+            changesLog.add(ItemState.createAddedState(newPredecessorsProp));
+
+            PlainChangesLogImpl changesLogDelete = new PlainChangesLogImpl();
+            changesLogDelete.add(ItemState.createDeletedState(propVersionHistory));
+            changesLogDelete.add(ItemState.createDeletedState(propBaseVersion));
+            changesLogDelete.add(ItemState.createDeletedState(propPredecessors));
+            dataKeeper.save(changesLogDelete);
+            // remove version history
+            dataKeeper.save(changesLog);
+            userSession.save();
+            LOG.info("Completed: Import version history for node with path=" + versionedChild.getQPath().getAsString()
+               + " and UUID=" + versionedChild.getIdentifier());
+         }
+      }
+   }
+
+   /**
     * Remover helper.
     * 
     * @author sj

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java	2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java	2011-02-22 14:52:13 UTC (rev 4006)
@@ -24,10 +24,12 @@
 import org.exoplatform.services.jcr.impl.core.NodeImpl;
 import org.exoplatform.services.jcr.impl.core.PropertyImpl;
 import org.exoplatform.services.jcr.impl.core.SessionDataManager;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
 import org.exoplatform.services.jcr.util.VersionHistoryImporter;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
 import java.util.Calendar;
 
 import javax.jcr.ImportUUIDBehavior;
@@ -275,4 +277,776 @@
          session.save();
       }
    }
+
+   public void testImportVersionHistoryWithChildVersions() throws Exception
+   {
+      loadTestTree();
+      Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+      // make checkin/checkout a lot
+      wc1.checkin();
+      wc1.checkout();
+
+      // export import version history and node
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      session.exportSystemView("/parent/wc1", out, false, false, true);
+
+      ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+      session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+      // prepare data for version import
+      String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+      String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+      StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+      String[] predecessorsHistory;
+      for (Value value : jcrPredecessors)
+      {
+         if (jcrPredecessorsBuilder.length() > 0)
+            jcrPredecessorsBuilder.append(",");
+         jcrPredecessorsBuilder.append(value.getString());
+      }
+      if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+      }
+
+      // remember "picture" nodes version history data
+      Node picture = (NodeImpl)session.getItem("/parent/wc1/medias/picture");
+      String chversionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+      String chbaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] chjcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+      StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+      String[] chpredecessorsHistory;
+      for (Value value : chjcrPredecessors)
+      {
+         if (chjcrPredecessorsBuilder.length() > 0)
+            chjcrPredecessorsBuilder.append(",");
+         chjcrPredecessorsBuilder.append(value.getString());
+      }
+      if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+      }
+
+      // remove node
+      wc1.remove();
+      session.save();
+
+      out.close();
+      vhout.close();
+
+      // import
+      session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+         ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+            predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      picture = wc1.getNode("medias").getNode("picture");
+      assertTrue(picture.isNodeType("mix:versionable"));
+      assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+      assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+      assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+   }
+
+   public void testImportVersionHistoryPreloadChildVersionHistoryWithChildVersions() throws Exception
+   {
+      loadTestTree();
+      Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+      Node picture = (NodeImpl)session.getItem("/parent/wc1/medias/picture");
+
+      // make checkin/checkout a lot
+
+      wc1.checkin();
+      wc1.checkout();
+
+      picture.checkin();
+      picture.checkout();
+
+      // export import version history and node
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      session.exportSystemView("/parent/wc1", out, false, false);
+
+      ByteArrayOutputStream childvhout = new ByteArrayOutputStream();
+      session.exportSystemView(picture.getVersionHistory().getPath(), childvhout, false, false, true);
+
+      ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+      session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+      // prepare data for version import
+
+      String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+      String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+      StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+      String[] predecessorsHistory;
+      for (Value value : jcrPredecessors)
+      {
+         if (jcrPredecessorsBuilder.length() > 0)
+            jcrPredecessorsBuilder.append(",");
+         jcrPredecessorsBuilder.append(value.getString());
+      }
+      if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+      }
+
+      // prepare data for child version import
+
+      String chversionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+      String chbaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] chjcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+      StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+      String[] chpredecessorsHistory;
+      for (Value value : chjcrPredecessors)
+      {
+         if (chjcrPredecessorsBuilder.length() > 0)
+            chjcrPredecessorsBuilder.append(",");
+         chjcrPredecessorsBuilder.append(value.getString());
+      }
+      if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+      }
+
+      // remove node
+      wc1.remove();
+      session.save();
+
+      out.close();
+      vhout.close();
+
+      // import
+      session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+         ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      wc1 = (NodeImpl)session.getItem("/parent/wc1");
+      picture = wc1.getNode("medias").getNode("picture");
+
+      VersionHistoryImporter chversionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)picture, new ByteArrayInputStream(childvhout.toByteArray()),
+            chbaseVersion, chpredecessorsHistory, chversionHistory);
+      chversionHistoryImporter.doImport();
+      session.save();
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+            predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      assertTrue(picture.isNodeType("mix:versionable"));
+      assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+      assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+      assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+   }
+
+   /**
+    * Many mix:versionable subnodes. 
+    * @throws Exception
+    */
+   public void testImportVersionHistoryWithManySubversions() throws Exception
+   {
+
+      // wc1/medias/picture
+      Node wc1 = testRoot.addNode("wc1", "nt:folder");
+      wc1.addMixin("mix:versionable");
+      testRoot.save();
+      Node medias = wc1.addNode("medias", "nt:folder");
+
+      Node picture = medias.addNode("picture", "nt:file");
+      picture.addMixin("mix:versionable");
+
+      Node res = picture.addNode("jcr:content", "nt:resource");
+      res.setProperty("jcr:lastModified", Calendar.getInstance());
+      res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+      MimeTypeResolver mimres = new MimeTypeResolver();
+      res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+      root.save();
+
+      Node subNode1 = medias.addNode("subnode1", "nt:folder");
+      subNode1.addMixin("mix:versionable");
+      root.save();
+
+      Node subNode2 = subNode1.addNode("subnode2", "nt:folder");
+      Node subNode3 = subNode2.addNode("subnode3", "nt:folder");
+      subNode3.addMixin("mix:versionable");
+      root.save();
+
+      Node subNode4 = subNode3.addNode("subnode4", "nt:folder");
+      subNode4.addMixin("mix:versionable");
+      root.save();
+
+      // /medias/subnode1/subnode2/subnode3/subnode4
+      wc1.checkin();
+      wc1.checkout();
+
+      picture.checkin();
+      picture.checkout();
+
+      subNode1.checkin();
+      subNode1.checkout();
+
+      subNode4.checkin();
+      subNode4.checkout();
+
+      subNode3.checkin();
+      subNode3.checkout();
+
+      // export import version history and node
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      session.exportSystemView("/parent/wc1", out, false, false, true);
+
+      ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+      session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+      // prepare data for version import
+
+      String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+      String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+      StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+      String[] predecessorsHistory;
+      for (Value value : jcrPredecessors)
+      {
+         if (jcrPredecessorsBuilder.length() > 0)
+            jcrPredecessorsBuilder.append(",");
+         jcrPredecessorsBuilder.append(value.getString());
+      }
+      if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+      }
+
+      // prepare data for child version import
+
+      String chversionHistory = subNode4.getProperty("jcr:versionHistory").getValue().getString();
+      String chbaseVersion = subNode4.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] chjcrPredecessors = subNode4.getProperty("jcr:predecessors").getValues();
+      StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+      String[] chpredecessorsHistory;
+      for (Value value : chjcrPredecessors)
+      {
+         if (chjcrPredecessorsBuilder.length() > 0)
+            chjcrPredecessorsBuilder.append(",");
+         chjcrPredecessorsBuilder.append(value.getString());
+      }
+      if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+      }
+
+      // remove node
+      wc1.remove();
+      session.save();
+
+      out.close();
+      vhout.close();
+
+      // import
+      session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+         ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+      subNode4 = (NodeImpl)session.getItem("/parent/wc1/medias/subnode1/subnode2/subnode3/subnode4");
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+            predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      assertTrue(subNode4.isNodeType("mix:versionable"));
+      assertEquals(chversionHistory, subNode4.getProperty("jcr:versionHistory").getValue().getString());
+      assertEquals(chbaseVersion, subNode4.getProperty("jcr:baseVersion").getValue().getString());
+      assertEquals(chpredecessorsHistory[0], subNode4.getProperty("jcr:predecessors").getValues()[0].getString());
+   }
+
+   public void testImportVersionHistoryManyVersions() throws Exception
+   {
+      // wc1/medias/picture
+      Node wc1 = testRoot.addNode("wc1", "nt:folder");
+      wc1.addMixin("mix:versionable");
+      testRoot.save();
+      Node medias = wc1.addNode("medias", "nt:folder");
+
+      Node picture = medias.addNode("picture", "nt:file");
+      picture.addMixin("mix:versionable");
+
+      Node res = picture.addNode("jcr:content", "nt:resource");
+      res.setProperty("jcr:lastModified", Calendar.getInstance());
+      res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+      MimeTypeResolver mimres = new MimeTypeResolver();
+      res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+      root.save();
+
+      // make checkin/checkout a lot
+      wc1.checkin();
+      wc1.checkout();
+
+      picture.checkin();
+      picture.checkout();
+
+      res.setProperty("jcr:data", new ByteArrayInputStream("new data".getBytes()));
+      root.save();
+
+      picture.checkin();
+      picture.checkout();
+
+      // check before import
+
+      picture.restore("1", true);
+      String strvalue = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("bla bla", strvalue);
+
+      picture.restore("2", true);
+      strvalue = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("new data", strvalue);
+
+      picture.checkout();
+
+      // make new version
+      assertTrue(picture.getProperty("jcr:isCheckedOut").getValue().getBoolean());
+
+      // export import version history and node
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      session.exportSystemView("/parent/wc1", out, false, false, true);
+
+      ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+      session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+      // prepare data for version import
+
+      String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+      String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+      StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+      String[] predecessorsHistory;
+      for (Value value : jcrPredecessors)
+      {
+         if (jcrPredecessorsBuilder.length() > 0)
+            jcrPredecessorsBuilder.append(",");
+         jcrPredecessorsBuilder.append(value.getString());
+      }
+      if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+      }
+
+      String childVersionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+      String childBaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] childJcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+      StringBuilder childJcrPredecessorsBuilder = new StringBuilder();
+      String[] childPredecessorsHistory;
+      for (Value value : childJcrPredecessors)
+      {
+         if (childJcrPredecessorsBuilder.length() > 0)
+            childJcrPredecessorsBuilder.append(",");
+         childJcrPredecessorsBuilder.append(value.getString());
+      }
+      if (childJcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         childPredecessorsHistory = childJcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         childPredecessorsHistory = new String[]{childJcrPredecessorsBuilder.toString()};
+      }
+
+      String chversionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+      String chbaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] chjcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+      StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+      String[] chpredecessorsHistory;
+      for (Value value : chjcrPredecessors)
+      {
+         if (chjcrPredecessorsBuilder.length() > 0)
+            chjcrPredecessorsBuilder.append(",");
+         chjcrPredecessorsBuilder.append(value.getString());
+      }
+      if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+      }
+
+      // remove node
+      wc1.remove();
+      session.save();
+
+      out.close();
+      vhout.close();
+
+      // import
+      session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+         ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+            predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      picture = wc1.getNode("medias").getNode("picture");
+      assertTrue(picture.isNodeType("mix:versionable"));
+      assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+      assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+      assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+      assertTrue(picture.getProperty("jcr:isCheckedOut").getValue().getBoolean());
+
+      String value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("new data", value);
+
+      picture.restore("1", true);
+      value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("bla bla", value);
+
+      picture.restore("2", true);
+      value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("new data", value);
+
+      picture.checkout();
+
+      // make new version
+      assertTrue(picture.getProperty("jcr:isCheckedOut").getValue().getBoolean());
+      res = picture.getNode("jcr:content");
+      res.setProperty("jcr:data", new ByteArrayInputStream("third".getBytes()));
+      root.save();
+
+      picture.checkin();
+      picture.checkout();
+
+      picture.restore("1", true);
+      value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("bla bla", value);
+
+      picture.restore("3", true);
+      value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+      assertEquals("third", value);
+   }
+
+   /**
+    * Many mix:versionable subnodes. 
+    * @throws Exception
+    */
+   public void testImportVersionHistoryWithManyVersions() throws Exception
+   {
+
+      // wc1/medias/picture
+      Node wc1 = testRoot.addNode("wc1", "nt:folder");
+      wc1.addMixin("mix:versionable");
+      testRoot.save();
+      Node medias = wc1.addNode("medias", "nt:folder");
+
+      Node picture = medias.addNode("picture", "nt:file");
+      picture.addMixin("mix:versionable");
+
+      Node res = picture.addNode("jcr:content", "nt:resource");
+      res.setProperty("jcr:lastModified", Calendar.getInstance());
+      res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+      MimeTypeResolver mimres = new MimeTypeResolver();
+      res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+      root.save();
+
+      wc1.checkin();
+      wc1.checkout();
+
+      wc1.checkin();
+      wc1.checkout();
+
+      // export import version history and node
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      session.exportSystemView("/parent/wc1", out, false, false, true);
+
+      ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+      session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+      // prepare data for version import
+      String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+      String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+      Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+      StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+      String[] predecessorsHistory;
+      for (Value value : jcrPredecessors)
+      {
+         if (jcrPredecessorsBuilder.length() > 0)
+            jcrPredecessorsBuilder.append(",");
+         jcrPredecessorsBuilder.append(value.getString());
+      }
+      if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+      {
+         predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+      }
+      else
+      {
+         predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+      }
+      // remove node
+      wc1.remove();
+      session.save();
+
+      out.close();
+      vhout.close();
+
+      // import
+      session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+         ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      wc1 = (NodeImpl)session.getItem("/parent/wc1");
+      picture = wc1.getNode("medias").getNode("picture");
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+            predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      assertTrue(picture.isNodeType("mix:versionable"));
+   }
+
+   public void testImportVersionHistoryNonSysWorkspace() throws Exception
+   {
+
+      SessionImpl session = (SessionImpl)this.repository.login(credentials, "ws1");
+
+      Node root = session.getRootNode();
+      Node testRoot = root.addNode("parent", "nt:folder");
+      root.save();
+
+      try
+      {
+         // wc1/medias/picture
+         Node wc1 = testRoot.addNode("wc1", "nt:folder");
+         wc1.addMixin("mix:versionable");
+         testRoot.save();
+         Node medias = wc1.addNode("medias", "nt:folder");
+
+         Node picture = medias.addNode("picture", "nt:file");
+         picture.addMixin("mix:versionable");
+
+         Node res = picture.addNode("jcr:content", "nt:resource");
+         res.setProperty("jcr:lastModified", Calendar.getInstance());
+         res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+         MimeTypeResolver mimres = new MimeTypeResolver();
+         res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+         root.save();
+
+         // make checkin/checkout a lot
+
+         wc1.checkin();
+         wc1.checkout();
+
+         // export import version history and node
+         ByteArrayOutputStream out = new ByteArrayOutputStream();
+         session.exportSystemView("/parent/wc1", out, false, false, true);
+
+         ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+         session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+         // prepare data for version import
+
+         String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+         String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+         Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+         StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+         String[] predecessorsHistory;
+         for (Value value : jcrPredecessors)
+         {
+            if (jcrPredecessorsBuilder.length() > 0)
+               jcrPredecessorsBuilder.append(",");
+            jcrPredecessorsBuilder.append(value.getString());
+         }
+         if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+         {
+            predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+         }
+         else
+         {
+            predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+         }
+
+         // remove node
+         wc1.remove();
+         session.save();
+
+         out.close();
+         vhout.close();
+
+         // import
+         session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+            ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+         session.save();
+
+         wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+         VersionHistoryImporter versionHistoryImporter =
+            new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+               predecessorsHistory, versionHistory);
+         versionHistoryImporter.doImport();
+         session.save();
+
+         picture = wc1.getNode("medias").getNode("picture");
+         assertTrue(picture.isNodeType("mix:versionable"));
+      }
+      finally
+      {
+         testRoot.remove();
+         root.save();
+         session.logout();
+      }
+   }
+
+   public void testImportVersionHistoryFromFileWithChildVH() throws Exception
+   {
+
+      String baseVersion = "397dad17c0a8004201c7b45ea76d4b1b";
+      String[] predecessorsHistory = new String[]{"397dad17c0a8004201c7b45ea76d4b1b"};
+      String versionHistory = "397dac8bc0a8004201729d052a305832";
+
+      String chbaseVersion = "397dac9ac0a8004201cde5722fec978e";
+      String[] chpredecessorsHistory = new String[]{"397dac9ac0a8004201cde5722fec978e"};
+      String chversionHistory = "397dac9ac0a8004200f37de3ace7b0ad";
+
+      InputStream is =
+         TestImportVersionedChild.class.getResourceAsStream("/import-export/data_with_versioned_child.xml");
+      InputStream vhis =
+         TestImportVersionedChild.class.getResourceAsStream("/import-export/vh_with_versioned_child.xml");
+
+      // import
+      session.importXML("/parent", is, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, vhis, baseVersion, predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      Node picture = wc1.getNode("medias").getNode("picture");
+      assertTrue(picture.isNodeType("mix:versionable"));
+      assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+      assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+      assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+
+   }
+
+   public void testImportVersionHistoryFromFile() throws Exception
+   {
+
+      String baseVersion = "0019980ec0a80042014313ff82e97096";
+      String[] predecessorsHistory = new String[]{"0019980ec0a80042014313ff82e97096"};
+      String versionHistory = "001997a1c0a80042007d98739b97e1bc";
+
+      String chbaseVersion = "001997b1c0a8004200d65c82779a2e13";
+      String[] chpredecessorsHistory = new String[]{"001997b1c0a8004200d65c82779a2e13"};
+      String chversionHistory = "001997b1c0a8004201d35a6fa36ef4e7";
+
+      InputStream is = TestImportVersionedChild.class.getResourceAsStream("/import-export/data.xml");
+      InputStream vhis = TestImportVersionedChild.class.getResourceAsStream("/import-export/vh.xml");
+
+      // import
+      session.importXML("/parent", is, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+      session.save();
+
+      Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+      VersionHistoryImporter versionHistoryImporter =
+         new VersionHistoryImporter((NodeImpl)wc1, vhis, baseVersion, predecessorsHistory, versionHistory);
+      versionHistoryImporter.doImport();
+      session.save();
+
+      Node picture = wc1.getNode("medias").getNode("picture");
+      assertTrue(picture.isNodeType("mix:versionable"));
+      assertFalse(chversionHistory.equals(picture.getProperty("jcr:versionHistory").getValue().getString()));
+      assertFalse(chbaseVersion.equals(picture.getProperty("jcr:baseVersion").getValue().getString()));
+      assertFalse(chpredecessorsHistory[0].equals(picture.getProperty("jcr:predecessors").getValues()[0].getString()));
+
+      // try to remove picture, there must be RepositoryException
+      try
+      {
+         wc1.remove();
+         session.save();
+         fail();
+      }
+      catch (RepositoryException e)
+      {
+         // OK - wc1  Version History contain nt:versionedChild with link to non exist Version history
+
+         // remove bugy version history
+         SessionDataManager dataManager = session.getTransientNodesManager();
+         NodeImpl vhPicture =
+            (NodeImpl)session.getItem("/jcr:system/jcr:versionStorage/" + versionHistory
+               + "/1/jcr:frozenNode/medias/picture");
+
+         assertTrue(vhPicture.isNodeType("nt:versionedChild"));
+
+         PlainChangesLog changesLogDelete = new PlainChangesLogImpl();
+         changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)vhPicture.getProperty("jcr:primaryType"))
+            .getData()));
+         changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)vhPicture
+            .getProperty("jcr:childVersionHistory")).getData()));
+
+         for (ItemState itemState : changesLogDelete.getAllStates())
+         {
+            dataManager.delete(itemState.getData(), itemState.getAncestorToSave());
+         }
+
+         session.save();
+      }
+   }
+
 }

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml	2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><sv:node xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:test="http://www.apache.org/jackrabbit/test" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0" xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/" xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rma="http://www.rma.com/jcr/" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/" xmlns:rep="internal" sv:name="wc1"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:nam!
 e="jcr:uuid" sv:type="String"><sv:value>00199791c0a800420106a227837ca02a</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>0019980ec0a80042014313ff82e97096</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-07T14:30:00.593+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>0019980ec0a80042014313ff82e97096</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>001997a1c0a80042007d98739b97e1bc</sv:value></sv:property><sv:node sv:name="medias"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-07T14:30:00.625+02:00</sv:value></sv:property><sv:node sv:name="picture"><sv:property sv:name="jcr:primary!
 Type" sv:type="Name"><sv:value>nt:file</sv:value></sv:property!
 ><sv:pro
perty sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>001997b1c0a8004201ab6f6dfdaf70f9</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>001997b1c0a8004200d65c82779a2e13</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-07T14:30:00.625+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>001997b1c0a8004200d65c82779a2e13</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>001997b1c0a8004201d35a6fa36ef4e7</sv:value></sv:property><sv:node sv:name="jcr:content"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:resource</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:!
 value>001997b1c0a800420058c90fbc883ce3</sv:value></sv:property><sv:property sv:name="jcr:data" sv:type="Binary"><sv:value>YmxhIGJsYQ==</sv:value></sv:property><sv:property sv:name="jcr:lastModified" sv:type="Date"><sv:value>2011-02-07T14:30:00.625+02:00</sv:value></sv:property><sv:property sv:name="jcr:mimeType" sv:type="String"><sv:value>text/plain</sv:value></sv:property></sv:node></sv:node></sv:node></sv:node>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml	2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><sv:node xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:test="http://www.apache.org/jackrabbit/test" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0" xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/" xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rma="http://www.rma.com/jcr/" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/" xmlns:rep="internal" sv:name="wc1"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:nam!
 e="jcr:uuid" sv:type="String"><sv:value>397dac7bc0a80042019e86f907ef0339</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>397dad17c0a8004201c7b45ea76d4b1b</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.859+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dad17c0a8004201c7b45ea76d4b1b</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>397dac8bc0a8004201729d052a305832</sv:value></sv:property><sv:node sv:name="medias"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property><sv:node sv:name="picture"><sv:property sv:name="jcr:primary!
 Type" sv:type="Name"><sv:value>nt:file</sv:value></sv:property!
 ><sv:pro
perty sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac9ac0a800420182f12f406ca1a3</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>397dac9ac0a8004201cde5722fec978e</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dac9ac0a8004201cde5722fec978e</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>397dac9ac0a8004200f37de3ace7b0ad</sv:value></sv:property><sv:node sv:name="jcr:content"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:resource</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:!
 value>397dac9ac0a8004201e6a413bc33907f</sv:value></sv:property><sv:property sv:name="jcr:data" sv:type="Binary"><sv:value>YmxhIGJsYQ==</sv:value></sv:property><sv:property sv:name="jcr:lastModified" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property><sv:property sv:name="jcr:mimeType" sv:type="String"><sv:value>text/plain</sv:value></sv:property></sv:node></sv:node></sv:node></sv:node>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml	2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sv:node sv:name="001997a1c0a80042007d98739b97e1bc"
+         xmlns:xs="http://www.w3.org/2001/XMLSchema"
+         xmlns:test="http://www.apache.org/jackrabbit/test"
+         xmlns:sv="http://www.jcp.org/jcr/sv/1.0"
+         xmlns:rma="http://www.rma.com/jcr/" xmlns:rep="internal"
+         xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/"
+         xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+         xmlns:mix="http://www.jcp.org/jcr/mix/1.0"
+         xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/"
+         xmlns:jcr="http://www.jcp.org/jcr/1.0"
+         xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions"
+         xmlns:fn="http://www.w3.org/2005/xpath-functions"
+         xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0"
+         xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0"
+         xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sv:property sv:name="jcr:primaryType" sv:type="Name">
+    <sv:value>nt:versionHistory</sv:value>
+  </sv:property>
+
+  <sv:property sv:name="jcr:uuid" sv:type="String">
+    <sv:value>001997a1c0a80042007d98739b97e1bc</sv:value>
+  </sv:property>
+
+  <sv:property sv:name="jcr:versionableUuid" sv:type="String">
+    <sv:value>00199791c0a800420106a227837ca02a</sv:value>
+  </sv:property>
+
+  <sv:node sv:name="jcr:rootVersion">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name">
+      <sv:value>nt:version</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:mixinTypes" sv:type="Name">
+      <sv:value>mix:referenceable</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:uuid" sv:type="String">
+      <sv:value>001997a1c0a8004201a3af806d45ed9b</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:created" sv:type="Date">
+      <sv:value>2011-02-07T14:30:00.609+02:00</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:successors" sv:type="Reference">
+      <sv:value>0019980ec0a80042014313ff82e97096</sv:value>
+    </sv:property>
+  </sv:node>
+
+  <sv:node sv:name="1">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name">
+      <sv:value>nt:version</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:mixinTypes" sv:type="Name">
+      <sv:value>mix:referenceable</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:uuid" sv:type="String">
+      <sv:value>0019980ec0a80042014313ff82e97096</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:created" sv:type="Date">
+      <sv:value>2011-02-07T14:30:00.718+02:00</sv:value>
+    </sv:property>
+
+    <sv:property sv:name="jcr:predecessors" sv:type="Reference">
+      <sv:value>001997a1c0a8004201a3af806d45ed9b</sv:value>
+    </sv:property>
+
+    <sv:node sv:name="jcr:frozenNode">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name">
+        <sv:value>nt:frozenNode</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:mixinTypes" sv:type="Name">
+        <sv:value>mix:referenceable</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:uuid" sv:type="String">
+        <sv:value>0019980ec0a8004200d64e422bf86f49</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:created" sv:type="Date">
+        <sv:value>2011-02-07T14:30:00.734+02:00</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:frozenMixinTypes" sv:type="Name">
+        <sv:value>mix:versionable</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:frozenPrimaryType" sv:type="Name">
+        <sv:value>nt:folder</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:frozenUuid" sv:type="String">
+        <sv:value>00199791c0a800420106a227837ca02a</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:predecessors" sv:type="Reference">
+        <sv:value>001997a1c0a8004201a3af806d45ed9b</sv:value>
+      </sv:property>
+
+      <sv:property sv:name="jcr:versionHistory" sv:type="Reference">
+        <sv:value>001997a1c0a80042007d98739b97e1bc</sv:value>
+      </sv:property>
+
+      <sv:node sv:name="medias">
+        <sv:property sv:name="jcr:primaryType" sv:type="Name">
+          <sv:value>nt:folder</sv:value>
+        </sv:property>
+
+        <sv:property sv:name="jcr:created" sv:type="Date">
+          <sv:value>2011-02-07T14:30:00.734+02:00</sv:value>
+        </sv:property>
+
+        <sv:node sv:name="picture">
+          <sv:property sv:name="jcr:primaryType" sv:type="Name">
+            <sv:value>nt:versionedChild</sv:value>
+          </sv:property>
+
+          <sv:property sv:name="jcr:childVersionHistory" sv:type="Reference">
+            <sv:value>001997b1c0a8004201d35a6fa36ef4e7</sv:value>
+          </sv:property>
+        </sv:node>
+      </sv:node>
+    </sv:node>
+  </sv:node>
+
+  <sv:node sv:name="jcr:versionLabels">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name">
+      <sv:value>nt:versionLabels</sv:value>
+    </sv:property>
+  </sv:node>
+</sv:node>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml	2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><sv:node xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:test="http://www.apache.org/jackrabbit/test" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0" xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/" xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rma="http://www.rma.com/jcr/" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/" xmlns:rep="internal" sv:name="397dac8bc0a8004201729d052a305832"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionHistory</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac8bc0a8004201729d052a!
 305832</sv:value></sv:property><sv:property sv:name="jcr:versionableUuid" sv:type="String"><sv:value>397dac7bc0a80042019e86f907ef0339</sv:value></sv:property><sv:node sv:name="jcr:rootVersion"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:version</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac8bc0a8004201a2e53eb73949bd</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.875+02:00</sv:value></sv:property><sv:property sv:name="jcr:successors" sv:type="Reference"><sv:value>397dad17c0a8004201c7b45ea76d4b1b</sv:value></sv:property></sv:node><sv:node sv:name="1"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:version</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><!
 sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397d!
 ad17c0a8
004201c7b45ea76d4b1b</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:41.031+02:00</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dac8bc0a8004201a2e53eb73949bd</sv:value></sv:property><sv:node sv:name="jcr:frozenNode"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:frozenNode</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dad27c0a800420029031c7e421afa</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:41.031+02:00</sv:value></sv:property><sv:property sv:name="jcr:frozenMixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:name="jcr:frozenPrimaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:nam!
 e="jcr:frozenUuid" sv:type="String"><sv:value>397dac7bc0a80042019e86f907ef0339</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dac8bc0a8004201a2e53eb73949bd</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>397dac8bc0a8004201729d052a305832</sv:value></sv:property><sv:node sv:name="medias"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:41.031+02:00</sv:value></sv:property><sv:node sv:name="picture"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionedChild</sv:value></sv:property><sv:property sv:name="jcr:childVersionHistory" sv:type="Reference"><sv:value>397dac9ac0a8004200f37de3ace7b0ad</sv:value></sv:property><sv:versionhistory sv:name="397dac9ac0a8004200f37de3ace7b0ad"><sv:node sv:name="397dac9ac0a8004200f37de3ace7b0ad"><sv:proper!
 ty sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versi!
 onHistor
y</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac9ac0a8004200f37de3ace7b0ad</sv:value></sv:property><sv:property sv:name="jcr:versionableUuid" sv:type="String"><sv:value>397dac9ac0a800420182f12f406ca1a3</sv:value></sv:property><sv:node sv:name="jcr:rootVersion"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:version</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac9ac0a8004201cde5722fec978e</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property></sv:node><sv:node sv:name="jcr:versionLabels"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionLabels</sv:value></sv:property></sv:node></sv:node></sv:versionhistory></sv:node></sv:node></sv:node></sv:node><sv:node sv:name="j!
 cr:versionLabels"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionLabels</sv:value></sv:property></sv:node></sv:node>



More information about the exo-jcr-commits mailing list