Skip to content

Commit 5e97834

Browse files
committed
added template builder for array classes
1 parent c4b1576 commit 5e97834

4 files changed

Lines changed: 261 additions & 7 deletions

File tree

src/main/java/org/msgpack/template/builder/AbstractTemplateBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.lang.annotation.Annotation;
2121
import java.lang.reflect.AccessibleObject;
2222
import java.lang.reflect.Field;
23+
import java.lang.reflect.GenericArrayType;
2324
import java.lang.reflect.Modifier;
2425
import java.lang.reflect.Type;
2526
import java.util.ArrayList;
@@ -246,6 +247,13 @@ public static boolean matchAtClassTemplateBuilder(Class<?> targetClass, boolean
246247
}
247248
}
248249

250+
public static boolean matchAtArrayTemplateBuilder(Class<?> targetClass, boolean hasAnnotation) {
251+
if (((Type) targetClass) instanceof GenericArrayType){
252+
return true;
253+
}
254+
return targetClass.isArray();
255+
}
256+
249257
public static boolean matchAtOrdinalEnumTemplateBuilder(Class<?> targetClass, boolean hasAnnotation) {
250258
if (hasAnnotation) {
251259
return AbstractTemplateBuilder.isAnnotated(targetClass, OrdinalEnum.class)
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
//
2+
// MessagePack for Java
3+
//
4+
// Copyright (C) 2009-2011 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.io.IOException;
21+
import java.lang.reflect.Array;
22+
import java.lang.reflect.GenericArrayType;
23+
import java.lang.reflect.ParameterizedType;
24+
import java.lang.reflect.Type;
25+
26+
import org.msgpack.MessageTypeException;
27+
import org.msgpack.packer.Packer;
28+
import org.msgpack.template.AbstractTemplate;
29+
import org.msgpack.template.BooleanArrayTemplate;
30+
import org.msgpack.template.DoubleArrayTemplate;
31+
import org.msgpack.template.FieldList;
32+
import org.msgpack.template.FloatArrayTemplate;
33+
import org.msgpack.template.IntegerArrayTemplate;
34+
import org.msgpack.template.LongArrayTemplate;
35+
import org.msgpack.template.ShortArrayTemplate;
36+
import org.msgpack.template.Template;
37+
import org.msgpack.template.TemplateRegistry;
38+
import org.msgpack.unpacker.Unpacker;
39+
import org.slf4j.Logger;
40+
import org.slf4j.LoggerFactory;
41+
42+
43+
public class ArrayTemplateBuilder extends AbstractTemplateBuilder {
44+
45+
private static final Logger LOG = LoggerFactory.getLogger(ArrayTemplateBuilder.class);
46+
47+
static class ReflectionObjectArrayTemplate extends AbstractTemplate {
48+
private Class<?> componentClass;
49+
50+
private Template elementTemplate;
51+
52+
public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) {
53+
this.componentClass = componentClass;
54+
this.elementTemplate = elementTemplate;
55+
}
56+
57+
@Override
58+
public void write(Packer packer, Object v, boolean required) throws IOException {
59+
if (v == null) {
60+
if (required) {
61+
throw new MessageTypeException("Attempted to write null");
62+
}
63+
packer.writeNil();
64+
return;
65+
}
66+
if (!(v instanceof Object[]) || !componentClass.isAssignableFrom(v.getClass().getComponentType())) {
67+
throw new MessageTypeException();
68+
}
69+
70+
Object[] array = (Object[]) v;
71+
int length = array.length;
72+
packer.writeArrayBegin(length);
73+
for (int i = 0; i < length; i++) {
74+
elementTemplate.write(packer,array[i], required);
75+
}
76+
packer.writeArrayEnd();
77+
}
78+
79+
@Override
80+
public Object read(Unpacker unpacker, Object to, boolean required) throws IOException {
81+
if (!required && unpacker.trySkipNil()) {
82+
return null;
83+
}
84+
85+
int length = unpacker.readArrayBegin();
86+
Object[] array = (Object[]) Array.newInstance(componentClass,
87+
length);
88+
for (int i = 0; i < length; i++) {
89+
array[i] = elementTemplate.read(unpacker, null, required);
90+
}
91+
unpacker.readArrayEnd();
92+
return array;
93+
}
94+
}
95+
96+
static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate {
97+
private Class<?> componentClass;
98+
99+
private Template componentTemplate;
100+
101+
public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) {
102+
this.componentClass = componentClass;
103+
this.componentTemplate = componentTemplate;
104+
}
105+
106+
Class<?> getComponentClass() {
107+
return componentClass;
108+
}
109+
110+
@Override
111+
public void write(Packer packer, Object v, boolean required) throws IOException {
112+
if (v == null) {
113+
if (required) {
114+
throw new MessageTypeException("Attempted to write null");
115+
}
116+
packer.writeNil();
117+
return;
118+
}
119+
if (!(v instanceof Object[]) || !componentClass.isAssignableFrom(v.getClass().getComponentType())) {
120+
throw new MessageTypeException();
121+
}
122+
123+
Object[] array = (Object[]) v;
124+
int length = array.length;
125+
packer.writeArrayBegin(length);
126+
for (int i = 0; i < length; i++) {
127+
componentTemplate.write(packer, array[i], required);
128+
}
129+
packer.writeArrayEnd();
130+
}
131+
132+
@Override
133+
public Object read(Unpacker unpacker, Object to, boolean required) throws IOException {
134+
if (!required && unpacker.trySkipNil()) {
135+
return null;
136+
}
137+
138+
int length = unpacker.readArrayBegin();
139+
Object[] array = (Object[]) Array.newInstance(componentClass, length);
140+
for (int i = 0; i < length; i++) {
141+
array[i] = componentTemplate.read(unpacker, null, required);
142+
}
143+
unpacker.readArrayEnd();
144+
return array;
145+
}
146+
}
147+
148+
public ArrayTemplateBuilder(TemplateRegistry registry) {
149+
super(registry);
150+
}
151+
152+
@Override
153+
public boolean matchType(Type targetType, boolean forceBuild) {
154+
Class<?> targetClass = (Class<?>) targetType;
155+
boolean matched = AbstractTemplateBuilder.matchAtArrayTemplateBuilder(targetClass, false);
156+
if (matched) {
157+
LOG.debug("matched type: " + targetClass.getName());
158+
}
159+
return matched;
160+
}
161+
162+
@Override
163+
public <T> Template<T> buildTemplate(Type arrayType) {
164+
Type baseType;
165+
Class<?> baseClass;
166+
int dim = 1;
167+
if (arrayType instanceof GenericArrayType) {
168+
GenericArrayType type = (GenericArrayType) arrayType;
169+
baseType = type.getGenericComponentType();
170+
while (baseType instanceof GenericArrayType) {
171+
baseType = ((GenericArrayType) baseType)
172+
.getGenericComponentType();
173+
dim += 1;
174+
}
175+
if (baseType instanceof ParameterizedType) {
176+
baseClass = (Class<?>) ((ParameterizedType) baseType)
177+
.getRawType();
178+
} else {
179+
baseClass = (Class<?>) baseType;
180+
}
181+
} else {
182+
Class<?> type = (Class<?>) arrayType;
183+
baseClass = type.getComponentType();
184+
while (baseClass.isArray()) {
185+
baseClass = baseClass.getComponentType();
186+
dim += 1;
187+
}
188+
baseType = baseClass;
189+
}
190+
return toTemplate(arrayType, baseType, baseClass, dim);
191+
192+
}
193+
194+
@Override
195+
public <T> Template<T> buildTemplate(Class<T> targetClass, FieldList flist) throws TemplateBuildException {
196+
// TODO Auto-generated method stub
197+
return null;
198+
}
199+
200+
@Override
201+
protected <T> Template<T> buildTemplate(Class<T> targetClass, FieldEntry[] entries) {
202+
// TODO Auto-generated method stub
203+
return null;
204+
}
205+
206+
private Template toTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim) {
207+
if (dim == 1) {
208+
if (baseClass == boolean.class) {
209+
return BooleanArrayTemplate.getInstance();
210+
} else if (baseClass == short.class) {
211+
return ShortArrayTemplate.getInstance();
212+
} else if (baseClass == int.class) {
213+
return IntegerArrayTemplate.getInstance();
214+
} else if (baseClass == long.class) {
215+
return LongArrayTemplate.getInstance();
216+
} else if (baseClass == float.class) {
217+
return FloatArrayTemplate.getInstance();
218+
} else if (baseClass == double.class) {
219+
return DoubleArrayTemplate.getInstance();
220+
} else {
221+
Template baseTemplate = registry.lookup(genericBaseType);
222+
return new ReflectionObjectArrayTemplate(baseClass, baseTemplate);
223+
}
224+
} else if (dim == 2) {
225+
Class<?> componentClass = Array.newInstance(baseClass, 0).getClass();
226+
Template componentTemplate = toTemplate(arrayType, genericBaseType, baseClass, dim - 1);
227+
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
228+
} else {
229+
ReflectionMultidimentionalArrayTemplate componentTemplate =
230+
(ReflectionMultidimentionalArrayTemplate) toTemplate(arrayType, genericBaseType, baseClass, dim - 1);
231+
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
232+
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
233+
}
234+
}
235+
236+
@Override
237+
public void writeTemplate(Type targetType, String directoryName) {
238+
throw new UnsupportedOperationException(targetType.toString());
239+
}
240+
241+
@Override
242+
public <T> Template<T> loadTemplate(Type targetType) {
243+
return null;
244+
}
245+
246+
}

