View Javadoc

1   /**
2    * Copyright (c) 2002-2011 "Neo Technology,"
3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
4    *
5    * This file is part of Neo4j.
6    *
7    * Neo4j is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation, either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
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 }