/* Copyright (c) 2007 Wayne Meissner, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/** Provide custom mappings to and from native types. The default lookup
* checks classes corresponding to converters in the order added; if the
* class to be converted is an instance of the converter's registered class,
* the converter will be used.<p>
* Derived classes should install additional converters using
* {@link #addToNativeConverter}
* and/or {@link #addFromNativeConverter} in the default constructor. Classes
* for primitive types will automatically register for the corresponding
* Object type and vice versa (i.e. you don't have to register both
* <code>int.class</code> and <code>Integer.class</code>).
* If you want different mapping behavior than the default, simply override
* {@link #getToNativeConverter} and {@link #getFromNativeConverter}.
* @see Library#OPTION_TYPE_MAPPER
*/
public class DefaultTypeMapper implements TypeMapper {
private static class Entry {
public Class type;
public Object converter;
public Entry(Class type, Object converter) {
this.type = type;
this.converter = converter;
}
}
private List toNativeConverters = new ArrayList();
private List fromNativeConverters = new ArrayList();
private Class getAltClass(Class cls) {
if (cls == Boolean.class) {
return boolean.class;
}
else if (cls == boolean.class) {
return Boolean.class;
}
else if (cls == Byte.class) {
return byte.class;
}
else if (cls == byte.class) {
return Byte.class;
}
else if (cls == Character.class) {
return char.class;
}
else if (cls == char.class) {
return Character.class;
}
else if (cls == Short.class) {
return short.class;
}
else if (cls == short.class) {
return Short.class;
}
else if (cls == Integer.class) {
return int.class;
}
else if (cls == int.class) {
return Integer.class;
}
else if (cls == Long.class) {
return long.class;
}
else if (cls == long.class) {
return Long.class;
}
else if (cls == Float.class) {
return float.class;
}
else if (cls == float.class) {
return Float.class;
}
else if (cls == Double.class) {
return double.class;
}
else if (cls == double.class) {
return Double.class;
}
return null;
}
/** Add a {@link ToNativeConverter} to define the conversion into a native
* type from arguments of the given Java type. Converters are
* checked for in the order added.
*/
public void addToNativeConverter(Class cls, ToNativeConverter converter) {
toNativeConverters.add(new Entry(cls, converter));
Class alt = getAltClass(cls);
if (alt != null) {
toNativeConverters.add(new Entry(alt, converter));
}
}
/** Add a {@link FromNativeConverter} to convert a native result type into the
* given Java type. Converters are checked for in the order added.
*/
public void addFromNativeConverter(Class cls, FromNativeConverter converter) {
fromNativeConverters.add(new Entry(cls, converter));
Class alt = getAltClass(cls);
if (alt != null) {
fromNativeConverters.add(new Entry(alt, converter));
}
}
/** Add a {@link TypeConverter} to provide bidirectional mapping between
* a native and Java type.
*/
protected void addTypeConverter(Class cls, TypeConverter converter) {
addFromNativeConverter(cls, converter);
addToNativeConverter(cls, converter);
}
private Object lookupConverter(Class javaClass, List converters) {
for (Iterator i=converters.iterator();i.hasNext();) {
Entry entry = (Entry)i.next();
if (entry.type.isAssignableFrom(javaClass)) {
return entry.converter;
}
}
return null;
}
/* (non-Javadoc)
* @see com.sun.jna.TypeMapper#getFromNativeConverter(java.lang.Class)
*/
public FromNativeConverter getFromNativeConverter(Class javaType) {
return (FromNativeConverter)lookupConverter(javaType, fromNativeConverters);
}
/* (non-Javadoc)
* @see com.sun.jna.TypeMapper#getToNativeConverter(java.lang.Class)
*/
public ToNativeConverter getToNativeConverter(Class javaType) {
return (ToNativeConverter)lookupConverter(javaType, toNativeConverters);
}
}