From be6a2225545f6e8197ebc43a0e5238702e5fbe0b Mon Sep 17 00:00:00 2001 From: Britt Park Date: Tue, 12 Sep 2006 03:16:10 +0000 Subject: [PATCH] Extended the content model to include relevant avm specific types. cm:avmcontent and cm:avmfolder are 'abstract'. cm:avmplaincontent is derived from cm:avmcontent and is just a plain file. cm:avmlayeredcontent is derived from cm:avmcontent and is (surprise) a layered file and has a d:noderef mandatory property, cm:avmfileindirection, that is the (possibly non-existent) file that the layered file is transparent to. cm:avmplainfolder is derived from cm:avmfolder and is just a plain directory. cm:avmlayeredfolder is a layered directory and has a property, cm:avmdirinderection, that is the (possibly non-existent) directory that the layered directory is transparent to. The ContentModel QName constants are. TYPE_AVM_PLAIN_FOLDER TYPE_AVM_LAYERED_FOLDER TYPE_AVM_PLAIN_CONTENT TYPE_AVM_LAYERED_CONTENT PROP_AVM_DIR_INDIRECTION PROP_AVM_FILE_INDIRECTION One can now create all four flavors of avm nodes through AVMNodeService.createNode(). The advantage of using these over the corresponding AVMService methods is that since (for now) AVMService, is permission and indexing unaware. Backed out cm:mounted aspect and dispatching code in DbNodeServiceImpl. (Dave and Derek, you may now relax) as we are implementing the UI with AVM dedicated screens. Finally, beginning interface for AVM node tree synchronization and comparison. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3764 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/model/contentModel.xml | 54 +++++++++---- .../java/org/alfresco/model/ContentModel.java | 16 +++- .../org/alfresco/repo/avm/AVMInterpreter.java | 42 ---------- .../org/alfresco/repo/avm/AVMNodeService.java | 78 ++++++++++++++++--- .../org/alfresco/repo/avm/AVMServiceTest.java | 28 ++++++- .../repo/node/db/DbNodeServiceImpl.java | 43 +--------- .../service/cmr/avmsync/AVMDifference.java | 28 +++++++ .../service/cmr/avmsync/AvmSyncService.java | 75 ++++++++++++++++++ 8 files changed, 256 insertions(+), 108 deletions(-) create mode 100644 source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java create mode 100644 source/java/org/alfresco/service/cmr/avmsync/AvmSyncService.java diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml index dc35262083..b48f0085bd 100644 --- a/config/alfresco/model/contentModel.xml +++ b/config/alfresco/model/contentModel.xml @@ -79,11 +79,29 @@ + - AVM Content - cm:content + AVM Content + cm:content + + AVM Plain content + cm:avmcontent + + + + AVM Layered Content + cm:content + + + File Layer Indirection + d:noderef + true + + + + Dictionary Model cm:content @@ -143,9 +161,27 @@ cm:folder + - AVM Folder - cm:folder + AVM Folder + cm:folder + + + + AVM Plain Folder + cm:avmfolder + + + + AVM Layered Folder + cm:avmfolder + + + Directory Layer Indirection + d:noderef + true + + @@ -696,16 +732,6 @@ - - Mounted - - - Mountpoint - d:noderef - - - - diff --git a/source/java/org/alfresco/model/ContentModel.java b/source/java/org/alfresco/model/ContentModel.java index fd2f92fc79..c2558c4ba5 100644 --- a/source/java/org/alfresco/model/ContentModel.java +++ b/source/java/org/alfresco/model/ContentModel.java @@ -98,6 +98,12 @@ public interface ContentModel static final QName TYPE_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content"); static final QName PROP_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content"); static final QName TYPE_AVM_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmcontent"); + static final QName TYPE_AVM_PLAIN_CONTENT = + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmplaincontent"); + static final QName TYPE_AVM_LAYERED_CONTENT = + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmlayeredcontent"); + static final QName PROP_AVM_FILE_INDIRECTION = + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmfileindirection"); // title aspect static final QName ASPECT_TITLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "titled"); @@ -133,8 +139,8 @@ public interface ContentModel public final static QName PROP_EXPIRY_DATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "expiryDate"); // version aspect - static final QName ASPECT_VERSIONABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionable"); - static final QName PROP_VERSION_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionLabel"); + static final QName ASPECT_VERSIONABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionable"); + static final QName PROP_VERSION_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionLabel"); static final QName PROP_INITIAL_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "initialVersion"); static final QName PROP_AUTO_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "autoVersion"); @@ -144,6 +150,12 @@ public interface ContentModel /** child association type supported by {@link #TYPE_FOLDER} */ static final QName ASSOC_CONTAINS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "contains"); static final QName TYPE_AVM_FOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmfolder"); + static final QName TYPE_AVM_PLAIN_FOLDER = + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmplainfolder"); + static final QName TYPE_AVM_LAYERED_FOLDER = + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmlayeredfolder"); + static final QName PROP_AVM_DIR_INDIRECTION = + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avmdirindirection"); // person static final QName TYPE_PERSON = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "person"); diff --git a/source/java/org/alfresco/repo/avm/AVMInterpreter.java b/source/java/org/alfresco/repo/avm/AVMInterpreter.java index 8b1f4a070a..149fb3cc21 100644 --- a/source/java/org/alfresco/repo/avm/AVMInterpreter.java +++ b/source/java/org/alfresco/repo/avm/AVMInterpreter.java @@ -437,48 +437,6 @@ public class AVMInterpreter AVMNodeDescriptor ca = fService.getCommonAncestor(left, right); out.println(ca); } - else if (command[0].equals("mount")) - { - if (command.length != 5) - { - return "Syntax Error."; - } - int version = Integer.parseInt(command[1]); - String avmPath = command[2]; - String alfPath = command[3]; - String mountName = command[4]; - String [] components = alfPath.split("/"); - NodeRef nodeRef = fNodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore")); - for (String name : components) - { - fgLogger.error(name); - List children = - fNodeService.getChildAssocs(nodeRef); - for (ChildAssociationRef child : children) - { - fgLogger.error(" " + child.getQName()); - if (child.getQName().getLocalName().equals(name)) - { - nodeRef = child.getChildRef(); - break; - } - } - } - Map properties = - new HashMap(); - properties.put(ContentModel.PROP_NAME, mountName); - ChildAssociationRef childRef = - fNodeService.createNode(nodeRef, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.APP_MODEL_1_0_URI, mountName), - ContentModel.TYPE_FOLDER, - properties); - properties.clear(); - properties.put(ContentModel.PROP_MOUNTPOINT, - AVMNodeConverter.ToNodeRef(version, avmPath)); - fNodeService.addAspect(childRef.getChildRef(), - ContentModel.ASPECT_MOUNTED, - properties); - } else { return "Syntax Error."; diff --git a/source/java/org/alfresco/repo/avm/AVMNodeService.java b/source/java/org/alfresco/repo/avm/AVMNodeService.java index 41ea718498..281f578bd7 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeService.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeService.java @@ -268,16 +268,36 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi // Do the creates for supported types, or error out. try { - if (nodeTypeQName.equals(ContentModel.TYPE_AVM_FOLDER) || + if (nodeTypeQName.equals(ContentModel.TYPE_AVM_PLAIN_FOLDER) || nodeTypeQName.equals(ContentModel.TYPE_FOLDER)) { fAVMService.createDirectory(avmPath, nodeName); } - else if (nodeTypeQName.equals(ContentModel.TYPE_AVM_CONTENT) + else if (nodeTypeQName.equals(ContentModel.TYPE_AVM_PLAIN_CONTENT) ||nodeTypeQName.equals(ContentModel.TYPE_CONTENT)) { fAVMService.createFile(avmPath, nodeName); } + else if (nodeTypeQName.equals(ContentModel.TYPE_AVM_LAYERED_CONTENT)) + { + NodeRef indirection = (NodeRef)properties.get(ContentModel.PROP_AVM_FILE_INDIRECTION); + if (indirection == null) + { + throw new InvalidTypeException("No Indirection Property", nodeTypeQName); + } + Object [] indVersionPath = AVMNodeConverter.ToAVMVersionPath(indirection); + fAVMService.createLayeredFile((String)indVersionPath[1], avmPath, nodeName); + } + else if (nodeTypeQName.equals(ContentModel.TYPE_AVM_LAYERED_FOLDER)) + { + NodeRef indirection = (NodeRef)properties.get(ContentModel.PROP_AVM_DIR_INDIRECTION); + if (indirection == null) + { + throw new InvalidTypeException("No Indirection Property.", nodeTypeQName); + } + Object [] indVersionPath = AVMNodeConverter.ToAVMVersionPath(indirection); + fAVMService.createLayeredDirectory((String)indVersionPath[1], avmPath, nodeName); + } else { throw new InvalidTypeException("Invalid node type for AVM.", nodeTypeQName); @@ -450,14 +470,23 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi { AVMNodeDescriptor desc = fAVMService.lookup((Integer)avmVersionPath[0], (String)avmVersionPath[1]); - if (desc.isDirectory()) + if (desc.isPlainDirectory()) { - return ContentModel.TYPE_AVM_FOLDER; + return ContentModel.TYPE_AVM_PLAIN_FOLDER; + } + else if (desc.isPlainFile()) + { + return ContentModel.TYPE_AVM_PLAIN_CONTENT; + } + else if (desc.isLayeredDirectory()) + { + return ContentModel.TYPE_AVM_LAYERED_FOLDER; } else { - return ContentModel.TYPE_AVM_CONTENT; + return ContentModel.TYPE_AVM_LAYERED_CONTENT; } + } catch (AVMNotFoundException e) { @@ -845,6 +874,16 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi result.put(ContentModel.PROP_NODE_DBID, new Long(desc.getId())); result.put(ContentModel.PROP_STORE_PROTOCOL, "avm"); result.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); + if (desc.isLayeredDirectory()) + { + result.put(ContentModel.PROP_AVM_DIR_INDIRECTION, + AVMNodeConverter.ToNodeRef(-1, desc.getIndirection())); + } + if (desc.isLayeredFile()) + { + result.put(ContentModel.PROP_AVM_FILE_INDIRECTION, + AVMNodeConverter.ToNodeRef(-1, desc.getIndirection())); + } if (desc.isFile()) { try @@ -969,6 +1008,22 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi { return nodeRef.getStoreRef().getIdentifier(); } + else if (qName.equals(ContentModel.PROP_AVM_DIR_INDIRECTION)) + { + if (desc.isLayeredDirectory()) + { + return AVMNodeConverter.ToNodeRef(-1, desc.getIndirection()); + } + return null; + } + else if (qName.equals(ContentModel.PROP_AVM_FILE_INDIRECTION)) + { + if (desc.isLayeredFile()) + { + return AVMNodeConverter.ToNodeRef(-1, desc.getIndirection()); + } + return null; + } else { fgLogger.error("Invalid Built In Property: " + qName); @@ -1002,14 +1057,17 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi Map values = new HashMap(); for (QName qName : properties.keySet()) { - // TODO This is until modification of built-in properties // For AVM nodes is in place. if (isBuiltInProperty(qName)) { if (qName.equals(ContentModel.PROP_CONTENT)) { - fAVMService.setContentData((String)avmVersionPath[1], - (ContentData)properties.get(qName)); + AVMNodeDescriptor desc = fAVMService.lookup(-1, (String)avmVersionPath[1]); + if (desc.isPlainFile()) + { + fAVMService.setContentData((String)avmVersionPath[1], + (ContentData)properties.get(qName)); + } } } values.put(qName, new PropertyValue(null, properties.get(qName))); @@ -1036,7 +1094,9 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi ContentModel.PROP_NODE_UUID, ContentModel.PROP_NODE_DBID, ContentModel.PROP_STORE_PROTOCOL, - ContentModel.PROP_STORE_IDENTIFIER + ContentModel.PROP_STORE_IDENTIFIER, + ContentModel.PROP_AVM_FILE_INDIRECTION, + ContentModel.PROP_AVM_DIR_INDIRECTION }; /** diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index e6c7e40106..e4ecdc2504 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -21,6 +21,7 @@ import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.PrintStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -41,8 +42,10 @@ import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avm.LayeringDescriptor; import org.alfresco.service.cmr.avm.VersionDescriptor; import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; @@ -2304,7 +2307,30 @@ public class AVMServiceTest extends AVMServiceTestBase setupBasicTree(); FileFolderService ffs = (FileFolderService)fContext.getBean("FileFolderService"); assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c"), - "banana", ContentModel.TYPE_AVM_CONTENT) != null); + "banana", ContentModel.TYPE_AVM_PLAIN_CONTENT) != null); + assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c"), + "apples", ContentModel.TYPE_AVM_PLAIN_FOLDER) != null); + NodeService ns = (NodeService)fContext.getBean("NodeService"); + Map properties = new HashMap(); + properties.put(ContentModel.PROP_AVM_DIR_INDIRECTION, + AVMNodeConverter.ToNodeRef(-1, "main:/a")); + assertTrue(ns.createNode(AVMNodeConverter.ToNodeRef(-1, "main:/"), + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "layer"), + ContentModel.TYPE_AVM_LAYERED_FOLDER, + properties) != null); + assertTrue(ns.getProperty(AVMNodeConverter.ToNodeRef(-1, "main:/layer"), + ContentModel.PROP_AVM_DIR_INDIRECTION) != null); + properties.clear(); + properties.put(ContentModel.PROP_AVM_FILE_INDIRECTION, + AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); + assertTrue(ns.createNode(AVMNodeConverter.ToNodeRef(-1, "main:/"), + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "foo"), + ContentModel.TYPE_AVM_LAYERED_CONTENT, + properties) != null); + assertTrue(ns.getProperty(AVMNodeConverter.ToNodeRef(-1, "main:/foo"), + ContentModel.PROP_AVM_FILE_INDIRECTION) != null); fService.createSnapshot("main"); System.out.println(recursiveList("main", -1, true)); } diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java index ca5706fc2d..92a4abbf4f 100644 --- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java @@ -31,7 +31,6 @@ import java.util.Stack; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; -import org.alfresco.repo.avm.AVMContext; import org.alfresco.repo.domain.ChildAssoc; import org.alfresco.repo.domain.Node; import org.alfresco.repo.domain.NodeAssoc; @@ -253,20 +252,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl Assert.notNull(assocTypeQName); Assert.notNull(assocQName); - // get the parent node - Node parentNode = getNodeNotNull(parentRef); - - if (parentNode.getAspects().contains(ContentModel.ASPECT_MOUNTED)) - { - NodeRef mounted = (NodeRef)parentNode.getProperties().get(ContentModel.PROP_MOUNTPOINT). - getValue(DataTypeDefinition.NODE_REF); - return AVMContext.fgInstance.getNodeService().createNode(mounted, - assocTypeQName, - assocQName, - nodeTypeQName, - properties); - } - // null property map is allowed if (properties == null) { @@ -317,6 +302,9 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl propertiesAfter = setPropertiesImpl(childNode, properties); } + // get the parent node + Node parentNode = getNodeNotNull(parentRef); + // create the association ChildAssoc childAssoc = nodeDaoService.newChildAssoc( parentNode, @@ -724,15 +712,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { Node parentNode = getNodeNotNull(parentRef); - if (parentNode.getAspects().contains(ContentModel.ASPECT_MOUNTED)) - { - NodeRef mounted = - (NodeRef)parentNode.getProperties().get(ContentModel.PROP_MOUNTPOINT). - getValue(DataTypeDefinition.NODE_REF); - AVMContext.fgInstance.getNodeService().removeChild(mounted, childRef); - return; - } - Node childNode = getNodeNotNull(childRef); Long childNodeId = childNode.getId(); @@ -1017,14 +996,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl public List getChildAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern) { Node node = getNodeNotNull(nodeRef); - if (node.getAspects().contains(ContentModel.ASPECT_MOUNTED)) - { - NodeRef mounted = (NodeRef)node.getProperties().get(ContentModel.PROP_MOUNTPOINT). - getValue(DataTypeDefinition.NODE_REF); - return AVMContext.fgInstance.getNodeService().getChildAssocs(mounted, - typeQNamePattern, - qnamePattern); - } // get the assocs pointing from it Collection childAssocRefs = nodeDaoService.getChildAssocRefs(node); // shortcut if there are no assocs @@ -1061,14 +1032,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl public NodeRef getChildByName(NodeRef nodeRef, QName assocTypeQName, String childName) { Node node = getNodeNotNull(nodeRef); - if (node.getAspects().contains(ContentModel.ASPECT_MOUNTED)) - { - NodeRef mounted = (NodeRef)node.getProperties().get(ContentModel.PROP_MOUNTPOINT). - getValue(DataTypeDefinition.NODE_REF); - return AVMContext.fgInstance.getNodeService().getChildByName(mounted, - assocTypeQName, - childName); - } ChildAssoc childAssoc = nodeDaoService.getChildAssoc(node, assocTypeQName, childName); if (childAssoc != null) { diff --git a/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java b/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java new file mode 100644 index 0000000000..2e3acf20e1 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.service.cmr.avmsync; + +/** + * Represents the difference between corresponding nodes + * in parallel avm node trees. It it indicates for the difference + * whether the source is older, newer, or in conflict with the destination. + * @author britt + */ +public class AVMDifference +{ +} diff --git a/source/java/org/alfresco/service/cmr/avmsync/AvmSyncService.java b/source/java/org/alfresco/service/cmr/avmsync/AvmSyncService.java new file mode 100644 index 0000000000..0f91cc96ea --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avmsync/AvmSyncService.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.service.cmr.avmsync; + +import java.util.List; + +/** + * This service handles comparisons and synchronizations between + * corresponding avm node trees. + * @author britt + */ +public interface AvmSyncService +{ + /** + * Get a difference list between two corresponding node trees. + * @param srcVersion The version id for the source tree. + * @param srcPath The avm path to the source tree. + * @param dstVersion The version id for the destination tree. + * @param dstPath The avm path to the destination tree. + * @return A List of AVMDifference structs which can be used for + * the update operation. + */ + public List compare(int srcVersion, String srcPath, + int dstVersion, String dstPath); + + /** + * Updates the destination nodes in the AVMDifferences + * with the source nodes. Normally any conflicts or cases in + * which the source of an AVMDifference is older than the destination + * will cause the transaction to roll back. + * @param diffList A List of AVMDifference structs. + * @param ignoreConflicts If this is true the update will skip those + * AVMDifferences which are in conflict or for which the source is older than + * the destination. + * @param overrideConflicts If this is true the update will override conflicting + * AVMDifferences and replace the destination with the conflicting source. + * @param overrideOlder If this is true the update will override AVMDifferences + * in which the source is older than the destination and overwrite the destination. + */ + public void update(List diffList, boolean ignoreConflicts, + boolean overrideConflicts, boolean overrideOlder); + + /** + * Flattens a layer so that all all nodes under and including + * layerPath become translucent to any nodes in the + * corresponding location under and including underlyingPath + * that are the same version. + * @param layerPath The overlying layer path. + * @param underlyingPath The underlying path. + */ + public void flatten(String layerPath, String underlyingPath); + + /** + * Takes a layer, deletes it and recreates it pointing at the same underlying + * node. Any changes in the layer are lost (except to history if the layer has been + * snapshotted.) + * @param layerPath + */ + public void resetLayer(String layerPath); +}