1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.neo4j.server.rest.repr;
21
22 import java.lang.annotation.ElementType;
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.lang.annotation.Target;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.concurrent.ConcurrentHashMap;
31
32 public abstract class ObjectRepresentation extends MappingRepresentation
33 {
34 @Target( ElementType.METHOD )
35 @Retention( RetentionPolicy.RUNTIME )
36 protected @interface Mapping
37 {
38 String value();
39 }
40
41 private static Map<Class<?>, Map<String, PropertyGetter>> serializations = new ConcurrentHashMap<Class<?>, Map<String, PropertyGetter>>();
42
43 private final Map<String, PropertyGetter> serialization = serialization( getClass() );
44
45 ObjectRepresentation( RepresentationType type )
46 {
47 super( type );
48 }
49
50 public ObjectRepresentation( String type )
51 {
52 super( type );
53 }
54
55 private static Map<String, PropertyGetter> serialization(
56 Class<? extends ObjectRepresentation> type )
57 {
58 Map<String, PropertyGetter> serialization = serializations.get( type );
59 if ( serialization == null )
60 {
61 synchronized ( type )
62 {
63 serialization = serializations.get( type );
64 if ( serialization == null )
65 {
66 serialization = new HashMap<String, PropertyGetter>();
67 for ( Method method : type.getMethods() )
68 {
69 Mapping property = method.getAnnotation( Mapping.class );
70 if ( property != null )
71 {
72 serialization.put( property.value(), getter( method ) );
73 }
74 }
75 }
76 }
77 }
78 return serialization;
79 }
80
81 private static PropertyGetter getter( final Method method )
82 {
83
84
85 return new PropertyGetter( method )
86 {
87 @Override
88 Object get( ObjectRepresentation object )
89 {
90 Throwable e;
91 try
92 {
93 return method.invoke( object );
94 }
95 catch ( InvocationTargetException ex )
96 {
97 e = ex.getTargetException();
98 if ( e instanceof RuntimeException )
99 {
100 throw (RuntimeException) e;
101 }
102 else if ( e instanceof Error )
103 {
104 throw (Error) e;
105 }
106 }
107 catch ( Exception ex )
108 {
109 e = ex;
110 }
111 throw new IllegalStateException( "Serialization failure", e );
112 }
113 };
114 }
115
116 private static abstract class PropertyGetter
117 {
118 PropertyGetter( Method method )
119 {
120 if ( method.getParameterTypes().length != 0 )
121 {
122 throw new IllegalStateException(
123 "Property getter method may not have any parameters." );
124 }
125 if ( !Representation.class.isAssignableFrom( (Class<?>) method.getReturnType() ) )
126 {
127 throw new IllegalStateException(
128 "Property getter must return Representation object." );
129 }
130 }
131
132 void putTo( MappingSerializer serializer, ObjectRepresentation object, String key )
133 {
134 Object value = get( object );
135 if ( value != null ) ( (Representation) value ).putTo( serializer, key );
136 }
137
138 abstract Object get( ObjectRepresentation object );
139 }
140
141 @Override
142 protected final void serialize( MappingSerializer serializer )
143 {
144 for ( Map.Entry<String, PropertyGetter> property : serialization.entrySet() )
145 {
146 property.getValue().putTo( serializer, this, property.getKey() );
147 }
148 extraData( serializer );
149 }
150
151 void extraData( MappingSerializer serializer )
152 {
153 }
154 }