com.feilong.lib.xstream.mapper.ImplicitCollectionMapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of feilong Show documentation
Show all versions of feilong Show documentation
feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.
/*
* Copyright (C) 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 16. February 2005 by Joe Walnes
*/
package com.feilong.lib.xstream.mapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.feilong.lib.xstream.InitializationException;
import com.feilong.lib.xstream.converters.reflection.ReflectionProvider;
import com.feilong.lib.xstream.core.util.Primitives;
public class ImplicitCollectionMapper extends MapperWrapper{
private ReflectionProvider reflectionProvider;
public ImplicitCollectionMapper(Mapper wrapped, ReflectionProvider reflectionProvider){
super(wrapped);
this.reflectionProvider = reflectionProvider;
}
// { definedIn (Class) -> (ImplicitCollectionMapperForClass) }
private final Map classNameToMapper = new HashMap();
private ImplicitCollectionMapperForClass getMapper(final Class declaredFor,final String fieldName){
Class definedIn = declaredFor;
Field field = fieldName != null ? reflectionProvider.getFieldOrNull(definedIn, fieldName) : null;
Class inheritanceStop = field != null ? field.getDeclaringClass() : null;
while (definedIn != null){
ImplicitCollectionMapperForClass mapper = (ImplicitCollectionMapperForClass) classNameToMapper.get(definedIn);
if (mapper != null){
return mapper;
}
if (definedIn == inheritanceStop){
break;
}
definedIn = definedIn.getSuperclass();
}
return null;
}
private ImplicitCollectionMapperForClass getOrCreateMapper(Class definedIn){
ImplicitCollectionMapperForClass mapper = (ImplicitCollectionMapperForClass) classNameToMapper.get(definedIn);
if (mapper == null){
mapper = new ImplicitCollectionMapperForClass(definedIn);
classNameToMapper.put(definedIn, mapper);
}
return mapper;
}
@Override
public String getFieldNameForItemTypeAndName(Class definedIn,Class itemType,String itemFieldName){
ImplicitCollectionMapperForClass mapper = getMapper(definedIn, null);
if (mapper != null){
return mapper.getFieldNameForItemTypeAndName(itemType, itemFieldName);
}else{
return null;
}
}
@Override
public Class getItemTypeForItemFieldName(Class definedIn,String itemFieldName){
ImplicitCollectionMapperForClass mapper = getMapper(definedIn, null);
if (mapper != null){
return mapper.getItemTypeForItemFieldName(itemFieldName);
}else{
return null;
}
}
@Override
public ImplicitCollectionMapping getImplicitCollectionDefForFieldName(Class itemType,String fieldName){
ImplicitCollectionMapperForClass mapper = getMapper(itemType, fieldName);
if (mapper != null){
return mapper.getImplicitCollectionDefForFieldName(fieldName);
}else{
return null;
}
}
public void add(Class definedIn,String fieldName,Class itemType){
add(definedIn, fieldName, null, itemType);
}
public void add(Class definedIn,String fieldName,String itemFieldName,Class itemType){
add(definedIn, fieldName, itemFieldName, itemType, null);
}
public void add(Class definedIn,String fieldName,String itemFieldName,Class itemType,String keyFieldName){
Field field = null;
if (definedIn != null){
Class declaredIn = definedIn;
while (declaredIn != Object.class){
try{
field = declaredIn.getDeclaredField(fieldName);
if (!Modifier.isStatic(field.getModifiers())){
break;
}
field = null;
}catch (final SecurityException e){
throw new InitializationException("Access denied for field with implicit collection", e);
}catch (final NoSuchFieldException e){
declaredIn = declaredIn.getSuperclass();
}
}
}
if (field == null){
throw new InitializationException("No field \"" + fieldName + "\" for implicit collection");
}else if (Map.class.isAssignableFrom(field.getType())){
if (itemFieldName == null && keyFieldName == null){
itemType = Map.Entry.class;
}
}else if (!Collection.class.isAssignableFrom(field.getType())){
Class fieldType = field.getType();
if (!fieldType.isArray()){
throw new InitializationException("Field \"" + fieldName + "\" declares no collection or array");
}else{
Class componentType = fieldType.getComponentType();
componentType = componentType.isPrimitive() ? Primitives.box(componentType) : componentType;
if (itemType == null){
itemType = componentType;
}else{
itemType = itemType.isPrimitive() ? Primitives.box(itemType) : itemType;
if (!componentType.isAssignableFrom(itemType)){
throw new InitializationException(
"Field \"" + fieldName + "\" declares an array, but the array type is not compatible with "
+ itemType.getName());
}
}
}
}
ImplicitCollectionMapperForClass mapper = getOrCreateMapper(definedIn);
mapper.add(new ImplicitCollectionMappingImpl(fieldName, itemType, itemFieldName, keyFieldName));
}
private class ImplicitCollectionMapperForClass{
private Class definedIn;
// { (NamedItemType) -> (ImplicitCollectionDefImpl) }
private Map namedItemTypeToDef = new HashMap();
// { itemFieldName (String) -> (ImplicitCollectionDefImpl) }
private Map itemFieldNameToDef = new HashMap();
// { fieldName (String) -> (ImplicitCollectionDefImpl) }
private Map fieldNameToDef = new HashMap();
ImplicitCollectionMapperForClass(Class definedIn){
this.definedIn = definedIn;
}
public String getFieldNameForItemTypeAndName(Class itemType,String itemFieldName){
ImplicitCollectionMappingImpl unnamed = null;
for (Iterator iterator = namedItemTypeToDef.keySet().iterator(); iterator.hasNext();){
NamedItemType itemTypeForFieldName = (NamedItemType) iterator.next();
ImplicitCollectionMappingImpl def = (ImplicitCollectionMappingImpl) namedItemTypeToDef.get(itemTypeForFieldName);
if (itemType == Mapper.Null.class){
unnamed = def;
break;
}else if (itemTypeForFieldName.itemType.isAssignableFrom(itemType)){
if (def.getItemFieldName() != null){
if (def.getItemFieldName().equals(itemFieldName)){
return def.getFieldName();
}
}else{
if (unnamed == null || unnamed.getItemType() == null
|| (def.getItemType() != null && unnamed.getItemType().isAssignableFrom(def.getItemType()))){
unnamed = def;
}
}
}
}
if (unnamed != null){
return unnamed.getFieldName();
}else{
ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getFieldNameForItemTypeAndName(itemType, itemFieldName) : null;
}
}
public Class getItemTypeForItemFieldName(String itemFieldName){
ImplicitCollectionMappingImpl def = getImplicitCollectionDefByItemFieldName(itemFieldName);
if (def != null){
return def.getItemType();
}else{
ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getItemTypeForItemFieldName(itemFieldName) : null;
}
}
private ImplicitCollectionMappingImpl getImplicitCollectionDefByItemFieldName(String itemFieldName){
if (itemFieldName == null){
return null;
}else{
ImplicitCollectionMappingImpl mapping = (ImplicitCollectionMappingImpl) itemFieldNameToDef.get(itemFieldName);
if (mapping != null){
return mapping;
}else{
ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getImplicitCollectionDefByItemFieldName(itemFieldName) : null;
}
}
}
public ImplicitCollectionMapping getImplicitCollectionDefForFieldName(String fieldName){
ImplicitCollectionMapping mapping = (ImplicitCollectionMapping) fieldNameToDef.get(fieldName);
if (mapping != null){
return mapping;
}else{
ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getImplicitCollectionDefForFieldName(fieldName) : null;
}
}
public void add(ImplicitCollectionMappingImpl def){
fieldNameToDef.put(def.getFieldName(), def);
namedItemTypeToDef.put(def.createNamedItemType(), def);
if (def.getItemFieldName() != null){
itemFieldNameToDef.put(def.getItemFieldName(), def);
}
}
}
private static class ImplicitCollectionMappingImpl implements ImplicitCollectionMapping{
private final String fieldName;
private final String itemFieldName;
private final Class itemType;
private final String keyFieldName;
ImplicitCollectionMappingImpl(String fieldName, Class itemType, String itemFieldName, String keyFieldName){
this.fieldName = fieldName;
this.itemFieldName = itemFieldName;
this.itemType = itemType;
this.keyFieldName = keyFieldName;
}
public NamedItemType createNamedItemType(){
return new NamedItemType(itemType, itemFieldName);
}
@Override
public String getFieldName(){
return fieldName;
}
@Override
public String getItemFieldName(){
return itemFieldName;
}
@Override
public Class getItemType(){
return itemType;
}
@Override
public String getKeyFieldName(){
return keyFieldName;
}
}
private static class NamedItemType{
Class itemType;
String itemFieldName;
NamedItemType(Class itemType, String itemFieldName){
this.itemType = itemType == null ? Object.class : itemType;
this.itemFieldName = itemFieldName;
}
@Override
public boolean equals(Object obj){
if (obj instanceof NamedItemType){
NamedItemType b = (NamedItemType) obj;
return itemType.equals(b.itemType) && isEquals(itemFieldName, b.itemFieldName);
}else{
return false;
}
}
private static boolean isEquals(Object a,Object b){
if (a == null){
return b == null;
}else{
return a.equals(b);
}
}
@Override
public int hashCode(){
int hash = itemType.hashCode() << 7;
if (itemFieldName != null){
hash += itemFieldName.hashCode();
}
return hash;
}
}
}