01: /*
02: * Copyright (C) 2005 Joe Walnes.
03: * Copyright (C) 2006, 2007 XStream Committers.
04: * All rights reserved.
05: *
06: * The software in this package is published under the terms of the BSD
07: * style license a copy of which has been included with this distribution in
08: * the LICENSE.txt file.
09: *
10: * Created on 06. April 2005 by Joe Walnes
11: */
12:
13: // ***** READ THIS *****
14: // This class will only compile with JDK 1.5.0 or above as it test Java enums.
15: // If you are using an earlier version of Java, just don't try to build this class. XStream should work fine without it.
16: package com.thoughtworks.xstream.converters.enums;
17:
18: import com.thoughtworks.xstream.converters.collections.MapConverter;
19: import com.thoughtworks.xstream.converters.MarshallingContext;
20: import com.thoughtworks.xstream.converters.UnmarshallingContext;
21: import com.thoughtworks.xstream.mapper.Mapper;
22: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
23: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
24: import com.thoughtworks.xstream.core.util.Fields;
25:
26: import java.util.EnumMap;
27: import java.lang.reflect.Field;
28:
29: /**
30: * Serializes an Java 5 EnumMap, including the type of Enum it's for.
31: *
32: * @author Joe Walnes
33: */
34: public class EnumMapConverter extends MapConverter {
35:
36: private final static Field typeField;
37: static {
38: // field name is "keyType" in Sun JDK, but different in IKVM
39: Field assumedTypeField = null;
40: Field[] fields = EnumMap.class.getDeclaredFields();
41: for (int i = 0; i < fields.length; i++) {
42: if (fields[i].getType() == Class.class) {
43: // take the fist member of type "Class"
44: assumedTypeField = fields[i];
45: assumedTypeField.setAccessible(true);
46: break;
47: }
48: }
49: if (assumedTypeField == null) {
50: throw new ExceptionInInitializerError(
51: "Cannot detect element type of EnumMap");
52: }
53: typeField = assumedTypeField;
54: }
55:
56: public EnumMapConverter(Mapper mapper) {
57: super (mapper);
58: }
59:
60: public boolean canConvert(Class type) {
61: return type == EnumMap.class;
62: }
63:
64: public void marshal(Object source, HierarchicalStreamWriter writer,
65: MarshallingContext context) {
66: Class type = (Class) Fields.read(typeField, source);
67: writer.addAttribute(mapper().aliasForAttribute("enum-type"),
68: mapper().serializedClass(type));
69: super .marshal(source, writer, context);
70: }
71:
72: public Object unmarshal(HierarchicalStreamReader reader,
73: UnmarshallingContext context) {
74: Class type = mapper().realClass(
75: reader.getAttribute(mapper().aliasForAttribute(
76: "enum-type")));
77: EnumMap map = new EnumMap(type);
78: populateMap(reader, context, map);
79: return map;
80: }
81: }
|