001: /*
002: * Copyright (C) 2005 Joe Walnes.
003: * Copyright (C) 2006, 2007 XStream Committers.
004: * All rights reserved.
005: *
006: * The software in this package is published under the terms of the BSD
007: * style license a copy of which has been included with this distribution in
008: * the LICENSE.txt file.
009: *
010: * Created on 06. April 2005 by Joe Walnes
011: */
012:
013: // ***** READ THIS *****
014: // This class will only compile with JDK 1.5.0 or above as it test Java enums.
015: // If you are using an earlier version of Java, just don't try to build this class. XStream should work fine without it.
016: package com.thoughtworks.xstream.converters.enums;
017:
018: import com.thoughtworks.xstream.converters.Converter;
019: import com.thoughtworks.xstream.converters.MarshallingContext;
020: import com.thoughtworks.xstream.converters.UnmarshallingContext;
021: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
022: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
023: import com.thoughtworks.xstream.mapper.Mapper;
024: import com.thoughtworks.xstream.core.util.Fields;
025:
026: import java.lang.reflect.Field;
027: import java.util.EnumSet;
028: import java.util.Iterator;
029:
030: /**
031: * Serializes a Java 5 EnumSet.
032: *
033: * @author Joe Walnes
034: * @author Jörg Schaible
035: */
036: public class EnumSetConverter implements Converter {
037:
038: private final static Field typeField;
039: static {
040: // field name is "elementType" in Sun JDK, but different in Harmony
041: Field assumedTypeField = null;
042: Field[] fields = EnumSet.class.getDeclaredFields();
043: for (int i = 0; i < fields.length; i++) {
044: if (fields[i].getType() == Class.class) {
045: // take the fist member of type "Class"
046: assumedTypeField = fields[i];
047: assumedTypeField.setAccessible(true);
048: break;
049: }
050: }
051: if (assumedTypeField == null) {
052: throw new ExceptionInInitializerError(
053: "Cannot detect element type of EnumSet");
054: }
055: typeField = assumedTypeField;
056: }
057:
058: private final Mapper mapper;
059:
060: public EnumSetConverter(Mapper mapper) {
061: this .mapper = mapper;
062: }
063:
064: public boolean canConvert(Class type) {
065: return EnumSet.class.isAssignableFrom(type);
066: }
067:
068: public void marshal(Object source, HierarchicalStreamWriter writer,
069: MarshallingContext context) {
070: EnumSet set = (EnumSet) source;
071: Class enumTypeForSet = (Class) Fields.read(typeField, set);
072: writer.addAttribute(mapper.aliasForAttribute("enum-type"),
073: mapper.serializedClass(enumTypeForSet));
074: writer.setValue(joinEnumValues(set));
075: }
076:
077: private String joinEnumValues(EnumSet set) {
078: boolean seenFirst = false;
079: StringBuffer result = new StringBuffer();
080: for (Iterator iterator = set.iterator(); iterator.hasNext();) {
081: Enum value = (Enum) iterator.next();
082: if (seenFirst) {
083: result.append(',');
084: } else {
085: seenFirst = true;
086: }
087: result.append(value.name());
088: }
089: return result.toString();
090: }
091:
092: public Object unmarshal(HierarchicalStreamReader reader,
093: UnmarshallingContext context) {
094: Class enumTypeForSet = mapper.realClass(reader
095: .getAttribute(mapper.aliasForAttribute("enum-type")));
096: EnumSet set = EnumSet.noneOf(enumTypeForSet);
097: String[] enumValues = reader.getValue().split(",");
098: for (int i = 0; i < enumValues.length; i++) {
099: String enumValue = enumValues[i];
100: if (enumValue.length() > 0) {
101: set.add(Enum.valueOf(enumTypeForSet, enumValue));
102: }
103: }
104: return set;
105: }
106:
107: }
|