1 package net.sourceforge.jparam.conversion.converters;
2
3 import net.sourceforge.jparam.JParamException;
4 import net.sourceforge.jparam.conversion.weights.ScalarConversionWeight;
5 import net.sourceforge.jparam.typename.TypeNameRegistry;
6
7 /***
8 * @author Ron_Sidi
9 *
10 * The base class for all converters, it implements all the basic funcionality
11 * of a converter.
12 *
13 */
14 public abstract class AbstractConverter implements IConverter {
15
16 /***
17 * the source and target classes, and conversion weight, subclasses
18 * must initialize these in order to index the converter correctly
19 */
20 Class sourceClass;
21
22 Class targetClass;
23
24 ScalarConversionWeight conversionWeight;
25
26
27
28
29 public Class getTargetClass() {
30 return targetClass;
31 }
32
33
34
35
36 public ScalarConversionWeight getWeight() {
37 return conversionWeight;
38 }
39
40
41
42
43 public Class getSourceClass() {
44 return sourceClass;
45 }
46
47
48
49
50 public Object convert(Object o) throws JParamException {
51
52 if (!sourceClass.isInstance(o)) {
53 throw new JParamException("Cannot convert from: " + o.getClass()
54 + " supported class: " + sourceClass);
55 }
56
57 try {
58
59 Object ret = internalConvert(o);
60
61
62
63
64
65
66 if (!targetClass.isInstance(ret)) {
67 throw new JParamException("Converter returned invalid class: " + ret.getClass()
68 + " expected class: " + targetClass + "\nReturned value: " + ret);
69 }
70 return ret;
71 } catch (JParamException e) {
72
73
74 throw e;
75 } catch (Exception e) {
76
77 throw new JParamException(
78 "Unexpected error occured while converting: " + o + " to: "
79 + targetClass, e);
80 }
81 }
82
83 /***
84 * Internal conversion method, all subclasses must implement the actual
85 * conversion logic here
86 * <p>
87 * No tests are needed since the given object is of the expected type
88 *
89 * @param o An object instanceof <code>getSourceClass</code>
90 * @return An object instanceof <code>getTargetClass</code>
91 * @throws Exception If there was an error performing the conversion
92 */
93 protected abstract Object internalConvert(Object o) throws Exception;
94
95
96
97
98 public String toString() {
99 StringBuffer result = new StringBuffer();
100 result.append(toConversionString());
101 result.append("(");
102 result.append(conversionWeight);
103 result.append(")");
104
105 return result.toString();
106 }
107
108 public String toConversionString() {
109 StringBuffer result = new StringBuffer();
110 try {
111
112 result.append(TypeNameRegistry.getInstance().getJParamTypeName(
113 sourceClass));
114 } catch (JParamException e) {
115
116 result.append(sourceClass.getName());
117 }
118
119 result.append(" -> ");
120
121 try {
122 result.append(TypeNameRegistry.getInstance().getJParamTypeName(
123 targetClass));
124 } catch (JParamException e) {
125 result.append(targetClass.getName());
126 }
127
128 return result.toString();
129 }
130
131 /***
132 * Tests if this converter is equal to the given converter, all validity
133 * checks of source/target/weight and class instance are performed in the
134 * <code>equal</code> method, the derived class can perform all casts with
135 * no verification
136 *
137 * The check must verify equality, and not similarity meaning to converters
138 * performing the same conversion with the same weight are not necesarily
139 * equal, for instance two conversion paths from the same source to the same
140 * target but not through the same types, will cause ambiguity if not equal
141 *
142 * @param o A converter to check for equality
143 * @return true if the converters are equal
144 */
145 protected abstract boolean converterEquals(IConverter o);
146
147
148
149
150 public int hashCode() {
151 return sourceClass.hashCode() * 37 + targetClass.hashCode() * 37
152 + conversionWeight.hashCode();
153 }
154
155 /***
156 * Verify all trivial tests, and let subclass to specific verification
157 * only
158 *
159 * @see java.lang.Object#equals(java.lang.Object)
160 */
161 public boolean equals(Object obj) {
162 if (!obj.getClass().equals(this.getClass())) {
163 return false;
164 }
165
166 AbstractConverter other = (AbstractConverter) obj;
167
168 if (!sourceClass.equals(other.sourceClass)) {
169 return false;
170 }
171 if (!targetClass.equals(other.targetClass)) {
172 return false;
173 }
174 if (!conversionWeight.equals(other.conversionWeight)) {
175 return false;
176 }
177
178 return converterEquals(other);
179 }
180 }