src/main/java/org/msgpack/template/builder/TemplateBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525

2626
public interface TemplateBuilder {
27+
2728
boolean matchType(Type targetType, boolean forceBuild);
2829

2930
<T> Template<T> buildTemplate(Type targetType) throws TemplateBuildException;

src/main/java/org/msgpack/template/builder/TemplateBuilderChain.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,21 @@ public void init(TemplateRegistry registry) {
3838
}
3939

4040
TemplateBuilder builder;
41-
if (isSupportJavassist()) {
42-
// use dynamic code generation
41+
templateBuilders.add(new ArrayTemplateBuilder(registry));
42+
templateBuilders.add(new OrdinalEnumTemplateBuilder(registry));
43+
if (enableDynamicCodeGeneration()) { // use dynamic code generation
4344
builder = new JavassistTemplateBuilder(registry);
4445
templateBuilders.add(builder);
45-
templateBuilders.add(new ReflectionOrdinalEnumTemplateBuilder(registry));
4646
templateBuilders.add(new JavassistBeansTemplateBuilder(registry));
47-
} else {
48-
// use reflection
47+
} else { // use reflection
4948
builder = new ReflectionTemplateBuilder(registry);
5049
templateBuilders.add(builder);
51-
templateBuilders.add(new ReflectionOrdinalEnumTemplateBuilder(registry));
50+
templateBuilders.add(new OrdinalEnumTemplateBuilder(registry));
5251
templateBuilders.add(new ReflectionBeansTemplateBuilder(registry));
5352
}
5453
}
5554

56-
private static boolean isSupportJavassist(){
55+
private static boolean enableDynamicCodeGeneration(){
5756
try {
5857
return !System.getProperty("java.vm.name").equals("Dalvik");
5958
} catch (Exception e) {

0 commit comments

Comments
 (0)