Coverage Report - org.mule.expression.ExpressionUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ExpressionUtils
0%
0/85
0%
0/62
0
 
 1  
 /*
 2  
  * $Id: FunctionExpressionEvaluator.java 18005 2010-07-09 16:47:06Z aperepel $
 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  
 
 11  
 package org.mule.expression;
 12  
 
 13  
 import org.mule.api.MuleMessage;
 14  
 import org.mule.api.expression.RequiredValueException;
 15  
 import org.mule.api.transport.PropertyScope;
 16  
 import org.mule.config.i18n.CoreMessages;
 17  
 import org.mule.routing.filters.WildcardFilter;
 18  
 
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collections;
 21  
 import java.util.HashMap;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 
 25  
 import static org.mule.expression.ExpressionConstants.ALL_ARGUMENT;
 26  
 import static org.mule.expression.ExpressionConstants.DELIM;
 27  
 import static org.mule.expression.ExpressionConstants.OPTIONAL_ARGUMENT;
 28  
 
 29  
 /**
 30  
  * Used by the different header expression evaluators to read message properties, honuouring scope and return type
 31  
  */
 32  
 public final class ExpressionUtils
 33  
 {
 34  
     private ExpressionUtils()
 35  0
     {
 36  
         // don't instantiate
 37  0
     }
 38  
 
 39  
     public static Object getPropertyWithScope(String expression, MuleMessage msg)
 40  
     {
 41  0
         return getPropertyWithScope(expression, msg, Object.class);
 42  
     }
 43  
 
 44  
     /**
 45  
      * Handler scope-aware expressions like "#[header:INBOUND:foo]
 46  
      * @param expression the header name to evaluate.  this can be prefixed with a message scope such as INBOUND, OUTBOUND
 47  
      * or INVOCATION scope. If no scope is defined the default scope is OUTBOUND
 48  
      * 
 49  
      * @param msg the message to evaluate on
 50  
      * @param type the expected return type for this evaluation
 51  
      * @return  an object of type 'type' corresponding to the message header requested or null if the header was not on
 52  
      * the message in the specified scope
 53  
      */
 54  
     @SuppressWarnings("unchecked")
 55  
     public static <T> T getPropertyWithScope(String expression, MuleMessage msg, Class<T> type)
 56  
     {
 57  0
         PropertyScope defaultScope = getScope(expression);
 58  0
         if (defaultScope != null)
 59  
         {
 60  
             // cut-off leading scope and separator
 61  0
             expression = expression.substring(defaultScope.getScopeName().length() + 1);
 62  
         }
 63  
         else
 64  
         {
 65  
             // default
 66  0
             defaultScope = PropertyScope.OUTBOUND;
 67  
         }
 68  
 
 69  0
         if (expression.contains(ALL_ARGUMENT))
 70  
         {
 71  0
             WildcardFilter filter = new WildcardFilter(expression);
 72  0
             if (Map.class.isAssignableFrom(type))
 73  
             {
 74  0
                 Map<String, Object> props = new HashMap<String, Object>();
 75  0
                 for (String name : msg.getPropertyNames(defaultScope))
 76  
                 {
 77  0
                     if (filter.accept(name))
 78  
                     {
 79  0
                         props.put(name, msg.getProperty(name, defaultScope));
 80  
                     }
 81  
                 }
 82  0
                 return (T) returnMap(props, defaultScope);
 83  
             }
 84  0
             else if (List.class.isAssignableFrom(type))
 85  
             {
 86  0
                 List<Object> values = new ArrayList<Object>();
 87  0
                 for (String name : msg.getPropertyNames(defaultScope))
 88  
                 {
 89  0
                     if (filter.accept(name))
 90  
                     {
 91  0
                         values.add(msg.getProperty(name, defaultScope));
 92  
                     }
 93  
                 }
 94  0
                 return (T) returnList(values, defaultScope);
 95  
             }
 96  
             else
 97  
             {
 98  
                 //TODO i18n
 99  0
                 throw new IllegalArgumentException("Type specified is not a collection type but '" + ALL_ARGUMENT + "' was specified for all properties. Type is: " + type);
 100  
             }
 101  
         }
 102  0
         else if (Map.class.isAssignableFrom(type))
 103  
         {
 104  0
             String[] names = expression.split(DELIM);
 105  0
             Map<String, Object> props = new HashMap<String, Object>();
 106  0
             for (String name : names)
 107  
             {
 108  0
                 boolean required = true;
 109  0
                 name = name.trim();
 110  0
                 PropertyScope scope = getScope(name);
 111  0
                 if (scope != null)
 112  
                 {
 113  
                     // cut-off leading scope and separator
 114  0
                     name = name.substring(scope.getScopeName().length() + 1);
 115  
                 }
 116  
                 else
 117  
                 {
 118  0
                     scope = defaultScope;
 119  
                 }
 120  0
                 if (name.endsWith(OPTIONAL_ARGUMENT))
 121  
                 {
 122  0
                     name = name.substring(0, name.length() - OPTIONAL_ARGUMENT.length());
 123  0
                     required = false;
 124  
                 }
 125  0
                 Object value = msg.getProperty(name, scope);
 126  0
                 if (value == null && required)
 127  
                 {
 128  0
                     throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("headers", scope.getScopeName() + ":" + name));
 129  
                 }
 130  0
                 else if (value != null)
 131  
                 {
 132  0
                     props.put(name, value);
 133  
                 }
 134  
             }
 135  0
             return (T) returnMap(props, defaultScope);
 136  
         }
 137  0
         else if (List.class.isAssignableFrom(type))
 138  
         {
 139  0
             String[] names = expression.split(DELIM);
 140  0
             List<Object> values = new ArrayList<Object>();
 141  0
             for (String name : names)
 142  
             {
 143  0
                 boolean required = true;
 144  0
                 name = name.trim();
 145  0
                 PropertyScope scope = getScope(name);
 146  0
                 if (scope != null)
 147  
                 {
 148  
                     // cut-off leading scope and separator
 149  0
                     name = name.substring(scope.getScopeName().length() + 1);
 150  
                 }
 151  
                 else
 152  
                 {
 153  0
                     scope = defaultScope;
 154  
                 }
 155  0
                 if (name.endsWith(OPTIONAL_ARGUMENT))
 156  
                 {
 157  0
                     name = name.substring(0, name.length() - OPTIONAL_ARGUMENT.length());
 158  0
                     required = false;
 159  
                 }
 160  0
                 name = name.trim();
 161  0
                 Object value = msg.getProperty(name, scope);
 162  0
                 if (value == null && required)
 163  
                 {
 164  0
                     throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("headers-list", scope.getScopeName() + ":" + name));
 165  
                 }
 166  0
                 else if (value != null)
 167  
                 {
 168  0
                     values.add(value);
 169  
                 }
 170  
             }
 171  0
             return (T) returnList(values, defaultScope);
 172  
         }
 173  
         else
 174  
         {
 175  0
             boolean required = true;
 176  0
             if (expression.endsWith(OPTIONAL_ARGUMENT))
 177  
             {
 178  0
                 expression = expression.substring(0, expression.length() - OPTIONAL_ARGUMENT.length());
 179  0
                 required = false;
 180  
             }
 181  0
             Object result = msg.getProperty(expression.trim(), defaultScope);
 182  0
             if (result == null && required)
 183  
             {
 184  0
                 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("header", defaultScope.getScopeName() + ":" + expression));
 185  
 
 186  
             }
 187  0
             return (T) result;
 188  
         }
 189  
     }
 190  
 
 191  
     private static Map<String, Object> returnMap(Map<String, Object> props, PropertyScope scope)
 192  
     {
 193  0
         Map<String, Object> p = (props.size() == 0 ? Collections.<String, Object>emptyMap() : props);
 194  0
         if (scope.equals(PropertyScope.INBOUND))
 195  
         {
 196  0
             p = Collections.unmodifiableMap(p);
 197  
         }
 198  0
         return p;
 199  
     }
 200  
 
 201  
     private static List<Object> returnList(List<Object> values, PropertyScope scope)
 202  
     {
 203  0
         List<Object> l = (values.size() == 0 ? Collections.emptyList() : values);
 204  0
         if (scope.equals(PropertyScope.INBOUND))
 205  
         {
 206  0
             l = Collections.unmodifiableList(l);
 207  
         }
 208  0
         return l;
 209  
     }
 210  
 
 211  
     private static PropertyScope getScope(String expression)
 212  
     {
 213  
         // see if scope has been specified explicitly
 214  0
         final String[] tokens = expression.split(":", 2); // note we split only once, not on every separator
 215  
         PropertyScope scope;
 216  0
         if (tokens.length == 2)
 217  
         {
 218  0
             final String candidate = tokens[0];
 219  0
             scope = PropertyScope.get(candidate.toLowerCase());
 220  0
             if (scope == null)
 221  
             {
 222  0
                 throw new IllegalArgumentException(String.format("'%s' is not a valid property scope.", candidate));
 223  
             }
 224  
 
 225  0
             return scope;
 226  
         }
 227  0
         return null;
 228  
     }
 229  
 }