Mercurial > hg > Members > sugi > MessagePack-java
comparison src/main/java/org/msgpack/template/builder/DefaultBuildContext.java @ 0:cb825acd883a
first commit
author | sugi |
---|---|
date | Sat, 18 Oct 2014 15:06:15 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cb825acd883a |
---|---|
1 // | |
2 // MessagePack for Java | |
3 // | |
4 // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki | |
5 // | |
6 // Licensed under the Apache License, Version 2.0 (the "License"); | |
7 // you may not use this file except in compliance with the License. | |
8 // You may obtain a copy of the License at | |
9 // | |
10 // http://www.apache.org/licenses/LICENSE-2.0 | |
11 // | |
12 // Unless required by applicable law or agreed to in writing, software | |
13 // distributed under the License is distributed on an "AS IS" BASIS, | |
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 // See the License for the specific language governing permissions and | |
16 // limitations under the License. | |
17 // | |
18 package org.msgpack.template.builder; | |
19 | |
20 import java.lang.reflect.Constructor; | |
21 import java.lang.reflect.Field; | |
22 import java.lang.reflect.InvocationTargetException; | |
23 import java.lang.reflect.Modifier; | |
24 | |
25 import org.msgpack.*; | |
26 import org.msgpack.packer.Packer; | |
27 import org.msgpack.template.*; | |
28 import org.msgpack.unpacker.Unpacker; | |
29 | |
30 import javassist.CannotCompileException; | |
31 import javassist.CtClass; | |
32 import javassist.CtConstructor; | |
33 import javassist.CtNewConstructor; | |
34 import javassist.NotFoundException; | |
35 | |
36 @SuppressWarnings({ "rawtypes", "unchecked" }) | |
37 public class DefaultBuildContext extends BuildContext<FieldEntry> { | |
38 protected FieldEntry[] entries; | |
39 | |
40 protected Class<?> origClass; | |
41 | |
42 protected String origName; | |
43 | |
44 protected Template<?>[] templates; | |
45 | |
46 public DefaultBuildContext(JavassistTemplateBuilder director) { | |
47 super(director); | |
48 } | |
49 | |
50 public Template buildTemplate(Class targetClass, FieldEntry[] entries, | |
51 Template[] templates) { | |
52 this.entries = entries; | |
53 this.templates = templates; | |
54 this.origClass = targetClass; | |
55 this.origName = origClass.getName(); | |
56 return build(origName); | |
57 } | |
58 | |
59 protected void setSuperClass() throws CannotCompileException, NotFoundException { | |
60 tmplCtClass.setSuperclass(director.getCtClass( | |
61 JavassistTemplateBuilder.JavassistTemplate.class.getName())); | |
62 } | |
63 | |
64 protected void buildConstructor() throws CannotCompileException, | |
65 NotFoundException { | |
66 // Constructor(Class targetClass, Template[] templates) | |
67 CtConstructor newCtCons = CtNewConstructor.make( | |
68 new CtClass[] { | |
69 director.getCtClass(Class.class.getName()), | |
70 director.getCtClass(Template.class.getName() + "[]") | |
71 }, new CtClass[0], tmplCtClass); | |
72 tmplCtClass.addConstructor(newCtCons); | |
73 } | |
74 | |
75 protected Template buildInstance(Class<?> c) throws NoSuchMethodException, | |
76 InstantiationException, IllegalAccessException, | |
77 InvocationTargetException { | |
78 Constructor<?> cons = c.getConstructor(new Class[] { Class.class, Template[].class }); | |
79 Object tmpl = cons.newInstance(new Object[] { origClass, templates }); | |
80 return (Template) tmpl; | |
81 } | |
82 | |
83 protected void buildMethodInit() { | |
84 } | |
85 | |
86 protected String buildWriteMethodBody() { | |
87 resetStringBuilder(); | |
88 buildString("\n{\n"); | |
89 | |
90 buildString(" if ($2 == null) {\n"); | |
91 buildString(" if ($3) {\n"); | |
92 buildString(" throw new %s(\"Attempted to write null\");\n", MessageTypeException.class.getName()); | |
93 buildString(" }\n"); | |
94 buildString(" $1.writeNil();\n"); | |
95 buildString(" return;\n"); | |
96 buildString(" }\n"); | |
97 | |
98 buildString(" %s _$$_t = (%s) $2;\n", origName, origName); | |
99 buildString(" $1.writeArrayBegin(%d);\n", entries.length); | |
100 | |
101 for (int i = 0; i < entries.length; i++) { | |
102 FieldEntry e = entries[i]; | |
103 if (!e.isAvailable()) { | |
104 buildString(" $1.writeNil();\n"); | |
105 continue; | |
106 } | |
107 DefaultFieldEntry de = (DefaultFieldEntry) e; | |
108 boolean isPrivate = Modifier.isPrivate(de.getField().getModifiers()); | |
109 Class<?> type = de.getType(); | |
110 if (type.isPrimitive()) { // primitive types | |
111 if (!isPrivate) { | |
112 buildString(" $1.%s(_$$_t.%s);\n", primitiveWriteName(type), de.getName()); | |
113 } else { | |
114 buildString( | |
115 " %s.writePrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n", | |
116 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i); | |
117 } | |
118 } else { // reference types | |
119 if (!isPrivate) { | |
120 buildString(" if (_$$_t.%s == null) {\n", de.getName()); | |
121 } else { | |
122 buildString( | |
123 " if (%s.readPrivateField(_$$_t, %s.class, \"%s\") == null) {\n", | |
124 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName()); | |
125 } | |
126 if (de.isNotNullable()) { | |
127 buildString( | |
128 " throw new %s(\"%s cannot be null by @NotNullable\");\n", | |
129 MessageTypeException.class.getName(), de.getName()); | |
130 } else { | |
131 buildString(" $1.writeNil();\n"); | |
132 } | |
133 buildString(" } else {\n"); | |
134 if (!isPrivate) { | |
135 buildString(" templates[%d].write($1, _$$_t.%s);\n", i, de.getName()); | |
136 } else { | |
137 buildString( | |
138 " %s.writePrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n", | |
139 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i); | |
140 } | |
141 buildString(" }\n"); | |
142 } | |
143 } | |
144 | |
145 buildString(" $1.writeArrayEnd();\n"); | |
146 buildString("}\n"); | |
147 return getBuiltString(); | |
148 } | |
149 | |
150 public static Object readPrivateField(Object target, Class targetClass, String fieldName) { | |
151 Field field = null; | |
152 try { | |
153 field = targetClass.getDeclaredField(fieldName); | |
154 field.setAccessible(true); | |
155 Object valueReference = field.get(target); | |
156 return valueReference; | |
157 } catch (Exception e) { | |
158 throw new MessageTypeException(e); | |
159 } finally { | |
160 if (field != null) { | |
161 field.setAccessible(false); | |
162 } | |
163 } | |
164 } | |
165 | |
166 public static void writePrivateField(Packer packer, Object target, | |
167 Class targetClass, String fieldName, Template tmpl) { | |
168 Field field = null; | |
169 try { | |
170 field = targetClass.getDeclaredField(fieldName); | |
171 field.setAccessible(true); | |
172 Object valueReference = field.get(target); | |
173 tmpl.write(packer, valueReference); | |
174 } catch (Exception e) { | |
175 throw new MessageTypeException(e); | |
176 } finally { | |
177 if (field != null) { | |
178 field.setAccessible(false); | |
179 } | |
180 } | |
181 } | |
182 | |
183 protected String buildReadMethodBody() { | |
184 resetStringBuilder(); | |
185 buildString("\n{\n"); | |
186 | |
187 buildString(" if (!$3 && $1.trySkipNil()) {\n"); | |
188 buildString(" return null;\n"); | |
189 buildString(" }\n"); | |
190 | |
191 buildString(" %s _$$_t;\n", origName); | |
192 buildString(" if ($2 == null) {\n"); | |
193 buildString(" _$$_t = new %s();\n", origName); | |
194 buildString(" } else {\n"); | |
195 buildString(" _$$_t = (%s) $2;\n", origName); | |
196 buildString(" }\n"); | |
197 buildString(" $1.readArrayBegin();\n"); | |
198 | |
199 int i; | |
200 for (i = 0; i < entries.length; i++) { | |
201 FieldEntry e = entries[i]; | |
202 if (!e.isAvailable()) { | |
203 buildString(" $1.skip();\n"); | |
204 continue; | |
205 } | |
206 | |
207 if (e.isOptional()) { | |
208 buildString(" if ($1.trySkipNil()) {"); | |
209 // if Optional and nil, then keep default value | |
210 buildString(" } else {\n"); | |
211 } | |
212 | |
213 DefaultFieldEntry de = (DefaultFieldEntry) e; | |
214 boolean isPrivate = Modifier.isPrivate(de.getField().getModifiers()); | |
215 Class<?> type = de.getType(); | |
216 if (type.isPrimitive()) { | |
217 if (!isPrivate) { | |
218 buildString(" _$$_t.%s = $1.%s();\n", de.getName(), primitiveReadName(type)); | |
219 } else { | |
220 buildString( | |
221 " %s.readPrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n", | |
222 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i); | |
223 } | |
224 } else { | |
225 if (!isPrivate) { | |
226 buildString( | |
227 " _$$_t.%s = (%s) this.templates[%d].read($1, _$$_t.%s);\n", | |
228 de.getName(), de.getJavaTypeName(), i, de.getName()); | |
229 } else { | |
230 buildString( | |
231 " %s.readPrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n", | |
232 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i); | |
233 } | |
234 } | |
235 | |
236 if (de.isOptional()) { | |
237 buildString(" }\n"); | |
238 } | |
239 } | |
240 | |
241 buildString(" $1.readArrayEnd();\n"); | |
242 buildString(" return _$$_t;\n"); | |
243 | |
244 buildString("}\n"); | |
245 return getBuiltString(); | |
246 } | |
247 | |
248 public static void readPrivateField(Unpacker unpacker, Object target, | |
249 Class targetClass, String fieldName, Template tmpl) { | |
250 Field field = null; | |
251 try { | |
252 field = targetClass.getDeclaredField(fieldName); | |
253 field.setAccessible(true); | |
254 Object fieldReference = field.get(target); | |
255 Object valueReference = tmpl.read(unpacker, fieldReference); | |
256 if (valueReference != fieldReference) { | |
257 field.set(target, valueReference); | |
258 } | |
259 } catch (Exception e) { | |
260 throw new MessageTypeException(e); | |
261 } finally { | |
262 if (field != null) { | |
263 field.setAccessible(false); | |
264 } | |
265 } | |
266 } | |
267 | |
268 @Override | |
269 public void writeTemplate(Class<?> targetClass, FieldEntry[] entries, | |
270 Template[] templates, String directoryName) { | |
271 this.entries = entries; | |
272 this.templates = templates; | |
273 this.origClass = targetClass; | |
274 this.origName = origClass.getName(); | |
275 write(origName, directoryName); | |
276 } | |
277 | |
278 @Override | |
279 public Template loadTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) { | |
280 this.entries = entries; | |
281 this.templates = templates; | |
282 this.origClass = targetClass; | |
283 this.origName = origClass.getName(); | |
284 return load(origName); | |
285 } | |
286 } |