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 }