Index: oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java =================================================================== --- oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java (revision 1727274) +++ oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java (working copy) @@ -48,6 +48,12 @@ */ public class Template { + static final short ZERO_CHILD_NODES_TYPE = 0; + + static final short SINGLE_CHILD_NODE_TYPE = 1; + + static final short MANY_CHILD_NODES_TYPE = 2; + static final String ZERO_CHILD_NODES = null; static final String MANY_CHILD_NODES = ""; @@ -81,12 +87,16 @@ @CheckForNull private final String childName; - Template( - PropertyState primaryType, PropertyState mixinTypes, + Template(PropertyState primaryType, PropertyState mixinTypes, PropertyTemplate[] properties, String childName) { this.primaryType = primaryType; this.mixinTypes = mixinTypes; - this.properties = properties; + if (properties != null) { + this.properties = properties; + Arrays.sort(this.properties); + } else { + this.properties = new PropertyTemplate[0]; + } this.childName = childName; } @@ -293,8 +303,8 @@ @Override public int hashCode() { - return Objects.hashCode( - primaryType, mixinTypes, Arrays.asList(properties), childName); + return Objects.hashCode(primaryType, mixinTypes, + Arrays.asList(properties), getTemplateType(), childName); } @Override @@ -324,4 +334,14 @@ return builder.toString(); } + short getTemplateType() { + if (childName == ZERO_CHILD_NODES) { + return ZERO_CHILD_NODES_TYPE; + } else if (childName == MANY_CHILD_NODES) { + return MANY_CHILD_NODES_TYPE; + } else { + return SINGLE_CHILD_NODE_TYPE; + } + } + } Index: oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/TemplateTest.java =================================================================== --- oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/TemplateTest.java (revision 0) +++ oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/TemplateTest.java (revision 0) @@ -0,0 +1,80 @@ +/* + * 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.plugins.segment; + +import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty; + +import java.io.IOException; +import java.util.ArrayList; + +import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.api.Type; + +import static org.junit.Assert.*; + +import org.junit.Assert; +import org.junit.Test; + +public class TemplateTest { + + @Test + public void testHashCode() throws IOException { + // child node null vs "" + PropertyState primary = createProperty("primary", "primary"); + PropertyState mixin = createProperty("mixin", "mixin"); + PropertyTemplate[] properties = new PropertyTemplate[0]; + + Template t0 = new Template(primary, mixin, properties, ""); + Template t1 = new Template(primary, mixin, properties, null); + + assertNotEquals(t0.hashCode(), t1.hashCode()); + } + + @Test + public void testHashCode2() throws IOException { + // mixins null vs [] + PropertyState primary = createProperty("primary", "primary"); + PropertyState mixin = createProperty("mixin", new ArrayList(), + Type.STRINGS); + PropertyTemplate[] properties = new PropertyTemplate[0]; + String childNode = "c"; + + Template t0 = new Template(primary, null, properties, childNode); + Template t1 = new Template(primary, mixin, properties, childNode); + + assertNotEquals(t0.hashCode(), t1.hashCode()); + } + + @Test + public void testEquals() throws IOException { + // same properties, different order + PropertyState primary = createProperty("primary", "primary"); + PropertyState mixin = createProperty("mixin", "mixin"); + + PropertyTemplate p0 = new PropertyTemplate(createProperty("p0", "v0")); + PropertyTemplate p1 = new PropertyTemplate(createProperty("p1", "v1")); + PropertyTemplate[] pt0 = new PropertyTemplate[] { p0, p1 }; + PropertyTemplate[] pt1 = new PropertyTemplate[] { p1, p0 }; + + String childNode = "c"; + + Template t0 = new Template(primary, mixin, pt0, childNode); + Template t1 = new Template(primary, mixin, pt1, childNode); + + assertEquals(t0, t1); + } +}