You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by st...@apache.org on 2016/04/03 19:01:22 UTC
[03/10] incubator-johnzon git commit: JOHNZON-71 introduce
MapperConfig and improve ObjectConverter interface
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e41b829b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
deleted file mode 100644
index 68e5d69..0000000
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
+++ /dev/null
@@ -1,770 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.johnzon.mapper.reflection;
-
-import org.apache.johnzon.mapper.Adapter;
-import org.apache.johnzon.mapper.Converter;
-import org.apache.johnzon.mapper.JohnzonConverter;
-import org.apache.johnzon.mapper.JohnzonIgnore;
-import org.apache.johnzon.mapper.JohnzonVirtualObject;
-import org.apache.johnzon.mapper.JohnzonVirtualObjects;
-import org.apache.johnzon.mapper.access.AccessMode;
-import org.apache.johnzon.mapper.converter.DateWithCopyConverter;
-import org.apache.johnzon.mapper.converter.EnumConverter;
-import org.apache.johnzon.mapper.internal.AdapterKey;
-import org.apache.johnzon.mapper.internal.ConverterAdapter;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static java.util.Arrays.asList;
-import static org.apache.johnzon.mapper.reflection.Converters.matches;
-
-public class Mappings {
- public static class ClassMapping {
- public final Class<?> clazz;
- public final AccessMode.Factory factory;
- public final Map<String, Getter> getters;
- public final Map<String, Setter> setters;
-
-
- protected ClassMapping(final Class<?> clazz, final AccessMode.Factory factory,
- final Map<String, Getter> getters, final Map<String, Setter> setters) {
- this.clazz = clazz;
- this.factory = factory;
- this.getters = getters;
- this.setters = setters;
- }
- }
-
- public static class CollectionMapping {
- public final Class<?> raw;
- public final Type arg;
- public final boolean primitive;
-
- public CollectionMapping(final boolean primitive, final Class<?> collectionType, final Type fieldArgType) {
- this.raw = collectionType;
- this.arg = fieldArgType;
- this.primitive = primitive;
- }
- }
-
- public static class Getter {
- public final AccessMode.Reader reader;
- public final int version;
- public final Adapter converter;
- public final Adapter itemConverter;
- public final boolean primitive;
- public final boolean array;
- public final boolean map;
- public final boolean collection;
-
- public Getter(final AccessMode.Reader reader,
- final boolean primitive, final boolean array,
- final boolean collection, final boolean map,
- final Adapter<?, ?> converter,
- final int version) {
- this.reader = reader;
- this.version = version;
- this.array = array;
- this.collection = collection;
- this.primitive = primitive;
- if (converter != null && matches(reader.getType(), converter)) {
- this.converter = converter;
- this.itemConverter = null;
- } else if (converter != null) {
- this.converter = null;
- this.itemConverter = converter;
- } else {
- this.converter = null;
- this.itemConverter = null;
- }
- this.map = map && this.converter == null;
- }
-
- @Override
- public String toString() {
- return "Getter{" +
- "reader=" + reader +
- ", version=" + version +
- ", converter=" + converter +
- ", itemConverter=" + itemConverter +
- ", primitive=" + primitive +
- ", array=" + array +
- ", map=" + map +
- ", collection=" + collection +
- '}';
- }
- }
-
- public static class Setter {
- public final AccessMode.Writer writer;
- public final int version;
- public final Type paramType;
- public final Adapter<?, ?> converter;
- public final Adapter<?, ?> itemConverter;
- public final boolean primitive;
- public final boolean array;
-
- public Setter(final AccessMode.Writer writer, final boolean primitive, final boolean array,
- final Type paramType, final Adapter<?, ?> converter,
- final int version) {
- this.writer = writer;
- this.paramType = paramType;
- this.version = version;
- this.primitive = primitive;
- this.array = array;
- if (converter != null && matches(writer.getType(), converter)) {
- this.converter = converter;
- this.itemConverter = null;
- } else if (converter != null) {
- this.converter = null;
- this.itemConverter = converter;
- } else {
- this.converter = null;
- this.itemConverter = null;
- }
- }
-
- @Override
- public String toString() {
- return "Setter{" +
- "writer=" + writer +
- ", version=" + version +
- ", paramType=" + paramType +
- ", converter=" + converter +
- ", itemConverter=" + itemConverter +
- ", primitive=" + primitive +
- ", array=" + array +
- '}';
- }
- }
-
- private static final JohnzonParameterizedType VIRTUAL_TYPE = new JohnzonParameterizedType(Map.class, String.class, Object.class);
-
- protected final ConcurrentMap<Type, ClassMapping> classes = new ConcurrentHashMap<Type, ClassMapping>();
- protected final ConcurrentMap<Type, CollectionMapping> collections = new ConcurrentHashMap<Type, CollectionMapping>();
- protected final Comparator<String> fieldOrdering;
- protected final ConcurrentMap<AdapterKey, Adapter<?, ?>> adapters;
- private final AccessMode accessMode;
- private final int version;
-
- public Mappings(final Comparator<String> attributeOrder, final AccessMode accessMode,
- final int version, final ConcurrentMap<AdapterKey, Adapter<?, ?>> adapters) {
- this.fieldOrdering = attributeOrder;
- this.accessMode = accessMode;
- this.version = version;
- this.adapters = adapters;
- }
-
- public <T> CollectionMapping findCollectionMapping(final ParameterizedType genericType) {
- CollectionMapping collectionMapping = collections.get(genericType);
- if (collectionMapping == null) {
- collectionMapping = createCollectionMapping(genericType);
- if (collectionMapping == null) {
- return null;
- }
- final CollectionMapping existing = collections.putIfAbsent(genericType, collectionMapping);
- if (existing != null) {
- collectionMapping = existing;
- }
- }
- return collectionMapping;
- }
-
- private <T> CollectionMapping createCollectionMapping(final ParameterizedType aType) {
- final Type[] fieldArgTypes = aType.getActualTypeArguments();
- final Type raw = aType.getRawType();
- if (fieldArgTypes.length == 1 && Class.class.isInstance(raw)) {
- final Class<?> r = Class.class.cast(raw);
- final Class<?> collectionType;
- if (List.class.isAssignableFrom(r)) {
- collectionType = List.class;
- } else if (SortedSet.class.isAssignableFrom(r)) {
- collectionType = SortedSet.class;
- } else if (Set.class.isAssignableFrom(r)) {
- collectionType = Set.class;
- } else if (Deque.class.isAssignableFrom(r)) {
- collectionType = Deque.class;
- } else if (Queue.class.isAssignableFrom(r)) {
- collectionType = Queue.class;
- } else if (Collection.class.isAssignableFrom(r)) {
- collectionType = Collection.class;
- } else {
- return null;
- }
-
- final CollectionMapping mapping = new CollectionMapping(isPrimitive(fieldArgTypes[0]), collectionType, fieldArgTypes[0]);
- collections.putIfAbsent(aType, mapping);
- return mapping;
- }
- return null;
- }
-
- // has JSon API a method for this type
- public static boolean isPrimitive(final Type type) {
- if (type == String.class) {
- return true;
- } else if (type == char.class || type == Character.class) {
- return true;
- } else if (type == long.class || type == Long.class) {
- return true;
- } else if (type == int.class || type == Integer.class
- || type == byte.class || type == Byte.class
- || type == short.class || type == Short.class) {
- return true;
- } else if (type == double.class || type == Double.class
- || type == float.class || type == Float.class) {
- return true;
- } else if (type == boolean.class || type == Boolean.class) {
- return true;
- } else if (type == BigDecimal.class) {
- return true;
- } else if (type == BigInteger.class) {
- return true;
- }
- return false;
- }
-
- public ClassMapping getClassMapping(final Type clazz) {
- return classes.get(clazz);
- }
-
- public ClassMapping findOrCreateClassMapping(final Type clazz) {
- ClassMapping classMapping = classes.get(clazz);
- if (classMapping == null) {
- if (!Class.class.isInstance(clazz) || Map.class.isAssignableFrom(Class.class.cast(clazz))) {
- return null;
- }
-
- classMapping = createClassMapping(Class.class.cast(clazz));
- final ClassMapping existing = classes.putIfAbsent(clazz, classMapping);
- if (existing != null) {
- classMapping = existing;
- }
- }
- return classMapping;
- }
-
- protected ClassMapping createClassMapping(final Class<?> inClazz) {
- boolean copyDate = false;
- for (final Class<?> itf : inClazz.getInterfaces()) {
- if ("org.apache.openjpa.enhance.PersistenceCapable".equals(itf.getName())) {
- copyDate = true;
- break;
- }
- }
- final Class<?> clazz = findModelClass(inClazz);
-
- Comparator<String> fieldComparator = accessMode.fieldComparator(inClazz);
- fieldComparator = fieldComparator == null ? fieldOrdering : fieldComparator;
-
- final Map<String, Getter> getters = fieldComparator == null ? newOrderedMap(Getter.class) : new TreeMap<String, Getter>(fieldComparator);
- final Map<String, Setter> setters = fieldComparator == null ? newOrderedMap(Setter.class) : new TreeMap<String, Setter>(fieldComparator);
-
- final Map<String, AccessMode.Reader> readers = accessMode.findReaders(clazz);
- final Map<String, AccessMode.Writer> writers = accessMode.findWriters(clazz);
-
- final Collection<String> virtualFields = new HashSet<String>();
- {
- final JohnzonVirtualObjects virtualObjects = clazz.getAnnotation(JohnzonVirtualObjects.class);
- if (virtualObjects != null) {
- for (final JohnzonVirtualObject virtualObject : virtualObjects.value()) {
- handleVirtualObject(virtualFields, virtualObject, getters, setters, readers, writers, copyDate);
- }
- }
-
- final JohnzonVirtualObject virtualObject = clazz.getAnnotation(JohnzonVirtualObject.class);
- if (virtualObject != null) {
- handleVirtualObject(virtualFields, virtualObject, getters, setters, readers, writers, copyDate);
- }
- }
-
- for (final Map.Entry<String, AccessMode.Reader> reader : readers.entrySet()) {
- final String key = reader.getKey();
- if (virtualFields.contains(key)) {
- continue;
- }
- addGetterIfNeeded(getters, key, reader.getValue(), copyDate);
- }
-
- for (final Map.Entry<String, AccessMode.Writer> writer : writers.entrySet()) {
- final String key = writer.getKey();
- if (virtualFields.contains(key)) {
- continue;
- }
- addSetterIfNeeded(setters, key, writer.getValue(), copyDate);
- }
- return new ClassMapping(clazz, accessMode.findFactory(clazz), getters, setters);
- }
-
- protected Class<?> findModelClass(final Class<?> inClazz) {
- Class<?> clazz = inClazz;
- // unproxy to get a clean model
- while (clazz != null && clazz != Object.class
- && (clazz.getName().contains("$$") || clazz.getName().contains("$proxy")
- || clazz.getName().startsWith("org.apache.openjpa.enhance.") /* subclassing mode, not the default */)) {
- clazz = clazz.getSuperclass();
- }
- if (clazz == null || clazz == Object.class) { // shouldn't occur but a NPE protection
- clazz = inClazz;
- }
- return clazz;
- }
-
- private <T> Map<String, T> newOrderedMap(final Class<T> value) {
- return fieldOrdering != null ? new TreeMap<String, T>(fieldOrdering) : new HashMap<String, T>();
- }
-
- private void addSetterIfNeeded(final Map<String, Setter> setters,
- final String key,
- final AccessMode.Writer value,
- final boolean copyDate) {
- final JohnzonIgnore writeIgnore = value.getAnnotation(JohnzonIgnore.class);
- if (writeIgnore == null || writeIgnore.minVersion() >= 0) {
- if (key.equals("metaClass")) {
- return;
- }
- final Type param = value.getType();
- final Class<?> returnType = Class.class.isInstance(param) ? Class.class.cast(param) : null;
- final Setter setter = new Setter(
- value, isPrimitive(param), returnType != null && returnType.isArray(), param,
- findConverter(copyDate, value), writeIgnore != null ? writeIgnore.minVersion() : -1);
- setters.put(key, setter);
- }
- }
-
- private void addGetterIfNeeded(final Map<String, Getter> getters,
- final String key,
- final AccessMode.Reader value,
- final boolean copyDate) {
- final JohnzonIgnore readIgnore = value.getAnnotation(JohnzonIgnore.class);
- if (readIgnore == null || readIgnore.minVersion() >= 0) {
- final Class<?> returnType = Class.class.isInstance(value.getType()) ? Class.class.cast(value.getType()) : null;
- final ParameterizedType pt = ParameterizedType.class.isInstance(value.getType()) ? ParameterizedType.class.cast(value.getType()) : null;
- final Getter getter = new Getter(value, isPrimitive(returnType),
- returnType != null && returnType.isArray(),
- (pt != null && Collection.class.isAssignableFrom(Class.class.cast(pt.getRawType())))
- || (returnType != null && Collection.class.isAssignableFrom(returnType)),
- (pt != null && Map.class.isAssignableFrom(Class.class.cast(pt.getRawType())))
- || (returnType != null && Map.class.isAssignableFrom(returnType)),
- findConverter(copyDate, value),
- readIgnore != null ? readIgnore.minVersion() : -1);
- getters.put(key, getter);
- }
- }
-
- // idea is quite trivial, simulate an object with a Map<String, Object>
- private void handleVirtualObject(final Collection<String> virtualFields,
- final JohnzonVirtualObject o,
- final Map<String, Getter> getters,
- final Map<String, Setter> setters,
- final Map<String, AccessMode.Reader> readers,
- final Map<String, AccessMode.Writer> writers,
- final boolean copyDate) {
- final String[] path = o.path();
- if (path.length < 1) {
- throw new IllegalArgumentException("@JohnzonVirtualObject need a path");
- }
-
- // add them to ignored fields
- for (final JohnzonVirtualObject.Field f : o.fields()) {
- virtualFields.add(f.value());
- }
-
- // build "this" model
- final Map<String, Getter> objectGetters = newOrderedMap(Getter.class);
- final Map<String, Setter> objectSetters = newOrderedMap(Setter.class);
-
- for (final JohnzonVirtualObject.Field f : o.fields()) {
- final String name = f.value();
- if (f.read()) {
- final AccessMode.Reader reader = readers.get(name);
- if (reader != null) {
- addGetterIfNeeded(objectGetters, name, reader, copyDate);
- }
- }
- if (f.write()) {
- final AccessMode.Writer writer = writers.get(name);
- if (writer != null) {
- addSetterIfNeeded(objectSetters, name, writer, copyDate);
- }
- }
- }
-
- final String key = path[0];
-
- final Getter getter = getters.get(key);
- final MapBuilderReader newReader = new MapBuilderReader(objectGetters, path, version);
- getters.put(key, new Getter(getter == null ? newReader : new CompositeReader(getter.reader, newReader), false, false, false, true, null, -1));
-
- final Setter newSetter = setters.get(key);
- final MapUnwrapperWriter newWriter = new MapUnwrapperWriter(objectSetters, path);
- setters.put(key, new Setter(newSetter == null ? newWriter : new CompositeWriter(newSetter.writer, newWriter), false, false, VIRTUAL_TYPE, null, -1));
- }
-
- private Adapter findConverter(final boolean copyDate, final AccessMode.DecoratedType decoratedType) {
- Adapter converter = decoratedType.findConverter();
- if (converter != null) {
- return converter;
- }
-
- final JohnzonConverter annotation = decoratedType.getAnnotation(JohnzonConverter.class);
-
- Type typeToTest = decoratedType.getType();
- if (annotation != null) {
- try {
- converter = new ConverterAdapter(annotation.value().newInstance());
- } catch (final Exception e) {
- throw new IllegalArgumentException(e);
- }
- } else if (ParameterizedType.class.isInstance(decoratedType.getType())) {
- final ParameterizedType type = ParameterizedType.class.cast(decoratedType.getType());
- final Type rawType = type.getRawType();
- if (Class.class.isInstance(rawType)
- && Collection.class.isAssignableFrom(Class.class.cast(rawType))
- && type.getActualTypeArguments().length >= 1) {
- typeToTest = type.getActualTypeArguments()[0];
- } // TODO: map
- }
- if (converter == null && Class.class.isInstance(typeToTest)) {
- final Class type = Class.class.cast(typeToTest);
- if (Date.class.isAssignableFrom(type) && copyDate) {
- converter = new DateWithCopyConverter(Adapter.class.cast(adapters.get(new AdapterKey(Date.class, String.class))));
- } else if (type.isEnum()) {
- final AdapterKey key = new AdapterKey(String.class, type);
- converter = adapters.get(key); // first ensure user didnt override it
- if (converter == null) {
- converter = new ConverterAdapter(new EnumConverter(type));
- adapters.put(key, converter);
- }
- } else {
- for (final Map.Entry<AdapterKey, Adapter<?, ?>> adapterEntry : adapters.entrySet()) {
- if (adapterEntry.getKey().getFrom() == adapterEntry.getKey().getTo()) { // String -> String
- continue;
- }
- if (adapterEntry.getKey().getFrom() == type && !(
- // ignore internal converters to let primitives be correctly handled
- ConverterAdapter.class.isInstance(adapterEntry.getValue()) &&
- ConverterAdapter.class.cast(adapterEntry.getValue()).getConverter().getClass().getName().startsWith("org.apache.johnzon.mapper."))) {
-
- if (converter != null) {
- throw new IllegalArgumentException("Ambiguous adapter for " + decoratedType);
- }
- converter = adapterEntry.getValue();
- }
- }
- }
- }
- return converter;
- }
-
- private static class MapBuilderReader implements AccessMode.Reader {
- private final Map<String, Getter> getters;
- private final Map<String, Object> template;
- private final String[] paths;
- private final int version;
-
- public MapBuilderReader(final Map<String, Getter> objectGetters, final String[] paths, final int version) {
- this.getters = objectGetters;
- this.paths = paths;
- this.template = new LinkedHashMap<String, Object>();
- this.version = version;
-
- Map<String, Object> last = this.template;
- for (int i = 1; i < paths.length; i++) {
- final Map<String, Object> newLast = new LinkedHashMap<String, Object>();
- last.put(paths[i], newLast);
- last = newLast;
- }
- }
-
- @Override
- public Object read(final Object instance) {
- final Map<String, Object> map = new LinkedHashMap<String, Object>(template);
- Map<String, Object> nested = map;
- for (int i = 1; i < paths.length; i++) {
- nested = Map.class.cast(nested.get(paths[i]));
- }
- for (final Map.Entry<String, Getter> g : getters.entrySet()) {
- final Mappings.Getter getter = g.getValue();
- final Object value = getter.reader.read(instance);
- final Object val = value == null || getter.converter == null ? value : getter.converter.from(value);
- if (val == null) {
- continue;
- }
- if (getter.version >= 0 && version >= getter.version) {
- continue;
- }
-
- nested.put(g.getKey(), val);
- }
- return map;
- }
-
- @Override
- public Type getType() {
- return VIRTUAL_TYPE;
- }
-
- @Override
- public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
- }
-
- @Override
- public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
- return null;
- }
-
- @Override
- public Adapter<?, ?> findConverter() {
- return null;
- }
-
- @Override
- public boolean isNillable() {
- return false;
- }
- }
-
- private static class MapUnwrapperWriter implements AccessMode.Writer {
- private final Map<String, Setter> writers;
- private final Map<String, Class<?>> componentTypes;
- private final String[] paths;
-
- public MapUnwrapperWriter(final Map<String, Setter> writers, final String[] paths) {
- this.writers = writers;
- this.paths = paths;
- this.componentTypes = new HashMap<String, Class<?>>();
-
- for (final Map.Entry<String, Setter> setter : writers.entrySet()) {
- if (setter.getValue().array) {
- componentTypes.put(setter.getKey(), Class.class.cast(setter.getValue().paramType).getComponentType());
- }
- }
- }
-
- @Override
- public void write(final Object instance, final Object value) {
- Map<String, Object> nested = null;
- for (final String path : paths) {
- nested = Map.class.cast(nested == null ? value : nested.get(path));
- if (nested == null) {
- return;
- }
- }
-
- for (final Map.Entry<String, Setter> setter : writers.entrySet()) {
- final Setter setterValue = setter.getValue();
- final String key = setter.getKey();
- final Object rawValue = nested.get(key);
- Object val = value == null || setterValue.converter == null ?
- rawValue : Converter.class.cast(setterValue.converter).toString(rawValue);
- if (val == null) {
- continue;
- }
-
- if (setterValue.array && Collection.class.isInstance(val)) {
- final Collection<?> collection = Collection.class.cast(val);
- final Object[] array = (Object[]) Array.newInstance(componentTypes.get(key), collection.size());
- val = collection.toArray(array);
- }
-
- final AccessMode.Writer setterMethod = setterValue.writer;
- setterMethod.write(instance, val);
- }
- }
-
- @Override
- public Type getType() {
- return VIRTUAL_TYPE;
- }
-
- @Override
- public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
- }
-
- @Override
- public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
- return null;
- }
-
- @Override
- public Adapter<?, ?> findConverter() {
- return null;
- }
-
- @Override
- public boolean isNillable() {
- return false;
- }
- }
-
- private static class CompositeReader implements AccessMode.Reader {
- private final AccessMode.Reader[] delegates;
-
- public CompositeReader(final AccessMode.Reader... delegates) {
- final Collection<AccessMode.Reader> all = new LinkedList<AccessMode.Reader>();
- for (final AccessMode.Reader r : delegates) {
- if (CompositeReader.class.isInstance(r)) {
- all.addAll(asList(CompositeReader.class.cast(r).delegates));
- } else {
- all.add(r);
- }
- }
- this.delegates = all.toArray(new AccessMode.Reader[all.size()]);
- }
-
- @Override
- public Object read(final Object instance) {
- final Map<String, Object> map = new LinkedHashMap<String, Object>();
- for (final AccessMode.Reader reader : delegates) {
- final Map<String, Object> readerMap = (Map<String, Object>) reader.read(instance);
- for (final Map.Entry<String, Object> entry : readerMap.entrySet()) {
- final Object o = map.get(entry.getKey());
- if (o == null) {
- map.put(entry.getKey(), entry.getValue());
- } else if (Map.class.isInstance(o)) {
- // TODO
- } else {
- throw new IllegalStateException(entry.getKey() + " is ambiguous");
- }
- }
- }
- return map;
- }
-
- @Override
- public Type getType() {
- return VIRTUAL_TYPE;
- }
-
- @Override
- public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
- }
-
- @Override
- public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
- return null;
- }
-
- @Override
- public Adapter<?, ?> findConverter() {
- for (final AccessMode.Reader r : delegates) {
- final Adapter<?, ?> converter = r.findConverter();
- if (converter != null) {
- return converter;
- }
- }
- return null;
- }
-
- @Override
- public boolean isNillable() {
- for (final AccessMode.Reader r : delegates) {
- if (r.isNillable()) {
- return true;
- }
- }
- return false;
- }
- }
-
- private static class CompositeWriter implements AccessMode.Writer {
- private final AccessMode.Writer[] delegates;
-
- public CompositeWriter(final AccessMode.Writer... writers) {
- final Collection<AccessMode.Writer> all = new LinkedList<AccessMode.Writer>();
- for (final AccessMode.Writer r : writers) {
- if (CompositeWriter.class.isInstance(r)) {
- all.addAll(asList(CompositeWriter.class.cast(r).delegates));
- } else {
- all.add(r);
- }
- }
- this.delegates = all.toArray(new AccessMode.Writer[all.size()]);
- }
-
- @Override
- public void write(final Object instance, final Object value) {
- for (final AccessMode.Writer w : delegates) {
- w.write(instance, value);
- }
- }
-
- @Override
- public Type getType() {
- return VIRTUAL_TYPE;
- }
-
- @Override
- public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
- }
-
- @Override
- public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
- return null;
- }
-
- @Override
- public Adapter<?, ?> findConverter() {
- for (final AccessMode.Writer r : delegates) {
- final Adapter<?, ?> converter = r.findConverter();
- if (converter != null) {
- return converter;
- }
- }
- return null;
- }
-
- @Override
- public boolean isNillable() {
- for (final AccessMode.Writer r : delegates) {
- if (r.isNillable()) {
- return true;
- }
- }
- return false;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e41b829b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/AdapterTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/AdapterTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/AdapterTest.java
index 92df00c..87ff40d 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/AdapterTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/AdapterTest.java
@@ -62,7 +62,7 @@ public class AdapterTest {
}
public static class Root {
- public Foo foo = new Foo();
+ Foo foo = new Foo();
}
public static class Foo {
@@ -71,8 +71,8 @@ public class AdapterTest {
}
public static class Bar {
- public String simple;
- public int count;
+ String simple;
+ int count;
public Bar() {
// no-op
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/e41b829b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
index 9302c6e..21f5701 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
@@ -19,10 +19,13 @@
package org.apache.johnzon.mapper;
+import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
+import javax.json.JsonObject;
+
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,7 +50,10 @@ public class ObjectTypeTest {
.setAccessModeName(accessMode)
.build();
- String jsonString = "{ \"//javaType\": \"org.apache.johnzon.mapper.ObjectTypeTest$Customer\", \"firstName\":\"Bruce\", \"lastName\":\"Wayne\" }";
+ String expectedJsonString = "{\"//javaType\":\"org.apache.johnzon.mapper.ObjectTypeTest$Mutt\"," +
+ "\"mother\":{\"//javaType\":\"org.apache.johnzon.mapper.ObjectTypeTest$Poodle\",\"name\":\"Rosa\",\"hairCut\":true}," +
+ "\"father\":{\"//javaType\":\"org.apache.johnzon.mapper.ObjectTypeTest$Beagle\"," +
+ "\"father\":{\"//javaType\":\"org.apache.johnzon.mapper.ObjectTypeTest$Beagle\",\"name\":\"Wuffi\"},\"name\":\"Gnarl\"},\"name\":\"Snoopie\"}";
Poodle mum = new Poodle();
mum.setName("Rosa");
@@ -67,18 +73,45 @@ public class ObjectTypeTest {
String json = mapper.writeObjectAsString(snoopie);
Assert.assertNotNull(json);
+ //X TODO Assert.assertEquals(expectedJsonString, json);
}
public static class TestWithTypeConverter implements ObjectConverter<Dog> {
@Override
- public void writeJson(Dog instance, JsonbGenerator jsonbGenerator) {
+ public void writeJson(Dog instance, MappingGenerator jsonbGenerator) {
jsonbGenerator.getJsonGenerator().write("//javaType", instance.getClass().getName());
jsonbGenerator.writeObject(instance);
}
@Override
- public Dog fromJson(JsonbParser jsonParser, Type targetType) {
+ public Dog fromJson(MappingParser jsonParser, Type targetType) {
+ JsonObject jsonObject = jsonParser.getJsonReader().readObject();
+ String javaType = jsonObject.getString("//javaType");
+ if (javaType != null) {
+ // the following should get extracted in a utility class.
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ if (cl == null) {
+ cl = targetType.getClass().getClassLoader();
+ }
+
+ try {
+ Class subClass = cl.loadClass(javaType);
+ Class targetClass = null;
+ if (targetType instanceof Class) {
+ targetClass = (Class) targetType;
+ } else if (targetType instanceof ParameterizedType) {
+ targetClass = (Class)((ParameterizedType) targetType).getRawType();
+ }
+ if (targetClass != null && targetClass.isAssignableFrom(subClass)) {
+ targetType = subClass;
+ }
+ } catch (ClassNotFoundException e) {
+ // continue without better class match
+ }
+
+ jsonParser.readObject(jsonObject, targetType);
+ }
return null;
}
}
@@ -117,7 +150,7 @@ public class ObjectTypeTest {
}
public static class Poodle extends Dog {
- boolean hairCut = false;
+ private boolean hairCut = false;
public boolean isHairCut() {
return hairCut;