Re: [Simple-support] Serialize and deserialize undefined Xml attributes into a HashMap<String, Stri
Brought to you by:
niallg
|
From: Christian K. <c....@sp...> - 2012-11-16 17:41:48
|
Ah ok, thanks.
Now I tried it with two converters.
*The first one is this:*
public class HashMapConverter implements Converter<HashMap<String, String>>
{
@Override
public HashMap<String, String> read(InputNode node) throws Exception
{
// Is never called
return null;
}
@Override
public void write(OutputNode node, HashMap<String, String> hashMap)
throws Exception
{
OutputNode parent = node.getParent();
for (Entry<String, String> entry : hashMap.entrySet())
{
//Does not work
parent.setAttribute(entry.getKey(), entry.getValue());
}
node.remove();
}
}
This is the car class:
@Root(strict = false, name = "Car")
public class Car
{
@Attribute
public double length;
@Attribute
public String color;
@Attribute
public int nrOfDoors;
@ElementMap(required = false)
public HashMap<String, String> furtherAttributes;
}
And this how I set the converter. Set the converter by AnnotationStategy
and @Convert never works.
public void testCar() throws Exception
{
Car car = new Car();
car.color = "red";
car.length = 4.3;
car.nrOfDoors = 4;
car.furtherAttributes = new HashMap<String, String>();
car.furtherAttributes.put("fuelConsumption", "7.8");
car.furtherAttributes.put("fopSpeed", "190");
Registry registry = new Registry();
RegistryStrategy strategy = new RegistryStrategy(registry);
registry.bind(HashMap.class, HashMapConverter.class);
//registry.bind(Car.class, CarConverter.class);
StringWriter stringwriter = new StringWriter();
Serializer serializer = new Persister(strategy);
serializer.write(car, stringwriter);
String xml = stringwriter.toString();
}
But on this try, the read method of the converter is never called (There
is not furtherAttributes xml element) and I can't set attributes on the
parent node. (See comments in the HashMapConverter)
The second try was a converter for the car class:
public class CarConverter implements Converter<Car>
{
@Override
public Car read(InputNode node) throws Exception
{
Car car = new Car();
car.furtherAttributes = new HashMap<String, String>();
ArrayList<String> attributesWithAnnotation = new
ArrayList<String>();
for (Field field : car.getClass().getFields())
{
if (field.getAnnotation(Attribute.class) != null)
{
String name = field.getAnnotation(Attribute.class).name();
if (name == null || name.equals(""))
{
name = field.getName();
}
attributesWithAnnotation.add(name);
}
}
for (String entry : node.getAttributes())
{
if (!attributesWithAnnotation.contains(entry))
{
String furtherAttributeKey = entry;
String furtherAttributeValue = node.getAttribute(entry)
.getValue();
car.furtherAttributes.put(furtherAttributeKey,
furtherAttributeValue);
}
}
return car;
}
@Override
public void write(OutputNode outputNode, Car car) throws Exception
{
if (car.furtherAttributes != null &&
car.furtherAttributes.size() > 0)
{
for (Entry<String, String> entry :
car.furtherAttributes.entrySet())
{
outputNode.setAttribute(entry.getKey(), entry.getValue());
}
}
}
}
But there is the problem that only futherAttributes are serialised and
deserialised correctly.
In the read method I create the car object myself. So color, length and
the other field have the default value.
But I want, that all that fields are filled by SimpleXml.
What converter do you recommend?
Am 15.11.2012 23:45, schrieb Niall Gallagher - Yieldbroker:
> Sorry, my mistake I should have suggested a converter. Here you can use @Convert annotation like so.
>
> @Convert(CarConverter.class)
> Map<String, String> var;
>
> Take a look at the following converters
>
> https://simple.svn.sf.net/svnroot/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/convert/HideEnclosingConverterTest.java
> https://simple.svn.sf.net/svnroot/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/convert/ExampleConverters.java
>
>
> -----Original Message-----
> From: Christian Klotz [mailto:c....@sp...]
> Sent: Friday, 16 November 2012 12:28 AM
> To: Niall Gallagher - Yieldbroker
> Cc: sim...@li...
> Subject: Re: [Simple-support] Serialize and deserialize undefined Xml attributes into a HashMap<String, String>
>
> Hi Niall,
>
> thanks for your quick response.
>
>
> Now I have implemented an Visitor.
> In the read method, I can get a nodeMap with all xml attributes.
>
> I can also detect via refection which attributes have the annotation @Attribute.
> All other attributes should be stored in the HashMap "furtherAttributes".
>
> But I don't known how to put them into the HashMap "furtherAttributes".
> I do not have the resulting car object. Do you have any tip?
>
> public class AnyAttributesVisitor implements Visitor {
> @Override
> public void read(Type type, NodeMap<InputNode> nodeMap) throws Exception
> {
> // nodeMap contains all xml attributes of the car xml
> // Content is:
> // {color=attribute color='red', length=attribute length='4.3',
> // nrOfDoors=attribute nrOfDoors='4', fuelConsumption=attribute
> // fuelConsumption='7.8', topSpeed=attribute topSpeed='190'}
>
>
> //Detect attributes with Annotation @Attribute
> ArrayList<String> attributesWithAnnotation = new
> ArrayList<String>();
> for (Field field : type.getType().getFields())
> {
> if (field.getAnnotation(Attribute.class) != null)
> {
> String name = field.getAnnotation(Attribute.class).name();
>
> if (name == null || name.equals(""))
> {
> name = field.getName();
> }
>
> attributesWithAnnotation.add(name);
> }
> }
>
> for (String entry : nodeMap.getNode().getAttributes())
> {
> if (!attributesWithAnnotation.contains(entry))
> {
> String furtherAttributeKey = entry;
> String furtherAttributeValue = nodeMap.getNode()
> .getAttribute(entry).getValue();
>
> // TODO: Add Key and Value to the Hashmap furtherAttributes
>
> nodeMap.remove(furtherAttributeKey);
> }
> }
> }
>
> @Override
> public void write(Type type, NodeMap<OutputNode> nodeMap) throws
> Exception
> {
>
> }
> }
>
> This is my test case:
> public void testCarDeserialisation() throws Exception
> {
> String xml = "<Car color=\"red\" length=\"4.3\" nrOfDoors=\"4\"
> fuelConsumption=\"7.8\" topSpeed=\"190\" />";
>
> Serializer serializer = new Persister(new VisitorStrategy(
> new AnyAttributesVisitor()));
>
> Car car = serializer.read(Car.class, xml);
> }
>
> Thanks Christian
>
> Am 15.11.2012 00:33, schrieb Niall Gallagher - Yieldbroker:
>> I think a Visitor would be simpler than a Strategy, there are many test cases doing this very thing. Just browse through them, I am sure you will find a template. You can browse them here http://simple.svn.sourceforge.net/viewvc/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/
>>
>> -----Original Message-----
>> From: Christian Klotz [mailto:c....@sp...]
>> Sent: Wednesday, 14 November 2012 8:26 PM
>> To: sim...@li...
>> Subject: [Simple-support] Serialize and deserialize undefined Xml attributes into a HashMap<String, String>
>>
>> Hi SimpleXml Team,
>>
>> I use SimpleXml frequently on android and it is great.
>>
>> Now I have a question how to do that job:
>> All XML attributes that are not defined in the Java class with @Attribute should be serialized and deserialized into a HashMap<String,String>.
>>
>> Here is an example:
>>
>> This is out test class "Car"
>>
>> @Root(strict = false, name = "Car")
>> public class Car
>> {
>> @Attribute
>> public double length;
>>
>> @Attribute
>> public String color;
>>
>> @Attribute
>> public int nrOfDoors;
>>
>> public HashMap<String, String> furtherAttributes = new HashMap<String, String>(); }
>>
>> And this is the serialization test method:
>> public void testCar() throws Exception
>> {
>> Car car = new Car();
>>
>> car.color = "red";
>> car.length = 4.3;
>> car.nrOfDoors = 4;
>>
>> car.furtherAttributes.put("fuelConsumption", "7.8");
>> car.furtherAttributes.put("topSpeed", "190");
>>
>> Serializer serializer = new Persister();
>> StringWriter stringwriter = new StringWriter();
>> serializer.write(car, stringwriter);
>>
>> String xml = stringwriter.toString();
>> }
>>
>>
>> The result of the serialization is:
>> <Car color="red" length="4.3" nrOfDoors="4"/>
>>
>> So the furtherAttributes of the HashMap are missing. The result should be:
>> <Car color="red" length="4.3" nrOfDoors="4" fuelConsumption="7.8"
>> topSpeed="190" />
>>
>> And the way back should also work:
>> So if we have a xml like this:
>> <Car color="green" length="3.3" nrOfDoors="2" topSpeed="190" brand="audi" /> After the deserialization the HashMap "furtherAttributes" should have the two undefined attributes "topSpeed" and "brand".
>>
>> I already read the mailing list and some SimpleXml test cases.
>> So I try implement a new Strategy to solve that problem.
>>
>> The AnyAttributeRegistryStrategy looks for classes with annotation "AnyClass" and inside that class searches for the annotation "Any".
>> The annotation "Any" is used to tag the HashMap, where the futher attributes should be serialized to.
>>
>> public class AnyAttributeRegistryStrategy extends RegistryStrategy {
>> public AnyAttributeRegistryStrategy(Registry registry)
>> {
>> super(registry);
>> }
>>
>> @Override
>> public boolean write(Type type, Object value, NodeMap<OutputNode> node,
>> @SuppressWarnings("rawtypes") Map map) throws Exception
>> {
>>
>> if (value.getClass().getAnnotation(AnyClass.class) != null)
>> {
>> for (Field field : value.getClass().getFields())
>> {
>> if (field.getAnnotation(Any.class) != null)
>> {
>> Object mapObject = field.get(value);
>> if (mapObject instanceof Map<?, ?>)
>> {
>> Map<?, ?> keyValueMap = (Map<?, ?>) mapObject;
>> for (Entry<?, ?> keyValuePair :
>> keyValueMap.entrySet())
>> {
>> if (keyValuePair.getKey() != null
>> && keyValuePair.getValue() != null)
>> {
>> node.getNode().setAttribute( keyValuePair.getKey().toString(), keyValuePair.getValue().toString());
>> }
>> }
>>
>> }
>> }
>> }
>> }
>>
>> return super.write(type, value, node, map);
>> }
>> }
>>
>> And this is the Car class with the new annotations:
>> @AnyClass
>> @Root(strict = false, name = "Car")
>> public class Car
>> {
>> @Attribute
>> public double length;
>>
>> @Attribute
>> public String color;
>>
>> @Attribute
>> public int nrOfDoors;
>>
>> @Any
>> public HashMap<String, String> furtherAttributes = new HashMap<String, String>(); }
>>
>> Now the serialisation of the class to xml works.
>> But I do not have a correctly working solution for the deserialisation.
>> Do you have any ideas?
>>
>> Thanks for you help
>>
>> Christian Klotz
>>
>>
>>
>>
>>
>>
>> ------------------------------------------------------------------------------
>> Monitor your physical, virtual and cloud infrastructure from a single web console. Get in-depth insight into apps, servers, databases, vmware, SAP, cloud infrastructure, etc. Download 30-day Free Trial.
>> Pricing starts from $795 for 25 servers or applications!
>> http://p.sf.net/sfu/zoho_dev2dev_nov
>> _______________________________________________
>> Simple-support mailing list
>> Sim...@li...
>> https://lists.sourceforge.net/lists/listinfo/simple-support
>>
>
--
Mit freundlichen Grüßen / Kind regards
Christian Klotz
Software Engineer
SPEDION GmbH
Industriestraße 7
D - 63829 Krombach
Fon: +49 (0) 6024 / 50990-132
Fax: +49 (0) 6024 / 50990-121
mailto:c....@sp...
SPEDION GmbH - Industriestraße 7 - 63829 Krombach - Germany
Amtsgericht Aschaffenburg, HRB 8647
Geschäftsführer: Günter Englert, Wolfram Grohse
|