\r
protected ObjectLens(Class< ? > targetType) {\r
this.targetType = targetType;\r
- createBindRules(targetType);\r
+ prepareBindRules(targetType);\r
}\r
\r
public Class< ? > getTargetType() {\r
return String.format("(%s, %s)", setterContainer, relationSetterContainer);\r
}\r
\r
- private void createBindRules(Class< ? > targetType) {\r
+ private void prepareBindRules(Class< ? > targetType) {\r
// search for object parameters including superclass's ones \r
\r
// scan public fields\r
if (parentClassOfTheField == Object.class)\r
continue;\r
\r
+ // looking for only public fields\r
int fieldModifier = eachField.getModifiers();\r
if (Modifier.isPublic(fieldModifier) && !Modifier.isTransient(fieldModifier)\r
&& !Modifier.isStatic(fieldModifier)) {\r
continue;\r
}\r
else if (TypeInfo.isMap(fieldType)) {\r
- // TODO map putter\r
- Pair<Type, Type> keyValueTypes = ReflectionUtil\r
- .getGenericMapElementType(eachField);\r
- Pair<String, String> keyValueNames = pickRelationName(eachField.getName());\r
- if (keyValueNames == null) {\r
- // infer key and value names from type parameters in Map<Key, Value>\r
+ Pair<String, String> keyValueName = pickRelationName(eachField.getName());\r
+ if (keyValueName == null) {\r
+ // infer key, value names from the class type\r
+ Pair<Type, Type> mapElementType = ReflectionUtil\r
+ .getGenericMapElementType(eachField);\r
\r
+ Class< ? > keyType = Class.class.cast(mapElementType.getFirst());\r
+ Class< ? > valueType = Class.class.cast(mapElementType.getSecond());\r
+\r
+ keyValueName = new Pair<String, String>(keyType.getSimpleName(), valueType\r
+ .getSimpleName());\r
}\r
\r
+ relationSetterContainer.add(RelationSetter.newMapSetter(\r
+ keyValueName.getFirst(), keyValueName.getSecond(), eachField));\r
}\r
else if (TypeInfo.isCollection(fieldType)) {\r
Class< ? > elementType = ReflectionUtil.getRawClass(ReflectionUtil\r
public class ObjectMapper {
private static Logger _logger = Logger.getLogger(ObjectMapper.class);
- //-------------------------------------
- // dynamic parameters required for mapping tree-structured data to an object
// id -> corresponding object instance
- //-------------------------------------
private HashMap<Long, Object> objectHolder = new HashMap<Long, Object>();
- private Deque<Object> contextNodeStack = new ArrayDeque<Object>();
- private static QuerySet qs = null;
// schema -> binder
- private static HashMap<Schema, Binder> schema2binder = new HashMap<Schema, Binder>();
+ private HashMap<Schema, Binder> schema2binder = new HashMap<Schema, Binder>();
+
+ private Deque<Object> contextNodeStack = new ArrayDeque<Object>();
+ private final QuerySet qs;
+
+ private static HashMap<Class< ? >, ObjectMapper> prebuiltMapper = new HashMap<Class< ? >, ObjectMapper>();
/**
* interface for invoking setters or field setters of the object
}
}
+ public <T> ObjectMapper(Class<T> targetType) throws XerialException {
+ qs = buildQuery(targetType);
+ }
+
+ public static ObjectMapper getMapper(Class< ? > targetType) throws XerialException {
+ if (prebuiltMapper.containsKey(targetType))
+ return prebuiltMapper.get(targetType);
+ else {
+ ObjectMapper newInstance = new ObjectMapper(targetType);
+ prebuiltMapper.put(targetType, newInstance);
+ return newInstance;
+ }
+ }
+
+ public <T> T map(Class<T> targetType, TreeParser parser) throws XerialException {
+
+ T object = TypeInfo.createInstance(targetType);
+ return map(object, parser);
+ }
+
+ public <T> T map(T object, TreeParser parser) throws XerialException {
+ try {
+ if (object == null)
+ throw new XerialError(XerialErrorCode.INVALID_INPUT, "null object");
+
+ if (_logger.isTraceEnabled())
+ _logger.trace("query set: " + qs);
+
+ // set the root object
+ objectHolder.put(0L, object);
+ contextNodeStack.addLast(object);
+
+ AmoebaJoinHandler mapper = new RelationExtracter();
+
+ StreamAmoebaJoin aj = new StreamAmoebaJoin(qs, mapper);
+ aj.sweep(parser);
+ return object;
+ }
+ catch (IOException e) {
+ throw new XerialException(XerialErrorCode.IO_EXCEPTION, e);
+ }
+ catch (Exception e) {
+ throw new XerialException(XerialErrorCode.INHERITED, e);
+ }
+
+ }
+
+ public <T> void find(Class<T> targetType, TreeParser parser,
+ String coreNodeNameOfTheTargetType, ObjectHandler<T> handler) throws XerialException {
+
+ try {
+ AmoebaJoinHandler mapper = new RelationExtracter();
+
+ _logger.info(qs);
+
+ StreamAmoebaJoin aj = new StreamAmoebaJoin(qs, mapper);
+ aj.sweep(parser);
+ }
+ catch (IOException e) {
+ throw new XerialException(XerialErrorCode.IO_EXCEPTION, e);
+ }
+ catch (Exception e) {
+ throw new XerialException(XerialErrorCode.INHERITED, e);
+ }
+
+ }
+
private QuerySet buildQuery(Class< ? > targetType) {
QueryBuilder qb = new QueryBuilder();
qb.build(targetType, "root");
- return qb.qsBuilder.build();
+ return qb.qs.build();
}
private class QueryBuilder {
- QuerySetBuilder qsBuilder = new QuerySetBuilder();
+ QuerySetBuilder qs = new QuerySetBuilder();
private HashMap<String, Set<Class< ? >>> processedClassTable = new HashMap<String, Set<Class< ? >>>();
//Set<Class< ? >> processedClasses = new HashSet<Class< ? >>();
builder.add("entry");
builder.add(each.getParameterName());
Schema s = builder.build();
- qsBuilder.addQueryTarget(s);
+ qs.addQueryTarget(s);
schema2binder.put(s, new AttributeBinder(MapEntry.class, each));
continue;
}
builder.add(each.getParameterName());
Schema s = builder.build();
- qsBuilder.addQueryTarget(s);
+ qs.addQueryTarget(s);
schema2binder.put(s, new AttributeBinder(lens.getTargetType(), each));
}
Schema s = new SchemaBuilder().add(each.getCoreNodeName()).add(
each.getAttributeNodeName()).build();
- qsBuilder.addQueryTarget(s);
+ qs.addQueryTarget(s);
schema2binder.put(s, new RelationBinder(lens, each));
}
- public <T> ObjectMapper(Class<T> targetType) throws XerialException {
- if (qs == null) {
- schema2binder.clear();
- qs = buildQuery(targetType);
- }
- }
-
- public static ObjectMapper getMapper(Class< ? > targetType) throws XerialException {
- return new ObjectMapper(targetType);
- }
-
- public <T> T map(Class<T> targetType, TreeParser parser) throws XerialException {
-
- T object = TypeInfo.createInstance(targetType);
- return map(object, parser);
- }
-
- public <T> T map(T object, TreeParser parser) throws XerialException {
- try {
- if (object == null)
- throw new XerialError(XerialErrorCode.INVALID_INPUT, "null object");
-
- if (_logger.isTraceEnabled())
- _logger.trace("query set: " + qs);
-
- // set the root object
- objectHolder.put(0L, object);
- contextNodeStack.addLast(object);
-
- AmoebaJoinHandler mapper = new RelationExtracter();
-
- StreamAmoebaJoin aj = new StreamAmoebaJoin(qs, mapper);
- aj.sweep(parser);
- return object;
- }
- catch (IOException e) {
- throw new XerialException(XerialErrorCode.IO_EXCEPTION, e);
- }
- catch (Exception e) {
- throw new XerialException(XerialErrorCode.INHERITED, e);
- }
-
- }
-
- public <T> void find(Class<T> targetType, TreeParser parser,
- String coreNodeNameOfTheTargetType, ObjectHandler<T> handler) throws XerialException {
-
- try {
- AmoebaJoinHandler mapper = new RelationExtracter();
-
- _logger.info(qs);
-
- StreamAmoebaJoin aj = new StreamAmoebaJoin(qs, mapper);
- aj.sweep(parser);
- }
- catch (IOException e) {
- throw new XerialException(XerialErrorCode.IO_EXCEPTION, e);
- }
- catch (Exception e) {
- throw new XerialException(XerialErrorCode.INHERITED, e);
- }
-
- }
-
private Object getNodeInstance(Node node, Class< ? > nodeType) throws XerialException {
Object instance = objectHolder.get(node.nodeID);
if (instance != null)
//--------------------------------------\r
package org.xerial.lens.impl;\r
\r
+import java.lang.reflect.Field;\r
import java.lang.reflect.InvocationTargetException;\r
import java.lang.reflect.Method;\r
+import java.lang.reflect.Type;\r
+import java.util.Map;\r
\r
import org.xerial.core.XerialError;\r
import org.xerial.core.XerialErrorCode;\r
import org.xerial.core.XerialException;\r
+import org.xerial.util.Pair;\r
+import org.xerial.util.bean.TypeInfo;\r
+import org.xerial.util.reflect.ReflectionUtil;\r
\r
/**\r
* RelationSetter is for setting a node tuple to an object\r
* @author leo\r
* \r
*/\r
-public abstract class RelationSetter\r
-{\r
+public abstract class RelationSetter {\r
private final Class< ? > coreNodeType;\r
private final Class< ? > attributeNodeType;\r
\r
private final String coreNodeName;\r
private final String attributeNodeName;\r
\r
- protected RelationSetter(Class< ? > coreNodeType, String coreNodeName, Class< ? > attributeNodeType,\r
- String attributeNodeName)\r
- {\r
+ protected RelationSetter(Class< ? > coreNodeType, String coreNodeName,\r
+ Class< ? > attributeNodeType, String attributeNodeName) {\r
this.coreNodeType = coreNodeType;\r
this.attributeNodeType = attributeNodeType;\r
this.coreNodeName = coreNodeName;\r
this.attributeNodeName = attributeNodeName;\r
}\r
\r
- public Class< ? > getCoreNodeType()\r
- {\r
+ public Class< ? > getCoreNodeType() {\r
return coreNodeType;\r
}\r
\r
- public Class< ? > getAttributeNodeType()\r
- {\r
+ public Class< ? > getAttributeNodeType() {\r
return attributeNodeType;\r
}\r
\r
- public String getCoreNodeName()\r
- {\r
+ public String getCoreNodeName() {\r
return coreNodeName;\r
}\r
\r
- public String getAttributeNodeName()\r
- {\r
+ public String getAttributeNodeName() {\r
return attributeNodeName;\r
}\r
\r
@Override\r
- public String toString()\r
- {\r
- return String.format("(%s[%s], %s[%s])", coreNodeName, coreNodeType.getSimpleName(), attributeNodeName,\r
- attributeNodeType.getSimpleName());\r
+ public String toString() {\r
+ return String.format("(%s[%s], %s[%s])", coreNodeName, coreNodeType.getSimpleName(),\r
+ attributeNodeName, attributeNodeType.getSimpleName());\r
}\r
\r
@Override\r
- public boolean equals(Object obj)\r
- {\r
+ public boolean equals(Object obj) {\r
RelationSetter other = RelationSetter.class.cast(obj);\r
if (other == null)\r
return false;\r
}\r
\r
@Override\r
- public int hashCode()\r
- {\r
+ public int hashCode() {\r
return coreNodeName.hashCode() + attributeNodeName.hashCode();\r
}\r
\r
- public abstract void bind(Object object, Object coreValue, Object attributeValue) throws XerialException;\r
+ public abstract void bind(Object object, Object coreValue, Object attributeValue)\r
+ throws XerialException;\r
\r
- public static RelationSetter newRelationSetter(String coreNodeName, String attributeNodeName, Method setterMethod)\r
- {\r
+ public static RelationSetter newRelationSetter(String coreNodeName, String attributeNodeName,\r
+ Method setterMethod) {\r
Class< ? >[] argType = setterMethod.getParameterTypes();\r
if (argType.length != 2)\r
throw new XerialError(XerialErrorCode.INVALID_INPUT, setterMethod.toString());\r
- return new MethodRelationSetter(argType[0], coreNodeName, argType[1], attributeNodeName, setterMethod);\r
+ return new MethodRelationSetter(argType[0], coreNodeName, argType[1], attributeNodeName,\r
+ setterMethod);\r
}\r
\r
- private static class MethodRelationSetter extends RelationSetter\r
- {\r
+ private static class MethodRelationSetter extends RelationSetter {\r
private final Method setter;\r
\r
- public MethodRelationSetter(Class< ? > coreNodeType, String coreNodeName, Class< ? > attributeNodeType,\r
- String attributeNodeName, Method setter)\r
- {\r
+ public MethodRelationSetter(Class< ? > coreNodeType, String coreNodeName,\r
+ Class< ? > attributeNodeType, String attributeNodeName, Method setter) {\r
super(coreNodeType, coreNodeName, attributeNodeType, attributeNodeName);\r
this.setter = setter;\r
}\r
\r
@Override\r
- public void bind(Object object, Object coreValue, Object attributeValue) throws XerialException\r
- {\r
- try\r
- {\r
+ public void bind(Object object, Object coreValue, Object attributeValue)\r
+ throws XerialException {\r
+ try {\r
setter.invoke(object, coreValue, attributeValue);\r
}\r
- catch (IllegalArgumentException e)\r
- {\r
+ catch (IllegalArgumentException e) {\r
throw new XerialException(XerialErrorCode.WRONG_DATA_TYPE, e);\r
}\r
- catch (IllegalAccessException e)\r
- {\r
+ catch (IllegalAccessException e) {\r
throw new XerialException(XerialErrorCode.INVALID_INPUT, e);\r
}\r
- catch (InvocationTargetException e)\r
- {\r
+ catch (InvocationTargetException e) {\r
throw new XerialError(XerialErrorCode.WRONG_DATA_TYPE, e);\r
}\r
\r
}\r
}\r
\r
+ public static RelationSetter newMapSetter(String keyNodeName, String valueNodeName,\r
+ Field mapField) {\r
+ Pair<Type, Type> mapElementType = ReflectionUtil.getGenericMapElementType(mapField);\r
+\r
+ Class< ? > keyType = Class.class.cast(mapElementType.getFirst());\r
+ Class< ? > valueType = Class.class.cast(mapElementType.getSecond());\r
+\r
+ return new MapFieldSetter(keyType, keyNodeName, valueType, valueNodeName, mapField);\r
+ }\r
+\r
+ private static class MapFieldSetter extends RelationSetter {\r
+ private final Field mapField;\r
+ private final ParameterGetter mapTypeGetter;\r
+ private final Method putter;\r
+\r
+ public MapFieldSetter(Class< ? > coreNodeType, String coreNodeName,\r
+ Class< ? > attributeNodeType, String attributeNodeName, Field mapField) {\r
+ super(coreNodeType, coreNodeName, attributeNodeType, attributeNodeName);\r
+ this.mapField = mapField;\r
+ this.mapTypeGetter = ParameterGetter.newFieldGetter(this.mapField, null);\r
+\r
+ Class< ? > mapType = this.mapField.getType();\r
+ if (!TypeInfo.isMap(mapType))\r
+ throw new XerialError(XerialErrorCode.InvalidType, String.format(\r
+ "field: %s is not a Map type", mapField));\r
+\r
+ try {\r
+ this.putter = mapType.getMethod("put", Object.class, Object.class);\r
+ }\r
+ catch (Exception e) {\r
+ throw new XerialError(XerialErrorCode.INVALID_STATE, String.format(\r
+ "putter method is not found in %s", mapType));\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public void bind(Object object, Object coreValue, Object attributeValue)\r
+ throws XerialException {\r
+ try {\r
+ Object map = Map.class.cast(mapTypeGetter.get(object));\r
+ if (map == null) {\r
+ map = TypeInfo.createInstance(mapField.getType());\r
+ ReflectionUtil.setFieldValue(object, mapField, map);\r
+ }\r
+\r
+ putter.invoke(map, coreValue, attributeValue);\r
+ }\r
+ catch (IllegalArgumentException e) {\r
+ throw new XerialException(XerialErrorCode.WRONG_DATA_TYPE, e);\r
+ }\r
+ catch (IllegalAccessException e) {\r
+ throw new XerialException(XerialErrorCode.INVALID_INPUT, e);\r
+ }\r
+ catch (InvocationTargetException e) {\r
+ throw new XerialError(XerialErrorCode.WRONG_DATA_TYPE, e);\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
}\r
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import org.xerial.util.Pair;
import org.xerial.util.log.Logger;
-public class ObjectLensTest
-{
+public class ObjectLensTest {
private static Logger _logger = Logger.getLogger(ObjectLensTest.class);
@Before
- public void setUp() throws Exception
- {}
+ public void setUp() throws Exception {}
@After
- public void tearDown() throws Exception
- {}
+ public void tearDown() throws Exception {}
@Test
- public void pickPairedName() throws Exception
- {
+ public void pickPairedName() throws Exception {
Pair<String, String> p = ObjectLens.pickRelationName("Invoice_Order");
assertEquals("invoice", p.getFirst());
assertEquals("order", p.getSecond());
}
@Test
- public void pickPropertyName() throws Exception
- {
+ public void pickPropertyName() throws Exception {
String c = ObjectLens.pickPropertyName("addSomething");
assertEquals("something", c);
}
@Test
- public void canonicalNameTest() throws Exception
- {
+ public void canonicalNameTest() throws Exception {
assertEquals("itemrgb", ObjectLens.getCanonicalParameterName("itemRgb"));
assertEquals("itemref", ObjectLens.getCanonicalParameterName("item_ref"));
assertEquals("helloworld", ObjectLens.getCanonicalParameterName("Hello World"));
}
- public static class ExtMap extends TreeMap<Integer, String>
- {
+ public static class ExtMap extends TreeMap<Integer, String> {
/**
*
*/
public String name = "ext-map";
@Override
- public boolean equals(Object o)
- {
+ public boolean equals(Object o) {
if (!(o instanceof ExtMap))
return false;
}
@Test
- public void mapTest() throws Exception
- {
+ public void mapTest() throws Exception {
ExtMap extMap = new ExtMap();
extMap.put(1, "hello");
extMap.put(10, "world");
assertEquals(extMap, extMap2);
}
- public static class ExtList extends ArrayList<Integer>
- {
+ public static class ExtList extends ArrayList<Integer> {
/**
*
*/
public String name = "ext-list";
@Override
- public boolean equals(Object o)
- {
+ public boolean equals(Object o) {
if (!(o instanceof ExtList))
return false;
}
@Test
- public void arrayTest() throws Exception
- {
+ public void arrayTest() throws Exception {
ExtList extList = new ExtList();
extList.add(10);
}
- public static class PropReader
- {
+ public static class PropReader {
Properties prop = new Properties();
- public void put(String key, String value)
- {
+ public void put(String key, String value) {
prop.put(key, value);
}
}
@Test
- public void property() throws Exception
- {
- PropReader p = Lens.loadSilk(PropReader.class, FileResource.open(ObjectLensTest.class, "property.silk"));
+ public void property() throws Exception {
+ PropReader p = Lens.loadSilk(PropReader.class, FileResource.open(ObjectLensTest.class,
+ "property.silk"));
assertEquals(2, p.prop.size());
assertEquals("hello", p.prop.get("db.name"));
assertEquals("sqlite", p.prop.get("db.type"));
}
+ public static class MapField {
+ public Map<Integer, String> id_name;
+ }
+
+ @Test
+ public void mapPutter() throws Exception {
+ MapField m = Lens.loadSilk(MapField.class, FileResource.open(ObjectLensTest.class,
+ "map.silk"));
+ assertNotNull(m.id_name);
+ assertEquals(2, m.id_name.size());
+ String n1 = m.id_name.get(1);
+ String n2 = m.id_name.get(2);
+ assertEquals("leo", n1);
+ assertEquals("yui", n2);
+ }
+
}
--- /dev/null
+-id:1\r
+ -name: leo\r
+-id:2\r
+ -name: yui\r