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