/*
* Copyright (C) 2011 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.jboss.errai.marshalling.rebind;
import static org.jboss.errai.config.rebind.EnvUtil.getEnvironmentConfig;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.Stream.Builder;
import org.jboss.errai.codegen.meta.MetaClass;
import org.jboss.errai.codegen.meta.MetaClassFactory;
import org.jboss.errai.common.client.api.annotations.Portable;
import org.jboss.errai.common.metadata.MetaDataScanner;
import org.jboss.errai.common.metadata.ScannerSingleton;
import org.jboss.errai.config.rebind.EnvUtil;
import org.jboss.errai.config.rebind.EnvironmentConfig;
import org.jboss.errai.config.util.ClassScanner;
import org.jboss.errai.marshalling.client.api.Marshaller;
import org.jboss.errai.marshalling.client.api.annotations.ClientMarshaller;
import org.jboss.errai.marshalling.client.api.annotations.ImplementationAliases;
import org.jboss.errai.marshalling.client.api.annotations.ServerMarshaller;
import org.jboss.errai.marshalling.client.api.exceptions.InvalidMappingException;
import org.jboss.errai.marshalling.client.marshallers.BigDecimalMarshaller;
import org.jboss.errai.marshalling.client.marshallers.BigIntegerMarshaller;
import org.jboss.errai.marshalling.client.marshallers.BooleanMarshaller;
import org.jboss.errai.marshalling.client.marshallers.ByteMarshaller;
import org.jboss.errai.marshalling.client.marshallers.CharacterMarshaller;
import org.jboss.errai.marshalling.client.marshallers.DateMarshaller;
import org.jboss.errai.marshalling.client.marshallers.DoubleMarshaller;
import org.jboss.errai.marshalling.client.marshallers.FloatMarshaller;
import org.jboss.errai.marshalling.client.marshallers.IntegerMarshaller;
import org.jboss.errai.marshalling.client.marshallers.LinkedHashSetMarshaller;
import org.jboss.errai.marshalling.client.marshallers.LinkedListMarshaller;
import org.jboss.errai.marshalling.client.marshallers.LinkedMapMarshaller;
import org.jboss.errai.marshalling.client.marshallers.ListMarshaller;
import org.jboss.errai.marshalling.client.marshallers.LongMarshaller;
import org.jboss.errai.marshalling.client.marshallers.MapMarshaller;
import org.jboss.errai.marshalling.client.marshallers.ObjectMarshaller;
import org.jboss.errai.marshalling.client.marshallers.PriorityQueueMarshaller;
import org.jboss.errai.marshalling.client.marshallers.QueueMarshaller;
import org.jboss.errai.marshalling.client.marshallers.SQLDateMarshaller;
import org.jboss.errai.marshalling.client.marshallers.SetMarshaller;
import org.jboss.errai.marshalling.client.marshallers.ShortMarshaller;
import org.jboss.errai.marshalling.client.marshallers.SortedMapMarshaller;
import org.jboss.errai.marshalling.client.marshallers.SortedSetMarshaller;
import org.jboss.errai.marshalling.client.marshallers.StringBufferMarshaller;
import org.jboss.errai.marshalling.client.marshallers.StringBuilderMarshaller;
import org.jboss.errai.marshalling.client.marshallers.StringMarshaller;
import org.jboss.errai.marshalling.client.marshallers.TimeMarshaller;
import org.jboss.errai.marshalling.client.marshallers.TimestampMarshaller;
import org.jboss.errai.marshalling.rebind.api.CustomMapping;
import org.jboss.errai.marshalling.rebind.api.InheritedMappings;
import org.jboss.errai.marshalling.rebind.api.impl.defaultjava.DefaultJavaDefinitionMapper;
import org.jboss.errai.marshalling.rebind.api.model.ConstructorMapping;
import org.jboss.errai.marshalling.rebind.api.model.InstantiationMapping;
import org.jboss.errai.marshalling.rebind.api.model.Mapping;
import org.jboss.errai.marshalling.rebind.api.model.MappingDefinition;
import org.jboss.errai.marshalling.rebind.api.model.MemberMapping;
import org.jboss.errai.marshalling.rebind.api.model.impl.SimpleConstructorMapping;
import org.jboss.errai.marshalling.rebind.mappings.builtin.StackTraceElementDefinition;
import org.jboss.errai.marshalling.rebind.mappings.builtin.ThrowableDefinition;
import org.jboss.errai.marshalling.server.marshallers.DefaultDefinitionMarshaller;
import org.jboss.errai.marshalling.server.marshallers.ServerClassMarshaller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* The default implementation of {@link DefinitionsFactory}. This implementation covers the detection and mapping of
* classes annotated with the {@link Portable} annotation, and custom mappings annotated with {@link CustomMapping}.
*
* @author Mike Brock
*/
public class DefinitionsFactoryImpl implements DefinitionsFactory {
private final Set<MetaClass> exposedClasses = Collections.newSetFromMap(new LinkedHashMap<MetaClass, Boolean>());
private final Set<MetaClass> typesWithBuiltInMarshallers = new HashSet<>();
/**
* Map of aliases to the mapped marshalling type.
*/
private final Map<String, String> mappingAliases
= new LinkedHashMap<>();
private final Set<MetaClass> arraySignatures
= new LinkedHashSet<>();
private final Map<String, MappingDefinition> mappingDefinitions
= new LinkedHashMap<>();
private final Logger log = LoggerFactory.getLogger(MarshallerGeneratorFactory.class);
// key = all types, value = list of all types which inherit from.
private final Multimap<String, String> inheritanceMap
= HashMultimap.create();
DefinitionsFactoryImpl() {
loadCustomMappings();
}
@Override
public boolean hasDefinition(final String clazz) {
return mappingDefinitions.containsKey(clazz);
}
@Override
public MappingDefinition getDefinition(final String clazz) {
return mappingDefinitions.get(clazz);
}
@Override
public boolean hasDefinition(final MetaClass clazz) {
return hasDefinition(clazz.getFullyQualifiedName());
}
@Override
public boolean hasDefinition(final Class<?> clazz) {
return hasDefinition(clazz.getName());
}
@Override
public void addDefinition(final MappingDefinition definition) {
final String fqcn = definition.getMappingClass().getFullyQualifiedName();
final String internalName = definition.getMappingClass().getInternalName();
putDefinitionIfAbsent(fqcn, definition);
if (definition.getMappingClass().isPrimitiveWrapper()) {
putDefinitionIfAbsent(definition.getMappingClass().asUnboxed().getInternalName(), definition);
putDefinitionIfAbsent(definition.getMappingClass().asUnboxed().getFullyQualifiedName(), definition);
}
if (!fqcn.equals(internalName) && definition.getMappingClass().isArray()
&& definition.getMappingClass().getOuterComponentType().isPrimitive()) {
putDefinitionIfAbsent(internalName, definition);
}
if (log.isDebugEnabled())
log.debug("loaded definition: " + fqcn);
}
private void putDefinitionIfAbsent(final String key, final MappingDefinition value) {
if (mappingDefinitions.containsKey(key)) {
throw new IllegalStateException(
"Mapping definition collision for " + key +
"\nAlready have: " + mappingDefinitions.get(key) +
"\nAttempted to add: " + value);
}
mappingDefinitions.put(key, value);
}
@Override
public MappingDefinition getDefinition(final MetaClass clazz) {
MappingDefinition def = getDefinition(clazz.getFullyQualifiedName());
if (def == null) {
def = getDefinition(clazz.getInternalName());
}
return def;
}
@Override
public MappingDefinition getDefinition(final Class<?> clazz) {
return getDefinition(clazz.getName());
}
private void loadCustomMappings() {
exposedClasses.add(MetaClassFactory.get(Object.class));
final MetaDataScanner scanner = ScannerSingleton.getOrCreateInstance();
EnvUtil.clearCache();
final EnvironmentConfig environmentConfig = getEnvironmentConfig();
final Set<MetaClass> envExposedClasses = environmentConfig.getExposedClasses();
for (final Class<?> cls : findCustomMappings(scanner)) {
if (!MappingDefinition.class.isAssignableFrom(cls)) {
throw new RuntimeException("@CustomMapping class: " + cls.getName() + " does not inherit "
+ MappingDefinition.class.getName());
}
try {
final MappingDefinition definition = (MappingDefinition) cls.newInstance();
definition.setMarshallerInstance(new DefaultDefinitionMarshaller(definition));
addDefinition(definition);
if (!envExposedClasses.contains(definition.getMappingClass())) {
definition.setLazy(true);
}
exposedClasses.add(definition.getMappingClass());
if (log.isDebugEnabled())
log.debug("loaded custom mapping class: " + cls.getName() + " (for mapping: "
+ definition.getMappingClass().getFullyQualifiedName() + ")");
if (cls.isAnnotationPresent(InheritedMappings.class)) {
final InheritedMappings inheritedMappings = cls.getAnnotation(InheritedMappings.class);
for (final Class<?> c : inheritedMappings.value()) {
final MetaClass metaClass = MetaClassFactory.get(c);
final MappingDefinition aliasMappingDef = new MappingDefinition(metaClass, definition.alreadyGenerated());
aliasMappingDef.setMarshallerInstance(new DefaultDefinitionMarshaller(aliasMappingDef));
addDefinition(aliasMappingDef);
if (!envExposedClasses.contains(metaClass)) {
aliasMappingDef.setLazy(true);
}
exposedClasses.add(metaClass);
if (log.isDebugEnabled())
log.debug("mapping inherited mapping " + c.getName() + " -> " + cls.getName());
}
}
}
catch (final Throwable t) {
throw new RuntimeException("Failed to load definition", t);
}
}
for (final MappingDefinition def : mappingDefinitions.values()) {
mergeDefinition(def);
}
final Collection<MetaClass> cliMarshallers = ClassScanner.getTypesAnnotatedWith(ClientMarshaller.class, true);
final MetaClass Marshaller_MC = MetaClassFactory.get(Marshaller.class);
for (final MetaClass marshallerMetaClass : cliMarshallers) {
if (Marshaller_MC.isAssignableFrom(marshallerMetaClass)) {
final Class<? extends Marshaller> marshallerCls = marshallerMetaClass.asClass().asSubclass(Marshaller.class);
try {
final Class<?> type = marshallerMetaClass.getAnnotation(ClientMarshaller.class).value();
final MappingDefinition marshallMappingDef = new MappingDefinition(type, true);
marshallMappingDef.setClientMarshallerClass(marshallerCls);
addDefinition(marshallMappingDef);
exposedClasses.add(MetaClassFactory.get(type).asBoxed());
typesWithBuiltInMarshallers.add(MetaClassFactory.get(type).asBoxed());
if (marshallerCls.isAnnotationPresent(ImplementationAliases.class)) {
for (final Class<?> aliasCls : marshallerCls.getAnnotation(ImplementationAliases.class).value()) {
final MappingDefinition aliasMappingDef = new MappingDefinition(aliasCls, true);
aliasMappingDef.setClientMarshallerClass(marshallerCls.asSubclass(Marshaller.class));
addDefinition(aliasMappingDef);
exposedClasses.add(MetaClassFactory.get(aliasCls).asBoxed());
typesWithBuiltInMarshallers.add(MetaClassFactory.get(type).asBoxed());
mappingAliases.put(aliasCls.getName(), type.getName());
}
}
}
catch (final Throwable t) {
throw new RuntimeException("could not instantiate marshaller class: " + marshallerCls.getName(), t);
}
}
else {
throw new RuntimeException("class annotated with " + ClientMarshaller.class.getCanonicalName()
+ " does not implement " + Marshaller.class.getName());
}
}
final Set<Class<?>> serverMarshallers = findServerMarshallers(scanner);
for (final Class<?> marshallerCls : serverMarshallers) {
if (Marshaller.class.isAssignableFrom(marshallerCls)) {
try {
final Class<?> type = marshallerCls.getAnnotation(ServerMarshaller.class).value();
final MappingDefinition definition;
if (hasDefinition(type)) {
definition = getDefinition(type);
definition.setServerMarshallerClass(marshallerCls.asSubclass(Marshaller.class));
}
else {
definition = new MappingDefinition(type, true);
definition.setServerMarshallerClass(marshallerCls.asSubclass(Marshaller.class));
addDefinition(definition);
exposedClasses.add(MetaClassFactory.get(type).asBoxed());
typesWithBuiltInMarshallers.add(MetaClassFactory.get(type).asBoxed());
}
if (marshallerCls.isAnnotationPresent(ImplementationAliases.class)) {
for (final Class<?> aliasCls : marshallerCls.getAnnotation(ImplementationAliases.class).value()) {
if (hasDefinition(aliasCls)) {
getDefinition(aliasCls).setServerMarshallerClass(marshallerCls.asSubclass(Marshaller.class));
}
else {
final MappingDefinition aliasMappingDef = new MappingDefinition(aliasCls, true);
aliasMappingDef.setServerMarshallerClass(marshallerCls.asSubclass(Marshaller.class));
addDefinition(aliasMappingDef);
exposedClasses.add(MetaClassFactory.get(aliasCls));
typesWithBuiltInMarshallers.add(MetaClassFactory.get(type).asBoxed());
mappingAliases.put(aliasCls.getName(), type.getName());
}
}
}
}
catch (final Throwable t) {
throw new RuntimeException("could not instantiate marshaller class: " + marshallerCls.getName(), t);
}
}
else {
throw new RuntimeException("class annotated with " + ServerMarshaller.class.getCanonicalName()
+ " does not implement " + Marshaller.class.getName());
}
}
exposedClasses.addAll(envExposedClasses);
final List<MetaClass> exposedSuperTypes = exposedClasses
.stream()
.filter(mc -> mc.isAnnotationPresent(Portable.class) && mc.getAnnotation(Portable.class).mapSuperTypes())
.flatMap(mc -> {
final Builder<MetaClass> builder = Stream.builder();
MetaClass cur = mc;
while (cur.getSuperClass() != null && !cur.getSuperClass().getFullyQualifiedName().equals(Object.class.getName())) {
builder.accept((cur = cur.getSuperClass()));
}
return builder.build().filter(superType -> superType.isConcrete());
})
.collect(Collectors.toList());
exposedClasses.addAll(exposedSuperTypes);
final Map<String, String> configuredMappingAliases = new HashMap<>();
configuredMappingAliases.putAll(environmentConfig.getMappingAliases());
configuredMappingAliases.putAll(defaultMappingAliases());
mappingAliases.putAll(configuredMappingAliases);
final Map<MetaClass, MetaClass> aliasToMarshaller = new HashMap<>();
final List<MetaClass> enums = new ArrayList<>();
for (final MetaClass cls : exposedClasses) {
MetaClass mappedClass;
if (cls.isArray()) {
arraySignatures.add(cls);
mappedClass = cls.getOuterComponentType();
}
else {
mappedClass = cls;
}
if (mappedClass.isSynthetic())
continue;
final Portable portable = mappedClass.getAnnotation(Portable.class);
if (portable != null && !portable.aliasOf().equals(Object.class)) {
aliasToMarshaller.put(mappedClass, MetaClassFactory.get(portable.aliasOf()));
}
else if (!hasDefinition(mappedClass)) {
final MappingDefinition def = DefaultJavaDefinitionMapper.map(mappedClass, this);
def.setMarshallerInstance(new DefaultDefinitionMarshaller(def));
addDefinition(def);
for (final Mapping mapping : def.getAllMappings()) {
if (mapping.getType().isEnum()) {
enums.add(mapping.getType());
}
}
}
}
for (final MetaClass enumType : enums) {
if (!hasDefinition(enumType)) {
final MappingDefinition enumDef = DefaultJavaDefinitionMapper
.map(MetaClassFactory.get(enumType.asClass()), this);
enumDef.setMarshallerInstance(new DefaultDefinitionMarshaller(enumDef));
addDefinition(enumDef);
exposedClasses.add(MetaClassFactory.get(enumType.asClass()));
}
}
for (final Map.Entry<String, String> entry : configuredMappingAliases.entrySet()) {
try {
aliasToMarshaller.put(MetaClassFactory.get(entry.getKey()), MetaClassFactory.get(entry.getValue()));
}
catch (final Throwable t) {
throw new RuntimeException("error loading mapping alias", t);
}
}
for (final Map.Entry<MetaClass, MetaClass> entry : aliasToMarshaller.entrySet()) {
final MappingDefinition def = getDefinition(entry.getValue());
if (def == null) {
throw new InvalidMappingException("cannot alias type " + entry.getKey().getName()
+ " to " + entry.getValue().getName() + ": the specified alias type does not exist ");
}
final MappingDefinition aliasDef = new MappingDefinition(
def.getMarshallerInstance(), entry.getKey(), false
);
if (def.getMarshallerInstance() instanceof DefaultDefinitionMarshaller) {
aliasDef.setMarshallerInstance(new DefaultDefinitionMarshaller(aliasDef));
}
else {
aliasDef.setClientMarshallerClass(def.getClientMarshallerClass());
aliasDef.setServerMarshallerClass(def.getServerMarshallerClass());
}
mergeDefinition(aliasDef);
addDefinition(aliasDef);
}
for (final Map.Entry<String, MappingDefinition> entry : mappingDefinitions.entrySet()) {
fillInheritanceMap(entry.getValue().getMappingClass());
}
final MetaClass javaLangObjectRef = MetaClassFactory.get(Object.class);
for (final Map.Entry<String, MappingDefinition> entry : mappingDefinitions.entrySet()) {
final MappingDefinition def = entry.getValue();
final InstantiationMapping instantiationMapping = def.getInstantiationMapping();
for (final Mapping mapping : instantiationMapping.getMappings()) {
if (shouldUseObjectMarshaller(mapping.getType().getErased())) {
mapping.setType(javaLangObjectRef);
}
}
for (final Mapping mapping : entry.getValue().getMemberMappings()) {
if (shouldUseObjectMarshaller(mapping.getType().getErased())) {
mapping.setType(javaLangObjectRef);
}
}
}
assert getDefinition("java.util.Arrays$ArrayList") != null;
log.debug("comprehended " + exposedClasses.size() + " classes");
}
private Set<Class<?>> findCustomMappings(final MetaDataScanner scanner) {
Set<Class<?>> scannedMappings = scanner.getTypesAnnotatedWith(CustomMapping.class, true);
if (scannedMappings.isEmpty()) {
// This should only happen in OSGI environments where we can't get classpath URLs
log.warn("Unable to scan classpath for CustomMappings. Falling back to default.");
scannedMappings = new HashSet<>();
scannedMappings.add(ThrowableDefinition.class);
scannedMappings.add(StackTraceElementDefinition.class);
}
return scannedMappings;
}
private Set<Class<?>> findServerMarshallers(final MetaDataScanner scanner) {
Set<Class<?>> serverMarshallers = scanner.getTypesAnnotatedWith(ServerMarshaller.class, true);
if (serverMarshallers.isEmpty()) {
// This should only happen in OSGI environments where we can't get classpath URLs
log.warn("Unable to scan classpath for ServerMarshallers. Falling back to default.");
serverMarshallers = new HashSet<>();
serverMarshallers.add(BigDecimalMarshaller.class);
serverMarshallers.add(BigIntegerMarshaller.class);
serverMarshallers.add(BooleanMarshaller.class);
serverMarshallers.add(ByteMarshaller.class);
serverMarshallers.add(CharacterMarshaller.class);
serverMarshallers.add(DateMarshaller.class);
serverMarshallers.add(DoubleMarshaller.class);
serverMarshallers.add(FloatMarshaller.class);
serverMarshallers.add(IntegerMarshaller.class);
serverMarshallers.add(LinkedHashSetMarshaller.class);
serverMarshallers.add(LinkedListMarshaller.class);
serverMarshallers.add(LinkedMapMarshaller.class);
serverMarshallers.add(ListMarshaller.class);
serverMarshallers.add(LongMarshaller.class);
serverMarshallers.add(MapMarshaller.class);
serverMarshallers.add(ObjectMarshaller.class);
serverMarshallers.add(PriorityQueueMarshaller.class);
serverMarshallers.add(QueueMarshaller.class);
serverMarshallers.add(SetMarshaller.class);
serverMarshallers.add(ShortMarshaller.class);
serverMarshallers.add(SortedMapMarshaller.class);
serverMarshallers.add(SortedSetMarshaller.class);
serverMarshallers.add(SQLDateMarshaller.class);
serverMarshallers.add(StringBufferMarshaller.class);
serverMarshallers.add(StringBuilderMarshaller.class);
serverMarshallers.add(StringMarshaller.class);
serverMarshallers.add(TimeMarshaller.class);
serverMarshallers.add(TimestampMarshaller.class);
serverMarshallers.add(ServerClassMarshaller.class);
}
return serverMarshallers;
}
@Override
public boolean shouldUseObjectMarshaller(final MetaClass type) {
final boolean hasPortableSubtypes = inheritanceMap.containsKey(type.getFullyQualifiedName());
final MappingDefinition definition = getDefinition(type);
final boolean hasMarshaller = definition != null;
if (hasMarshaller) {
if (definition.getClass().isAnnotationPresent(CustomMapping.class)
|| definition.getClientMarshallerClass() != null) {
return false;
}
}
final boolean isConcrete = !(type.isAbstract() || type.isInterface());
if (!type.isArray() && !type.isEnum() && !isConcrete && !hasPortableSubtypes) {
throw new IllegalStateException("A field of type " + type
+ " appears in a portable class, but " + type + " has no portable implementations.");
}
return (hasPortableSubtypes && !hasMarshaller) || (hasPortableSubtypes && hasMarshaller && isConcrete);
}
/**
* Populates the inheritance map with all supertypes (except java.lang.Object) and all directly- and
* indirectly-implemented interfaces of the given class.
*
* @param mappingClass
*/
private void fillInheritanceMap(final MetaClass mappingClass) {
fillInheritanceMap(inheritanceMap, mappingClass, mappingClass);
}
/**
* Recursive subroutine of {@link #fillInheritanceMap(org.jboss.errai.codegen.meta.MetaClass)}.
*/
private static void fillInheritanceMap(final Multimap<String, String> inheritanceMap,
final MetaClass visiting,
final MetaClass mappingClass) {
if (visiting == null || visiting.equals(MetaClassFactory.get(Object.class)))
return;
if (!visiting.equals(mappingClass)) {
inheritanceMap.put(visiting.getFullyQualifiedName(), mappingClass.getFullyQualifiedName());
}
fillInheritanceMap(inheritanceMap, visiting.getSuperClass(), mappingClass);
for (final MetaClass iface : visiting.getInterfaces()) {
fillInheritanceMap(inheritanceMap, iface, mappingClass);
}
}
@Override
public void mergeDefinition(final MappingDefinition def) {
MetaClass cls = def.getMappingClass();
while ((cls = cls.getSuperClass()) != null) {
if (hasDefinition(cls) && cls.getParameterizedType() == null) {
final MappingDefinition toMerge = getDefinition(cls);
final Set<String> parentKeys = new HashSet<>();
for (final Mapping m : toMerge.getInstantiationMapping().getMappings())
parentKeys.add(m.getKey());
for (final MemberMapping m : toMerge.getMemberMappings())
parentKeys.add(m.getKey());
final Iterator<MemberMapping> defMappings = def.getMemberMappings().iterator();
while (defMappings.hasNext()) {
if (parentKeys.contains(defMappings.next().getKey()))
defMappings.remove();
}
for (final MemberMapping memberMapping : toMerge.getMemberMappings()) {
def.addInheritedMapping(memberMapping);
}
final InstantiationMapping instantiationMapping = def.getInstantiationMapping();
if (instantiationMapping instanceof ConstructorMapping &&
def.getInstantiationMapping().getMappings().length == 0 &&
def.getMappingClass().getDeclaredConstructor(toMerge.getInstantiationMapping().getSignature()) != null) {
final ConstructorMapping parentConstructorMapping = (ConstructorMapping) toMerge.getInstantiationMapping();
final MetaClass mergingClass = def.getMappingClass();
if (parentConstructorMapping instanceof SimpleConstructorMapping) {
final ConstructorMapping newMapping = ((SimpleConstructorMapping) parentConstructorMapping)
.getCopyForInheritance();
newMapping.setMappingClass(mergingClass);
def.setInheritedInstantiationMapping(newMapping);
}
}
if (log.isDebugEnabled())
log.debug("merged definition " + def.getMappingClass() + " with " + cls.getFullyQualifiedName());
}
}
}
@Override
public boolean isExposedClass(final MetaClass clazz) {
return exposedClasses.contains(clazz);
}
@Override
public Set<MetaClass> getExposedClasses() {
return Collections.unmodifiableSet(exposedClasses);
}
@Override
public Set<MetaClass> getArraySignatures() {
return arraySignatures;
}
@Override
public Map<String, String> getMappingAliases() {
return mappingAliases;
}
@Override
public Collection<MappingDefinition> getMappingDefinitions() {
return Collections.unmodifiableCollection(new ArrayList<>(mappingDefinitions.values()));
}
private static Map<String, String> defaultMappingAliases() {
final Map<String, String> mappingAliases = new HashMap<>();
mappingAliases.put("java.util.Arrays$ArrayList", "java.util.List");
mappingAliases.put("java.util.Collections$UnmodifiableList", "java.util.List");
mappingAliases.put("java.util.Collections$UnmodifiableSet", "java.util.Set");
mappingAliases.put("java.util.Collections$UnmodifiableMap", "java.util.Map");
mappingAliases.put("java.util.Collections$UnmodifiableRandomAccessList", "java.util.List");
mappingAliases.put("java.util.Collections$SynchronizedList", "java.util.List");
mappingAliases.put("java.util.Collections$SynchronizedSet", "java.util.Set");
mappingAliases.put("java.util.Collections$SynchronizedMap", "java.util.Map");
mappingAliases.put("java.util.Collections$SynchronizedRandomAccessList", "java.util.List");
mappingAliases.put("java.util.Collections$UnmodifiableSortedMap", "java.util.SortedMap");
mappingAliases.put("java.util.Collections$SynchronizedSortedMap", "java.util.SortedMap");
mappingAliases.put("java.util.Collections$UnmodifiableSortedSet", "java.util.SortedSet");
mappingAliases.put("java.util.Collections$SynchronizedSortedSet", "java.util.SortedSet");
mappingAliases.put("java.util.Collections$EmptySet", "java.util.Set");
mappingAliases.put("java.util.Collections$EmptyList", "java.util.List");
mappingAliases.put("java.util.Collections$EmptyMap", "java.util.Map");
mappingAliases.put("java.util.Collections$SingletonSet", "java.util.Set");
mappingAliases.put("java.util.Collections$SingletonList", "java.util.List");
mappingAliases.put("java.util.Collections$SingletonMap", "java.util.Map");
return mappingAliases;
}
@Override
public void resetDefinitionsAndReload() {
this.exposedClasses.clear();
this.mappingAliases.clear();
this.mappingDefinitions.clear();
this.typesWithBuiltInMarshallers.clear();
loadCustomMappings();
}
@Override
public boolean hasBuiltInDefinition(final MetaClass type) {
return typesWithBuiltInMarshallers.contains(type.asBoxed());
}
}