1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.neo4j.server.plugins;
21
22 import java.lang.reflect.ParameterizedType;
23 import java.lang.reflect.Type;
24
25 import org.neo4j.graphdb.Node;
26 import org.neo4j.graphdb.Path;
27 import org.neo4j.graphdb.Relationship;
28 import org.neo4j.helpers.collection.IterableWrapper;
29 import org.neo4j.server.rest.repr.ListRepresentation;
30 import org.neo4j.server.rest.repr.NodeRepresentation;
31 import org.neo4j.server.rest.repr.PathRepresentation;
32 import org.neo4j.server.rest.repr.RelationshipRepresentation;
33 import org.neo4j.server.rest.repr.Representation;
34 import org.neo4j.server.rest.repr.RepresentationType;
35 import org.neo4j.server.rest.repr.ValueRepresentation;
36
37 abstract class ResultConverter
38 {
39 static ResultConverter get( Type type )
40 {
41 return get( type, true );
42 }
43
44 private static ResultConverter get( Type type, boolean allowComplex )
45 {
46 if ( type instanceof Class<?> )
47 {
48 Class<?> cls = (Class<?>) type;
49 if ( allowComplex && Representation.class.isAssignableFrom( cls ) )
50 {
51 return IDENTITY_RESULT;
52 }
53 else if ( cls == Node.class )
54 {
55 return NODE_RESULT;
56 }
57 else if ( cls == Relationship.class )
58 {
59 return RELATIONSHIP_RESULT;
60 }
61 else if ( cls == Path.class )
62 {
63 return PATH_RESULT;
64 }
65 else if ( cls == String.class )
66 {
67 return STRING_RESULT;
68 }
69 else if ( cls == void.class || cls == Void.class )
70 {
71 return VOID_RESULT;
72 }
73 else if ( cls == long.class || cls == Long.class )
74 {
75 return LONG_RESULT;
76 }
77 else if ( cls == double.class || cls == float.class ||
78 cls == Double.class || cls == Float.class )
79 {
80 return DOUBLE_RESULT;
81 }
82 else if ( cls == boolean.class || cls == Boolean.class )
83 {
84 return BOOL_RESULT;
85 }
86 else if ( cls == char.class || cls == Character.class )
87 {
88 return CHAR_RESULT;
89 }
90 else if ( cls.isPrimitive() || ( Number.class.isAssignableFrom( cls ) &&
91 cls.getPackage().getName().equals( "java.lang" ) ) )
92 {
93 return INT_RESULT;
94 }
95 }
96 else if ( allowComplex && type instanceof ParameterizedType )
97 {
98 ParameterizedType parameterizedType = (ParameterizedType) type;
99 Class<?> raw = (Class<?>) parameterizedType.getRawType();
100 Type paramType = parameterizedType.getActualTypeArguments()[0];
101 if ( !( paramType instanceof Class<?> ) )
102 {
103 throw new IllegalStateException(
104 "Parameterized result types must have a concrete type parameter." );
105 }
106 Class<?> param = (Class<?>) paramType;
107 if ( Iterable.class.isAssignableFrom( raw ) )
108 {
109 return new ListResult( get( param, false ) );
110 }
111 }
112 throw new IllegalStateException( "Illegal result type: " + type );
113 }
114
115 abstract Representation convert( Object obj );
116
117 abstract RepresentationType type();
118
119 private static abstract class ValueResult extends ResultConverter
120 {
121 private final RepresentationType type;
122
123 ValueResult( RepresentationType type )
124 {
125 this.type = type;
126 }
127
128 @Override
129 final RepresentationType type()
130 {
131 return type;
132 }
133 }
134
135 private static final ResultConverter
136 IDENTITY_RESULT = new ResultConverter()
137 {
138 @Override
139 Representation convert( Object obj )
140 {
141 return (Representation) obj;
142 }
143
144 @Override
145 RepresentationType type()
146 {
147 return null;
148 }
149 },
150 NODE_RESULT = new ValueResult( RepresentationType.NODE )
151 {
152 @Override
153 Representation convert( Object obj )
154 {
155 return new NodeRepresentation( (Node) obj );
156 }
157 }, RELATIONSHIP_RESULT = new ValueResult( RepresentationType.RELATIONSHIP )
158 {
159 @Override
160 Representation convert( Object obj )
161 {
162 return new RelationshipRepresentation( (Relationship) obj );
163 }
164 }, PATH_RESULT = new ValueResult( RepresentationType.PATH )
165 {
166 @Override
167 Representation convert( Object obj )
168 {
169 return new PathRepresentation( (Path) obj );
170 }
171 }, STRING_RESULT = new ValueResult( RepresentationType.STRING )
172 {
173 @Override
174 Representation convert( Object obj )
175 {
176 return ValueRepresentation.string( (String) obj );
177 }
178 }, LONG_RESULT = new ValueResult( RepresentationType.LONG )
179 {
180 @Override
181 Representation convert( Object obj )
182 {
183 return ValueRepresentation.number( ( (Number) obj ).longValue() );
184 }
185 }, DOUBLE_RESULT = new ValueResult( RepresentationType.DOUBLE )
186 {
187 @Override
188 Representation convert( Object obj )
189 {
190 return ValueRepresentation.number( ( (Number) obj ).doubleValue() );
191 }
192 }, BOOL_RESULT = new ValueResult( RepresentationType.BOOLEAN )
193 {
194 @Override
195 @SuppressWarnings( "boxing" )
196 Representation convert( Object obj )
197 {
198 return ValueRepresentation.bool( (Boolean) obj );
199 }
200 }, INT_RESULT = new ValueResult( RepresentationType.INTEGER )
201 {
202 @Override
203 Representation convert( Object obj )
204 {
205 return ValueRepresentation.number( ( (Number) obj ).intValue() );
206 }
207 }, CHAR_RESULT = new ValueResult( RepresentationType.CHAR )
208 {
209 @Override
210 @SuppressWarnings( "boxing" )
211 Representation convert( Object obj )
212 {
213 return ValueRepresentation.number( (Character) obj );
214 }
215 }, VOID_RESULT = new ValueResult( RepresentationType.NOTHING )
216 {
217 @Override
218 Representation convert( Object obj )
219 {
220 return Representation.emptyRepresentation();
221 }
222 };
223
224 private static class ListResult extends ResultConverter
225 {
226 private final ResultConverter itemConverter;
227
228 ListResult( ResultConverter itemConverter )
229 {
230 this.itemConverter = itemConverter;
231 }
232
233 @Override
234 @SuppressWarnings( "unchecked" )
235 Representation convert( Object obj )
236 {
237 return new ListRepresentation( itemConverter.type(),
238 new IterableWrapper<Representation, Object>( (Iterable<Object>) obj )
239 {
240 @Override
241 protected Representation underlyingObjectToObject( Object object )
242 {
243 return itemConverter.convert( object );
244 }
245 } );
246 }
247
248 @Override
249 RepresentationType type()
250 {
251 return null;
252 }
253 }
254 }