1 package net.sourceforge.jparam.conversion.converters;
2
3 import java.util.HashSet;
4 import java.util.Iterator;
5 import java.util.Set;
6
7 import net.sourceforge.jparam.JParam;
8 import net.sourceforge.jparam.JParamException;
9 import net.sourceforge.jparam.typename.TypeNameRegistry;
10 import net.sourceforge.jparam.util.Utils;
11
12 /***
13 * @author Ron_Sidi
14 *
15 * A converter representing an ambigous conversion, it should hold all possible
16 * conversions from the source to the target using the same weight
17 */
18 public class AmbigousConverter extends AbstractConverter {
19
20 private Set converters = new HashSet();
21
22 AmbigousConverter(Set converters) {
23 this.converters = converters;
24 IConverter conv = (IConverter) converters.iterator().next();
25 this.conversionWeight = conv.getWeight();
26 this.sourceClass = conv.getSourceClass();
27 this.targetClass = conv.getTargetClass();
28 }
29
30 protected Object internalConvert(Object o) throws Exception {
31 StringBuffer message = new StringBuffer();
32 try {
33 String sourceName = TypeNameRegistry.getInstance()
34 .getJParamTypeName(sourceClass);
35 String targetName = TypeNameRegistry.getInstance()
36 .getJParamTypeName(targetClass);
37
38 message.append("More than one conversion path found from ");
39 message.append(sourceName);
40 message.append(" ( ");
41 try {
42 message.append(JParam.toString(o));
43 } catch (Exception e) {
44 message.append(o);
45 }
46 message.append(" ) to ");
47 message.append(targetName);
48 message.append(":");
49
50 for (Iterator iter = converters.iterator(); iter.hasNext();) {
51 IConverter converter = (IConverter) iter.next();
52 message.append("\n\t");
53 message.append(converter.toConversionString());
54 }
55 message.append("\n");
56 } catch (Exception e) {
57 message
58 .append("This conversion is ambigous, all possible conversions: "
59 + converters
60 + " error generating correct error: "
61 + e);
62 }
63
64 throw new JParamException(message.toString());
65 }
66
67 public static IConverter createConverter(IConverter first, IConverter second) {
68 Utils.assert(
69 first.getSourceClass().equals(second.getSourceClass()) && first.getTargetClass().equals(second.getTargetClass()),
70 "Cannot create ambiguity between non-compatible converters");
71 Utils
72 .assert(first.getWeight().equals(
73 second.getWeight()),
74 "Cannot create ambiuity between non-similar weighted converters");
75
76 Set converters = new HashSet();
77 if (first instanceof AmbigousConverter) {
78 converters.addAll(((AmbigousConverter) first).converters);
79 } else {
80 converters.add(first);
81 }
82
83 if (second instanceof AmbigousConverter) {
84 converters.addAll(((AmbigousConverter) second).converters);
85 } else {
86 converters.add(second);
87 }
88
89 return new AmbigousConverter(converters);
90 }
91
92 IConverter[] getConverters() {
93 return (IConverter[]) converters.toArray(new IConverter[converters
94 .size()]);
95 }
96
97 protected boolean converterEquals(IConverter o) {
98 AmbigousConverter other = (AmbigousConverter) o;
99 if (converters.size() != other.converters.size()) {
100 return false;
101 }
102
103 Iterator myIter = converters.iterator();
104 Iterator otherIter = other.converters.iterator();
105 for (; myIter.hasNext() && otherIter.hasNext();) {
106 IConverter myConverter = (IConverter) myIter.next();
107 IConverter otherConverter = (IConverter) otherIter.next();
108
109 if (!myConverter.equals(otherConverter)) {
110 return false;
111 }
112 }
113
114 return true;
115 }
116
117 public String toConversionString() {
118 StringBuffer result = new StringBuffer("AMBIGOUS(");
119
120 for (Iterator iter = converters.iterator(); iter.hasNext();) {
121 IConverter converter = (IConverter) iter.next();
122 result.append(converter.toConversionString());
123 if (iter.hasNext()) {
124 result.append("; ");
125 }
126 }
127
128 result.append(")");
129 return result.toString();
130 }
131
132 public IConverter update(IConverter updatedConverter) {
133 Set newConverters = new HashSet();
134
135 boolean converterUpdated = false;
136 for (Iterator iter = converters.iterator(); iter.hasNext();) {
137 IConverter converter = (IConverter) iter.next();
138 IConverter newConverter = converter.update(updatedConverter);
139 if (newConverter != converter) {
140 converterUpdated = true;
141 }
142 newConverters.add(converter.update(updatedConverter));
143 }
144
145 if (converterUpdated) {
146 if (newConverters.size() > 1) {
147 return new AmbigousConverter(newConverters);
148 }
149
150 return (IConverter) newConverters.iterator().next();
151 }
152
153 return this;
154 }
155 }