diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltMessageRouter.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltMessageRouter.java index c58673ace92af..e051008fd292b 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltMessageRouter.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltMessageRouter.java @@ -157,7 +157,7 @@ public void visit( QueryResult.Record record ) throws Exception @Override public void addMetadata( String key, AnyValue value ) { - metadata.put( key, value ); + metadata.add( key, value ); } } ); diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java index 4b36b9d4df56f..56cd87c8e5235 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java @@ -21,9 +21,7 @@ import java.io.IOException; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.neo4j.bolt.runtime.BoltConnection; @@ -35,14 +33,14 @@ import org.neo4j.logging.Log; import org.neo4j.values.AnyValue; import org.neo4j.values.virtual.MapValue; -import org.neo4j.values.virtual.VirtualValues; +import org.neo4j.values.virtual.MapValueBuilder; class MessageProcessingHandler implements BoltResponseHandler { // Errors that are expected when the client disconnects mid-operation private static final Set CLIENT_MID_OP_DISCONNECT_ERRORS = new HashSet<>( Arrays.asList( Status.Transaction.Terminated, Status.Transaction.LockClientStopped ) ); - protected final Map metadata = new HashMap<>(); + protected final MapValueBuilder metadata = new MapValueBuilder( ); protected final Log log; protected final BoltConnection connection; @@ -72,7 +70,7 @@ public void onRecords( BoltResult result, boolean pull ) throws Exception @Override public void onMetadata( String key, AnyValue value ) { - metadata.put( key, value ); + metadata.add( key, value ); } @Override @@ -118,7 +116,7 @@ else if ( error != null ) MapValue getMetadata() { - return VirtualValues.map( metadata ); + return metadata.build(); } private void clearState() diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/Neo4jPackV1.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/Neo4jPackV1.java index 548eefc7c7853..081dc119c60bc 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/Neo4jPackV1.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/Neo4jPackV1.java @@ -26,9 +26,7 @@ import java.time.OffsetTime; import java.time.ZonedDateTime; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.neo4j.bolt.messaging.StructType; import org.neo4j.bolt.v1.packstream.PackInput; @@ -44,6 +42,7 @@ import org.neo4j.values.storable.Values; import org.neo4j.values.virtual.ListValue; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.NodeValue; import org.neo4j.values.virtual.RelationshipValue; import org.neo4j.values.virtual.VirtualValues; @@ -541,10 +540,10 @@ public MapValue unpackMap() throws IOException { return VirtualValues.EMPTY_MAP; } - Map map; + MapValueBuilder map; if ( size == UNKNOWN_SIZE ) { - map = new HashMap<>(); + map = new MapValueBuilder( ); boolean more = true; while ( more ) { @@ -560,7 +559,7 @@ public MapValue unpackMap() throws IOException case STRING: key = unpackString(); val = unpack(); - if ( map.put( key, val ) != null ) + if ( map.add( key, val ) != null ) { throw new BoltIOException( Status.Request.Invalid, "Duplicate map key `" + key + "`." ); } @@ -574,7 +573,7 @@ public MapValue unpackMap() throws IOException } else { - map = new HashMap<>( size, 1 ); + map = new MapValueBuilder( size ); for ( int i = 0; i < size; i++ ) { PackType keyType = peekNextType(); @@ -591,13 +590,13 @@ public MapValue unpackMap() throws IOException } AnyValue val = unpack(); - if ( map.put( key, val ) != null ) + if ( map.add( key, val ) != null ) { throw new BoltIOException( Status.Request.Invalid, "Duplicate map key `" + key + "`." ); } } } - return VirtualValues.map( map ); + return map.build(); } } } diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/CypherAdapterStream.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/CypherAdapterStream.java index 3397b1eb0f6d5..cddd1bf4f2765 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/CypherAdapterStream.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/CypherAdapterStream.java @@ -21,11 +21,8 @@ import java.time.Clock; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import org.neo4j.bolt.v1.messaging.BoltIOException; import org.neo4j.bolt.v1.runtime.spi.BoltResult; import org.neo4j.cypher.result.QueryResult; import org.neo4j.graphdb.ExecutionPlanDescription; @@ -36,6 +33,7 @@ import org.neo4j.values.AnyValue; import org.neo4j.values.storable.Values; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.VirtualValues; import static org.neo4j.values.storable.Values.intValue; @@ -101,26 +99,26 @@ public void accept( final Visitor visitor ) throws Exception private MapValue queryStats( QueryStatistics queryStatistics ) { - Map result = new HashMap<>(); - addIfNonZero( result, "nodes-created", queryStatistics.getNodesCreated() ); - addIfNonZero( result, "nodes-deleted", queryStatistics.getNodesDeleted() ); - addIfNonZero( result, "relationships-created", queryStatistics.getRelationshipsCreated() ); - addIfNonZero( result, "relationships-deleted", queryStatistics.getRelationshipsDeleted() ); - addIfNonZero( result, "properties-set", queryStatistics.getPropertiesSet() ); - addIfNonZero( result, "labels-added", queryStatistics.getLabelsAdded() ); - addIfNonZero( result, "labels-removed", queryStatistics.getLabelsRemoved() ); - addIfNonZero( result, "indexes-added", queryStatistics.getIndexesAdded() ); - addIfNonZero( result, "indexes-removed", queryStatistics.getIndexesRemoved() ); - addIfNonZero( result, "constraints-added", queryStatistics.getConstraintsAdded() ); - addIfNonZero( result, "constraints-removed", queryStatistics.getConstraintsRemoved() ); - return VirtualValues.map( result ); + MapValueBuilder builder = new MapValueBuilder(); + addIfNonZero( builder, "nodes-created", queryStatistics.getNodesCreated() ); + addIfNonZero( builder, "nodes-deleted", queryStatistics.getNodesDeleted() ); + addIfNonZero( builder, "relationships-created", queryStatistics.getRelationshipsCreated() ); + addIfNonZero( builder, "relationships-deleted", queryStatistics.getRelationshipsDeleted() ); + addIfNonZero( builder, "properties-set", queryStatistics.getPropertiesSet() ); + addIfNonZero( builder, "labels-added", queryStatistics.getLabelsAdded() ); + addIfNonZero( builder, "labels-removed", queryStatistics.getLabelsRemoved() ); + addIfNonZero( builder, "indexes-added", queryStatistics.getIndexesAdded() ); + addIfNonZero( builder, "indexes-removed", queryStatistics.getIndexesRemoved() ); + addIfNonZero( builder, "constraints-added", queryStatistics.getConstraintsAdded() ); + addIfNonZero( builder, "constraints-removed", queryStatistics.getConstraintsRemoved() ); + return builder.build(); } - private void addIfNonZero( Map map, String name, int count ) + private void addIfNonZero( MapValueBuilder builder, String name, int count ) { if ( count > 0 ) { - map.put( name, intValue( count ) ); + builder.add( name, intValue( count ) ); } } @@ -150,26 +148,28 @@ private static class NotificationConverter public static AnyValue convert( Iterable notifications ) { List out = new ArrayList<>(); + MapValueBuilder builder = new MapValueBuilder(); for ( Notification notification : notifications ) { - Map notificationMap = new HashMap<>( 4 ); - notificationMap.put( "code", stringValue( notification.getCode() ) ); - notificationMap.put( "title", stringValue( notification.getTitle() ) ); - notificationMap.put( "description", stringValue( notification.getDescription() ) ); - notificationMap.put( "severity", stringValue( notification.getSeverity().toString() ) ); + + builder.add( "code", stringValue( notification.getCode() ) ); + builder.add( "title", stringValue( notification.getTitle() ) ); + builder.add( "description", stringValue( notification.getDescription() ) ); + builder.add( "severity", stringValue( notification.getSeverity().toString() ) ); InputPosition pos = notification.getPosition(); // position is optional - if ( !pos.equals( InputPosition.empty ) ) + boolean includePosition = !pos.equals( InputPosition.empty ); + if ( includePosition ) { // only add the position if it is not empty - Map posMap = new HashMap<>( 3 ); - posMap.put( "offset", intValue( pos.getOffset() ) ); - posMap.put( "line", intValue( pos.getLine() ) ); - posMap.put( "column", intValue( pos.getColumn() ) ); - notificationMap.put( "position", VirtualValues.map( posMap ) ); + builder.add( "position", VirtualValues.map( new String[]{"offset", "line", "columne"}, + new AnyValue[]{ + intValue( pos.getOffset() ), + intValue( pos.getLine() ), + intValue( pos.getColumn() ) } ) ); } - out.add( VirtualValues.map( notificationMap ) ); + out.add( builder.build() ); } return VirtualValues.fromList( out ); } diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/ExecutionPlanConverter.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/ExecutionPlanConverter.java index c62dc4f86cdfd..bddc279ef9d32 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/ExecutionPlanConverter.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/ExecutionPlanConverter.java @@ -19,16 +19,15 @@ */ package org.neo4j.bolt.v1.runtime; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; import org.neo4j.graphdb.ExecutionPlanDescription; import org.neo4j.kernel.impl.util.ValueUtils; import org.neo4j.values.AnyValue; import org.neo4j.values.virtual.ListValue; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.VirtualValues; import static org.neo4j.values.storable.Values.doubleValue; @@ -44,21 +43,21 @@ private ExecutionPlanConverter() public static MapValue convert( ExecutionPlanDescription plan ) { - Map out = new HashMap<>(); - out.put( "operatorType", stringValue( plan.getName() ) ); - out.put( "args", ValueUtils.asMapValue( plan.getArguments() ) ); - out.put( "identifiers", ValueUtils.asListValue( plan.getIdentifiers() ) ); - out.put( "children", children( plan ) ); + MapValueBuilder out = new MapValueBuilder( ); + out.add( "operatorType", stringValue( plan.getName() ) ); + out.add( "args", ValueUtils.asMapValue( plan.getArguments() ) ); + out.add( "identifiers", ValueUtils.asListValue( plan.getIdentifiers() ) ); + out.add( "children", children( plan ) ); if ( plan.hasProfilerStatistics() ) { ExecutionPlanDescription.ProfilerStatistics profile = plan.getProfilerStatistics(); - out.put( "dbHits", longValue( profile.getDbHits() ) ); - out.put( "pageCacheHits", longValue( profile.getPageCacheHits() ) ); - out.put( "pageCacheMisses", longValue( profile.getPageCacheMisses() ) ); - out.put( "pageCacheHitRatio", doubleValue( profile.getPageCacheHitRatio() ) ); - out.put( "rows", longValue( profile.getRows() ) ); + out.add( "dbHits", longValue( profile.getDbHits() ) ); + out.add( "pageCacheHits", longValue( profile.getPageCacheHits() ) ); + out.add( "pageCacheMisses", longValue( profile.getPageCacheMisses() ) ); + out.add( "pageCacheHitRatio", doubleValue( profile.getPageCacheHitRatio() ) ); + out.add( "rows", longValue( profile.getRows() ) ); } - return VirtualValues.map( out ); + return out.build(); } private static ListValue children( ExecutionPlanDescription plan ) diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/CypherAdapterStreamTest.java b/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/CypherAdapterStreamTest.java index e9f555fab44c7..db87c93f9ebae 100644 --- a/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/CypherAdapterStreamTest.java +++ b/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/CypherAdapterStreamTest.java @@ -24,7 +24,6 @@ import java.time.Clock; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -40,6 +39,7 @@ import org.neo4j.values.AnyValue; import org.neo4j.values.storable.DoubleValue; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.VirtualValues; import static java.util.Arrays.asList; @@ -53,7 +53,6 @@ import static org.neo4j.graphdb.QueryExecutionType.QueryType.READ_WRITE; import static org.neo4j.graphdb.QueryExecutionType.explained; import static org.neo4j.graphdb.QueryExecutionType.query; -import static org.neo4j.helpers.collection.MapUtil.genericMap; import static org.neo4j.helpers.collection.MapUtil.map; import static org.neo4j.values.storable.Values.doubleValue; import static org.neo4j.values.storable.Values.intValue; @@ -98,7 +97,7 @@ public void shouldIncludeBasicMetadata() throws Throwable // Then assertThat( meta.get( "type" ), equalTo( stringValue( "rw" ) ) ); - assertThat( meta.get( "stats" ), equalTo( VirtualValues.map( mapValues( + assertThat( meta.get( "stats" ), equalTo( mapValues( "nodes-created", intValue( 1 ), "nodes-deleted", intValue( 2 ), "relationships-created", intValue( 3 ), @@ -109,7 +108,7 @@ public void shouldIncludeBasicMetadata() throws Throwable "constraints-added", intValue( 8 ), "constraints-removed", intValue( 9 ), "labels-added", intValue( 10 ), - "labels-removed", intValue( 11 ) ) + "labels-removed", intValue( 11 ) ) ) ); assertThat( meta.get( "result_consumed_after" ), equalTo( longValue( 1337L ) ) ); } @@ -136,19 +135,18 @@ public void shouldIncludePlanIfPresent() throws Throwable MapValue meta = metadataOf( stream ); // Then - Map expectedChild = mapValues( - "args", VirtualValues.map( mapValues( "arg2", intValue( 1 ) ) ), + MapValue expectedChild = mapValues( + "args", mapValues( "arg2", intValue( 1 ) ), "identifiers", list( stringValue( "id2" ) ), "operatorType", stringValue( "Scan" ), "children", VirtualValues.EMPTY_LIST ); - Map expectedPlan = mapValues( - "args", VirtualValues.map( mapValues( "arg1", intValue( 1 ) ) ), + MapValue expectedPlan = mapValues( + "args", mapValues( "arg1", intValue( 1 ) ), "identifiers", list( stringValue( "id1" ) ), "operatorType", stringValue( "Join" ), - "children", list( VirtualValues.map( expectedChild ) ) - ); - assertThat( meta.get( "plan" ), equalTo( VirtualValues.map( expectedPlan ) ) ); + "children", list( expectedChild ) ); + assertThat( meta.get( "plan" ), equalTo( expectedPlan ) ); } @Test @@ -173,8 +171,8 @@ public void shouldIncludeProfileIfPresent() throws Throwable MapValue meta = metadataOf( stream ); // Then - Map expectedChild = mapValues( - "args", VirtualValues.map( mapValues( "arg2", intValue( 1 ) ) ), + MapValue expectedChild = mapValues( + "args", mapValues( "arg2", intValue( 1 ) ) , "identifiers", list( stringValue( "id2" ) ), "operatorType", stringValue( "Scan" ), "children", VirtualValues.EMPTY_LIST, @@ -185,11 +183,11 @@ public void shouldIncludeProfileIfPresent() throws Throwable "pageCacheHitRatio", doubleValue( 4.0 / 11 ) ); - Map expectedProfile = mapValues( - "args", VirtualValues.map( mapValues( "arg1", intValue( 1 ) ) ), + MapValue expectedProfile = mapValues( + "args", mapValues( "arg1", intValue( 1 ) ), "identifiers", list( stringValue( "id1" ) ), "operatorType", stringValue( "Join" ), - "children", list( VirtualValues.map( expectedChild ) ), + "children", list( expectedChild ), "rows", longValue( 1L ), "dbHits", longValue( 2L ), "pageCacheHits", longValue( 4L ), @@ -197,12 +195,18 @@ public void shouldIncludeProfileIfPresent() throws Throwable "pageCacheHitRatio", doubleValue( 4.0 / 7 ) ); - assertMapEqualsWithDelta( (MapValue) meta.get( "profile" ), VirtualValues.map( expectedProfile ), 0.0001 ); + assertMapEqualsWithDelta( (MapValue) meta.get( "profile" ), expectedProfile, 0.0001 ); } - private Map mapValues( Object... values ) + private MapValue mapValues( Object... values ) { - return genericMap( values ); + int i = 0; + MapValueBuilder builder = new MapValueBuilder(); + while ( i < values.length ) + { + builder.add( (String) values[i++], (AnyValue) values[i++] ); + } + return builder.build(); } @Test @@ -229,30 +233,29 @@ public void shouldIncludeNotificationsIfPresent() throws Throwable MapValue meta = metadataOf( stream ); // Then - Map msg1 = mapValues( + MapValue msg1 = mapValues( "severity", stringValue( "WARNING" ), "code", stringValue( "Neo.ClientError.Schema.IndexNotFound" ), "title", stringValue( "The request (directly or indirectly) referred to an index that does not exist." ), "description", stringValue( "The hinted index does not exist, please check the schema" ) ); - Map msg2 = mapValues( + MapValue msg2 = mapValues( "severity", stringValue( "WARNING" ), "code", stringValue( "Neo.ClientNotification.Statement.PlannerUnsupportedWarning" ), "title", stringValue( "This query is not supported by the COST planner." ), "description", stringValue( "Using COST planner is unsupported for this query, please use RULE planner instead" ), - "position", VirtualValues - .map( mapValues( "offset", intValue( 4 ), "column", intValue( 6 ), "line", intValue( 5 ) ) ) + "position", mapValues( "offset", intValue( 4 ), "column", intValue( 6 ), "line", intValue( 5 ) ) ); assertThat( meta.get( "notifications" ), - equalTo( list( VirtualValues.map( msg1 ), VirtualValues.map( msg2 ) ) ) ); + equalTo( list( msg1, msg2 ) ) ); } private MapValue metadataOf( CypherAdapterStream stream ) throws Exception { - final Map meta = new HashMap<>(); + final MapValueBuilder meta = new MapValueBuilder( ); stream.accept( new BoltResult.Visitor() { @Override @@ -264,10 +267,10 @@ public void visit( QueryResult.Record record ) @Override public void addMetadata( String key, AnyValue value ) { - meta.put( key, value ); + meta.add( key, value ); } } ); - return VirtualValues.map( meta ); + return meta.build(); } private static void assertMapEqualsWithDelta( MapValue a, MapValue b, double delta ) diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/bookmarking/BookmarkTest.java b/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/bookmarking/BookmarkTest.java index 73e70de709137..6c9c5b61bc4c0 100644 --- a/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/bookmarking/BookmarkTest.java +++ b/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/bookmarking/BookmarkTest.java @@ -21,13 +21,10 @@ import org.junit.Test; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - import org.neo4j.kernel.impl.util.ValueUtils; import org.neo4j.values.AnyValue; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.VirtualValues; import static java.util.Arrays.asList; @@ -42,7 +39,7 @@ public class BookmarkTest { private MapValue singletonMap( String key, Object value ) { - return VirtualValues.map( Collections.singletonMap( key, ValueUtils.of( value ) )); + return VirtualValues.map( new String[]{key}, new AnyValue[]{ValueUtils.of( value )} ); } @Test @@ -363,12 +360,12 @@ public void shouldSkipNullsInMultipleBookmarks() throws Exception private static MapValue params( String bookmark, Object bookmarks ) { - Map result = new HashMap<>(); + MapValueBuilder builder = new MapValueBuilder(); if ( bookmark != null ) { - result.put( "bookmark", ValueUtils.of( bookmark ) ); + builder.add( "bookmark", ValueUtils.of( bookmark ) ); } - result.put( "bookmarks", ValueUtils.of( bookmarks ) ); - return VirtualValues.map( result ); + builder.add( "bookmarks", ValueUtils.of( bookmarks ) ); + return builder.build(); } } diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v1/transport/integration/AuthenticationIT.java b/community/bolt/src/test/java/org/neo4j/bolt/v1/transport/integration/AuthenticationIT.java index b239ddec23bbb..55da6d93eeaca 100644 --- a/community/bolt/src/test/java/org/neo4j/bolt/v1/transport/integration/AuthenticationIT.java +++ b/community/bolt/src/test/java/org/neo4j/bolt/v1/transport/integration/AuthenticationIT.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -53,6 +52,7 @@ import org.neo4j.kernel.internal.Version; import org.neo4j.test.TestGraphDatabaseFactory; import org.neo4j.test.rule.fs.EphemeralFileSystemRule; +import org.neo4j.values.AnyValue; import org.neo4j.values.virtual.MapValue; import org.neo4j.values.virtual.VirtualValues; @@ -566,7 +566,7 @@ public boolean gotSpecialMessage() private MapValue singletonMap( String key, Object value ) { - return VirtualValues.map( Collections.singletonMap( key, ValueUtils.of( value ) ) ); + return VirtualValues.map( new String[]{key}, new AnyValue[]{ValueUtils.of( value )} ); } private FailureMessage collectAuthFailureOnFailedAuth() diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v2/transport/integration/BoltV2TransportIT.java b/community/bolt/src/test/java/org/neo4j/bolt/v2/transport/integration/BoltV2TransportIT.java index 7e090904cd6dc..6e84248346ad8 100644 --- a/community/bolt/src/test/java/org/neo4j/bolt/v2/transport/integration/BoltV2TransportIT.java +++ b/community/bolt/src/test/java/org/neo4j/bolt/v2/transport/integration/BoltV2TransportIT.java @@ -43,7 +43,6 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.runners.Parameterized.Parameters; @@ -276,7 +275,7 @@ private void testSendingOfBoltV2Value( T value ) throws Exc negotiateBoltV2(); connection.send( util.chunk( - run( "CREATE (n:Node {value: $value}) RETURN 42", map( singletonMap( "value", value ) ) ), + run( "CREATE (n:Node {value: $value}) RETURN 42", map( new String[]{"value"}, new AnyValue[]{value} ) ), pullAll() ) ); assertThat( connection, util.eventuallyReceives( @@ -306,7 +305,7 @@ private void testSendingAndReceivingOfBoltV2Value( T value negotiateBoltV2(); connection.send( util.chunk( - run( "RETURN $value", map( singletonMap( "value", value ) ) ), + run( "RETURN $value", map( new String[]{"value"} , new AnyValue[]{value} ) ), pullAll() ) ); assertThat( connection, util.eventuallyReceives( diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java index 35ec7d60bf598..c7ae226f15e3e 100644 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java +++ b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledConversionUtils.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -55,6 +54,7 @@ import org.neo4j.values.storable.Values; import org.neo4j.values.virtual.ListValue; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.NodeValue; import org.neo4j.values.virtual.RelationshipValue; import org.neo4j.values.virtual.VirtualNodeValue; @@ -298,12 +298,12 @@ else if ( anyValue instanceof List ) else if ( anyValue instanceof Map ) { Map incoming = (Map) anyValue; - HashMap outgoing = new HashMap<>( incoming.size() ); + MapValueBuilder builder = new MapValueBuilder( incoming.size() ); for ( Map.Entry entry : incoming.entrySet() ) { - outgoing.put( entry.getKey(), materializeAnyResult( proxySpi, entry.getValue() ) ); + builder.add( entry.getKey(), materializeAnyResult( proxySpi, entry.getValue() ) ); } - return VirtualValues.map( outgoing ); + return builder.build(); } else if ( anyValue instanceof PrimitiveNodeStream ) { diff --git a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMaterializeValueMapper.java b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMaterializeValueMapper.java index 1e48ef6d2f639..adbfc94e1cbf4 100644 --- a/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMaterializeValueMapper.java +++ b/community/cypher/cypher/src/main/java/org/neo4j/cypher/internal/codegen/CompiledMaterializeValueMapper.java @@ -20,9 +20,7 @@ package org.neo4j.cypher.internal.codegen; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.neo4j.kernel.impl.core.EmbeddedProxySPI; import org.neo4j.kernel.impl.util.ValueUtils; @@ -41,6 +39,7 @@ import org.neo4j.values.storable.TimeValue; import org.neo4j.values.storable.Values; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.NodeReference; import org.neo4j.values.virtual.NodeValue; import org.neo4j.values.virtual.PathValue; @@ -106,9 +105,9 @@ public AnyValue mapRelationship( VirtualRelationshipValue value ) @Override public AnyValue mapMap( MapValue value ) { - Map map = new HashMap<>(); - value.foreach( ( k, v ) -> map.put( k, v.map( this ) ) ); - return VirtualValues.map( map ); + MapValueBuilder builder = new MapValueBuilder(); + value.foreach( ( k, v ) -> builder.add( k, v.map( this ) ) ); + return builder.build(); } @Override diff --git a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/MapSupport.scala b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/MapSupport.scala index 4883f4b193238..8f64e349939e4 100644 --- a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/MapSupport.scala +++ b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/MapSupport.scala @@ -20,11 +20,12 @@ package org.neo4j.cypher.internal.runtime.interpreted import java.util -import java.util.Map import org.neo4j.cypher.internal.runtime.{Operations, QueryContext} +import org.neo4j.function.ThrowingBiConsumer import org.neo4j.values.AnyValue -import org.neo4j.values.virtual.{MapValue, VirtualRelationshipValue, VirtualNodeValue, VirtualValues} +import org.neo4j.values.storable.Values +import org.neo4j.values.virtual.{MapValue, VirtualNodeValue, VirtualRelationshipValue} import scala.collection.immutable @@ -43,16 +44,16 @@ trait MapSupport { def castToMap: PartialFunction[AnyValue, QueryContext => MapValue] = { case x: MapValue => _ => x - case x: VirtualNodeValue => ctx => VirtualValues.map(new LazyMap(ctx, ctx.nodeOps, x.id())) - case x: VirtualRelationshipValue => ctx => VirtualValues.map(new LazyMap(ctx, ctx.relationshipOps, x.id())) + case x: VirtualNodeValue => ctx => new LazyMap(ctx, ctx.nodeOps, x.id()) + case x: VirtualRelationshipValue => ctx => new LazyMap(ctx, ctx.relationshipOps, x.id()) } } class LazyMap[T](ctx: QueryContext, ops: Operations[T], id: Long) - extends java.util.Map[String, AnyValue] { - - import scala.collection.JavaConverters._ + extends MapValue { + import scala.collection.JavaConverters._ +// private lazy val allProps: util.Map[String, AnyValue] = ops.propertyKeyIds(id) .map(propertyId => { val value: AnyValue = ops.getProperty(id, propertyId) @@ -60,41 +61,27 @@ class LazyMap[T](ctx: QueryContext, ops: Operations[T], id: Long) } ).toMap.asJava - override def values(): util.Collection[AnyValue] = allProps.values() - - override def containsValue(value: scala.Any): Boolean = allProps.containsValue(value) - - override def remove(key: scala.Any): AnyValue = throw new UnsupportedOperationException() - - override def put(key: String, - value: AnyValue): AnyValue = throw new UnsupportedOperationException() - - override def putAll(m: util.Map[_ <: String, _ <: AnyValue]): Unit = throw new UnsupportedOperationException() - - override def get(key: scala.Any): AnyValue = - ctx.getOptPropertyKeyId(key.asInstanceOf[String]) match { - case Some(keyId) => - ops.getProperty(id, keyId) - case None => - null - } - override def keySet(): util.Set[String] = allProps.keySet() - override def entrySet(): util.Set[util.Map.Entry[String, AnyValue]] = allProps.entrySet() - - override def containsKey(key: Any): Boolean = ctx.getOptPropertyKeyId(key.asInstanceOf[String]) - .exists(ops.hasProperty(id, _)) - - override def clear(): Unit = throw new UnsupportedOperationException - - override lazy val isEmpty: Boolean = ops.propertyKeyIds(id).isEmpty + override def foreach[E <: Exception](f: ThrowingBiConsumer[String, AnyValue, E]): Unit = { + val it = allProps.entrySet().iterator() + while(it.hasNext) { + val entry = it.next() + f.accept(entry.getKey, entry.getValue) + } + } - override lazy val size: Int = ops.propertyKeyIds(id).size + override def containsKey(key: String): Boolean = ctx.getOptPropertyKeyId(key).exists(ops.hasProperty(id, _)) - override def hashCode(): Int = allProps.hashCode() + override def get(key: String): AnyValue = + ctx.getOptPropertyKeyId(key) match { + case Some(keyId) => + ops.getProperty(id, keyId) + case None => + Values.NO_VALUE + } - override def equals(obj: scala.Any): Boolean = allProps.equals(obj) + override def size(): Int = ops.propertyKeyIds(id).size } object MapSupport { diff --git a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/ValueConversion.scala b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/ValueConversion.scala index c0b40e28c87c3..0b8d207fad418 100644 --- a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/ValueConversion.scala +++ b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/ValueConversion.scala @@ -31,9 +31,7 @@ import org.neo4j.values.AnyValue import org.neo4j.values.storable.Values.byteArray import org.neo4j.values.storable._ import org.neo4j.values.virtual.VirtualValues.fromArray -import org.neo4j.values.virtual.{MapValue, VirtualValues} - -import scala.collection.JavaConverters._ +import org.neo4j.values.virtual.{MapValue, MapValueBuilder, VirtualValues} object ValueConversion { def getValueConverter(cType: CypherType): Any => AnyValue = { @@ -65,7 +63,14 @@ object ValueConversion { (v) => if (v == null) Values.NO_VALUE else converter(v) } - def asValues(params: Map[String, Any]): MapValue = VirtualValues.map(Eagerly.immutableMapValues(params, asValue).asJava) + def asValues(params: Map[String, Any]): MapValue = { + val builder = new MapValueBuilder(params.size) + params.foreach { + case (key,value) => builder.add(key, asValue(value)) + } + builder.build() + } + def asValue(value: Any): AnyValue = value match { case null => Values.NO_VALUE case s: String => Values.stringValue(s) @@ -85,7 +90,12 @@ object ValueConversion { case x: OffsetTime => TimeValue.time(x) case x: LocalTime => LocalTimeValue.localTime(x) case x: TemporalAmount => Values.durationValue(x) - case m: Map[_, _] => VirtualValues.map(Eagerly.immutableMapValues(m.asInstanceOf[Map[String, Any]], asValue).asJava) + case m: Map[_, _] => + val builder = new MapValueBuilder + m.foreach { + case (k,v) => builder.add(k.asInstanceOf[String], asValue(v)) + } + builder.build() case m: java.util.Map[_, _] => ValueUtils.asMapValue(m.asInstanceOf[java.util.Map[String, AnyRef]]) case a: TraversableOnce[_] => VirtualValues.list(a.map(asValue).toArray:_*) case c: java.util.Collection[_] => ValueUtils.asListValue(c) diff --git a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/DesugaredMapProjection.scala b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/DesugaredMapProjection.scala index 42f385d6463fb..29dcb731b0951 100644 --- a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/DesugaredMapProjection.scala +++ b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/DesugaredMapProjection.scala @@ -19,13 +19,12 @@ */ package org.neo4j.cypher.internal.runtime.interpreted.commands.expressions -import org.neo4j.cypher.internal.runtime.interpreted.{ExecutionContext, GraphElementPropertyFunctions, IsMap} import org.neo4j.cypher.internal.runtime.interpreted.pipes.QueryState +import org.neo4j.cypher.internal.runtime.interpreted.{ExecutionContext, GraphElementPropertyFunctions, IsMap} import org.neo4j.values.AnyValue import org.neo4j.values.storable.Values -import org.neo4j.values.virtual.VirtualValues +import org.neo4j.values.virtual.{MapValueBuilder, VirtualValues} -import scala.collection.JavaConverters._ import scala.collection.Map case class DesugaredMapProjection(id: String, includeAllProps: Boolean, literalExpressions: Map[String, Expression]) @@ -38,12 +37,13 @@ case class DesugaredMapProjection(id: String, includeAllProps: Boolean, literalE case v if v == Values.NO_VALUE => return Values.NO_VALUE case IsMap(m) => if (includeAllProps) m(state.query) else VirtualValues.emptyMap() } - val mapOfLiteralValues = literalExpressions.map { - case (k, e) => (k, e(ctx, state)) - }.toMap.asJava + val builder = new MapValueBuilder() + literalExpressions.foreach { + case (k, e) => builder.add(k, e(ctx, state)) + } - mapOfProperties.updatedWith(VirtualValues.map(mapOfLiteralValues)) + mapOfProperties.updatedWith(builder.build()) } override def rewrite(f: (Expression) => Expression) = diff --git a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/LiteralMap.scala b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/LiteralMap.scala index d156f43c014b6..4f816e3b966c9 100644 --- a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/LiteralMap.scala +++ b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/expressions/LiteralMap.scala @@ -19,20 +19,22 @@ */ package org.neo4j.cypher.internal.runtime.interpreted.commands.expressions -import org.neo4j.cypher.internal.runtime.interpreted.{ExecutionContext, GraphElementPropertyFunctions} import org.neo4j.cypher.internal.runtime.interpreted.pipes.QueryState +import org.neo4j.cypher.internal.runtime.interpreted.{ExecutionContext, GraphElementPropertyFunctions} import org.neo4j.values.AnyValue -import org.neo4j.values.virtual.VirtualValues +import org.neo4j.values.virtual.MapValueBuilder -import scala.collection.JavaConverters._ import scala.collection.Map case class LiteralMap(data: Map[String, Expression]) extends Expression with GraphElementPropertyFunctions { - def apply(ctx: ExecutionContext, state: QueryState): AnyValue = - VirtualValues.map(data.map { - case (k, e) => (k, e(ctx, state)) - }.asJava) + def apply(ctx: ExecutionContext, state: QueryState): AnyValue = { + val builder = new MapValueBuilder + data.foreach { + case (k, e) => builder.add(k, e(ctx, state)) + } + builder.build() + } def rewrite(f: (Expression) => Expression) = f(LiteralMap(data.rewrite(f))) diff --git a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/pipes/LoadCSVPipe.scala b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/pipes/LoadCSVPipe.scala index 1a9da6c1519e4..5107ddc12f27f 100644 --- a/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/pipes/LoadCSVPipe.scala +++ b/community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/pipes/LoadCSVPipe.scala @@ -20,19 +20,16 @@ package org.neo4j.cypher.internal.runtime.interpreted.pipes import java.net.URL -import java.util import org.opencypher.v9_0.util.LoadExternalResourceException +import org.neo4j.cypher.internal.ir.v3_5.{CSVFormat, HasHeaders, NoHeaders} import org.neo4j.cypher.internal.runtime.interpreted.ExecutionContext import org.neo4j.cypher.internal.runtime.interpreted.commands.expressions.Expression -import org.neo4j.cypher.internal.ir.v3_5.{CSVFormat, HasHeaders, NoHeaders} import org.neo4j.cypher.internal.runtime.{ArrayBackedMap, QueryContext} import org.opencypher.v9_0.util.attribution.Id import org.neo4j.values._ import org.neo4j.values.storable.{TextValue, Value, Values} -import org.neo4j.values.virtual.VirtualValues - -import scala.collection.JavaConverters._ +import org.neo4j.values.virtual.{MapValueBuilder, VirtualValues} case class LoadCSVPipe(source: Pipe, format: CSVFormat, @@ -88,12 +85,13 @@ case class LoadCSVPipe(source: Pipe, //we need to make a copy here since someone may hold on this //reference, e.g. EagerPipe - val resultCopy = new util.HashMap[String, AnyValue](internalMap.size) + + var builder = new MapValueBuilder for ((key, maybeNull) <- internalMap) { val value = if (maybeNull == null) Values.NO_VALUE else maybeNull - resultCopy.put(key, value) + builder.add(key, value) } - executionContextFactory.copyWith(context, variable, VirtualValues.map(resultCopy)) + executionContextFactory.copyWith(context, variable, builder.build()) } else null } } diff --git a/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/AddTest.scala b/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/AddTest.scala index 72deaac9d3bf6..519bc566af166 100644 --- a/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/AddTest.scala +++ b/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/AddTest.scala @@ -21,11 +21,11 @@ package org.neo4j.cypher.internal.runtime.interpreted.commands import java.nio.charset.StandardCharsets -import org.neo4j.cypher.internal.runtime.interpreted.{ExecutionContext, QueryStateHelper} import org.neo4j.cypher.internal.runtime.interpreted.commands.expressions.{Add, Literal, ParameterExpression} import org.opencypher.v9_0.util.CypherTypeException import org.opencypher.v9_0.util.test_helpers.CypherFunSuite import org.neo4j.values.AnyValue +import org.neo4j.cypher.internal.runtime.interpreted.{ExecutionContext, QueryStateHelper} import org.neo4j.values.storable.Values.{longValue, stringValue, utf8Value} import org.neo4j.values.storable.{UTF8StringValue, Values} import org.neo4j.values.virtual.VirtualValues @@ -69,12 +69,10 @@ class AddTest extends CypherFunSuite { } test("UTF8 value addition") { - import scala.collection.JavaConverters._ // Given val hello = "hello".getBytes(StandardCharsets.UTF_8) val world = "world".getBytes(StandardCharsets.UTF_8) - val params: Map[String, AnyValue] = Map("p1" -> utf8Value(hello), "p2" -> utf8Value(world)) - val state = QueryStateHelper.emptyWith(params = VirtualValues.map(params.asJava)) + val state = QueryStateHelper.emptyWith(params = VirtualValues.map(Array("p1", "p2"), Array( utf8Value(hello), utf8Value(world)))) // When val result = Add(ParameterExpression("p1"), ParameterExpression("p2"))(m,state) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/ValueUtils.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/ValueUtils.java index a202e3daf884f..5c46034ae41ed 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/ValueUtils.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/ValueUtils.java @@ -20,7 +20,6 @@ package org.neo4j.kernel.impl.util; import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -44,17 +43,16 @@ import org.neo4j.values.storable.TextValue; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; -import org.neo4j.values.virtual.RelationshipValue; import org.neo4j.values.virtual.ListValue; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.NodeValue; import org.neo4j.values.virtual.PathValue; +import org.neo4j.values.virtual.RelationshipValue; import org.neo4j.values.virtual.VirtualNodeValue; import org.neo4j.values.virtual.VirtualRelationshipValue; import org.neo4j.values.virtual.VirtualValues; -import static org.neo4j.values.virtual.VirtualValues.map; - public final class ValueUtils { private ValueUtils() @@ -233,18 +231,12 @@ public static ListValue asListOfEdges( Relationship[] rels ) public static MapValue asMapValue( Map map ) { - return map( mapValues( map ) ); - } - - private static Map mapValues( Map map ) - { - HashMap newMap = new HashMap<>( map.size() ); + MapValueBuilder builder = new MapValueBuilder( map.size() ); for ( Map.Entry entry : map.entrySet() ) { - newMap.put( entry.getKey(), of( entry.getValue() ) ); + builder.add( entry.getKey(), of( entry.getValue() ) ); } - - return newMap; + return builder.build(); } public static NodeValue fromNodeProxy( Node node ) diff --git a/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java b/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java index af7083cdd341b..9ac3d81672949 100644 --- a/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java +++ b/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java @@ -295,9 +295,9 @@ private static final class CombinedMapValue extends MapValue { private final MapValue[] maps; - CombinedMapValue( MapValue...mapValues) + CombinedMapValue( MapValue... mapValues ) { - this.maps = mapValues; + this.maps = mapValues; } public Set keySet() diff --git a/community/values/src/main/java/org/neo4j/values/virtual/MapValueBuilder.java b/community/values/src/main/java/org/neo4j/values/virtual/MapValueBuilder.java new file mode 100644 index 0000000000000..9182e49d009d6 --- /dev/null +++ b/community/values/src/main/java/org/neo4j/values/virtual/MapValueBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002-2018 "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.HashMap; +import java.util.Map; + +import org.neo4j.values.AnyValue; + +public class MapValueBuilder +{ + private final Map map; + + public MapValueBuilder() + { + this.map = new HashMap<>(); + } + + public MapValueBuilder( int size ) + { + this.map = new HashMap<>( size ); + } + + public MapValueBuilder add( String key, AnyValue value ) + { + map.put( key, value ); + return this; + } + + public MapValue build() + { + return new MapValue.MapWrappingMapValue( map ); + } + +} 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 ad7053fb1ef7e..74ce765186720 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 @@ -22,7 +22,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; -import java.util.Map; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.ArrayValue; @@ -150,11 +149,6 @@ public static MapValue map( String[] keys, AnyValue[] values ) return new MapValue.MapWrappingMapValue( map ); } - public static MapValue map( Map map ) - { - return new MapValue.MapWrappingMapValue( map ); - } - public static NodeReference node( long id ) { return new NodeReference( id ); diff --git a/community/values/src/test/java/org/neo4j/values/ValueMapperTest.java b/community/values/src/test/java/org/neo4j/values/ValueMapperTest.java index dda3e170e7777..92e21689d41a3 100644 --- a/community/values/src/test/java/org/neo4j/values/ValueMapperTest.java +++ b/community/values/src/test/java/org/neo4j/values/ValueMapperTest.java @@ -19,19 +19,20 @@ */ package org.neo4j.values; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Arrays; import java.util.List; import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - import org.neo4j.graphdb.spatial.Point; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; +import org.neo4j.values.virtual.MapValueBuilder; import org.neo4j.values.virtual.NodeValue; import org.neo4j.values.virtual.PathValue; import org.neo4j.values.virtual.RelationshipValue; @@ -39,7 +40,6 @@ import org.neo4j.values.virtual.VirtualRelationshipValue; import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; import static org.junit.Assert.assertEquals; import static org.neo4j.values.storable.CoordinateReferenceSystem.Cartesian; import static org.neo4j.values.storable.CoordinateReferenceSystem.WGS84; @@ -171,9 +171,13 @@ private static AnyValue valueOf( Object obj ) { @SuppressWarnings( "unchecked" ) Map map = (Map) obj; - return map( map.entrySet().stream() - .map( e -> new Entry( e.getKey(), valueOf( e.getValue() ) ) ) - .collect( toMap( e -> e.key, e -> e.value ) ) ); + MapValueBuilder builder = new MapValueBuilder( map.size() ); + for ( Map.Entry entry : map.entrySet() ) + { + builder.add( entry.getKey(), valueOf( entry.getValue() ) ); + } + + return builder.build(); } throw new AssertionError( "cannot convert: " + obj + " (a " + obj.getClass().getName() + ")" ); } diff --git a/community/values/src/test/java/org/neo4j/values/utils/PrettyPrinterTest.java b/community/values/src/test/java/org/neo4j/values/utils/PrettyPrinterTest.java index 7e2e1d5918b2d..30d026263ba8d 100644 --- a/community/values/src/test/java/org/neo4j/values/utils/PrettyPrinterTest.java +++ b/community/values/src/test/java/org/neo4j/values/utils/PrettyPrinterTest.java @@ -22,7 +22,6 @@ import org.junit.Test; import java.time.ZoneOffset; -import java.util.HashMap; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.CoordinateReferenceSystem; @@ -171,7 +170,8 @@ public void shouldHandleEdgeValueWithoutProperties() { NodeValue startNode = VirtualValues.nodeValue( 1L, Values.stringArray( "L" ), EMPTY_MAP ); NodeValue endNode = VirtualValues.nodeValue( 2L, Values.stringArray( "L" ), EMPTY_MAP ); - RelationshipValue rel = VirtualValues.relationshipValue( 42L, startNode, endNode, stringValue( "R" ), EMPTY_MAP ); + RelationshipValue rel = + VirtualValues.relationshipValue( 42L, startNode, endNode, stringValue( "R" ), EMPTY_MAP ); PrettyPrinter printer = new PrettyPrinter(); // When @@ -201,7 +201,8 @@ public void shouldHandlePaths() // Given NodeValue startNode = VirtualValues.nodeValue( 1L, Values.stringArray( "L" ), EMPTY_MAP ); NodeValue endNode = VirtualValues.nodeValue( 2L, Values.stringArray( "L" ), EMPTY_MAP ); - RelationshipValue rel = VirtualValues.relationshipValue( 42L, startNode, endNode, stringValue( "R" ), EMPTY_MAP ); + RelationshipValue rel = + VirtualValues.relationshipValue( 42L, startNode, endNode, stringValue( "R" ), EMPTY_MAP ); PathValue path = VirtualValues.path( new NodeValue[]{startNode, endNode}, new RelationshipValue[]{rel} ); PrettyPrinter printer = new PrettyPrinter(); @@ -405,19 +406,19 @@ public void shouldHandleDateTimeWithTimeZoneOffset() private MapValue props( Object... keyValue ) { - HashMap map = new HashMap<>( keyValue.length ); - String key = null; + String[] keys = new String[keyValue.length / 2]; + AnyValue[] values = new AnyValue[keyValue.length / 2]; for ( int i = 0; i < keyValue.length; i++ ) { if ( i % 2 == 0 ) { - key = (String) keyValue[i]; + keys[i / 2] = (String) keyValue[i]; } else { - map.put( key, (AnyValue) keyValue[i] ); + values[i / 2] = (AnyValue) keyValue[i]; } } - return VirtualValues.map( map ); + return VirtualValues.map( keys, values ); } } diff --git a/community/values/src/test/java/org/neo4j/values/virtual/MapValueTest.java b/community/values/src/test/java/org/neo4j/values/virtual/MapValueTest.java index 3d7afa85bffaf..b0f3d2c741276 100644 --- a/community/values/src/test/java/org/neo4j/values/virtual/MapValueTest.java +++ b/community/values/src/test/java/org/neo4j/values/virtual/MapValueTest.java @@ -135,7 +135,6 @@ void shouldUpdateWitOtherMapValue() MapValue b = VirtualValues.map( new String[]{"k1", "k2", "k4"}, new AnyValue[]{stringValue( "version1" ), stringValue( "version2" ), stringValue( "version4" )} ); - // When MapValue updated = a.updatedWith( b );