diff --git a/community/bolt/pom.xml b/community/bolt/pom.xml index d833c16a103ba..90c7a6f20594f 100644 --- a/community/bolt/pom.xml +++ b/community/bolt/pom.xml @@ -60,12 +60,6 @@ ${project.version} - - org.neo4j - neo4j-values - ${project.version} - - org.neo4j neo4j-kernel diff --git a/community/values/src/main/java/org/neo4j/values/AnyValueWriter.java b/community/values/src/main/java/org/neo4j/values/AnyValueWriter.java index 681cccc3aeb67..cefbe1a9bb146 100644 --- a/community/values/src/main/java/org/neo4j/values/AnyValueWriter.java +++ b/community/values/src/main/java/org/neo4j/values/AnyValueWriter.java @@ -19,12 +19,9 @@ */ package org.neo4j.values; -import java.io.IOException; - import org.neo4j.values.virtual.CoordinateReferenceSystem; import org.neo4j.values.virtual.EdgeValue; import org.neo4j.values.virtual.LabelSet; -import org.neo4j.values.virtual.LabelValue; import org.neo4j.values.virtual.MapValue; import org.neo4j.values.virtual.NodeValue; @@ -40,8 +37,6 @@ public interface AnyValueWriter extends ValueWriter void beginLabels( int numberOfLabels ) throws E; - void writeLabel( LabelValue labelValue ) throws E; - void endLabels() throws E; void writeEdgeReference( long edgeId ) throws E; diff --git a/community/values/src/main/java/org/neo4j/values/virtual/ArrayHelpers.java b/community/values/src/main/java/org/neo4j/values/virtual/ArrayHelpers.java index f3bec2ec837fd..934efc87b5042 100644 --- a/community/values/src/main/java/org/neo4j/values/virtual/ArrayHelpers.java +++ b/community/values/src/main/java/org/neo4j/values/virtual/ArrayHelpers.java @@ -19,14 +19,18 @@ */ package org.neo4j.values.virtual; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; + import org.neo4j.values.AnyValue; -import org.neo4j.values.AnyValues; +import org.neo4j.values.Value; import org.neo4j.values.Values; import org.neo4j.values.VirtualValue; /** * This class is way too similar to org.neo4j.collection.primitive.PrimitiveArrays. - * + *

* Should we introduce dependency on primitive collections? */ final class ArrayHelpers @@ -47,11 +51,23 @@ static boolean isSortedSet( int[] keys ) return true; } - static boolean isSortedSet( VirtualValue[] keys ) + static boolean isSortedSet( VirtualValue[] keys, Comparator comparator ) + { + for ( int i = 0; i < keys.length - 1; i++ ) + { + if ( comparator.compare( keys[i], keys[i + 1] ) >= 0 ) + { + return false; + } + } + return true; + } + + static boolean isSortedSet( Value[] keys, Comparator comparator ) { for ( int i = 0; i < keys.length - 1; i++ ) { - if ( AnyValues.COMPARATOR.compare( keys[i], keys[i + 1] ) >= 0 ) + if ( comparator.compare( keys[i], keys[i + 1] ) >= 0 ) { return false; } @@ -70,4 +86,29 @@ static boolean hasNullOrNoValue( AnyValue[] values ) } return false; } + + static Iterator asIterator( T[] array ) + { + assert array != null; + return new Iterator() + { + private int index; + + @Override + public boolean hasNext() + { + return index < array.length; + } + + @Override + public T next() + { + if ( !hasNext() ) + { + throw new NoSuchElementException(); + } + return array[index++]; + } + }; + } } diff --git a/community/values/src/main/java/org/neo4j/values/virtual/LabelSet.java b/community/values/src/main/java/org/neo4j/values/virtual/LabelSet.java index 90cb0d72ffea3..6b9fa1b95ee2a 100644 --- a/community/values/src/main/java/org/neo4j/values/virtual/LabelSet.java +++ b/community/values/src/main/java/org/neo4j/values/virtual/LabelSet.java @@ -21,51 +21,46 @@ import java.util.Arrays; import java.util.Comparator; +import java.util.Iterator; import org.neo4j.values.AnyValue; import org.neo4j.values.AnyValueWriter; +import org.neo4j.values.AnyValues; +import org.neo4j.values.TextValue; import org.neo4j.values.VirtualValue; +import static org.neo4j.values.virtual.ArrayHelpers.asIterator; import static org.neo4j.values.virtual.ArrayHelpers.isSortedSet; import static org.neo4j.values.virtual.VirtualValueGroup.LABEL_SET; -public abstract class LabelSet extends VirtualValue +public abstract class LabelSet extends VirtualValue implements Iterable { public abstract int size(); - public abstract int getLabelId( int offset ); - + /** + * This implementation is assuming that the label set is fairly + * small, maintains a sorted set of labels. + */ static class ArrayBasedLabelSet extends LabelSet { - private final LabelValue[] labelIds; + private final TextValue[] labels; - ArrayBasedLabelSet( LabelValue[] labels ) + ArrayBasedLabelSet( TextValue[] labels ) { assert labels != null; - assert isSortedSet( labels ); - - this.labelIds = labels; - } - - @Override - public int size() - { - return labelIds.length; - } - - @Override - public int getLabelId( int offset ) - { - return labelIds[offset].id(); + this.labels = new TextValue[labels.length]; + System.arraycopy( labels, 0, this.labels, 0, this.labels.length ); + Arrays.sort( this.labels, AnyValues.COMPARATOR ); + assert isSortedSet( this.labels, AnyValues.COMPARATOR ); } @Override public void writeTo( AnyValueWriter writer ) throws E { - writer.beginLabels( labelIds.length ); - for ( LabelValue label : labelIds ) + writer.beginLabels( labels.length ); + for ( TextValue label : labels ) { - writer.writeLabel( label ); + label.writeTo( writer ); } writer.endLabels(); } @@ -73,7 +68,7 @@ public void writeTo( AnyValueWriter writer ) throws E @Override public int hash() { - return Arrays.hashCode( labelIds ); + return Arrays.hashCode( labels ); } @Override @@ -83,19 +78,40 @@ public boolean equals( VirtualValue other ) { return false; } - LabelSet that = (LabelSet) other; - if ( labelIds.length != that.size() ) + if ( labels.length != ((LabelSet) other).size() ) { return false; } - for ( int i = 0; i < labelIds.length; i++ ) - { - if ( labelIds[i].id() != that.getLabelId( i ) ) + + if ( other instanceof ArrayBasedLabelSet ) + { //fast route + ArrayBasedLabelSet that = (ArrayBasedLabelSet) other; + + for ( int i = 0; i < labels.length; i++ ) + { + if ( !labels[i].equals( that.labels[i] ) ) + { + return false; + } + } + return true; + } + else + { //slow route + LabelSet that = (LabelSet) other; + Iterator thisIterator = iterator(); + Iterator thatIterator = that.iterator(); + while ( thisIterator.hasNext() && thatIterator.hasNext() ) { - return false; + TextValue label1 = thisIterator.next(); + TextValue label2 = thatIterator.next(); + if ( !label1.equals( label2 ) ) + { + return false; + } } + return true; } - return true; } @Override @@ -117,17 +133,55 @@ public int compareTo( VirtualValue other, Comparator comparator ) if ( x == 0 ) { - for ( int i = 0; i < size(); i++ ) + if ( otherSet instanceof ArrayBasedLabelSet ) + { + ArrayBasedLabelSet otherArraySet = (ArrayBasedLabelSet) otherSet; + for ( int i = 0; i < size(); i++ ) + { + x = comparator.compare( labels[i], otherArraySet.labels[i] ); + if ( x != 0 ) + { + return x; + } + } + } + else { - x = Integer.compare( this.labelIds[i].id(), otherSet.getLabelId( i ) ); - if ( x != 0 ) + Iterator thisIterator = iterator(); + Iterator thatIterator = otherSet.iterator(); + while ( thisIterator.hasNext() && thatIterator.hasNext() ) { - return x; + TextValue label1 = thisIterator.next(); + TextValue label2 = thatIterator.next(); + x = comparator.compare( label1, label2 ); + if ( x != 0 ) + { + return x; + } } } } return x; } + + @Override + public String toString() + { + return Arrays.toString( labels ); + } + + @Override + public int size() + { + return labels.length; + } + + @SuppressWarnings( "NullableProblems" ) + @Override + public Iterator iterator() + { + return asIterator( labels ); + } } } diff --git a/community/values/src/main/java/org/neo4j/values/virtual/LabelValue.java b/community/values/src/main/java/org/neo4j/values/virtual/LabelValue.java deleted file mode 100644 index e247363f5761e..0000000000000 --- a/community/values/src/main/java/org/neo4j/values/virtual/LabelValue.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.values.virtual; - -import java.util.Comparator; - -import org.neo4j.values.AnyValue; -import org.neo4j.values.AnyValueWriter; -import org.neo4j.values.TextValue; -import org.neo4j.values.VirtualValue; - -public class LabelValue extends VirtualValue -{ - private final int id; - private final TextValue value; - - LabelValue( int id, TextValue value ) - { - assert id >= 0; - assert value != null; - - this.id = id; - this.value = value; - } - - int id() - { - return id; - } - - @Override - public void writeTo( AnyValueWriter writer ) throws E - { - writer.writeNodeReference( id ); - } - - @Override - public int hash() - { - return Integer.hashCode( id ) + 31 * ( value.hashCode() ); - } - - @Override - public boolean equals( VirtualValue other ) - { - if ( other == null || !(other instanceof LabelValue) ) - { - return false; - } - LabelValue that = (LabelValue) other; - return id == that.id && value.equals( that.value ); - } - - @Override - public VirtualValueGroup valueGroup() - { - return VirtualValueGroup.LABEL; - } - - @Override - public int compareTo( VirtualValue other, Comparator comparator ) - { - if ( !(other instanceof LabelValue) ) - { - throw new IllegalArgumentException( "Cannot compare different virtual values" ); - } - LabelValue otherNode = (LabelValue) other; - return Long.compare( id, otherNode.id ); - } -} diff --git a/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java b/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java index e703634470df0..9a71cae41374d 100644 --- a/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java +++ b/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java @@ -63,12 +63,7 @@ public static MapValue map( HashMap map ) return new MapValue( map ); } - public static LabelValue label( int id, TextValue value ) - { - return new LabelValue( id, value ); - } - - public static LabelSet labels( LabelValue... labels ) + public static LabelSet labels( TextValue... labels ) { return new LabelSet.ArrayBasedLabelSet( labels ); } diff --git a/community/values/src/test/java/org/neo4j/values/AnyValueComparatorTest.java b/community/values/src/test/java/org/neo4j/values/AnyValueComparatorTest.java index 836bbfc9d07ba..33fafc681ea70 100644 --- a/community/values/src/test/java/org/neo4j/values/AnyValueComparatorTest.java +++ b/community/values/src/test/java/org/neo4j/values/AnyValueComparatorTest.java @@ -39,7 +39,6 @@ import static org.neo4j.values.virtual.VirtualValues.edge; import static org.neo4j.values.virtual.VirtualValues.edgeValue; import static org.neo4j.values.virtual.VirtualValues.emptyMap; -import static org.neo4j.values.virtual.VirtualValues.label; import static org.neo4j.values.virtual.VirtualValues.labels; import static org.neo4j.values.virtual.VirtualValues.node; import static org.neo4j.values.virtual.VirtualValues.nodeValue; @@ -68,7 +67,7 @@ public class AnyValueComparatorTest // Node node( 1L ), - nodeValue( 2L, labels( label( 1, stringValue( "L" ) ) ), emptyMap() ), + nodeValue( 2L, labels( stringValue( "L" ) ), emptyMap() ), node( 3L ), // Edge @@ -91,11 +90,11 @@ public class AnyValueComparatorTest // LabelSet labels(), - labels( label( 1, stringValue( "L" ) ) ), - labels( label( 2, stringValue( "L" ) ) ), - labels( label( 1, stringValue( "L" ) ), label( 2, stringValue( "M" ) ) ), - labels( label( 1, stringValue( "L" ) ), label( 2, stringValue( "M" ) ), label( 4, stringValue( "N" ) ) ), - labels( label( 1, stringValue( "L" ) ), label( 3, stringValue( "M" ) ), label( 4, stringValue( "N" ) ) ), + labels( stringValue( "L" ) ), + labels( stringValue( "M" ) ), + labels( stringValue( "L" ), stringValue( "M" ) ), + labels( stringValue( "L" ), stringValue( "M" ), stringValue( "N" ) ), + labels( stringValue( "L" ), stringValue( "M" ), stringValue( "O" ) ), // Point pointCartesian( -1.0, -1.0 ), diff --git a/community/values/src/test/java/org/neo4j/values/virtual/BufferAnyValueWriter.java b/community/values/src/test/java/org/neo4j/values/virtual/BufferAnyValueWriter.java index e47c464411aa7..4269c4b8576e5 100644 --- a/community/values/src/test/java/org/neo4j/values/virtual/BufferAnyValueWriter.java +++ b/community/values/src/test/java/org/neo4j/values/virtual/BufferAnyValueWriter.java @@ -36,7 +36,6 @@ enum SpecialKind WriteNodeReference, EndNode, BeginLabels, - WriteLabel, EndLabels, WriteEdge, WriteEdgeReference, @@ -111,12 +110,6 @@ public void beginLabels( int numberOfLabels ) buffer.add( Specials.beginLabels( numberOfLabels ) ); } - @Override - public void writeLabel( LabelValue label ) - { - buffer.add( Specials.writeLabel( label ) ); - } - @Override public void endLabels() { @@ -209,11 +202,6 @@ public static Special beginLabels( int numberOfLabels ) return new Special( SpecialKind.BeginLabels, numberOfLabels ); } - public static Special writeLabel( LabelValue labelValue ) - { - return new Special( SpecialKind.WriteLabel, labelValue.id() ); - } - public static Special endLabels() { return new Special( SpecialKind.EndLabels, 0 ); diff --git a/community/values/src/test/java/org/neo4j/values/virtual/LabelSetTest.java b/community/values/src/test/java/org/neo4j/values/virtual/LabelSetTest.java index 08b72fbe4f107..e096aedf9078e 100644 --- a/community/values/src/test/java/org/neo4j/values/virtual/LabelSetTest.java +++ b/community/values/src/test/java/org/neo4j/values/virtual/LabelSetTest.java @@ -21,10 +21,11 @@ import org.junit.Test; +import org.neo4j.values.TextValue; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.neo4j.values.Values.stringValue; -import static org.neo4j.values.virtual.VirtualValues.label; import static org.neo4j.values.virtual.VirtualValues.labels; public class LabelSetTest @@ -54,7 +55,7 @@ public void shouldAssertSorted() { try { - labels( label( 2, stringValue( "M" ) ), label( 1, stringValue( "L" ) ) ); + labels( stringValue( "M" ), stringValue( "L" ) ); fail( "should throw on nonsorted input" ); } catch ( Throwable t ) @@ -68,7 +69,7 @@ public void shouldAssertSet() { try { - labels( label( 1, stringValue( "L" ) ), label( 1, stringValue( "L" ) ) ); + labels( stringValue( "L" ), stringValue( "L" ) ); fail( "should throw on nonunique input" ); } catch ( Throwable t ) @@ -79,10 +80,10 @@ public void shouldAssertSet() private LabelSet labelSet( int... ids ) { - LabelValue[] labelValues = new LabelValue[ids.length]; + TextValue[] labelValues = new TextValue[ids.length]; for ( int i = 0; i < ids.length; i++ ) { - labelValues[i] = label( ids[i], stringValue( Integer.toString( ids[i] ) ) ); + labelValues[i] = stringValue( Integer.toString( ids[i] ) ); } return labels( labelValues ); } diff --git a/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueTestUtil.java b/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueTestUtil.java index 2a20f02e448a1..ddcb45bd65348 100644 --- a/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueTestUtil.java +++ b/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueTestUtil.java @@ -22,6 +22,7 @@ import java.util.Arrays; import org.neo4j.values.AnyValue; +import org.neo4j.values.TextValue; import org.neo4j.values.Values; import org.neo4j.values.VirtualValue; @@ -30,7 +31,6 @@ import static org.neo4j.values.Values.stringValue; import static org.neo4j.values.virtual.VirtualValues.edgeValue; import static org.neo4j.values.virtual.VirtualValues.emptyMap; -import static org.neo4j.values.virtual.VirtualValues.label; import static org.neo4j.values.virtual.VirtualValues.labels; import static org.neo4j.values.virtual.VirtualValues.nodeValue; @@ -51,10 +51,10 @@ public static AnyValue toAnyValue( Object o ) public static NodeValue node( long id, String... labels ) { - LabelValue[] labelValues = new LabelValue[labels.length]; + TextValue[] labelValues = new TextValue[labels.length]; for ( int i = 0; i < labels.length; i++ ) { - labelValues[i] = label( i, stringValue( labels[i] ) ); + labelValues[i] = stringValue( labels[i] ); } return nodeValue( id, labels( labelValues ), emptyMap() ); } @@ -117,7 +117,7 @@ public static void assertNotEqual( VirtualValue a, VirtualValue b ) public static NodeValue[] nodes( long... ids ) { return Arrays.stream( ids ) - .mapToObj( id -> nodeValue( id, labels( label( 0, stringValue( "L" ) ) ), emptyMap() ) ) + .mapToObj( id -> nodeValue( id, labels( stringValue( "L" ) ), emptyMap() ) ) .toArray( NodeValue[]::new ); } diff --git a/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueWriteToTest.java b/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueWriteToTest.java index 4266deb168a0f..c106618d662f7 100644 --- a/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueWriteToTest.java +++ b/community/values/src/test/java/org/neo4j/values/virtual/VirtualValueWriteToTest.java @@ -43,14 +43,12 @@ import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.endPoint; import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.writeEdge; import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.writeEdgeReference; -import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.writeLabel; import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.writeNode; import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.writeNodeReference; import static org.neo4j.values.virtual.BufferAnyValueWriter.Specials.writePath; import static org.neo4j.values.virtual.VirtualValues.edge; import static org.neo4j.values.virtual.VirtualValues.edgeValue; import static org.neo4j.values.virtual.VirtualValues.emptyMap; -import static org.neo4j.values.virtual.VirtualValues.label; import static org.neo4j.values.virtual.VirtualValues.labels; import static org.neo4j.values.virtual.VirtualValues.map; import static org.neo4j.values.virtual.VirtualValues.nodeValue; @@ -86,13 +84,11 @@ public static Iterable data() endMap() ), shouldWrite( - labels( label( 1, stringValue( "L" ) ), - label( 2, stringValue( "M" ) ), - label( 3, stringValue( "N" ) ) ), + labels( stringValue( "L" ), stringValue( "M" ), stringValue( "N" ) ), beginLabels( 3 ), - writeLabel( label( 1, stringValue( "L" ) ) ), - writeLabel( label( 2, stringValue( "M" ) ) ), - writeLabel( label( 3, stringValue( "N" ) ) ), + "L", + "M", + "N", endLabels() ), shouldWrite( @@ -105,12 +101,13 @@ public static Iterable data() ), shouldWrite( VirtualValues.path( - new NodeValue[]{nodeValue( 20L, labels( label( 1, stringValue( "L" ))), emptyMap()), - nodeValue( 40L, labels( label( 1, stringValue( "L" ))), emptyMap())}, - new EdgeValue[]{edgeValue( 100L, 40L, 20L, stringValue( "T" ), emptyMap() ) }), - writePath( new NodeValue[]{nodeValue( 20L, labels( label( 1, stringValue( "L" ))), emptyMap()), - nodeValue( 40L, labels( label( 1, stringValue( "L" ))), emptyMap())}, - new EdgeValue[]{edgeValue( 100L, 40L, 20L, stringValue( "T" ), emptyMap() ) } ) + new NodeValue[]{nodeValue( 20L, labels( stringValue( "L" ) ), emptyMap() ), + nodeValue( 40L, labels( stringValue( "L" ) ), emptyMap() )}, + new EdgeValue[]{edgeValue( 100L, 40L, 20L, stringValue( "T" ), emptyMap() )} ), + writePath( + new NodeValue[]{nodeValue( 20L, labels( stringValue( "L" ) ), emptyMap() ), + nodeValue( 40L, labels( stringValue( "L" ) ), emptyMap() )}, + new EdgeValue[]{edgeValue( 100L, 40L, 20L, stringValue( "T" ), emptyMap() )} ) ), shouldWrite( VirtualValues.pointCartesian( 2.0, -4.0 ), @@ -152,12 +149,12 @@ public static Iterable data() ), shouldWrite( nodeValue( 1337L, labels( - label( 1, stringValue( "L1" ) ), - label( 2, stringValue( "L2" ) ) ), + stringValue( "L1" ), + stringValue( "L2" ) ), map( new String[]{"foo"}, new AnyValue[]{stringValue( "foo" )} ) ), writeNode( 1337L, labels( - label( 1, stringValue( "L1" ) ), - label( 2, stringValue( "L2" ) ) ), + stringValue( "L1" ), + stringValue( "L2" ) ), map( new String[]{"foo"}, new AnyValue[]{stringValue( "foo" )} ) ) ), shouldWrite(