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 22. January 2005 by Joe Walnes
011: */
012: package com.thoughtworks.xstream.mapper;
013:
014: import com.thoughtworks.xstream.alias.ClassMapper;
015:
016: import java.util.Arrays;
017: import java.util.Collection;
018:
019: /**
020: * Mapper that detects arrays and changes the name so it can identified as an array
021: * (for example Foo[] gets serialized as foo-array). Supports multi-dimensional arrays.
022: *
023: * @author Joe Walnes
024: */
025: public class ArrayMapper extends MapperWrapper {
026:
027: private final static Collection BOXED_TYPES = Arrays
028: .asList(new Class[] { Boolean.class, Byte.class,
029: Character.class, Short.class, Integer.class,
030: Long.class, Float.class, Double.class });
031:
032: public ArrayMapper(Mapper wrapped) {
033: super (wrapped);
034: }
035:
036: /**
037: * @deprecated As of 1.2, use {@link #ArrayMapper(Mapper)}
038: */
039: public ArrayMapper(ClassMapper wrapped) {
040: this ((Mapper) wrapped);
041: }
042:
043: public String serializedClass(Class type) {
044: StringBuffer arraySuffix = new StringBuffer();
045: while (type.isArray()) {
046: type = type.getComponentType();
047: arraySuffix.append("-array");
048: }
049: String name = boxedTypeName(type);
050: if (name == null) {
051: name = super .serializedClass(type);
052: }
053: if (arraySuffix.length() > 0) {
054: return name + arraySuffix;
055: } else {
056: return name;
057: }
058: }
059:
060: public Class realClass(String elementName) {
061: int dimensions = 0;
062:
063: // strip off "-array" suffix
064: while (elementName.endsWith("-array")) {
065: elementName = elementName.substring(0,
066: elementName.length() - 6); // cut off -array
067: dimensions++;
068: }
069:
070: if (dimensions > 0) {
071: Class componentType = primitiveClassNamed(elementName);
072: if (componentType == null) {
073: componentType = super .realClass(elementName);
074: }
075: try {
076: return arrayType(dimensions, componentType);
077: } catch (ClassNotFoundException e) {
078: throw new CannotResolveClassException(elementName
079: + " : " + e.getMessage());
080: }
081: } else {
082: return super .realClass(elementName);
083: }
084: }
085:
086: private Class arrayType(int dimensions, Class componentType)
087: throws ClassNotFoundException {
088: StringBuffer className = new StringBuffer();
089: for (int i = 0; i < dimensions; i++) {
090: className.append('[');
091: }
092: if (componentType.isPrimitive()) {
093: className
094: .append(charThatJavaUsesToRepresentPrimitiveArrayType(componentType));
095: return Class.forName(className.toString());
096: } else {
097: className.append('L').append(componentType.getName())
098: .append(';');
099: return Class.forName(className.toString(), false,
100: componentType.getClassLoader());
101: }
102: }
103:
104: private Class primitiveClassNamed(String name) {
105: return name.equals("void") ? Void.TYPE
106: : name.equals("boolean") ? Boolean.TYPE : name
107: .equals("byte") ? Byte.TYPE : name
108: .equals("char") ? Character.TYPE : name
109: .equals("short") ? Short.TYPE : name
110: .equals("int") ? Integer.TYPE : name
111: .equals("long") ? Long.TYPE : name
112: .equals("float") ? Float.TYPE : name
113: .equals("double") ? Double.TYPE : null;
114: }
115:
116: private char charThatJavaUsesToRepresentPrimitiveArrayType(
117: Class primvCls) {
118: return (primvCls == boolean.class) ? 'Z'
119: : (primvCls == byte.class) ? 'B'
120: : (primvCls == char.class) ? 'C'
121: : (primvCls == short.class) ? 'S'
122: : (primvCls == int.class) ? 'I'
123: : (primvCls == long.class) ? 'J'
124: : (primvCls == float.class) ? 'F'
125: : (primvCls == double.class) ? 'D'
126: : 0;
127: }
128:
129: private String boxedTypeName(Class type) {
130: return BOXED_TYPES.contains(type) ? type.getName() : null;
131: }
132: }
|