1 package net.sourceforge.jparam.conversion.converters;
2
3 import java.util.Arrays;
4 import java.util.HashSet;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.Set;
8
9 import net.sourceforge.jparam.JParamException;
10 import net.sourceforge.jparam.conversion.weights.ScalarConversionWeight;
11 import net.sourceforge.jparam.typename.TypeNameRegistry;
12 import net.sourceforge.jparam.util.Utils;
13
14 public class PathConverter extends AbstractConverter {
15 IConverter[] path;
16
17 /***
18 * @param path
19 */
20 public PathConverter(IConverter[] path) {
21 setPath(path);
22 conversionWeight = path[0].getWeight();
23
24 for (int i = 1; i < path.length; i++) {
25 conversionWeight = new ScalarConversionWeight(conversionWeight,
26 path[i].getWeight());
27 }
28 }
29
30 private PathConverter(IConverter first, IConverter second) {
31 List localPath = new LinkedList();
32 if (first instanceof PathConverter) {
33 PathConverter firstPath = (PathConverter) first;
34 for (int i = 0; i < firstPath.path.length; i++) {
35 localPath.add(firstPath.path[i]);
36 }
37 } else {
38 localPath.add(first);
39 }
40
41 if (second instanceof PathConverter) {
42 PathConverter secondPath = (PathConverter) second;
43 for (int i = 0; i < secondPath.path.length; i++) {
44 localPath.add(secondPath.path[i]);
45 }
46 } else {
47 localPath.add(second);
48 }
49
50 setPath((IConverter[]) localPath.toArray(new IConverter[localPath
51 .size()]));
52 conversionWeight = new ScalarConversionWeight(first
53 .getWeight(), second.getWeight());
54 }
55
56 private void setPath(IConverter[] path) {
57 this.path = path;
58 this.sourceClass = path[0].getSourceClass();
59 this.targetClass = path[path.length - 1].getTargetClass();
60 }
61
62 public boolean equals(Object o) {
63 if (!o.getClass().equals(PathConverter.class)) {
64 return false;
65 }
66
67 PathConverter other = (PathConverter) o;
68
69 return Arrays.equals(other.path, path)
70 && conversionWeight.equals(other.conversionWeight);
71 }
72
73 public Object internalConvert(Object o) throws JParamException {
74 for (int i = 0; i < path.length; i++) {
75 o = path[i].convert(o);
76 }
77
78 return o;
79 }
80
81 public static IConverter createConversionPath(IConverter first,
82 IConverter second) {
83 IConverter[] firstConverters;
84 IConverter[] secondConverters;
85
86 if (first instanceof AmbigousConverter) {
87 firstConverters = ((AmbigousConverter) first).getConverters();
88 } else {
89 firstConverters = new IConverter[] { first };
90 }
91
92 if (second instanceof AmbigousConverter) {
93 secondConverters = ((AmbigousConverter) second).getConverters();
94 } else {
95 secondConverters = new IConverter[] { second };
96 }
97
98 if ((firstConverters.length > 1) || (secondConverters.length > 1)) {
99 Set converters = new HashSet();
100 for (int i = 0; i < firstConverters.length; i++) {
101 for (int j = 0; j < secondConverters.length; j++) {
102 converters.add(new PathConverter(firstConverters[i],
103 secondConverters[j]));
104 }
105 }
106 return new AmbigousConverter(converters);
107 }
108
109 return new PathConverter(first, second);
110 }
111
112 protected boolean converterEquals(IConverter o) {
113 PathConverter other = (PathConverter) o;
114
115 return Arrays.equals(path, other.path);
116 }
117
118 public String toConversionString() {
119 StringBuffer result = new StringBuffer();
120
121 try {
122 result.append(TypeNameRegistry.getInstance().getJParamTypeName(
123 sourceClass));
124 } catch (JParamException e) {
125 result.append(sourceClass.getName());
126 }
127
128 for (int i = 0; i < path.length; i++) {
129 result.append(" -> ");
130 try {
131 result.append(TypeNameRegistry.getInstance().getJParamTypeName(
132 path[i].getTargetClass()));
133 } catch (JParamException e) {
134 result.append(path[i].getTargetClass().getName());
135 }
136 }
137
138 return result.toString();
139 }
140
141 public IConverter update(IConverter updatedConverter) {
142 IConverter retConverter = this;
143
144 if (Utils.isDebugEnabled(this)) {
145 System.err.println("Updating " + this + " with: "
146 + updatedConverter);
147 }
148
149 List prefix = new LinkedList();
150
151 Class updatedSource = updatedConverter.getSourceClass();
152 Class updatedTarget = updatedConverter.getSourceClass();
153
154 int sourceIndex = 0;
155 for (; sourceIndex < path.length; sourceIndex++) {
156 IConverter curStep = path[sourceIndex];
157 if (updatedSource.equals(curStep.getSourceClass())) {
158 break;
159 }
160 prefix.add(curStep);
161 }
162
163 if (sourceIndex < path.length) {
164 List postfix = new LinkedList();
165 int targetIndex = sourceIndex + 1;
166 for (; targetIndex < path.length; targetIndex++) {
167 IConverter curStep = path[targetIndex];
168 if (updatedTarget.equals(curStep.getTargetClass())) {
169 break;
170 }
171 postfix.add(curStep);
172 }
173
174 if (targetIndex < path.length) {
175 IConverter preConverter = null;
176 IConverter postConverter = null;
177
178 if (prefix.size() > 0) {
179 preConverter = new PathConverter((IConverter[]) prefix
180 .toArray(new IConverter[prefix.size()]));
181 }
182
183 if (postfix.size() > 0) {
184 postConverter = new PathConverter((IConverter[]) postfix
185 .toArray(new IConverter[postfix.size()]));
186 }
187
188 IConverter secondHalf;
189 if (postConverter != null) {
190 secondHalf = createConversionPath(updatedConverter,
191 postConverter);
192 } else {
193 secondHalf = updatedConverter;
194 }
195
196 if (preConverter != null) {
197 retConverter = createConversionPath(preConverter,
198 secondHalf);
199 } else {
200 retConverter = createConversionPath(updatedConverter,
201 secondHalf);
202 }
203 }
204 }
205
206 if (Utils.isDebugEnabled(this)) {
207 if (retConverter != this) {
208 System.err.println("Converter updated, new converter: "
209 + retConverter);
210 } else {
211 System.err.println("No change");
212 }
213 }
214 return this;
215 }
216 }