View Javadoc
1   package org.neo4j.driver.projection;
2   
3   import org.neo4j.driver.exception.Neo4jClientException;
4   import org.neo4j.driver.internal.types.InternalTypeSystem;
5   import org.neo4j.driver.internal.value.IntegerValue;
6   import org.neo4j.driver.internal.value.ListValue;
7   import org.neo4j.driver.internal.value.StringValue;
8   import org.neo4j.driver.v1.Value;
9   import org.neo4j.driver.v1.types.Node;
10  import org.neo4j.driver.v1.types.Relationship;
11  
12  import java.lang.reflect.ParameterizedType;
13  import java.util.stream.StreamSupport;
14  
15  /**
16   * Helper class to easy convert Neo4j driver Value.
17   */
18  public class ConversionHelper {
19  
20      /**
21       * Convert a Neo4j driver value to the specified class.
22       */
23      public static <Z> Z convertDriverValueTo(Z type, Value value) {
24          Z result = null;
25  
26          Class clazz;
27          if (type instanceof ParameterizedType) {
28              ParameterizedType ptype = (ParameterizedType) type;
29              clazz = (Class) ptype.getRawType();
30          } else {
31              clazz = (Class) type;
32          }
33  
34          if (value.type() != InternalTypeSystem.TYPE_SYSTEM.NULL()) {
35  
36              // Depends of the projection
37              switch (clazz.getSimpleName()) {
38                  case "String":
39                      result = (Z) value.asString();
40                      break;
41                  case "Long":
42                      result = (Z) Long.valueOf(value.asLong());
43                      break;
44                  case "Integer":
45                      result = (Z) Integer.valueOf(value.asInt());
46                      break;
47                  case "Float":
48                      result = (Z) Float.valueOf(value.asFloat());
49                      break;
50                  case "Boolean":
51                      result = (Z) Boolean.valueOf(value.asBoolean());
52                      break;
53                  case "Number":
54                      result = (Z) value.asNumber();
55                      break;
56                  case "Double":
57                      result = (Z) Double.valueOf(value.asDouble());
58                      break;
59                  case "Node":
60                      result = (Z) value.asNode();
61                      break;
62                  case "Relationship":
63                      result = (Z) value.asRelationship();
64                      break;
65                  case "Path":
66                      // TODO : make a generic type for path ? A list of Map ?
67                      result = (Z) value.asPath();
68                      break;
69                  case "ArrayList":
70                  case "List":
71                      if (type instanceof ParameterizedType && ((ParameterizedType) type).getActualTypeArguments().length == 1) {
72                          try {
73                              Class pClazz = Class.forName(((ParameterizedType) type).getActualTypeArguments()[0].getTypeName());
74                              result = (Z) value.asList(e -> pClazz.cast(convertDriverValueTo(pClazz, e)));
75                          } catch (ClassNotFoundException e) {
76                              throw new Neo4jClientException(e);
77                          }
78                      } else {
79                          result = (Z) value.asList();
80                      }
81                      break;
82                  case "Map":
83                      result = (Z) value.asMap();
84                      break;
85                  case "byte[]":
86                      result = (Z) value.asByteArray();
87                      break;
88                  // projection type is a more complex
89                  default:
90                      if (InternalTypeSystem.TYPE_SYSTEM.NODE().isTypeOf(value)) {
91                          result = (Z) convertDriverNodeTo(clazz, value.asNode());
92                      }
93                      if (InternalTypeSystem.TYPE_SYSTEM.RELATIONSHIP().isTypeOf(value)) {
94                          result = (Z) convertDriverRelationshipTo(clazz, value.asRelationship());
95                      }
96                      break;
97              }
98  
99          }
100 
101         return result;
102     }
103 
104     /**
105      * Convert a Neo4j driver Node to the specified class.
106      */
107     private static <Z> Z convertDriverNodeTo(Class<Z> clazz, Node node) {
108         Z result = null;
109         if (node != null) {
110             DynamicClassConstructor<Z> generator = new DynamicClassConstructor(clazz);
111             result = generator.construct();
112 
113             // Try to set the neo4j internal id
114             generator.add(result, "_id", new IntegerValue(node.id()));
115 
116             // Try to set Neo4j labels
117             StringValue[] labels = StreamSupport.stream(node.labels().spliterator(), false).map(item -> new StringValue(item)).toArray(StringValue[]::new);
118 
119             generator.add(result, "labels", new ListValue(labels));
120 
121             // Setting all node's properties
122             for (String key : node.keys()) {
123                 generator.add(result, key, node.get(key));
124             }
125         }
126         return result;
127     }
128 
129     /**
130      * Convert a Neo4j driver Relationship to the specified class.
131      */
132     private static <Z> Z convertDriverRelationshipTo(Class<Z> clazz, Relationship rel) {
133         Z result = null;
134         if (rel != null) {
135             DynamicClassConstructor<Z> generator = new DynamicClassConstructor(clazz);
136             result = generator.construct();
137 
138             // Try to set the Neo4j internal id
139             generator.add(result, "_id", new IntegerValue(rel.id()));
140 
141             // Try to set Neo4j type
142             generator.add(result, "type", new StringValue(rel.type()));
143 
144             // Try to set Neo4j start node
145             generator.add(result, "startId", new IntegerValue(rel.startNodeId()));
146 
147             // Try to set Neo4j end node
148             generator.add(result, "endId", new IntegerValue(rel.endNodeId()));
149 
150             // Setting all node's properties
151             for (String key : rel.keys()) {
152                 generator.add(result, key, rel.get(key));
153             }
154         }
155         return result;
156     }
157 }