package org.glassfish.gmbal.impl ;
import org.glassfish.gmbal.impl.trace.TraceRuntime;
import org.glassfish.gmbal.impl.trace.TraceRegistrationFine;
import org.glassfish.pfl.tf.spi.annotation.InfoMethod;
import org.glassfish.gmbal.impl.trace.TraceRegistration;
import org.glassfish.pfl.basic.algorithm.DumpToString;
import org.glassfish.pfl.basic.contain.Pair;
import org.glassfish.pfl.basic.facet.FacetAccessor;
import org.glassfish.pfl.basic.algorithm.Algorithms;
import org.glassfish.pfl.basic.func.UnaryPredicate;
import java.lang.reflect.Array ;
import java.lang.reflect.Constructor ;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection ;
import java.util.List ;
import java.util.ArrayList ;
import java.util.Map ;
import java.util.HashMap ;
import java.util.Iterator ;
import java.util.Enumeration ;
import java.util.Dictionary ;
import java.util.Arrays;
import javax.management.ObjectName ;
import javax.management.JMException;
import javax.management.openmbean.ArrayType ;
import javax.management.openmbean.OpenType ;
import javax.management.openmbean.OpenDataException ;
import javax.management.openmbean.SimpleType ;
import javax.management.openmbean.TabularType ;
import javax.management.openmbean.CompositeType ;
import javax.management.openmbean.CompositeData ;
import javax.management.openmbean.CompositeDataSupport ;
import javax.management.openmbean.TabularData ;
import javax.management.openmbean.TabularDataSupport ;
import org.glassfish.gmbal.AMXClient;
import org.glassfish.gmbal.ManagedObject ;
import org.glassfish.gmbal.ManagedData ;
import org.glassfish.gmbal.typelib.EvaluatedArrayType;
import org.glassfish.gmbal.typelib.EvaluatedClassAnalyzer;
import org.glassfish.gmbal.typelib.EvaluatedClassDeclaration;
import org.glassfish.gmbal.typelib.EvaluatedMethodDeclaration;
import org.glassfish.gmbal.typelib.EvaluatedType;
import static org.glassfish.gmbal.typelib.EvaluatedType.* ;
@TraceRuntime
@TraceRegistration
@TraceRegistrationFine
public abstract class TypeConverterImpl implements TypeConverter {
private static final Map<EvaluatedType,OpenType> simpleTypeMap =
new HashMap<EvaluatedType,OpenType>() ;
private static final Map<OpenType,EvaluatedClassDeclaration> simpleOpenTypeMap =
new HashMap<OpenType,EvaluatedClassDeclaration>() ;
private static void initMaps( final OpenType otype,
final EvaluatedClassDeclaration... types ) {
boolean first = true ;
for (EvaluatedClassDeclaration type : types) {
simpleTypeMap.put( type, otype ) ;
if (first) {
first = false ;
simpleOpenTypeMap.put( otype, type ) ;
}
}
}
static {
initMaps( SimpleType.BOOLEAN, EBOOLEANW, EBOOLEAN ) ;
initMaps( SimpleType.CHARACTER, ECHARW, ECHAR ) ;
initMaps( SimpleType.INTEGER, EINTW, EINT ) ;
initMaps( SimpleType.SHORT, ESHORTW, ESHORT ) ;
initMaps( SimpleType.LONG, ELONGW, ELONG ) ;
initMaps( SimpleType.BYTE, EBYTEW, EBYTE ) ;
initMaps( SimpleType.FLOAT, EFLOATW, EFLOAT ) ;
initMaps( SimpleType.DOUBLE, EDOUBLEW, EDOUBLE ) ;
initMaps( SimpleType.STRING, ESTRING ) ;
initMaps( SimpleType.VOID, EVOID ) ;
initMaps( SimpleType.DATE, EDATE ) ;
initMaps( SimpleType.OBJECTNAME, EOBJECT_NAME ) ;
initMaps( SimpleType.BIGDECIMAL, EBIG_DECIMAL ) ;
initMaps( SimpleType.BIGINTEGER, EBIG_INTEGER ) ;
}
public static Class getJavaClass( final OpenType ot ) {
if (ot instanceof SimpleType) {
final SimpleType st = (SimpleType)ot ;
return simpleOpenTypeMap.get( st ).cls() ;
} else if (ot instanceof ArrayType) {
final ArrayType at = (ArrayType)ot ;
final OpenType cot = at.getElementOpenType() ;
final Class cjt = getJavaClass( cot ) ;
final Object temp = Array.newInstance( cjt, 0 ) ;
return temp.getClass() ;
} else if (ot instanceof TabularType) {
return TabularData.class ;
} else if (ot instanceof CompositeType) {
return CompositeData.class ;
} else {
throw Exceptions.self.unsupportedOpenType( ot ) ;
}
}
private static EvaluatedType canonicalType( EvaluatedType et ) {
OpenType ot = simpleTypeMap.get( et ) ;
if (ot == null) {
return et ;
} else {
return simpleOpenTypeMap.get( ot ) ;
}
}
public static Class getJavaClass( final EvaluatedType type ) {
if (type instanceof EvaluatedClassDeclaration) {
return ((EvaluatedClassDeclaration)type).cls() ;
} else if (type instanceof EvaluatedArrayType) {
final EvaluatedArrayType gat = (EvaluatedArrayType)type ;
final EvaluatedType ctype = canonicalType( gat.componentType() ) ;
final Class cclass = getJavaClass( ctype ) ;
final Object temp = Array.newInstance( cclass, 0 ) ;
return temp.getClass() ;
} else {
throw Exceptions.self.cannotConvertToJavaType(type) ;
}
}
@TraceRegistration
public static TypeConverter makeTypeConverter( final EvaluatedType type,
final ManagedObjectManagerInternal mom ) {
TypeConverter result = null ;
try {
final OpenType stype = simpleTypeMap.get( type ) ;
if (stype != null) {
result = handleSimpleType( type, stype ) ;
} else if (type instanceof EvaluatedClassDeclaration) {
EvaluatedClassDeclaration cls = (EvaluatedClassDeclaration)type ;
final ManagedObject mo = mom.getFirstAnnotationOnClass( cls,
ManagedObject.class ) ;
final ManagedData md = mom.getFirstAnnotationOnClass( cls,
ManagedData.class ) ;
if (mo != null) {
result = handleManagedObject( cls, mom, mo ) ;
} else if (md != null) {
result = handleManagedData( cls, mom, md ) ;
} else if (cls.cls().isEnum()) {
result = handleEnum( cls ) ;
} else {
result = handleClass( cls, mom ) ;
}
} else if (type instanceof EvaluatedArrayType) {
result = handleArrayType( (EvaluatedArrayType)type, mom ) ;
} else {
throw new IllegalArgumentException( "Unknown kind of Type "
+ type ) ;
}
} catch (RuntimeException exc) {
throw exc ;
} catch (OpenDataException exc) {
throw new RuntimeException( exc ) ;
}
return result ;
}
private static TypeConverter handleSimpleType( final EvaluatedType type,
final OpenType stype ) {
final EvaluatedType canType = canonicalType( type ) ;
return new TypeConverterImpl( type, stype ) {
public Object toManagedEntity( final Object obj ) {
return obj ;
}
@Override
public Object fromManagedEntity( final Object entity ) {
return entity ;
}
@Override
public boolean isIdentity() {
return canType.equals( type ) ;
}
} ;
}
public static final String NULL_STRING = "<NULL>" ;
@TraceRegistration
private static TypeConverter handleManagedObject(
final EvaluatedClassDeclaration type,
final ManagedObjectManagerInternal mom, final ManagedObject mo ) {
TypeConverter result = null ;
result = new TypeConverterImpl( type, SimpleType.OBJECTNAME ) {
public Object toManagedEntity( Object obj ) {
if (obj == null) {
return AMXClient.NULL_OBJECTNAME ;
} else {
return mom.getObjectName( obj ) ;
}
}
@Override
public Object fromManagedEntity( final Object entity ) {
if (!(entity instanceof ObjectName)) {
throw Exceptions.self.entityNotObjectName( entity ) ;
}
final ObjectName oname = (ObjectName)entity ;
if (oname.equals( AMXClient.NULL_OBJECTNAME )) {
return null ;
} else {
return mom.getObject( oname ) ;
}
}
} ;
return result ;
}
@TraceRegistration
private static Collection<AttributeDescriptor> analyzeManagedData(
final EvaluatedClassDeclaration cls, final ManagedObjectManagerInternal mom ) {
Collection<AttributeDescriptor> result = null ;
final EvaluatedClassAnalyzer ca = mom.getClassAnalyzer( cls,
ManagedData.class ).second() ;
final Pair<Map<String,AttributeDescriptor>,
Map<String,AttributeDescriptor>> ainfos =
mom.getAttributes( ca,
ManagedObjectManagerInternal.AttributeDescriptorType
.COMPOSITE_DATA_ATTR ) ;
result = ainfos.first().values() ;
return result ;
}
@InfoMethod
private static void describe( String msg, Object data ) {}
@TraceRegistration
private static CompositeType makeCompositeType(
final EvaluatedClassDeclaration cls,
final ManagedObjectManagerInternal mom, final ManagedData md,
Collection<AttributeDescriptor> minfos ) {
CompositeType result = null ;
String name = md.name() ;
if (name.equals( "" )) {
name = mom.getTypeName( cls.cls(), "GMBAL_TYPE",
md.name() ) ;
}
describe( "name", name ) ;
final String mdDescription = mom.getDescription( cls ) ;
describe( "mdDescription", mdDescription ) ;
final int length = minfos.size() ;
final String[] attrNames = new String[ length ] ;
final String[] attrDescriptions = new String[ length ] ;
final OpenType[] attrOTypes = new OpenType[ length ] ;
int ctr = 0 ;
for (AttributeDescriptor minfo : minfos) {
attrNames[ctr] = minfo.id() ;
attrDescriptions[ctr] = minfo.description() ;
attrOTypes[ctr] = minfo.tc().getManagedType() ;
ctr++ ;
}
describe( "attrNames=", Arrays.asList(attrNames) ) ;
describe( "attrDescriptions=", Arrays.asList(attrDescriptions) ) ;
describe( "attrOTypes=", Arrays.asList(attrOTypes) ) ;
try {
result = new CompositeType(
name, mdDescription, attrNames, attrDescriptions, attrOTypes ) ;
} catch (OpenDataException exc) {
throw Exceptions.self.exceptionInMakeCompositeType(exc) ;
}
return result ;
}
@TraceRegistration
private static TypeConverter handleManagedData(
final EvaluatedClassDeclaration cls,
final ManagedObjectManagerInternal mom, final ManagedData md ) {
TypeConverter result = null ;
final Collection<AttributeDescriptor> minfos = analyzeManagedData(
cls, mom ) ;
final CompositeType myType = makeCompositeType( cls, mom, md, minfos ) ;
describe( "minfos=", minfos ) ;
describe( "myType=", myType ) ;
result = new TypeConverterImpl( cls, myType ) {
@TraceRuntime
public Object toManagedEntity( Object obj ) {
Object runResult = null ;
Map<String,Object> data = new HashMap<String,Object>() ;
for (AttributeDescriptor minfo : minfos) {
describe( "Fetching attribute ", minfo.id() ) ;
Object value = null ;
if (minfo.isApplicable( obj )) {
try {
FacetAccessor fa = mom.getFacetAccessor( obj ) ;
value = minfo.get(fa );
} catch (JMException ex) {
Exceptions.self.errorInConstructingOpenData(
cls.name(), minfo.id(), ex ) ;
}
}
data.put( minfo.id(), value ) ;
}
try {
runResult = new CompositeDataSupport( myType, data ) ;
} catch (OpenDataException exc) {
throw Exceptions.self.exceptionInHandleManagedData(exc) ;
}
return runResult ;
}
} ;
return result ;
}
private static TypeConverter handleEnum( final EvaluatedClassDeclaration cls ) {
return new TypeConverterImpl( cls, SimpleType.STRING ) {
public Object toManagedEntity( final Object obj ) {
if (obj == null)
return NULL_STRING ;
else
return obj.toString() ;
}
@Override
@SuppressWarnings("unchecked")
public Object fromManagedEntity( final Object entity ) {
if (NULL_STRING.equals(entity)) {
return null ;
}
if (!(entity instanceof String)) {
throw Exceptions.self.notAString(entity) ;
}
return Enum.valueOf( cls.cls(), (String)entity ) ;
}
} ;
}
private static ArrayType getArrayType( OpenType ot ) throws OpenDataException {
ArrayType result ;
if (ot instanceof ArrayType) {
ArrayType atype = (ArrayType)ot ;
int dim = atype.getDimension() ;
OpenType lowestComponentType = atype.getElementOpenType() ;
result = new ArrayType( dim + 1, lowestComponentType ) ;
} else {
result = new ArrayType( 1, ot ) ;
}
return result ;
}
@SuppressWarnings("unchecked")
@TraceRegistration
private static TypeConverter handleArrayType( final EvaluatedArrayType type,
final ManagedObjectManagerInternal mom ) throws OpenDataException {
TypeConverter result = null ;
final EvaluatedType ctype = type.componentType() ;
final TypeConverter ctypeTc = mom.getTypeConverter( ctype ) ;
final OpenType cotype = ctypeTc.getManagedType() ;
final OpenType ot = getArrayType( cotype ) ;
describe( "ctype", ctype ) ;
describe( "ctypeTc", ctypeTc ) ;
describe( "cotype", cotype ) ;
describe( "ot", ot ) ;
result = new TypeConverterImpl( type, ot ) {
@TraceRuntime
public Object toManagedEntity( final Object obj ) {
if (isIdentity()) {
return obj ;
} else {
final Class cclass = getJavaClass( cotype ) ;
final int length =
obj == null ? 0 : Array.getLength( obj ) ;
final Object result = Array.newInstance( cclass, length ) ;
for (int ctr=0; ctr<length; ctr++) {
describe( "Entering (handleArrayType):toManagedEntity",
ctr ) ;
try {
final Object elem = Array.get( obj, ctr ) ;
final Object relem = ctypeTc.toManagedEntity( elem ) ;
Array.set( result, ctr, relem ) ;
} finally {
describe( "Exiting (handleArrayType):toManagedEntity",
ctr ) ;
}
}
return result ;
}
}
@Override
@TraceRuntime
public Object fromManagedEntity( final Object entity ) {
if (isIdentity()) {
return entity ;
} else {
final Class cclass = getJavaClass( ctype ) ;
final int length =
entity == null ? 0 : Array.getLength( entity ) ;
final Object result = Array.newInstance( cclass, length ) ;
for (int ctr=0; ctr<length; ctr++) {
describe( "Entering (handleArrayType):fromManagedEntity",
ctr ) ;
try {
final Object elem = Array.get( entity, ctr ) ;
final Object relem =
ctypeTc.fromManagedEntity( elem ) ;
Array.set( result, ctr, relem ) ;
} finally {
describe( "Exiting (handleArrayType):fromManagedEntity",
ctr ) ;
}
}
return result ;
}
}
@Override
public boolean isIdentity() {
return ctypeTc.isIdentity() ;
}
} ;
return result ;
}
private static final Runnable NoOp = new Runnable() {
public void run() {}
} ;
private static EvaluatedMethodDeclaration findMethod(
final EvaluatedClassAnalyzer eca, final String mname ) {
return Algorithms.getFirst( eca.findMethods(
new UnaryPredicate<EvaluatedMethodDeclaration>() {
public boolean evaluate( EvaluatedMethodDeclaration m ) {
return m.name().equals( mname ) ;
}
}
), NoOp ) ;
}
private static EvaluatedType getReturnType( EvaluatedClassDeclaration decl,
String mname ) {
EvaluatedClassAnalyzer eca = new EvaluatedClassAnalyzer( decl ) ;
EvaluatedMethodDeclaration meth = findMethod( eca, mname ) ;
if (meth == null) {
return null ;
} else {
return meth.returnType() ;
}
}
private static EvaluatedType getParameterType(
EvaluatedClassDeclaration decl, String mname, int pindex ) {
EvaluatedClassAnalyzer eca = new EvaluatedClassAnalyzer( decl ) ;
EvaluatedMethodDeclaration meth = findMethod( eca, mname ) ;
if (meth == null) {
return null ;
} else {
if (pindex < meth.parameterTypes().size()) {
return meth.parameterTypes().get( pindex ) ;
} else {
throw new IndexOutOfBoundsException(
"Parameter index is out of bounds" ) ;
}
}
}
private static Table emptyTable() {
return new Table() {
public Object get(Object key) {
return null ;
}
public Iterator iterator() {
return emptyIterator() ;
}
} ;
}
private static Iterator emptyIterator() {
List list = new ArrayList() ;
return list.iterator() ;
}
@TraceRegistration
private static TypeConverter handleClass(
final EvaluatedClassDeclaration type,
final ManagedObjectManagerInternal mom ) {
TypeConverter result = null ;
if (Iterable.class.isAssignableFrom(type.cls())) {
EvaluatedClassDeclaration type2 =
(EvaluatedClassDeclaration)getReturnType( type, "iterator") ;
if (type2 == null) {
throw Exceptions.self.iteratorNotFound(type) ;
}
EvaluatedType tcType = getReturnType( type2, "next" ) ;
if (tcType == null) {
throw Exceptions.self.nextNotFound(type) ;
}
TypeConverter tc = mom.getTypeConverter( tcType ) ;
result = new TypeConverterListBase( type, tc ) {
protected Iterator getIterator( Object obj ) {
if (obj == null) {
return emptyIterator() ;
} else {
return ((Iterable)obj).iterator() ;
}
}
} ;
} else if (Collection.class.isAssignableFrom(type.cls())) {
EvaluatedClassDeclaration type2 =
(EvaluatedClassDeclaration)getReturnType( type, "iterator") ;
EvaluatedType tcType = getReturnType( type2, "next" ) ;
TypeConverter tc = mom.getTypeConverter( tcType ) ;
result = new TypeConverterListBase( type, tc ) {
protected Iterator getIterator( Object obj ) {
if (obj == null) {
return emptyIterator() ;
} else {
return ((Iterable)obj).iterator() ;
}
}
} ;
} else if (Iterator.class.isAssignableFrom(type.cls())) {
EvaluatedType tcType = getReturnType( type, "next" ) ;
TypeConverter tc = mom.getTypeConverter( tcType ) ;
result = new TypeConverterListBase( type, tc ) {
protected Iterator getIterator( Object obj ) {
if (obj == null) {
return emptyIterator() ;
} else {
return (Iterator)obj ;
}
}
} ;
} else if (Enumeration.class.isAssignableFrom(type.cls())) {
EvaluatedType tcType = getReturnType( type, "next" ) ;
TypeConverter tc = mom.getTypeConverter( tcType ) ;
result = new TypeConverterListBase( type, tc ) {
@SuppressWarnings("unchecked")
protected Iterator getIterator( Object obj ) {
if (obj == null) {
return emptyIterator() ;
} else {
return new EnumerationAdapter( (Enumeration)obj ) ;
}
}
} ;
} else if (Map.class.isAssignableFrom(type.cls())) {
EvaluatedType type1 = getParameterType( type, "put", 0 ) ;
TypeConverter firstTc = mom.getTypeConverter( type1 ) ;
EvaluatedType type2 = getReturnType( type, "put" ) ;
TypeConverter secondTc = mom.getTypeConverter( type2 ) ;
result = new TypeConverterMapBase( type, firstTc, secondTc ) {
@SuppressWarnings("unchecked")
protected Table getTable( Object obj ) {
if (obj == null) {
return emptyTable() ;
} else {
return new TableMapImpl( (Map)obj ) ;
}
}
} ;
} else if (Dictionary.class.isAssignableFrom(type.cls())) {
EvaluatedType type1 = getParameterType( type, "put", 0 ) ;
TypeConverter firstTc = mom.getTypeConverter( type1 ) ;
EvaluatedType type2 = getReturnType( type, "put" ) ;
TypeConverter secondTc = mom.getTypeConverter( type2 ) ;
result = new TypeConverterMapBase( type, firstTc, secondTc ) {
@SuppressWarnings("unchecked")
protected Table getTable( Object obj ) {
if (obj == null) {
return emptyTable() ;
} else {
return new TableDictionaryImpl( (Dictionary)obj ) ;
}
}
} ;
} else {
result = handleAsString( type ) ;
}
return result ;
}
@SuppressWarnings({"unchecked"})
private static TypeConverter handleAsString(
final EvaluatedClassDeclaration cls ) {
Constructor tcons ;
try {
SecurityManager sman = System.getSecurityManager() ;
if (sman == null) {
tcons = cls.cls().getDeclaredConstructor(String.class) ;
} else {
tcons = Algorithms.doPrivileged(
new Algorithms.Action<Constructor>() {
public Constructor run() throws Exception {
return cls.cls().getDeclaredConstructor(String.class ) ;
}
}) ;
}
} catch (Exception exc) {
Exceptions.self.noStringConstructorAvailable( exc, cls.name() ) ;
tcons = null ;
}
final Constructor cons = tcons ;
return new TypeConverterImpl( cls, SimpleType.STRING ) {
public Object toManagedEntity( Object obj ) {
if (obj == null) {
return NULL_STRING ;
} else {
return obj.toString() ;
}
}
@Override
public Object fromManagedEntity( final Object entity ) {
if (entity == null) {
return null ;
}
if (cons == null) {
throw Exceptions.self.noStringConstructor(cls.cls());
}
try {
final String str = (String) entity;
return cons.newInstance(str);
} catch (InstantiationException exc) {
throw Exceptions.self.stringConversionError(cls.cls(), exc ) ;
} catch (IllegalAccessException exc) {
throw Exceptions.self.stringConversionError(cls.cls(), exc ) ;
} catch (InvocationTargetException exc) {
throw Exceptions.self.stringConversionError(cls.cls(), exc ) ;
}
}
} ;
}
private static class EnumerationAdapter<T> implements Iterator<T> {
final private Enumeration<T> enumeration ;
public EnumerationAdapter( final Enumeration<T> en ) {
this.enumeration = en ;
}
public boolean hasNext() {
return enumeration.hasMoreElements() ;
}
public T next() {
return enumeration.nextElement() ;
}
public void remove() {
throw Exceptions.self.removeNotSupported() ;
}
}
public static class TypeConverterPlaceHolderImpl implements TypeConverter {
private EvaluatedType et ;
public TypeConverterPlaceHolderImpl( EvaluatedType type ) {
et = type ;
}
public EvaluatedType getDataType() {
throw Exceptions.self.recursiveTypesNotSupported( et ) ;
}
public OpenType getManagedType() {
throw Exceptions.self.recursiveTypesNotSupported( et ) ;
}
public Object toManagedEntity( Object obj ) {
throw Exceptions.self.recursiveTypesNotSupported( et ) ;
}
public Object fromManagedEntity( Object entity ) {
throw Exceptions.self.recursiveTypesNotSupported( et ) ;
}
public boolean isIdentity() {
throw Exceptions.self.recursiveTypesNotSupported( et ) ;
}
}
private abstract static class TypeConverterListBase
extends TypeConverterImpl {
final TypeConverter memberTc ;
public TypeConverterListBase( final EvaluatedType dataType,
final TypeConverter memberTc ) {
super( dataType, makeArrayType( memberTc.getManagedType() ) ) ;
this.memberTc = memberTc ;
}
@SuppressWarnings("unchecked")
private static ArrayType makeArrayType( final OpenType ot ) {
try {
return getArrayType( ot ) ;
} catch (OpenDataException exc) {
throw Exceptions.self.openTypeInArrayTypeException( ot, exc) ;
}
}
protected abstract Iterator getIterator( Object obj ) ;
public Object toManagedEntity( final Object obj ) {
final Iterator iter = getIterator( obj ) ;
final List<Object> list = new ArrayList<Object>() ;
while (iter.hasNext()) {
list.add( iter.next() ) ;
}
final Class cclass = getJavaClass( memberTc.getManagedType() ) ;
final Object result = Array.newInstance( cclass, list.size() ) ;
int ctr = 0 ;
for (Object elem : list) {
final Object mappedElem = memberTc.toManagedEntity( elem ) ;
Array.set( result, ctr++, mappedElem ) ;
}
return result ;
}
}
private interface Table<K,V> extends Iterable<K> {
V get( K key ) ;
}
private static class TableMapImpl<K,V> implements Table<K,V> {
final private Map<K,V> map ;
public TableMapImpl( final Map<K,V> map ) {
this.map = map ;
}
public Iterator<K> iterator() {
return map.keySet().iterator() ;
}
public V get( final K key ) {
return map.get( key ) ;
}
}
private static class TableDictionaryImpl<K,V> implements Table<K,V> {
final private Dictionary<K,V> dict ;
public TableDictionaryImpl( final Dictionary<K,V> dict ) {
this.dict = dict ;
}
@SuppressWarnings("unchecked")
public Iterator<K> iterator() {
return new EnumerationAdapter( dict.keys() ) ;
}
public V get( final K key ) {
return dict.get( key ) ;
}
}
private abstract static class TypeConverterMapBase
extends TypeConverterImpl {
final private TypeConverter keyTypeConverter ;
final private TypeConverter valueTypeConverter ;
public TypeConverterMapBase( EvaluatedType dataType,
TypeConverter keyTypeConverter, TypeConverter valueTypeConverter ) {
super( dataType, makeMapTabularType( keyTypeConverter,
valueTypeConverter ) ) ;
this.keyTypeConverter = keyTypeConverter ;
this.valueTypeConverter = valueTypeConverter ;
}
private static TabularType makeMapTabularType(
final TypeConverter firstTc, final TypeConverter secondTc ) {
final String mapType = firstTc + "->" + secondTc ;
final String[] itemNames = new String[] { "key", "value" } ;
final String description = Exceptions.self.rowTypeDescription(
mapType) ;
final String[] itemDescriptions = new String[] {
Exceptions.self.keyFieldDescription(mapType),
Exceptions.self.valueFieldDescription(mapType)
} ;
final OpenType[] itemTypes = new OpenType[] {
firstTc.getManagedType(), secondTc.getManagedType()
} ;
try {
final CompositeType rowType = new CompositeType( mapType,
description, itemNames, itemDescriptions, itemTypes ) ;
final String[] keys = new String[] { "key" } ;
final String tableName =
Exceptions.self.tableName( mapType ) ;
final String tableDescription =
Exceptions.self.tableDescription( mapType ) ;
final TabularType result = new TabularType( tableName,
tableDescription, rowType, keys ) ;
return result ;
} catch (OpenDataException exc) {
throw Exceptions.self.exceptionInMakeMapTabularType(exc) ;
}
}
protected abstract Table getTable( Object obj ) ;
@SuppressWarnings("unchecked")
public Object toManagedEntity( Object obj ) {
try {
final Table table = getTable( obj ) ;
final TabularType ttype = (TabularType)getManagedType() ;
final CompositeType ctype = ttype.getRowType() ;
final TabularData result = new TabularDataSupport( ttype ) ;
for (Object key : table) {
@SuppressWarnings("unchecked")
final Object value = table.get( key ) ;
final Object mappedKey =
keyTypeConverter.toManagedEntity( key ) ;
final Object mappedValue =
valueTypeConverter.toManagedEntity( value ) ;
final Map items = new HashMap() ;
items.put( "key", mappedKey ) ;
items.put( "value", mappedValue ) ;
CompositeDataSupport cdata = new CompositeDataSupport(
ctype, items ) ;
result.put( cdata ) ;
}
return result ;
} catch (OpenDataException exc) {
throw Exceptions.self.excInMakeMapTabularDataToManagedEntity(
exc ) ;
}
}
}
@DumpToString
protected final EvaluatedType dataType ;
@DumpToString
protected final OpenType managedType ;
protected TypeConverterImpl( final EvaluatedType dataType,
final OpenType managedType ) {
this.dataType = dataType ;
this.managedType = managedType ;
}
public final EvaluatedType getDataType() {
return dataType ;
}
public final OpenType getManagedType() {
return managedType ;
}
public abstract Object toManagedEntity( Object obj ) ;
public Object fromManagedEntity( Object entity ) {
throw Exceptions.self.openToJavaNotSupported(managedType, dataType) ;
}
public boolean isIdentity() {
return false ;
}
private String displayOpenType( OpenType otype ) {
if (otype instanceof SimpleType) {
SimpleType stype = (SimpleType)otype ;
return "SimpleType(" + stype.getTypeName() + ")" ;
} else if (otype instanceof ArrayType) {
ArrayType atype = (ArrayType)otype ;
return "ArrayType(" + displayOpenType( atype.getElementOpenType() )
+ "," + atype.getDimension() + ")" ;
} else if (otype instanceof CompositeType) {
CompositeType ctype = (CompositeType)otype ;
return "CompositeType(" + ctype.getTypeName() + ")" ;
} else if (otype instanceof TabularType) {
TabularType ttype = (TabularType)otype ;
return "TabularType(" + ttype.getTypeName() + ","
+ "rowType=" + ttype.getRowType()
+ "indexNames=" + ttype.getIndexNames() + ")" ;
} else {
return "UNKNOWN(" + otype + ")" ;
}
}
@Override
public String toString() {
return "TypeConverter[dataType=" + dataType
+ ",managedType=" + displayOpenType( managedType ) + "]" ;
}
}