Re: [Simple-support] Support for almost-primitive types, Converters in attributes and Arrays in att
Brought to you by:
niallg
|
From: Raphael J. <rap...@gm...> - 2011-06-14 13:26:02
|
2011/5/26 Niall Gallagher <gal...@ya...>
> Hi,
>
> Yes, it does work for attributes. Check out the test cases, in particular
> PrimitiveArrayTransformTest.
>
> Niall
Sorry, you were right, it works for attributes.
But it works only for arrays ('[]'), not for Lists or Collections.
However, there should not be any fundamental differences between those two
types, they are still "a bunch of something".
This does not work :
@Attribute(name="group-by", required=false)
private List<Field> groupBy = new List<Field>();
Also, I have implemented a core Converter and integrated it in the framework
so that all objects with a "Constructor(String value)" are serialized out of
the box without the need of any further work, annotation, or strategy. I
have integrated it only for parsing attributes at the moment; not for
elements.
I hope this can be useful to someone.
Regards,
Raphael
===== The converter
==================================================================
package org.simpleframework.xml.core;
import java.lang.reflect.Constructor;
import org.simpleframework.xml.stream.InputNode;
import org.simpleframework.xml.stream.OutputNode;
/**
* Converter for classes that have a constructor with a single String.
* It uses this constructor for new instances, and toString for
serialiasing.
*/
public class StringConstructorConverter implements Converter {
// ----------------------------------------------------
// Static method
// ----------------------------------------------------
static public boolean hasStringConstructor(Class<?> type) {
return (getStringConstructor(type) != null);
}
// ----------------------------------------------------
// Attributes
// ----------------------------------------------------
Class<?> type;
// ----------------------------------------------------
// Private methods
// ----------------------------------------------------
static private Constructor<?> getStringConstructor(Class<?> type) {
try {
return type.getConstructor(String.class);
} catch (NoSuchMethodException e) {
return null;
}
}
// ----------------------------------------------------
// Constructor
// ----------------------------------------------------
public StringConstructorConverter(Class<?> type) {
this.type = type;
}
/** Instantiate the object with the string constructor */
public Object read(InputNode node) throws Exception {
return getStringConstructor(this.type).newInstance(node.getValue());
}
/** Use "toString" as the representation of this object */
public void write(OutputNode node, Object value) throws Exception {
node.setValue(value.toString());
}
/** This should not happen, ginore the existing value */
public Object read(InputNode node, Object value) throws Exception {
return this.read(node);
}
/** Do not validate, we'll see ... */
public boolean validate(InputNode node) throws Exception {
return true;
}
}
============ Integration into the Framework : AttributeLabel#getConverter
====================
public Converter getConverter(Context context) throws Exception {
String ignore = getEmpty(context);
Type type = getContact();
if(!context.isPrimitive(type)) {
if (!StringConstructorConverter.hasStringConstructor(type.getType()))
{
throw new AttributeException("Cannot use %s to represent %s", label,
type);
} else {
return new StringConstructorConverter(type.getType());
}
}
return new Primitive(context, type, ignore);
}
=================================================================================================
|