View Javadoc

1   package net.sourceforge.jparam.conversion.weights;
2   
3   /***
4    * A class representing the weight of a single scalar conversion, from one
5    * type to another
6    * 
7    * Chained conversion are supported
8    * 
9    * @author Ron_Sidi
10   *
11   */
12  public class ScalarConversionWeight implements Comparable {
13      
14      // the different conversion types
15  	static final int _CONV_IMPOSSIBLE = 0;
16  	static final int _CONV_USER = 1;
17  	static final int _CONV_TENTATIVE = 2;
18  	static final int _CONV_TO_PARENT = 3;
19  	static final int _CONV_STANDARD = 4;
20  	static final int _CONV_PROMOTION = 5;
21  	static final int _CONV_EXACT = 6;
22  
23  	// this string will be used when this weight is printed
24  	static final String[] WEIGHT_NAME = { "IMPOSSIBLE", "USER", "TENTATIVE",
25  			"TO_PARENT", "STANDARD", "PROMOTION" };
26  
27  	// some public constant for the basic conversion weights
28  	public static final ScalarConversionWeight CONV_IMPOSSIBLE = new ScalarConversionWeight(
29  			_CONV_IMPOSSIBLE);
30  
31  	public static final ScalarConversionWeight CONV_USER = new ScalarConversionWeight(
32  			_CONV_USER);
33  
34  	public static final ScalarConversionWeight CONV_TENTATIVE = new ScalarConversionWeight(
35  			_CONV_TENTATIVE);
36  
37  	public static final ScalarConversionWeight CONV_TO_PARENT = new ScalarConversionWeight(
38  			_CONV_TO_PARENT);
39  
40  	public static final ScalarConversionWeight CONV_PROMOTE = new ScalarConversionWeight(
41  			_CONV_PROMOTION);
42  
43  	public static final ScalarConversionWeight CONV_STANDARD = new ScalarConversionWeight(
44  			_CONV_STANDARD);
45  
46  	public static final ScalarConversionWeight CONV_EXACT = new ScalarConversionWeight(
47  			_CONV_EXACT);
48  
49  	// conv_exact is not playing a part, if the conversion is an exact match then conversion
50  	// count of all other types is 0
51  	int NUMBER_OF_CONVERSION_TYPES = _CONV_EXACT;
52  
53  	// the number of conversion of each type
54  	int[] weights = new int[NUMBER_OF_CONVERSION_TYPES];
55  
56  	
57  	/* (non-Javadoc)
58  	 * @see java.lang.Comparable#compareTo(java.lang.Object)
59  	 */
60  	public int compareTo(Object o) {
61  		if (!o.getClass().equals(ScalarConversionWeight.class)) {
62  			throw new IllegalArgumentException(
63  					"Cannot compare ScalarConversionWeight to something else: "
64  							+ o.getClass().getName());
65  		}
66  		
67  		// check different conversion weights in decending order of importance
68  		// the first that differ will decide the order
69  		ScalarConversionWeight other = (ScalarConversionWeight) o;
70  		for (int i = 0; i < weights.length; i++) {
71  			if (other.weights[i] != weights[i]) {
72  				return (weights[i] - other.weights[i] < 0) ? -1 : 1;
73  			}
74  		}
75  		
76  		// if all conversion counts are equal then the total weight is equal
77  		return 0;
78  	}
79  
80  	
81  	/***
82  	 * This constructor is intentionally private, no one should be able to
83  	 * create a <code>ScalarConversionWeight</code> directly, either use one
84  	 * of the supplied constant or concat two weights
85  	 * 
86  	 * @param conversionType
87  	 */
88  	private ScalarConversionWeight(int conversionType) {
89  	    // create a single conversion of the given type, if _CONV_EXACT is 
90  	    // supplied then the count of all conversions will be 0
91  		if (conversionType != _CONV_EXACT) {
92  			weights[conversionType] = 1;
93  		}
94  	}
95  
96  	/***
97  	 * Create a <code>ScalarConversionWeight</code> representing both
98  	 * conversions
99  	 * 
100 	 * @param first
101 	 * @param second
102 	 */
103 	public ScalarConversionWeight(ScalarConversionWeight first,
104 			ScalarConversionWeight second) {
105 	    // simply add all conversions
106 		for (int i = 0; i < weights.length; i++) {
107 			weights[i] = first.weights[i] + second.weights[i];
108 		}
109 		
110 		// only one user conversion is supported, we could assert here...
111 		if (weights[_CONV_USER] > 1) {
112 			weights[_CONV_USER] = 1;
113 		}
114 	}
115 
116 	/* (non-Javadoc)
117 	 * @see java.lang.Object#hashCode()
118 	 */
119 	public int hashCode() {
120 		int hash = 0;
121 		for (int i = 0; i < weights.length; i++) {
122 			hash = hash * 10 + weights[i];
123 		}
124 
125 		return hash;
126 	}
127 
128 	/* (non-Javadoc)
129 	 * @see java.lang.Object#equals(java.lang.Object)
130 	 */
131 	public boolean equals(Object o) {
132 		if (o.getClass().equals(ScalarConversionWeight.class)) {
133 			return compareTo(o) == 0;
134 		}
135 		return false;
136 	}
137 
138 	/***
139 	 * Return a string representation of this weight, all types of conversion
140 	 * ordered from hardest to easiest, along with the count of each
141 	 * 
142 	 * @see java.lang.Object#toString()
143 	 */
144 	public String toString() {
145 
146 		if (weights[_CONV_IMPOSSIBLE] > 0)
147 			return WEIGHT_NAME[_CONV_IMPOSSIBLE];
148 
149 		StringBuffer result = new StringBuffer();
150 		boolean exact = true;
151 
152 		for (int i = 0; i < NUMBER_OF_CONVERSION_TYPES; ++i) {
153 			if (weights[i] != 0) {
154 				if (!exact)
155 					result.append(" + ");
156 				if (weights[i] != 1)
157 					result.append(weights[i]).append("*");
158 				result.append(WEIGHT_NAME[i]);
159 				exact = false;
160 			}
161 		}
162 
163 		if (exact) {
164 			return "EXACT";
165 		}
166 		return result.toString();
167 	}
168 }