com.arangodb.velocypack.VPack Maven / Gradle / Ivy
/*
* DISCLAIMER
*
* Copyright 2016 ArangoDB GmbH, Cologne, Germany
*
* Licensed 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.
*
* Copyright holder is ArangoDB GmbH, Cologne, Germany
*/
package com.arangodb.velocypack;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
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.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import com.arangodb.velocypack.VPackBuilder.BuilderOptions;
import com.arangodb.velocypack.annotations.Expose;
import com.arangodb.velocypack.annotations.SerializedName;
import com.arangodb.velocypack.exception.VPackException;
import com.arangodb.velocypack.exception.VPackParserException;
import com.arangodb.velocypack.internal.DefaultVPackBuilderOptions;
import com.arangodb.velocypack.internal.VPackCache;
import com.arangodb.velocypack.internal.VPackCache.FieldInfo;
import com.arangodb.velocypack.internal.VPackDeserializers;
import com.arangodb.velocypack.internal.VPackInstanceCreators;
import com.arangodb.velocypack.internal.VPackKeyMapAdapters;
import com.arangodb.velocypack.internal.VPackSerializers;
/**
* @author Mark - mark at arangodb.com
*
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class VPack {
private static final String ATTR_KEY = "key";
private static final String ATTR_VALUE = "value";
private final Map> serializers;
private final Map> enclosingSerializers;
private final Map> deserializers;
private final Map>> deserializersByName;
private final Map> instanceCreators;
private final Map> keyMapAdapters;
private final BuilderOptions builderOptions;
private final VPackCache cache;
private final VPackSerializationContext serializationContext;
private final VPackDeserializationContext deserializationContext;
private final boolean serializeNullValues;
public static class Builder {
private final Map> serializers;
private final Map> enclosingSerializers;
private final Map> deserializers;
private final Map>> deserializersByName;
private final Map> instanceCreators;
private final BuilderOptions builderOptions;
private boolean serializeNullValues;
private VPackFieldNamingStrategy fieldNamingStrategy;
private final Map, VPackAnnotationFieldFilter extends Annotation>> annotationFieldFilter;
private final Map, VPackAnnotationFieldNaming extends Annotation>> annotationFieldNaming;
public Builder() {
super();
serializers = new HashMap>();
enclosingSerializers = new HashMap>();
deserializers = new HashMap>();
deserializersByName = new HashMap>>();
instanceCreators = new HashMap>();
builderOptions = new DefaultVPackBuilderOptions();
serializeNullValues = false;
annotationFieldFilter = new HashMap, VPackAnnotationFieldFilter extends Annotation>>();
annotationFieldNaming = new HashMap, VPackAnnotationFieldNaming extends Annotation>>();
instanceCreators.put(Collection.class, VPackInstanceCreators.COLLECTION);
instanceCreators.put(List.class, VPackInstanceCreators.LIST);
instanceCreators.put(Set.class, VPackInstanceCreators.SET);
instanceCreators.put(Map.class, VPackInstanceCreators.MAP);
serializers.put(String.class, VPackSerializers.STRING);
serializers.put(Boolean.class, VPackSerializers.BOOLEAN);
serializers.put(boolean.class, VPackSerializers.BOOLEAN);
serializers.put(Integer.class, VPackSerializers.INTEGER);
serializers.put(int.class, VPackSerializers.INTEGER);
serializers.put(Long.class, VPackSerializers.LONG);
serializers.put(long.class, VPackSerializers.LONG);
serializers.put(Short.class, VPackSerializers.SHORT);
serializers.put(short.class, VPackSerializers.SHORT);
serializers.put(Double.class, VPackSerializers.DOUBLE);
serializers.put(double.class, VPackSerializers.DOUBLE);
serializers.put(Float.class, VPackSerializers.FLOAT);
serializers.put(float.class, VPackSerializers.FLOAT);
serializers.put(BigInteger.class, VPackSerializers.BIG_INTEGER);
serializers.put(BigDecimal.class, VPackSerializers.BIG_DECIMAL);
serializers.put(Number.class, VPackSerializers.NUMBER);
serializers.put(Character.class, VPackSerializers.CHARACTER);
serializers.put(char.class, VPackSerializers.CHARACTER);
serializers.put(Date.class, VPackSerializers.DATE);
serializers.put(java.sql.Date.class, VPackSerializers.SQL_DATE);
serializers.put(java.sql.Timestamp.class, VPackSerializers.SQL_TIMESTAMP);
serializers.put(VPackSlice.class, VPackSerializers.VPACK);
serializers.put(UUID.class, VPackSerializers.UUID);
deserializers.put(String.class, VPackDeserializers.STRING);
deserializers.put(Boolean.class, VPackDeserializers.BOOLEAN);
deserializers.put(boolean.class, VPackDeserializers.BOOLEAN);
deserializers.put(Integer.class, VPackDeserializers.INTEGER);
deserializers.put(int.class, VPackDeserializers.INTEGER);
deserializers.put(Long.class, VPackDeserializers.LONG);
deserializers.put(long.class, VPackDeserializers.LONG);
deserializers.put(Short.class, VPackDeserializers.SHORT);
deserializers.put(short.class, VPackDeserializers.SHORT);
deserializers.put(Double.class, VPackDeserializers.DOUBLE);
deserializers.put(double.class, VPackDeserializers.DOUBLE);
deserializers.put(Float.class, VPackDeserializers.FLOAT);
deserializers.put(float.class, VPackDeserializers.FLOAT);
deserializers.put(BigInteger.class, VPackDeserializers.BIG_INTEGER);
deserializers.put(BigDecimal.class, VPackDeserializers.BIG_DECIMAL);
deserializers.put(Number.class, VPackDeserializers.NUMBER);
deserializers.put(Character.class, VPackDeserializers.CHARACTER);
deserializers.put(char.class, VPackDeserializers.CHARACTER);
deserializers.put(Date.class, VPackDeserializers.DATE);
deserializers.put(java.sql.Date.class, VPackDeserializers.SQL_DATE);
deserializers.put(java.sql.Timestamp.class, VPackDeserializers.SQL_TIMESTAMP);
deserializers.put(VPackSlice.class, VPackDeserializers.VPACK);
deserializers.put(UUID.class, VPackDeserializers.UUID);
annotationFieldFilter.put(Expose.class, new VPackAnnotationFieldFilter() {
@Override
public boolean serialize(final Expose annotation) {
return annotation.serialize();
}
@Override
public boolean deserialize(final Expose annotation) {
return annotation.deserialize();
}
});
annotationFieldNaming.put(SerializedName.class, new VPackAnnotationFieldNaming() {
@Override
public String name(final SerializedName annotation) {
return annotation.value();
}
});
}
public VPack.Builder registerSerializer(final Type type, final VPackSerializer serializer) {
serializers.put(type, serializer);
return this;
}
public VPack.Builder registerEnclosingSerializer(final Type type, final VPackSerializer serializer) {
enclosingSerializers.put(type, serializer);
return this;
}
public VPack.Builder registerDeserializer(final Type type, final VPackDeserializer deserializer) {
deserializers.put(type, deserializer);
return this;
}
public VPack.Builder registerDeserializer(
final String fieldName,
final Type type,
final VPackDeserializer deserializer) {
Map> byName = deserializersByName.get(fieldName);
if (byName == null) {
byName = new HashMap>();
deserializersByName.put(fieldName, byName);
}
byName.put(type, deserializer);
return this;
}
public VPack.Builder registerInstanceCreator(final Type type, final VPackInstanceCreator creator) {
instanceCreators.put(type, creator);
return this;
}
public VPack.Builder buildUnindexedArrays(final boolean buildUnindexedArrays) {
builderOptions.setBuildUnindexedArrays(buildUnindexedArrays);
return this;
}
public VPack.Builder buildUnindexedObjects(final boolean buildUnindexedObjects) {
builderOptions.setBuildUnindexedObjects(buildUnindexedObjects);
return this;
}
public VPack.Builder serializeNullValues(final boolean serializeNullValues) {
this.serializeNullValues = serializeNullValues;
return this;
}
public VPack.Builder fieldNamingStrategy(final VPackFieldNamingStrategy fieldNamingStrategy) {
this.fieldNamingStrategy = fieldNamingStrategy;
return this;
}
public VPack.Builder annotationFieldFilter(
final Class type,
final VPackAnnotationFieldFilter fieldFilter) {
annotationFieldFilter.put(type, fieldFilter);
return this;
}
public VPack.Builder annotationFieldNaming(
final Class type,
final VPackAnnotationFieldNaming fieldNaming) {
annotationFieldNaming.put(type, fieldNaming);
return this;
}
public VPack build() {
return new VPack(serializers, enclosingSerializers, deserializers, instanceCreators, builderOptions,
serializeNullValues, fieldNamingStrategy, deserializersByName, annotationFieldFilter,
annotationFieldNaming);
}
}
private VPack(final Map> serializers,
final Map> enclosingSerializers, final Map> deserializers,
final Map> instanceCreators, final BuilderOptions builderOptions,
final boolean serializeNullValues, final VPackFieldNamingStrategy fieldNamingStrategy,
final Map>> deserializersByName,
final Map, VPackAnnotationFieldFilter extends Annotation>> annotationFieldFilter,
final Map, VPackAnnotationFieldNaming extends Annotation>> annotationFieldNaming) {
super();
this.serializers = serializers;
this.enclosingSerializers = enclosingSerializers;
this.deserializers = deserializers;
this.instanceCreators = instanceCreators;
this.builderOptions = builderOptions;
this.serializeNullValues = serializeNullValues;
this.deserializersByName = deserializersByName;
keyMapAdapters = new HashMap>();
cache = new VPackCache(fieldNamingStrategy, annotationFieldFilter, annotationFieldNaming);
serializationContext = new VPackSerializationContext() {
@Override
public void serialize(final VPackBuilder builder, final String attribute, final Object entity)
throws VPackParserException {
VPack.this.serialize(attribute, entity, entity.getClass(), builder, new HashMap());
}
};
deserializationContext = new VPackDeserializationContext() {
@Override
public T deserialize(final VPackSlice vpack, final Class type) throws VPackParserException {
return VPack.this.deserialize(vpack, type);
}
};
keyMapAdapters.put(String.class, VPackKeyMapAdapters.STRING);
keyMapAdapters.put(Boolean.class, VPackKeyMapAdapters.BOOLEAN);
keyMapAdapters.put(Integer.class, VPackKeyMapAdapters.INTEGER);
keyMapAdapters.put(Long.class, VPackKeyMapAdapters.LONG);
keyMapAdapters.put(Short.class, VPackKeyMapAdapters.SHORT);
keyMapAdapters.put(Double.class, VPackKeyMapAdapters.DOUBLE);
keyMapAdapters.put(Float.class, VPackKeyMapAdapters.FLOAT);
keyMapAdapters.put(BigInteger.class, VPackKeyMapAdapters.BIG_INTEGER);
keyMapAdapters.put(BigDecimal.class, VPackKeyMapAdapters.BIG_DECIMAL);
keyMapAdapters.put(Number.class, VPackKeyMapAdapters.NUMBER);
keyMapAdapters.put(Character.class, VPackKeyMapAdapters.CHARACTER);
}
public T deserialize(final VPackSlice vpack, final Type type) throws VPackParserException {
if (type == VPackSlice.class) {
return (T) vpack;
}
final T entity;
try {
entity = (T) getValue(null, vpack, type, null);
} catch (final Exception e) {
throw new VPackParserException(e);
}
return entity;
}
private VPackDeserializer> getDeserializer(final String fieldName, final Type type) {
VPackDeserializer> deserializer = null;
final Map> byName = deserializersByName.get(fieldName);
if (byName != null) {
deserializer = byName.get(type);
}
if (deserializer == null) {
deserializer = deserializers.get(type);
}
return deserializer;
}
private T deserializeObject(
final VPackSlice parent,
final VPackSlice vpack,
final Type type,
final String fieldName) throws InstantiationException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException, VPackException {
final T entity;
final VPackDeserializer> deserializer = getDeserializer(fieldName, type);
if (deserializer != null) {
entity = ((VPackDeserializer) deserializer).deserialize(parent, vpack, deserializationContext);
} else if (type == Object.class) {
entity = (T) getValue(parent, vpack, getType(vpack), fieldName);
} else {
entity = createInstance(type);
deserializeFields(entity, vpack);
}
return entity;
}
private Type getType(final VPackSlice vpack) {
final Type type;
if (vpack.isObject()) {
type = Map.class;
} else if (vpack.isString()) {
type = String.class;
} else if (vpack.isBoolean()) {
type = Boolean.class;
} else if (vpack.isArray()) {
type = Collection.class;
} else if (vpack.isDate()) {
type = Date.class;
} else if (vpack.isDouble()) {
type = Double.class;
} else if (vpack.isNumber()) {
type = Number.class;
} else if (vpack.isCustom()) {
type = String.class;
} else {
type = null;
}
return type;
}
private T createInstance(final Type type) throws InstantiationException, IllegalAccessException {
final T entity;
final VPackInstanceCreator> creator = instanceCreators.get(type);
if (creator != null) {
entity = (T) creator.createInstance();
} else if (type instanceof ParameterizedType) {
entity = createInstance(((ParameterizedType) type).getRawType());
} else {
entity = ((Class) type).newInstance();
}
return entity;
}
private void deserializeFields(final Object entity, final VPackSlice vpack) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException, VPackException {
final Map fields = cache.getFields(entity.getClass());
for (final Iterator> iterator = vpack.objectIterator(); iterator.hasNext();) {
final Entry next = iterator.next();
final FieldInfo fieldInfo = fields.get(next.getKey());
if (fieldInfo != null && fieldInfo.isDeserialize()) {
deserializeField(vpack, next.getValue(), entity, fieldInfo);
}
}
}
private void deserializeField(
final VPackSlice parent,
final VPackSlice vpack,
final Object entity,
final FieldInfo fieldInfo) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException, VPackException {
if (!vpack.isNone()) {
final Object value = getValue(parent, vpack, fieldInfo.getType(), fieldInfo.getFieldName());
fieldInfo.set(entity, value);
}
}
private Object getValue(
final VPackSlice parent,
final VPackSlice vpack,
final Type type,
final String fieldName) throws InstantiationException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException, VPackException {
final Object value;
if (vpack.isNull()) {
value = null;
} else {
final VPackDeserializer> deserializer = getDeserializer(fieldName, type);
if (deserializer != null) {
value = ((VPackDeserializer
© 2015 - 2025 Weber Informatics LLC | Privacy Policy