All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.getperka.flatpack.codexes.DefaultCodexMapper Maven / Gradle / Ivy
/*
* #%L
* FlatPack serialization code
* %%
* Copyright (C) 2012 Perka Inc.
* %%
* 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.
* #L%
*/
package com.getperka.flatpack.codexes;
import static com.getperka.flatpack.util.FlatPackTypes.BOXED_TYPES;
import static com.getperka.flatpack.util.FlatPackTypes.PRIMITIVE_TYPES;
import static com.getperka.flatpack.util.FlatPackTypes.box;
import static com.getperka.flatpack.util.FlatPackTypes.createType;
import static com.getperka.flatpack.util.FlatPackTypes.erase;
import static com.getperka.flatpack.util.FlatPackTypes.getParameterization;
import static com.getperka.flatpack.util.FlatPackTypes.getSingleParameterization;
import static com.getperka.flatpack.util.FlatPackTypes.instantiable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import javax.inject.Inject;
import org.joda.time.DateTimeZone;
import com.getperka.flatpack.HasUuid;
import com.getperka.flatpack.ext.Codex;
import com.getperka.flatpack.ext.CodexMapper;
import com.getperka.flatpack.ext.TypeContext;
import com.getperka.flatpack.ext.TypeHint;
import com.getperka.flatpack.util.FlatPackCollections;
import com.google.gson.JsonElement;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.ProvisionException;
/**
* Support for all built-in types.
*/
public class DefaultCodexMapper implements CodexMapper {
private Injector injector;
private final Map, ValueCodex>> simpleCodexes = FlatPackCollections.mapForIteration();
protected DefaultCodexMapper() {}
@Override
public Codex> getCodex(TypeContext context, Type type) {
Class> erased = erase(type);
// Simple types
if (simpleCodexes.containsKey(erased)) {
return simpleCodexes.get(erased);
}
for (Entry, ValueCodex>> entry : simpleCodexes.entrySet()) {
if (entry.getKey().isAssignableFrom(erased)) {
return entry.getValue();
}
}
// Entities
if (HasUuid.class.isAssignableFrom(erased)) {
return getInstance(EntityCodex.class, type);
}
// Annotations
if (erased.isAnnotation()) {
return simpleCodexes.get(Annotation.class);
}
// Enums
if (Enum.class.isAssignableFrom(erased)) {
return getInstance(EnumCodex.class, erased);
}
// Collections and collection-like objects
if (erased.isArray()) {
// Treat an array like a list
if (erased.getComponentType().isPrimitive()) {
return getInstance(PrimitiveArrayCodex.class, box(erased.getComponentType()));
}
return getInstance(ArrayCodex.class, erased.getComponentType());
}
if (Collection.class.equals(erased) || List.class.isAssignableFrom(erased)) {
Type valueType = getSingleParameterization(type, Collection.class);
return getInstance(ListCodex.class, valueType);
}
if (Set.class.isAssignableFrom(erased)) {
Type valueType = getSingleParameterization(type, Collection.class);
return getInstance(SetCodex.class, valueType);
}
// Maps, either or
if (Map.class.isAssignableFrom(erased)) {
Type[] params = getParameterization(Map.class, type);
if (HasUuid.class.isAssignableFrom(erase(params[0]))) {
return getInstance(EntityMapCodex.class, params[0], params[1]);
} else if (context.getCodex(params[0]) instanceof ValueCodex) {
return getInstance(StringMapCodex.class, params[0], params[1]);
}
}
// java.util.Date and subtypes
if (java.util.Date.class.isAssignableFrom(erased)) {
return getInstance(DateCodex.class, erased);
}
/*
* Try to find a one-arg String or Object constructor. This is kind of shady, but it works for a
* number of the auxiliary value types used in the model classes, mainly joda-time.
*/
try {
return getInstance(ToStringCodex.class, type);
} catch (ProvisionException ignored) {}
return null;
}
@Inject
void inject(Injector injector) {
this.injector = injector;
simpleCodexes.put(Annotation.class, injector.getInstance(AnnotationCodex.class));
simpleCodexes.put(BigDecimal.class, (NumberCodex>) injector.getInstance(
Key.get(createType(NumberCodex.class, BigDecimal.class))));
simpleCodexes.put(BigInteger.class, (NumberCodex>) injector.getInstance(
Key.get(createType(NumberCodex.class, BigInteger.class))));
simpleCodexes.put(boolean.class, injector.getInstance(BooleanCodex.class));
simpleCodexes.put(Boolean.class, injector.getInstance(BooleanCodex.class));
simpleCodexes.put(char.class, injector.getInstance(CharacterCodex.class));
simpleCodexes.put(Character.class, injector.getInstance(CharacterCodex.class));
simpleCodexes.put(Class.class, injector.getInstance(HasUuidClassCodex.class));
simpleCodexes.put(DateTimeZone.class, injector.getInstance(DateTimeZoneCodex.class));
simpleCodexes.put(JsonElement.class, injector.getInstance(JsonElementCodex.class));
simpleCodexes.put(String.class, injector.getInstance(StringCodex.class));
simpleCodexes.put(TypeHint.class, injector.getInstance(TypeHintCodex.class));
simpleCodexes.put(UUID.class, injector.getInstance(UUIDCodex.class));
simpleCodexes.put(void.class, injector.getInstance(VoidCodex.class));
simpleCodexes.put(Void.class, injector.getInstance(VoidCodex.class));
for (Class> clazz : BOXED_TYPES) {
if (Number.class.isAssignableFrom(clazz)) {
@SuppressWarnings("unchecked")
Key> key = (Key>) Key.get(createType(NumberCodex.class, clazz));
simpleCodexes.put(clazz, injector.getInstance(key));
}
}
for (Class> clazz : PRIMITIVE_TYPES) {
Class> boxed = box(clazz);
if (Number.class.isAssignableFrom(boxed)) {
@SuppressWarnings("unchecked")
Key> key = (Key>) Key.get(createType(NumberCodex.class, boxed));
simpleCodexes.put(clazz, injector.getInstance(key));
}
}
}
private Codex> getInstance(Class> codexType, Type type) {
Key> key = Key.get(createType(codexType, instantiable(type)));
return (Codex>) injector.getInstance(key);
}
private Codex> getInstance(Class> codexType, Type type, Type type2) {
Key> key;
try {
key = Key.get(createType(codexType, type, type2));
} catch (ConfigurationException e) {
key = Key.get(createType(codexType, erase(type)));
}
return (Codex>) injector.getInstance(key);
}
}