Skip to content

Commit 9cad6f0

Browse files
committed
add MethodValuesSerializer
1 parent 3426b4b commit 9cad6f0

File tree

3 files changed

+361
-0
lines changed

3 files changed

+361
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package uk.co.real_logic.sbe.codec.java;
2+
3+
import java.lang.reflect.Method;
4+
import java.lang.reflect.Modifier;
5+
import java.util.ArrayList;
6+
import java.util.Arrays;
7+
import java.util.Collections;
8+
import java.util.HashMap;
9+
import java.util.HashSet;
10+
import java.util.LinkedHashSet;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.Set;
14+
15+
/**
16+
* Daneel Yaitskov
17+
*/
18+
public class MethodSelector
19+
{
20+
private final Set<String> ignoredMethods;
21+
private final Map<Class, Set<String>> sortedMethods = new HashMap<>();
22+
23+
public static Set<String> objectMethods()
24+
{
25+
return new HashSet<>(Arrays.asList("hashCode", "clone", "toString", "getClass"));
26+
}
27+
28+
public MethodSelector(Set<String> ignoredMethods)
29+
{
30+
this.ignoredMethods = ignoredMethods;
31+
}
32+
33+
public List<Method> select(Class clazz)
34+
{
35+
final Method[] methods = clazz.getMethods();
36+
final Set<String> sortedMethNames = getSortedMethods(clazz, methods);
37+
final Map<String, Method> sortedMethods = new HashMap<String, Method>();
38+
final List<Method> unsortedMethods = new ArrayList<Method>();
39+
for (Method method : methods)
40+
{
41+
selectMethod(sortedMethNames, sortedMethods, unsortedMethods, method);
42+
}
43+
for (String name : sortedMethNames)
44+
{
45+
unsortedMethods.add(sortedMethods.get(name));
46+
}
47+
return unsortedMethods;
48+
}
49+
50+
private Set<String> getSortedMethods(Class clazz, Method[] methods)
51+
{
52+
final Set<String> sortedMethNames = sortedMethods.get(clazz);
53+
if (sortedMethNames == null)
54+
{
55+
GroupOrder order = (GroupOrder) clazz.getAnnotation(GroupOrder.class);
56+
if (order == null)
57+
{
58+
sortedMethods.put(clazz, Collections.<String>emptySet());
59+
return Collections.emptySet();
60+
}
61+
else
62+
{
63+
Set<String> result = new LinkedHashSet<>();
64+
for (Class groupClazz : order.value())
65+
{
66+
for (Method method : methods)
67+
{
68+
if (method.getReturnType() == groupClazz
69+
&& method.getParameterTypes().length == 0)
70+
{
71+
result.add(method.getName());
72+
}
73+
}
74+
}
75+
sortedMethods.put(clazz, result);
76+
return result;
77+
}
78+
}
79+
return sortedMethNames;
80+
}
81+
82+
private void selectMethod(Set<String> sortedMethNames,
83+
Map<String, Method> sortedMethods,
84+
List<Method> unsortedMethods,
85+
Method method)
86+
{
87+
final int mods = method.getModifiers();
88+
if (!Modifier.isPublic(mods))
89+
{
90+
return;
91+
}
92+
if (Modifier.isStatic(mods))
93+
{
94+
return;
95+
}
96+
if (method.getParameterTypes().length != 0)
97+
{
98+
return;
99+
}
100+
if (method.getReturnType().equals(Void.TYPE))
101+
{
102+
return;
103+
}
104+
final String name = method.getName();
105+
if (ignoredMethods.contains(name))
106+
{
107+
return;
108+
}
109+
if (sortedMethNames == null)
110+
{
111+
unsortedMethods.add(method);
112+
}
113+
else
114+
{
115+
if (sortedMethNames.contains(name))
116+
{
117+
sortedMethods.put(name, method);
118+
}
119+
else
120+
{
121+
unsortedMethods.add(method);
122+
}
123+
}
124+
}
125+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package uk.co.real_logic.sbe.codec.java;
2+
3+
import com.google.gson.JsonArray;
4+
import com.google.gson.JsonElement;
5+
import com.google.gson.JsonNull;
6+
import com.google.gson.JsonObject;
7+
import com.google.gson.JsonPrimitive;
8+
9+
import java.lang.reflect.Array;
10+
import java.lang.reflect.InvocationTargetException;
11+
import java.lang.reflect.Method;
12+
import java.util.Iterator;
13+
import java.util.Map;
14+
15+
/**
16+
* Daneel Yaitskov
17+
*/
18+
public class MethodValuesSerializer
19+
{
20+
private final MethodSelector methodSelector;
21+
22+
public MethodValuesSerializer(MethodSelector methodSelector)
23+
{
24+
this.methodSelector = methodSelector;
25+
}
26+
27+
public JsonElement serialize(Object object)
28+
throws InvocationTargetException, IllegalAccessException
29+
{
30+
return serialize(object, true);
31+
}
32+
33+
JsonElement serialize(Object object, boolean visitIterable)
34+
throws InvocationTargetException, IllegalAccessException
35+
{
36+
if (object == null)
37+
{
38+
return JsonNull.INSTANCE;
39+
}
40+
Class clazz = object.getClass();
41+
if (Number.class.isAssignableFrom(clazz))
42+
{
43+
return new JsonPrimitive((Number) object);
44+
}
45+
else if (clazz == String.class)
46+
{
47+
return new JsonPrimitive((String) object);
48+
}
49+
else if (clazz == Boolean.class)
50+
{
51+
return new JsonPrimitive((Boolean) object);
52+
}
53+
else if (object instanceof Enum)
54+
{
55+
return new JsonPrimitive(((Enum) object).name());
56+
}
57+
else if (clazz.isArray())
58+
{
59+
JsonArray result = new JsonArray();
60+
int len = Array.getLength(object);
61+
for (int i = 0; i < len; ++i)
62+
{
63+
result.add(serialize(Array.get(object, i)));
64+
}
65+
return result;
66+
}
67+
else if (visitIterable && Iterable.class.isAssignableFrom(clazz))
68+
{
69+
Iterator iter = ((Iterable) object).iterator();
70+
JsonArray result = new JsonArray();
71+
while (iter.hasNext())
72+
{
73+
result.add(serialize(iter.next(), false));
74+
}
75+
return result;
76+
}
77+
else if (Map.class.isAssignableFrom(clazz))
78+
{
79+
JsonObject result = new JsonObject();
80+
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) object).entrySet())
81+
{
82+
result.add(entry.getKey().toString(), serialize(entry.getValue()));
83+
}
84+
return result;
85+
}
86+
else
87+
{
88+
return serializeObject(object, clazz);
89+
}
90+
}
91+
92+
private JsonElement serializeObject(Object object, Class clazz)
93+
throws InvocationTargetException, IllegalAccessException
94+
{
95+
JsonObject result = new JsonObject();
96+
for (Method method : methodSelector.select(clazz))
97+
{
98+
Object re = method.invoke(object);
99+
if (re == object)
100+
{
101+
continue;
102+
}
103+
result.add(method.getName(), serialize(re));
104+
}
105+
return result;
106+
}
107+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package uk.co.real_logic.sbe.codec.java;
2+
3+
import com.google.gson.JsonArray;
4+
import com.google.gson.JsonElement;
5+
import com.google.gson.JsonObject;
6+
import com.google.gson.JsonPrimitive;
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
10+
import java.lang.reflect.InvocationTargetException;
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.List;
14+
15+
/**
16+
* Daneel Yaitskov
17+
*/
18+
public class MethodValuesSerializerTest
19+
{
20+
enum E1
21+
{
22+
A, B
23+
}
24+
25+
static List<Class> order = new ArrayList<>();
26+
27+
@GroupOrder({X.Y.class, X.Z.class})
28+
static class X
29+
{
30+
class Z
31+
{
32+
public boolean publicBoolean()
33+
{
34+
order.add(Z.class);
35+
return true;
36+
}
37+
}
38+
39+
class Y
40+
{
41+
public boolean publicBoolean()
42+
{
43+
order.add(Y.class);
44+
return true;
45+
}
46+
}
47+
48+
class S
49+
{
50+
public boolean publicBoolean()
51+
{
52+
return true;
53+
}
54+
}
55+
56+
public Z publicZ()
57+
{
58+
return new Z();
59+
}
60+
61+
public Y publicY()
62+
{
63+
return new Y();
64+
}
65+
66+
public List<S> publicListS()
67+
{
68+
return Arrays.asList(new S());
69+
}
70+
71+
public E1 publicEnum()
72+
{
73+
return E1.A;
74+
}
75+
76+
public int[] publicIntArr()
77+
{
78+
return new int[] { 1 };
79+
}
80+
81+
public String publicString()
82+
{
83+
return "hello";
84+
}
85+
86+
public int publicInt()
87+
{
88+
return 1;
89+
}
90+
91+
public X publicSelfIgnored()
92+
{
93+
return X.this;
94+
}
95+
96+
public static int staticPublicIntIgnored()
97+
{
98+
return 23;
99+
}
100+
}
101+
102+
@Test
103+
public void test() throws InvocationTargetException, IllegalAccessException
104+
{
105+
MethodValuesSerializer serializer = new MethodValuesSerializer(
106+
new MethodSelector(MethodSelector.objectMethods()));
107+
JsonObject expected = new JsonObject();
108+
expected.add("publicInt", new JsonPrimitive(1));
109+
expected.add("publicString", new JsonPrimitive("hello"));
110+
expected.add("publicEnum", new JsonPrimitive("A"));
111+
JsonArray arr = new JsonArray();
112+
arr.add(new JsonPrimitive(1));
113+
expected.add("publicIntArr", arr);
114+
JsonArray ss = new JsonArray();
115+
JsonObject s = new JsonObject();
116+
s.add("publicBoolean", new JsonPrimitive(true));
117+
ss.add(s);
118+
expected.add("publicListS", ss);
119+
JsonObject z = new JsonObject();
120+
z.add("publicBoolean", new JsonPrimitive(true));
121+
expected.add("publicZ", z);
122+
JsonObject y = new JsonObject();
123+
y.add("publicBoolean", new JsonPrimitive(true));
124+
expected.add("publicY", y);
125+
JsonElement got = serializer.serialize(new X());
126+
Assert.assertEquals(expected, got);
127+
Assert.assertEquals(Arrays.asList(X.Y.class, X.Z.class), order);
128+
}
129+
}

0 commit comments

Comments
 (0)