Index: oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java	(revision )
@@ -21,7 +21,7 @@
 import static org.apache.jackrabbit.oak.OakAssert.assertSequence;
 
 import org.apache.jackrabbit.oak.Oak;
-import org.apache.jackrabbit.oak.plugins.commit.ConflictValidator;
+import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
 import org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler;
 import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
 import org.junit.After;
@@ -40,7 +40,7 @@
         repository = new Oak()
             .with(new OpenSecurityProvider())
             .with(JcrConflictHandler.JCR_CONFLICT_HANDLER)
-            .with(new ConflictValidator())
+            .with(new ConflictValidatorProvider())
             .createContentRepository();
     }
 
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java	(revision )
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.api;
 
+import com.google.common.base.Function;
+
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -329,5 +331,21 @@
      * @param name The name of the property
      */
     void removeProperty(@Nonnull String name);
+
+
+    /**
+     * Mapping from a Tree instance to its name.
+     */
+    Function<Tree, String> GET_NAME =
+            new Function<Tree, String>() {
+                @Override @Nullable
+                public String apply(@Nullable Tree input) {
+                    if (input != null) {
+                        return input.getName();
+                    } else {
+                        return null;
+                    }
+                }
+            };
 
 }
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ConflictAnnotatingRebaseDiff.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ConflictAnnotatingRebaseDiff.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ConflictAnnotatingRebaseDiff.java	(revision )
@@ -19,6 +19,16 @@
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.oak.api.PropertyState;
 
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_CHANGED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_CHANGED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.ADD_EXISTING_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_DELETED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_CHANGED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_DELETED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.ADD_EXISTING_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_DELETED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_DELETED_NODE;
+
 /**
  * This implementation of {@code AbstractRebaseDiff} implements a {@link NodeStateDiff},
  * which performs the conflict handling as defined in {@link MicroKernel#rebase(String, String)}
@@ -27,15 +37,6 @@
  */
 public class ConflictAnnotatingRebaseDiff extends AbstractRebaseDiff {
     public static final String CONFLICT = ":conflict";
-    public static final String DELETE_CHANGED_PROPERTY = "deleteChangedProperty";
-    public static final String DELETE_CHANGED_NODE = "deleteChangedNode";
-    public static final String ADD_EXISTING_PROPERTY = "addExistingProperty";
-    public static final String CHANGE_DELETED_PROPERTY = "changeDeletedProperty";
-    public static final String CHANGE_CHANGED_PROPERTY = "changeChangedProperty";
-    public static final String DELETE_DELETED_PROPERTY = "deleteDeletedProperty";
-    public static final String ADD_EXISTING_NODE = "addExistingNode";
-    public static final String CHANGE_DELETED_NODE = "changeDeletedNode";
-    public static final String DELETE_DELETED_NODE = "deleteDeletedNode";
 
     public ConflictAnnotatingRebaseDiff(NodeBuilder builder) {
         super(builder);
@@ -91,8 +92,8 @@
         conflictMarker(builder, DELETE_CHANGED_NODE).setChildNode(name, before);
     }
 
-    private static NodeBuilder conflictMarker(NodeBuilder builder, String name) {
-        return builder.child(CONFLICT).child(name);
+    private static NodeBuilder conflictMarker(NodeBuilder builder, ConflictType ct) {
+        return builder.child(CONFLICT).child(ct.getName());
     }
 
 }
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ConflictType.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ConflictType.java	(revision )
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ConflictType.java	(revision )
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.spi.state;
+
+/**
+ * Enum to define various types of conflicts.
+ *
+ * @see org.apache.jackrabbit.mk.api.MicroKernel#rebase(String, String)
+ */
+public enum ConflictType {
+
+    /**
+     * A property has been removed while a property of the same name has been changed in trunk.
+     */
+    DELETE_CHANGED_PROPERTY("deleteChangedProperty",false),
+
+    /**
+     * A node has been removed while a node of the same name has been changed in trunk.
+     */
+    DELETE_CHANGED_NODE("deleteChangedNode",true),
+
+    /**
+     * A property has been added that has a different value than a property with the same name
+     * that has been added in trunk.
+     */
+    ADD_EXISTING_PROPERTY("addExistingProperty",false),
+
+    /**
+     * A property has been changed while a property of the same name has been removed in trunk.
+     */
+    CHANGE_DELETED_PROPERTY("changeDeletedProperty",false),
+
+    /**
+     * A property has been changed while a property of the same name has been changed to a
+     * different value in trunk.
+     */
+    CHANGE_CHANGED_PROPERTY("changeChangedProperty",false),
+
+    /**
+     * A property has been removed while a property of the same name has been removed in trunk.
+     */
+    DELETE_DELETED_PROPERTY("deleteDeletedProperty",false),
+
+    /**
+     * A node has been added that is different from a node of them same name that has been added
+     * to the trunk.
+     */
+    ADD_EXISTING_NODE("addExistingNode",true),
+
+    /**
+     * A node has been changed while a node of the same name has been removed in trunk.
+     */
+    CHANGE_DELETED_NODE("changeDeletedNode",true),
+
+    /**
+     * A node has been removed while a node of the same name has been removed in trunk.
+     */
+    DELETE_DELETED_NODE("deleteDeletedNode",true),
+
+    UNKNOWN("unknown",false)
+    ;
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean effectsNode() {
+        return effectsNode;
+    }
+
+    public static ConflictType fromName(String name){
+        for(ConflictType t : values()){
+            if(t.getName().equals(name)){
+                return t;
+            }
+        }
+        throw new IllegalArgumentException("Unrecognized conflictType: "+name);
+    }
+
+    private final String name;
+    private final boolean effectsNode;
+
+    private ConflictType(String value, boolean node) {
+        this.name = value;
+        this.effectsNode = node;
+    }
+}
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictValidator.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictValidator.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictValidator.java	(revision )
@@ -16,15 +16,21 @@
  */
 package org.apache.jackrabbit.oak.plugins.commit;
 
+import com.google.common.base.Joiner;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
 import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.state.ConflictType;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
+import static com.google.common.collect.Iterables.transform;
 import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.MIX_REP_MERGE_CONFLICT;
 
 /**
  * {@link Validator} which checks the presence of conflict markers
@@ -34,17 +40,12 @@
  */
 public class ConflictValidator extends DefaultValidator {
 
-    private final ConflictValidator parent;
+    private final Tree parentAfter;
 
     private final String name;
 
-    public ConflictValidator() {
-        this.parent = null;
-        this.name = null;
-    }
-
-    private ConflictValidator(ConflictValidator parent, String name) {
-        this.parent = null;
+    public ConflictValidator(Tree parentAfter, String name) {
+        this.parentAfter = parentAfter;
         this.name = name;
     }
 
@@ -61,12 +62,12 @@
 
     @Override
     public Validator childNodeAdded(String name, NodeState after) {
-        return new ConflictValidator(this, name);
+        return new ConflictValidator(parentAfter.getChild(name), name);
     }
 
     @Override
     public Validator childNodeChanged(String name, NodeState before, NodeState after) {
-        return new ConflictValidator(this, name);
+        return new ConflictValidator(parentAfter.getChild(name), name);
     }
 
     @Override
@@ -78,28 +79,89 @@
         if (JcrConstants.JCR_MIXINTYPES.equals(property.getName())) {
             assert property.isArray();
             for (String v : property.getValue(STRINGS)) {
-                if (NodeTypeConstants.MIX_REP_MERGE_CONFLICT.equals(v)) {
+                if (MIX_REP_MERGE_CONFLICT.equals(v)) {
                     throw new CommitFailedException(
-                            CommitFailedException.STATE, 1, "Unresolved conflicts in " + getPath());
+                            CommitFailedException.STATE, 1, getConflictMessage());
                 }
             }
         }
     }
 
-    private String getPath() {
-        if (parent == null) {
-            return "/";
+    private String getConflictMessage(){
+        StringBuilder sb = new StringBuilder("Unresolved conflicts in ");
+        sb.append(parentAfter.getPath());
+        sb.append(" = {");
+        for(Tree conflict : parentAfter.getChild(NodeTypeConstants.REP_OURS).getChildren()){
+            ConflictType ct = ConflictType.fromName(conflict.getName());
+
+            sb.append(ct.getName()).append(" = {");
+            if(ct.effectsNode()){
+                sb.append(getChildNodeNamesAsString(conflict));
-        } else {
+            } else {
-            return parent.getPath(name);
+                for(PropertyState ps : conflict.getProperties()){
+                    PropertyState ours = null, theirs = null;
+                    switch(ct){
+                        case DELETE_CHANGED_PROPERTY:
+                            ours = null;
+                            theirs = ps;
+                            break;
+                        case ADD_EXISTING_PROPERTY:
+                        case CHANGE_CHANGED_PROPERTY:
+                            ours = ps;
+                            theirs = parentAfter.getProperty(ps.getName());
+                            break;
+                        case CHANGE_DELETED_PROPERTY:
+                            ours = ps;
+                            theirs = null;
+                            break;
-        }
+                    }
+
+                    sb.append(ps.getName())
+                      .append(" = {")
+                      .append(toString(ours))
+                      .append(',')
+                      .append(toString(theirs))
+                      .append("}");
+
+                    sb.append(",");
-    }
+                }
+                sb.deleteCharAt(sb.length()-1);
+            }
 
-    private String getPath(String name) {
-        if (parent == null) {
-            return "/" + name;
-        } else {
-            return parent.getPath(this.name) + "/" + name;
+            sb.append("},");
         }
+
+        sb.deleteCharAt(sb.length() - 1);
+        sb.append("}");
+        System.out.println(sb);
+        return sb.toString();
+    }
+
+    private static String getChildNodeNamesAsString(Tree t){
+        return Joiner.on(',').join(transform(t.getChildren(), Tree.GET_NAME));
+    }
+
+    private static String toString(PropertyState ps){
+        if(ps == null){
+            return "<N/A>";
+        }
+
+        final Type type = ps.getType();
+        if(type.isArray()){
+            return "<ARRAY>";
+        }
+        if(Type.BINARY == type){
+            return "<BINARY>";
+        }
+
+        String value = ps.getValue(Type.STRING);
+
+        //Trim the value so as to not blowup diff message
+        if(Type.STRING == type && value.length() > 10){
+            value = value.substring(0,10) + "...";
+        }
+
+        return value;
     }
 
 }
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeConstants.java	(revision )
@@ -52,11 +52,6 @@
      */
     String MIX_REP_MERGE_CONFLICT = "rep:MergeConflict";
     String REP_OURS = "rep:ours";
-    String ADD_EXISTING = "addExisting";
-    String CHANGE_DELETED = "changeDeleted";
-    String CHANGE_CHANGED = "changeChanged";
-    String DELETE_CHANGED = "deleteChanged";
-    String DELETE_DELETED = "deleteDeleted";
 
     String RESIDUAL_NAME = "*";
 
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/StringCache.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/StringCache.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/StringCache.java	(revision )
@@ -23,6 +23,7 @@
 import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
 
 import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.spi.state.ConflictType;
 
 /**
  * TODO document
@@ -114,11 +115,15 @@
             NodeTypeConstants.MIX_LASTMODIFIED,
             NodeTypeConstants.MIX_REP_MERGE_CONFLICT,
             NodeTypeConstants.REP_OURS,
-            NodeTypeConstants.ADD_EXISTING,
-            NodeTypeConstants.CHANGE_DELETED,
-            NodeTypeConstants.CHANGE_CHANGED,
-            NodeTypeConstants.DELETE_CHANGED,
-            NodeTypeConstants.DELETE_DELETED,
+            ConflictType.DELETE_CHANGED_PROPERTY.getName(),
+            ConflictType.DELETE_CHANGED_NODE.getName(),
+            ConflictType.ADD_EXISTING_PROPERTY.getName(),
+            ConflictType.CHANGE_DELETED_PROPERTY.getName(),
+            ConflictType.CHANGE_CHANGED_PROPERTY.getName(),
+            ConflictType.DELETE_DELETED_PROPERTY.getName(),
+            ConflictType.ADD_EXISTING_NODE.getName(),
+            ConflictType.CHANGE_DELETED_NODE.getName(),
+            ConflictType.DELETE_DELETED_NODE.getName(),
             VersionConstants.JCR_ACTIVITY,
             VersionConstants.JCR_ACTIVITIES,
             VersionConstants.JCR_ACTIVITY_TITLE,
Index: oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java	(revision )
@@ -29,7 +29,7 @@
 import org.apache.jackrabbit.oak.Oak;
 import org.apache.jackrabbit.oak.plugins.commit.AnnotatingConflictHandler;
 import org.apache.jackrabbit.oak.plugins.commit.ChildOrderConflictHandler;
-import org.apache.jackrabbit.oak.plugins.commit.ConflictValidator;
+import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
 import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -61,7 +61,7 @@
                     return Resolution.OURS;
                 }
             })
-            .with(new ConflictValidator())
+            .with(new ConflictValidatorProvider())
             .createContentRepository();
     }
 
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java	(revision )
@@ -16,16 +16,16 @@
  */
 package org.apache.jackrabbit.oak.plugins.commit;
 
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.ADD_EXISTING_NODE;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.ADD_EXISTING_PROPERTY;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.CHANGE_CHANGED_PROPERTY;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.CHANGE_DELETED_NODE;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.CHANGE_DELETED_PROPERTY;
 import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.CONFLICT;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.DELETE_CHANGED_NODE;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.DELETE_CHANGED_PROPERTY;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.DELETE_DELETED_NODE;
-import static org.apache.jackrabbit.oak.spi.state.ConflictAnnotatingRebaseDiff.DELETE_DELETED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.ADD_EXISTING_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.ADD_EXISTING_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_CHANGED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_DELETED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_DELETED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_CHANGED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_CHANGED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_DELETED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_DELETED_PROPERTY;
 
 import java.util.Map;
 
@@ -37,6 +37,7 @@
 import org.apache.jackrabbit.oak.spi.commit.ConflictHandler;
 import org.apache.jackrabbit.oak.spi.commit.ConflictHandler.Resolution;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.ConflictType;
 import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -78,7 +79,7 @@
     public boolean childNodeAdded(String name, NodeState after) {
         if (CONFLICT.equals(name)) {
             for (ChildNodeEntry conflict : after.getChildNodeEntries()) {
-                resolveConflict(conflict.getName(), conflict.getNodeState());
+                resolveConflict(ConflictType.fromName(conflict.getName()), conflict.getNodeState());
             }
 
             target.getChildNode(CONFLICT).remove();
@@ -94,42 +95,42 @@
 
     //------------------------------------------------------------< private >---
 
-    private void resolveConflict(String conflictName, NodeState conflictInfo) {
-        PropertyConflictHandler propertyConflictHandler = propertyConflictHandlers.get(conflictName);
+    private void resolveConflict(ConflictType conflictType, NodeState conflictInfo) {
+        PropertyConflictHandler propertyConflictHandler = propertyConflictHandlers.get(conflictType);
         if (propertyConflictHandler != null) {
             for (PropertyState ours : conflictInfo.getProperties()) {
                 PropertyState theirs = parent.getProperty(ours.getName());
                 Resolution resolution = propertyConflictHandler.resolve(ours, theirs);
-                applyResolution(resolution, conflictName, ours);
+                applyResolution(resolution, conflictType, ours);
             }
         }
         else {
-            NodeConflictHandler nodeConflictHandler = nodeConflictHandlers.get(conflictName);
+            NodeConflictHandler nodeConflictHandler = nodeConflictHandlers.get(conflictType);
             if (nodeConflictHandler != null) {
                 for (ChildNodeEntry oursCNE : conflictInfo.getChildNodeEntries()) {
                     String name = oursCNE.getName();
                     NodeState ours = oursCNE.getNodeState();
                     NodeState theirs = parent.getChildNode(name);
                     Resolution resolution = nodeConflictHandler.resolve(name, ours, theirs);
-                    applyResolution(resolution, conflictName, name, ours);
+                    applyResolution(resolution, conflictType, name, ours);
                 }
             }
             else {
-                LOG.warn("Ignoring unknown conflict '" + conflictName + '\'');
+                LOG.warn("Ignoring unknown conflict '" + conflictType + '\'');
             }
         }
 
-        NodeBuilder conflictMarker = getConflictMarker(conflictName);
+        NodeBuilder conflictMarker = getConflictMarker(conflictType);
         if (conflictMarker != null) {
             assert conflictMarker.getChildNodeCount(1) == 0;
         }
     }
 
-    private void applyResolution(Resolution resolution, String conflictName, PropertyState ours) {
+    private void applyResolution(Resolution resolution, ConflictType conflictType, PropertyState ours) {
         String name = ours.getName();
-        NodeBuilder conflictMarker = getConflictMarker(conflictName);
+        NodeBuilder conflictMarker = getConflictMarker(conflictType);
         if (resolution == Resolution.OURS) {
-            if (DELETE_CHANGED_PROPERTY.equals(conflictName)) {
+            if (DELETE_CHANGED_PROPERTY == conflictType) {
                 target.removeProperty(name);
             }
             else {
@@ -140,10 +141,10 @@
         conflictMarker.removeProperty(name);
     }
 
-    private void applyResolution(Resolution resolution, String conflictName, String name, NodeState ours) {
-        NodeBuilder conflictMarker = getConflictMarker(conflictName);
+    private void applyResolution(Resolution resolution, ConflictType conflictType, String name, NodeState ours) {
+        NodeBuilder conflictMarker = getConflictMarker(conflictType);
         if (resolution == Resolution.OURS) {
-            if (DELETE_CHANGED_NODE.equals(conflictName)) {
+            if (DELETE_CHANGED_NODE == conflictType) {
                 removeChild(target, name);
             }
             else {
@@ -153,7 +154,8 @@
         conflictMarker.getChildNode(name).remove();
     }
 
-    private NodeBuilder getConflictMarker(String conflictName) {
+    private NodeBuilder getConflictMarker(ConflictType conflictType) {
+        final String conflictName = conflictType.getName();
         if (target.hasChildNode(CONFLICT)) {
             NodeBuilder conflict = target.child(CONFLICT);
             if (conflict.hasChildNode(conflictName)) {
@@ -172,7 +174,7 @@
         Resolution resolve(String name, NodeState ours, NodeState theirs);
     }
 
-    private final Map<String, PropertyConflictHandler> propertyConflictHandlers = ImmutableMap.of(
+    private final Map<ConflictType, PropertyConflictHandler> propertyConflictHandlers = ImmutableMap.of(
         ADD_EXISTING_PROPERTY, new PropertyConflictHandler() {
             @Override
             public Resolution resolve(PropertyState ours, PropertyState theirs) {
@@ -205,7 +207,7 @@
         }
     );
 
-    private final Map<String, NodeConflictHandler> nodeConflictHandlers = ImmutableMap.of(
+    private final Map<ConflictType, NodeConflictHandler> nodeConflictHandlers = ImmutableMap.of(
         ADD_EXISTING_NODE, new NodeConflictHandler() {
             @Override
             public Resolution resolve(String name, NodeState ours, NodeState theirs) {
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictValidatorProvider.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictValidatorProvider.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictValidatorProvider.java	(revision )
@@ -18,6 +18,8 @@
 
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
 import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
@@ -32,7 +34,8 @@
 
     @Override
     public Validator getRootValidator(NodeState before, NodeState after) {
-        return new ConflictValidator();
+        Tree rootAfter = new ImmutableTree(after);
+        return new ConflictValidator(rootAfter,"");
     }
 
 }
Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/AnnotatingConflictHandler.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/AnnotatingConflictHandler.java	(revision c71bb71595ef40d1fcc0d3ed827ea60fa201480a)
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/AnnotatingConflictHandler.java	(revision )
@@ -16,24 +16,29 @@
  */
 package org.apache.jackrabbit.oak.plugins.commit;
 
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.commit.ConflictHandler;
+import org.apache.jackrabbit.oak.spi.state.ConflictType;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import java.util.List;
+
 import static com.google.common.collect.Lists.newArrayList;
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.oak.api.Type.NAMES;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.ADD_EXISTING;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.CHANGE_CHANGED;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.CHANGE_DELETED;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.DELETE_CHANGED;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.DELETE_DELETED;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.ADD_EXISTING_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.ADD_EXISTING_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_CHANGED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_DELETED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.CHANGE_DELETED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_CHANGED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_CHANGED_PROPERTY;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_DELETED_NODE;
+import static org.apache.jackrabbit.oak.spi.state.ConflictType.DELETE_DELETED_PROPERTY;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.MIX_REP_MERGE_CONFLICT;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_OURS;
 
-import java.util.List;
-
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.spi.commit.ConflictHandler;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-
 /**
  * This {@link ConflictHandler} implementation resolves conflicts to
  * {@link Resolution#THEIRS} and in addition marks nodes where a conflict
@@ -56,63 +61,63 @@
     @Override
     public Resolution addExistingProperty(NodeBuilder parent, PropertyState ours, PropertyState theirs) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(ADD_EXISTING).setProperty(ours);
+        createChild(marker, ADD_EXISTING_PROPERTY).setProperty(ours);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution changeDeletedProperty(NodeBuilder parent, PropertyState ours) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(CHANGE_DELETED).setProperty(ours);
+        createChild(marker, CHANGE_DELETED_PROPERTY).setProperty(ours);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution changeChangedProperty(NodeBuilder parent, PropertyState ours, PropertyState theirs) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(CHANGE_CHANGED).setProperty(ours);
+        createChild(marker, CHANGE_CHANGED_PROPERTY).setProperty(ours);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution deleteChangedProperty(NodeBuilder parent, PropertyState theirs) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(DELETE_CHANGED).setProperty(theirs);
+        createChild(marker, DELETE_CHANGED_PROPERTY).setProperty(theirs);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution deleteDeletedProperty(NodeBuilder parent, PropertyState ours) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(DELETE_DELETED).setProperty(ours);
+        createChild(marker, DELETE_DELETED_PROPERTY).setProperty(ours);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution addExistingNode(NodeBuilder parent, String name, NodeState ours, NodeState theirs) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(ADD_EXISTING).setChildNode(name, ours);
+        createChild(marker, ADD_EXISTING_NODE).setChildNode(name, ours);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution changeDeletedNode(NodeBuilder parent, String name, NodeState ours) {
         NodeBuilder marker = addConflictMarker(parent);
-        marker.child(CHANGE_DELETED).setChildNode(name, ours);
+        createChild(marker, CHANGE_DELETED_NODE).setChildNode(name, ours);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution deleteChangedNode(NodeBuilder parent, String name, NodeState theirs) {
         NodeBuilder marker = addConflictMarker(parent);
-        markChild(marker.child(DELETE_CHANGED), name);
+        markChild(createChild(marker, DELETE_CHANGED_NODE), name);
         return Resolution.THEIRS;
     }
 
     @Override
     public Resolution deleteDeletedNode(NodeBuilder parent, String name) {
         NodeBuilder marker = addConflictMarker(parent);
-        markChild(marker.child(DELETE_DELETED), name);
+        markChild(createChild(marker, DELETE_DELETED_NODE), name);
         return Resolution.THEIRS;
     }
 
@@ -122,6 +127,10 @@
             parent.setProperty(JCR_MIXINTYPES, mixins, NAMES);
         }
         return parent.child(REP_OURS);
+    }
+
+    private static NodeBuilder createChild(NodeBuilder parent, ConflictType ct) {
+        return parent.child(ct.getName());
     }
 
     private static void markChild(NodeBuilder parent, String name) {
