001: /*
002: * Copyright (C) 2006 Joe Walnes.
003: * Copyright (C) 2006, 2007, 2008 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 20. February 2006 by Mauro Talevi
011: */
012: package com.thoughtworks.xstream.mapper;
013:
014: import java.lang.reflect.Field;
015: import java.util.HashMap;
016: import java.util.HashSet;
017: import java.util.Map;
018: import java.util.Set;
019:
020: import com.thoughtworks.xstream.converters.Converter;
021: import com.thoughtworks.xstream.converters.ConverterLookup;
022: import com.thoughtworks.xstream.converters.SingleValueConverter;
023:
024: /**
025: * Mapper that allows the usage of attributes for fields and corresponding
026: * types or specified arbitrary types. It is responsible for the lookup of the
027: * {@link SingleValueConverter} for item types and attribute names.
028: *
029: * @author Paul Hammant
030: * @author Ian Cartwright
031: * @author Jörg Schaible
032: * @author Mauro Talevi
033: * @author Guilherme Silveira
034: * @since 1.2
035: */
036: public class AttributeMapper extends MapperWrapper {
037:
038: private final Map fieldNameToTypeMap = new HashMap();
039: private final Set typeSet = new HashSet();
040: private ConverterLookup converterLookup;
041: private final Set fieldToUseAsAttribute = new HashSet();
042:
043: /**
044: * @deprecated since 1.3
045: */
046: public AttributeMapper(Mapper wrapped) {
047: this (wrapped, null);
048: }
049:
050: public AttributeMapper(Mapper wrapped,
051: ConverterLookup converterLookup) {
052: super (wrapped);
053: this .converterLookup = converterLookup;
054: }
055:
056: /**
057: * @deprecated since 1.3
058: */
059: public void setConverterLookup(ConverterLookup converterLookup) {
060: this .converterLookup = converterLookup;
061: }
062:
063: public void addAttributeFor(final String fieldName, final Class type) {
064: fieldNameToTypeMap.put(fieldName, type);
065: }
066:
067: public void addAttributeFor(final Class type) {
068: typeSet.add(type);
069: }
070:
071: protected SingleValueConverter getLocalConverterFromItemType(
072: Class type) {
073: Converter converter = converterLookup
074: .lookupConverterForType(type);
075: if (converter != null
076: && converter instanceof SingleValueConverter) {
077: return (SingleValueConverter) converter;
078: } else {
079: return null;
080: }
081: }
082:
083: /**
084: * @deprecated since 1.3, use {@link #getConverterFromItemType(String, Class, Class)}
085: */
086: public SingleValueConverter getConverterFromItemType(
087: String fieldName, Class type) {
088: if (fieldNameToTypeMap.get(fieldName) == type) {
089: return getLocalConverterFromItemType(type);
090: } else {
091: return null;
092: }
093: }
094:
095: public SingleValueConverter getConverterFromItemType(
096: String fieldName, Class type, Class definedIn) {
097: Field field = getField(definedIn, fieldName);
098: if (fieldToUseAsAttribute.contains(field)
099: || fieldNameToTypeMap.get(fieldName) == type
100: || typeSet.contains(type)) {
101: SingleValueConverter converter = getLocalConverterFromItemType(type);
102: if (converter != null) {
103: return converter;
104: }
105: }
106: return super .getConverterFromItemType(fieldName, type,
107: definedIn);
108: }
109:
110: /**
111: * @deprecated since 1.3, use {@link #getConverterFromItemType(String, Class, Class)}
112: */
113: public SingleValueConverter getConverterFromItemType(Class type) {
114: if (typeSet.contains(type)) {
115: return getLocalConverterFromItemType(type);
116: } else {
117: return null;
118: }
119: }
120:
121: /**
122: * @deprecated since 1.3, use {@link #getConverterFromAttribute(Class, String)}
123: */
124: public SingleValueConverter getConverterFromAttribute(
125: String attributeName) {
126: SingleValueConverter converter = null;
127: Class type = (Class) fieldNameToTypeMap.get(attributeName);
128: if (type != null) {
129: converter = getLocalConverterFromItemType(type);
130: }
131: return converter;
132: }
133:
134: public SingleValueConverter getConverterFromAttribute(
135: Class definedIn, String attribute) {
136: Field field = getField(definedIn, attribute);
137: Class type = null;
138: if (fieldToUseAsAttribute.contains(field)
139: || (type = (Class) fieldNameToTypeMap.get(attribute)) != null
140: || typeSet.contains(field.getType())) {
141: SingleValueConverter converter = getLocalConverterFromItemType(type == null ? field
142: .getType()
143: : type);
144: if (converter != null) {
145: return converter;
146: }
147: }
148: return super .getConverterFromAttribute(definedIn, attribute);
149: }
150:
151: /**
152: * Tells this mapper to use an attribute for this field.
153: *
154: * @param field the field itself
155: * @since 1.2.2
156: */
157: public void addAttributeFor(Field field) {
158: fieldToUseAsAttribute.add(field);
159: }
160:
161: /**
162: * Tells this mapper to use an attribute for this field.
163: *
164: * @param definedIn the declaring class of the field
165: * @param fieldName the name of the field
166: * @throws IllegalArgumentException if the field does not exist
167: * @since 1.3
168: */
169: public void addAttributeFor(Class definedIn, String fieldName) {
170: fieldToUseAsAttribute.add(getField(definedIn, fieldName));
171: }
172:
173: private Field getField(Class definedIn, String fieldName) {
174: try {
175: return definedIn.getDeclaredField(fieldName);
176: } catch (NoSuchFieldException e) {
177: throw new IllegalArgumentException(fieldName
178: + " is not a proper field of "
179: + definedIn.getName());
180: }
181: }
182:
183: }
|