View Javadoc

1   /*
2    * $Id: TransformerWeighting.java 11542 2008-04-08 18:35:22Z rossmason $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  package org.mule.transformer;
11  
12  import org.mule.api.transformer.DiscoverableTransformer;
13  import org.mule.api.transformer.Transformer;
14  
15  import java.util.Iterator;
16  import java.util.List;
17  
18  /**
19   * Given a {@link org.mule.api.transformer.Transformer} instance, an input class and output class
20   * this object will create a weighting for a transformer. This weighthing can be used compare one transformer with
21   * another, which can be useful for choosing a transformer to use given the input class and required output class.
22   */
23  public class TransformerWeighting implements Comparable
24  {
25      private Transformer transformer;
26      private int inputWeighting;
27      private int outputWeighting;
28      private Class inputClass;
29      private Class outputClass;
30  
31      public TransformerWeighting(Class inputClass, Class outputClass, Transformer transformer)
32      {
33          this.inputClass = inputClass;
34          this.outputClass = outputClass;
35          this.transformer = transformer;
36          init();
37      }
38  
39      private void init()
40      {
41          inputWeighting = Integer.MAX_VALUE;
42          List sourceTypes = transformer.getSourceTypes();
43  
44          for (Iterator iterator = sourceTypes.iterator(); iterator.hasNext();)
45          {
46              Class aClass = (Class) iterator.next();
47              int weighting = getWeighting(-1, inputClass, aClass);
48              if (weighting < inputWeighting && weighting != -1)
49              {
50                  inputWeighting = weighting;
51              }
52          }
53  
54          outputWeighting = getWeighting(-1, outputClass, transformer.getReturnClass());
55  
56          inputWeighting = (inputWeighting == Integer.MAX_VALUE ? -1 : inputWeighting);
57          outputWeighting = (outputWeighting == Integer.MAX_VALUE ? -1 : outputWeighting);
58  
59      }
60  
61      protected int getWeighting(int weighting, Class src, Class dest)
62      {
63          int x = weighting + 1;
64          if (dest.equals(src))
65          {
66              return x;
67          }
68          else if (!dest.isAssignableFrom(src))
69          {
70              return -1;
71          }
72          else if (src.getInterfaces().length > 0)
73          {
74              for (int i = 0; i < src.getInterfaces().length; i++)
75              {
76                  Class aClass = src.getInterfaces()[i];
77                  if (dest.equals(aClass))
78                  {
79                      return x;
80                  }
81              }
82              return x + 1;
83          }
84          else if (src.getSuperclass() != null)
85          {
86              return getWeighting(x, src.getSuperclass(), dest);
87  
88          }
89          return x;
90      }
91  
92      public Class getInputClass()
93      {
94          return inputClass;
95      }
96  
97      public int getInputWeighting()
98      {
99          return inputWeighting;
100     }
101 
102     public Class getOutputClass()
103     {
104         return outputClass;
105     }
106 
107     public int getOutputWeighting()
108     {
109         return outputWeighting;
110     }
111 
112     public Transformer getTransformer()
113     {
114         return transformer;
115     }
116 
117     public boolean isExactMatch()
118     {
119         return inputWeighting == 0 && outputWeighting == 0;
120     }
121 
122     public boolean isNotMatch()
123     {
124         return inputWeighting == -1 || outputWeighting == -1;
125     }
126 
127     public int compareTo(Object o)
128     {
129         TransformerWeighting weighting = (TransformerWeighting) o;
130         if (weighting.getInputWeighting() == getInputWeighting() &&
131                 weighting.getOutputWeighting() == getOutputWeighting())
132         {
133             //We only check the weighting if we have an exact match
134             //These transformers should always implement DiscoverableTransformer, but jic we check here
135             if (weighting.getTransformer() instanceof DiscoverableTransformer
136                     && this.getTransformer() instanceof DiscoverableTransformer)
137             {
138                 int x = ((DiscoverableTransformer) weighting.getTransformer()).getPriorityWeighting();
139                 int y = ((DiscoverableTransformer) this.getTransformer()).getPriorityWeighting();
140                 if (x > y)
141                 {
142                     return -1;
143                 }
144                 if (x < y)
145                 {
146                     return 1;
147                 }
148                 return 0;
149             }
150             else
151             {
152                 return 0;
153             }
154         }
155         else
156         {
157             if (isNotMatch())
158             {
159                 return -1;
160             }
161             else if (weighting.isNotMatch() && !isNotMatch())
162             {
163                 return 1;
164             }
165             else if (weighting.isExactMatch() && !isExactMatch())
166             {
167                 return -1;
168             }
169             else if (weighting.getInputWeighting() < getInputWeighting() &&
170                     weighting.getOutputWeighting() < getOutputWeighting())
171             {
172                 return -1;
173             }
174             //If the outputWeighting is closer to 0 its a better match
175             else if (weighting.getInputWeighting() == getInputWeighting() &&
176                     weighting.getOutputWeighting() < getOutputWeighting())
177             {
178                 return -1;
179             }
180 
181             else if (weighting.getInputWeighting() < getInputWeighting() &&
182                     weighting.getOutputWeighting() == getOutputWeighting())
183             {
184                 return -1;
185             }
186             return 1;
187         }
188     }
189 
190     public boolean equals(Object o)
191     {
192         if (this == o)
193         {
194             return true;
195         }
196         if (o == null || getClass() != o.getClass())
197         {
198             return false;
199         }
200 
201         TransformerWeighting that = (TransformerWeighting) o;
202 
203         if (inputClass != null ? !inputClass.equals(that.inputClass) : that.inputClass != null)
204         {
205             return false;
206         }
207         if (outputClass != null ? !outputClass.equals(that.outputClass) : that.outputClass != null)
208         {
209             return false;
210         }
211 
212         return true;
213     }
214 
215     public int hashCode()
216     {
217         int result;
218         result = (transformer != null ? transformer.hashCode() : 0);
219         result = 31 * result + inputWeighting;
220         result = 31 * result + outputWeighting;
221         result = 31 * result + (inputClass != null ? inputClass.hashCode() : 0);
222         result = 31 * result + (outputClass != null ? outputClass.hashCode() : 0);
223         return result;
224     }
225 
226 
227     public String toString()
228     {
229         final StringBuffer sb = new StringBuffer();
230         sb.append("TransformerWeighting");
231         sb.append("{inputClass=").append(inputClass);
232         sb.append(", inputWeighting=").append(inputWeighting);
233         sb.append(", outputClass=").append(outputClass);
234         sb.append(", outputWeighting=").append(outputWeighting);
235         sb.append(", transformer=").append(transformer.getName());
236         sb.append('}');
237         return sb.toString();
238     }
239 }