Coverage Report - org.mule.transformer.TransformerWeighting
 
Classes in this File Line Coverage Branch Coverage Complexity
TransformerWeighting
0%
0/89
0%
0/90
0
 
 1  
 /*
 2  
  * $Id: TransformerWeighting.java 19191 2010-08-25 21:05:23Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.DataType;
 13  
 import org.mule.api.transformer.DiscoverableTransformer;
 14  
 import org.mule.api.transformer.Transformer;
 15  
 
 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  0
     {
 33  0
         this.inputClass = inputClass;
 34  0
         this.outputClass = outputClass;
 35  0
         this.transformer = transformer;
 36  0
         init();
 37  0
     }
 38  
 
 39  
     private void init()
 40  
     {
 41  0
         inputWeighting = Integer.MAX_VALUE;
 42  0
         List<DataType<?>> sourceTypes = transformer.getSourceDataTypes();
 43  
 
 44  0
         for (DataType type : sourceTypes)
 45  
         {
 46  0
             int weighting = getWeighting(-1, inputClass, type.getType());
 47  0
             if (weighting < inputWeighting && weighting != -1)
 48  
             {
 49  0
                 inputWeighting = weighting;
 50  
             }
 51  0
         }
 52  
 
 53  0
         outputWeighting = getWeighting(-1, outputClass, transformer.getReturnClass());
 54  
 
 55  0
         inputWeighting = (inputWeighting == Integer.MAX_VALUE ? -1 : inputWeighting);
 56  0
         outputWeighting = (outputWeighting == Integer.MAX_VALUE ? -1 : outputWeighting);
 57  
 
 58  0
     }
 59  
 
 60  
     /**
 61  
      * THis is a very basic algorithm for creating a match rating for two classes.  An offset weighting
 62  
      * can also be passed in. Where w is weighting,
 63  
      * if the classes match exactly, w+1 is returned,
 64  
      * if the classes are assignable and there is a direct equality to an interface on the class, w+2  is returned,
 65  
      * if the classes are assignable but no direct interface match, w+3 is returned
 66  
      * If the dest type is Object.class then w+4is returned. This is because matching on object will yeild a lot of options
 67  
      * putting those that use the Object.class generic type should get pushed down the list
 68  
      * If there a super class, that will get matched using the above criteria
 69  
      * If there is no match -1 is returned
 70  
      *
 71  
      * @param weighting an offset weighting, by defualt -1 should be used
 72  
      * @param src the src class being matched
 73  
      * @param dest the destination class to match to
 74  
      * @return a weighting where 0 would be an exact match, -1 would be no match and a positive integer that defines how close the match is
 75  
      */
 76  
     protected int getWeighting(int weighting, Class src, Class dest)
 77  
     {
 78  0
         int x = weighting + 1;
 79  
         //If we are getting a match for object.class, we need to put it at the bottom of
 80  
         //the matching list
 81  0
         if(dest.equals(Object.class))
 82  
         {
 83  0
             return x + 3;
 84  
         }
 85  
 
 86  0
         if (dest.equals(src))
 87  
         {
 88  0
             return x;
 89  
         }
 90  0
         else if (!dest.isAssignableFrom(src))
 91  
         {
 92  0
             return -1;
 93  
         }
 94  0
         else if (src.getInterfaces().length > 0)
 95  
         {
 96  0
             for (int i = 0; i < src.getInterfaces().length; i++)
 97  
             {
 98  0
                 Class aClass = src.getInterfaces()[i];
 99  0
                 if (dest.equals(aClass))
 100  
                 {
 101  0
                     return x + 1;
 102  
                 }
 103  
             }
 104  0
             return x + 2;
 105  
         }
 106  0
         else if (src.getSuperclass() != null)
 107  
         {
 108  0
             return getWeighting(x, src.getSuperclass(), dest);
 109  
 
 110  
         }
 111  0
         return -1;
 112  
     }
 113  
 
 114  
     public Class getInputClass()
 115  
     {
 116  0
         return inputClass;
 117  
     }
 118  
 
 119  
     public int getInputWeighting()
 120  
     {
 121  0
         return inputWeighting;
 122  
     }
 123  
 
 124  
     public Class getOutputClass()
 125  
     {
 126  0
         return outputClass;
 127  
     }
 128  
 
 129  
     public int getOutputWeighting()
 130  
     {
 131  0
         return outputWeighting;
 132  
     }
 133  
 
 134  
     public Transformer getTransformer()
 135  
     {
 136  0
         return transformer;
 137  
     }
 138  
 
 139  
     public boolean isExactMatch()
 140  
     {
 141  0
         return inputWeighting == 0 && outputWeighting == 0;
 142  
     }
 143  
 
 144  
     public boolean isNotMatch()
 145  
     {
 146  0
         return inputWeighting == -1 || outputWeighting == -1;
 147  
     }
 148  
 
 149  
     public int compareTo(Object o)
 150  
     {
 151  0
         TransformerWeighting weighting = (TransformerWeighting) o;
 152  0
         if (weighting.getInputWeighting() == getInputWeighting() &&
 153  
                 weighting.getOutputWeighting() == getOutputWeighting())
 154  
         {
 155  
             //We only check the weighting if we have an exact match
 156  
             //These transformers should always implement DiscoverableTransformer, but jic we check here
 157  0
             if (weighting.getTransformer() instanceof DiscoverableTransformer
 158  
                     && this.getTransformer() instanceof DiscoverableTransformer)
 159  
             {
 160  0
                 int x = ((DiscoverableTransformer) weighting.getTransformer()).getPriorityWeighting();
 161  0
                 int y = ((DiscoverableTransformer) this.getTransformer()).getPriorityWeighting();
 162  0
                 if (x > y)
 163  
                 {
 164  0
                     return -1;
 165  
                 }
 166  0
                 if (x < y)
 167  
                 {
 168  0
                     return 1;
 169  
                 }
 170  0
                 return 0;
 171  
             }
 172  
             else
 173  
             {
 174  0
                 return 0;
 175  
             }
 176  
         }
 177  
         else
 178  
         {
 179  0
             if (isNotMatch())
 180  
             {
 181  0
                 return -1;
 182  
             }
 183  0
             else if (weighting.isNotMatch() && !isNotMatch())
 184  
             {
 185  0
                 return 1;
 186  
             }
 187  0
             else if (weighting.isExactMatch() && !isExactMatch())
 188  
             {
 189  0
                 return -1;
 190  
             }
 191  0
             else if (weighting.getInputWeighting() < getInputWeighting() &&
 192  
                     weighting.getOutputWeighting() < getOutputWeighting())
 193  
             {
 194  0
                 return -1;
 195  
             }
 196  
             //If the outputWeighting is closer to 0 its a better match
 197  0
             else if (weighting.getInputWeighting() == getInputWeighting() &&
 198  
                     weighting.getOutputWeighting() < getOutputWeighting())
 199  
             {
 200  0
                 return -1;
 201  
             }
 202  
 
 203  0
             else if (weighting.getInputWeighting() < getInputWeighting() &&
 204  
                     weighting.getOutputWeighting() == getOutputWeighting())
 205  
             {
 206  0
                 return -1;
 207  
             }
 208  0
             return 1;
 209  
         }
 210  
     }
 211  
 
 212  
     public boolean equals(Object o)
 213  
     {
 214  0
         if (this == o)
 215  
         {
 216  0
             return true;
 217  
         }
 218  0
         if (o == null || getClass() != o.getClass())
 219  
         {
 220  0
             return false;
 221  
         }
 222  
 
 223  0
         TransformerWeighting that = (TransformerWeighting) o;
 224  
 
 225  0
         if (inputClass != null ? !inputClass.equals(that.inputClass) : that.inputClass != null)
 226  
         {
 227  0
             return false;
 228  
         }
 229  0
         if (outputClass != null ? !outputClass.equals(that.outputClass) : that.outputClass != null)
 230  
         {
 231  0
             return false;
 232  
         }
 233  
 
 234  0
         return true;
 235  
     }
 236  
 
 237  
     public int hashCode()
 238  
     {
 239  
         int result;
 240  0
         result = (transformer != null ? transformer.hashCode() : 0);
 241  0
         result = 31 * result + inputWeighting;
 242  0
         result = 31 * result + outputWeighting;
 243  0
         result = 31 * result + (inputClass != null ? inputClass.hashCode() : 0);
 244  0
         result = 31 * result + (outputClass != null ? outputClass.hashCode() : 0);
 245  0
         return result;
 246  
     }
 247  
 
 248  
 
 249  
     public String toString()
 250  
     {
 251  0
         final StringBuffer sb = new StringBuffer();
 252  0
         sb.append("TransformerWeighting");
 253  0
         sb.append("{inputClass=").append(inputClass);
 254  0
         sb.append(", inputWeighting=").append(inputWeighting);
 255  0
         sb.append(", outputClass=").append(outputClass);
 256  0
         sb.append(", outputWeighting=").append(outputWeighting);
 257  0
         sb.append(", transformer=").append(transformer.getName());
 258  0
         sb.append('}');
 259  0
         return sb.toString();
 260  
     }
 261  
 }