Coverage Report - org.mule.transformer.simple.MessagePropertiesTransformer
 
Classes in this File Line Coverage Branch Coverage Complexity
MessagePropertiesTransformer
0%
0/103
0%
0/64
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.simple;
 8  
 
 9  
 import org.mule.DefaultMuleMessage;
 10  
 import org.mule.api.MuleMessage;
 11  
 import org.mule.api.transport.PropertyScope;
 12  
 import org.mule.routing.filters.WildcardFilter;
 13  
 import org.mule.transformer.AbstractMessageTransformer;
 14  
 import org.mule.transformer.types.DataTypeFactory;
 15  
 import org.mule.transport.NullPayload;
 16  
 
 17  
 import java.text.MessageFormat;
 18  
 import java.util.ArrayList;
 19  
 import java.util.Arrays;
 20  
 import java.util.HashMap;
 21  
 import java.util.HashSet;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.Set;
 25  
 
 26  
 /**
 27  
  * <p>
 28  
  * A configurable message transformer that allows users to add, overwrite, rename and delete
 29  
  * properties on the current message. Users can set a {@link List} of 'deleteProperties' regular 
 30  
  * expressions to remove the matching properties from the message and can also set a {@link Map} 
 31  
  * of 'addProperties' that will be added to the message and possibly overwrite existing properties
 32  
  * with the same name.
 33  
  * <p/> 
 34  
  * <p>
 35  
  * If {@link #overwrite} is set to <code>false</code>, and a property 
 36  
  * exists on the message (even if the value is <code>null</code>, it will be left intact. The 
 37  
  * transformer then acts as a more gentle 'enricher'. The default setting is <code>true</code>.
 38  
  * </p>
 39  
  */
 40  
 public class MessagePropertiesTransformer extends AbstractMessageTransformer
 41  
 {
 42  0
     private List<String> deleteProperties = null;
 43  0
     private Map<String, Object> addProperties = null;
 44  
     /** the properties map containing rename mappings for message properties */
 45  
     private Map<String, String> renameProperties;
 46  
     private String getProperty;
 47  0
     private boolean overwrite = true;
 48  
     // outbound is the default scope
 49  0
     private PropertyScope scope = PropertyScope.OUTBOUND;
 50  
 
 51  
     public MessagePropertiesTransformer()
 52  0
     {
 53  0
         registerSourceType(DataTypeFactory.OBJECT);
 54  0
         setReturnDataType(DataTypeFactory.OBJECT);
 55  0
     }
 56  
 
 57  
     @Override
 58  
     public Object clone() throws CloneNotSupportedException
 59  
     {
 60  0
         MessagePropertiesTransformer clone = (MessagePropertiesTransformer) super.clone();
 61  
 
 62  0
         if (deleteProperties != null)
 63  
         {
 64  0
             clone.setDeleteProperties(new ArrayList<String>(deleteProperties));
 65  
         }
 66  
 
 67  0
         if (addProperties != null)
 68  
         {
 69  0
             clone.setAddProperties(new HashMap<String, Object>(addProperties));
 70  
         }
 71  
 
 72  0
         if (renameProperties != null)
 73  
         {
 74  0
             clone.setRenameProperties(new HashMap<String, String>(renameProperties));
 75  
         }
 76  0
         return clone;
 77  
     }
 78  
 
 79  
     @Override
 80  
     public Object transformMessage(MuleMessage message, String outputEncoding)
 81  
     {
 82  0
         if (deleteProperties != null && deleteProperties.size() > 0)
 83  
         {
 84  0
             deleteProperties(message);
 85  
         }
 86  
 
 87  0
         if (addProperties != null && addProperties.size() > 0)
 88  
         {
 89  0
             addProperties(message);
 90  
         }
 91  
 
 92  
         /* perform renaming transformation */
 93  0
         if (this.renameProperties != null && this.renameProperties.size() > 0)
 94  
         {
 95  0
             renameProperties(message);
 96  
         }
 97  
         
 98  0
         if (getProperty != null)
 99  
         {
 100  0
             Object prop = message.getProperty(getProperty, scope);
 101  0
             if (prop != null)
 102  
             {
 103  0
                 message = new DefaultMuleMessage(prop, muleContext);
 104  
             }
 105  
             else
 106  
             {
 107  0
                 message = new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
 108  
             }
 109  
         }
 110  
 
 111  0
         return message;
 112  
     }
 113  
 
 114  
     protected void deleteProperties(MuleMessage message)
 115  
     {
 116  0
         final Set<String> propertyNames = new HashSet<String>(message.getPropertyNames(scope));
 117  
         
 118  0
         for (String expression : deleteProperties)
 119  
         {
 120  0
             for (String key : propertyNames)
 121  
             {
 122  0
                 if (key.matches(expression))
 123  
                 {
 124  0
                     if (logger.isDebugEnabled())
 125  
                     {
 126  0
                         logger.debug(String.format("Removing property: '%s' from scope: '%s'", key, scope.getScopeName()));
 127  
                     }
 128  0
                     message.removeProperty(key, scope);
 129  
                 }
 130  
                 else
 131  
                 {
 132  
                     // fallback to the plain wildcard for simplicity
 133  0
                     WildcardFilter filter = new WildcardFilter(expression);
 134  0
                     if (filter.accept(key))
 135  
                     {
 136  0
                         message.removeProperty(key, scope);
 137  
                     }
 138  0
                 }
 139  
             }
 140  
         }
 141  0
     }
 142  
 
 143  
     protected void addProperties(MuleMessage message)
 144  
     {
 145  0
         for (Map.Entry<String, Object> entry : addProperties.entrySet())
 146  
         {
 147  0
             if (entry.getKey() == null)
 148  
             {
 149  0
                 logger.error("Setting Null property keys is not supported, this entry is being ignored");
 150  
             }
 151  
             else
 152  
             {
 153  0
                 final String key = entry.getKey();
 154  
 
 155  0
                 Object value= entry.getValue();
 156  0
                 Object realValue = value;
 157  
 
 158  
                 //Enable expression support for property values
 159  0
                 if (muleContext.getExpressionManager().isExpression(value.toString()))
 160  
                 {
 161  0
                     realValue = muleContext.getExpressionManager().evaluate(value.toString(), message);
 162  
                 }
 163  
 
 164  0
                 if (realValue != null)
 165  
                 {
 166  0
                     if (message.getProperty(key, scope) != null)
 167  
                     {
 168  0
                         if (overwrite)
 169  
                         {
 170  0
                             logger.debug("Overwriting message property " + key);
 171  0
                             message.setProperty(key, realValue, scope);
 172  
                         }
 173  0
                         else if(logger.isDebugEnabled())
 174  
                         {
 175  0
                             logger.debug(MessageFormat.format(
 176  
                                 "Message already contains the property and overwrite is false, skipping: key={0}, value={1}, scope={2}",
 177  
                                 key, realValue, scope));
 178  
                         }
 179  
                     }
 180  
                     //If value is null an exception will not be thrown if the key was marked as optional (with a '?'). If not
 181  
                     //optional the expression evaluator will throw an exception
 182  
                     else
 183  
                     {
 184  0
                         message.setProperty(key, realValue, scope);
 185  
                     }
 186  
                 }
 187  0
                 else if (logger.isInfoEnabled())
 188  
                 {
 189  0
                     logger.info(MessageFormat.format(
 190  
                         "Property with key ''{0}'', not found on message using ''{1}''. Since the value was marked optional, nothing was set on the message for this property",
 191  
                         key, value));
 192  
                 }
 193  0
             }
 194  
         }
 195  0
     }
 196  
 
 197  
     protected void renameProperties(MuleMessage message)
 198  
     {
 199  0
         for (Map.Entry<String, String> entry : this.renameProperties.entrySet())
 200  
         {
 201  0
             if (entry.getKey() == null)
 202  
             {
 203  0
                 logger.error("Setting Null property keys is not supported, this entry is being ignored");
 204  
             }
 205  
             else
 206  
             {
 207  0
                 final String key = entry.getKey();
 208  0
                 String value = entry.getValue();
 209  
 
 210  0
                 if (value == null)
 211  
                 {
 212  0
                     logger.error("Setting Null property values for renameProperties is not supported, this entry is being ignored");
 213  
                 }
 214  
                 else
 215  
                 {
 216  
                     //Enable expression support for property values
 217  0
                     if (muleContext.getExpressionManager().isValidExpression(value))
 218  
                     {
 219  0
                         Object temp = muleContext.getExpressionManager().evaluate(value, message);
 220  0
                         if (temp != null)
 221  
                         {
 222  0
                             value = temp.toString();
 223  
                         }
 224  
                     }
 225  
 
 226  
                     /* log transformation */
 227  0
                     if (logger.isDebugEnabled() && message.getProperty(key, scope) == null)
 228  
                     {
 229  0
                         logger.debug(String.format("renaming message property '%s' to '%s'", key, value));
 230  
                     }
 231  
 
 232  0
                     renameInScope(key, value, scope, message);
 233  
                 }
 234  0
             }
 235  
         }
 236  0
     }
 237  
 
 238  
     protected void renameInScope(String oldKey, String newKey, PropertyScope propertyScope, MuleMessage message)
 239  
     {
 240  0
         Object propValue = message.getProperty(oldKey, propertyScope);
 241  0
         message.removeProperty(oldKey, propertyScope);
 242  0
         message.setProperty(newKey, propValue, propertyScope);
 243  0
     }
 244  
 
 245  
     public List<String> getDeleteProperties()
 246  
     {
 247  0
         return deleteProperties;
 248  
     }
 249  
 
 250  
     /**
 251  
      * @see #setDeleteProperties(String...)
 252  
      */
 253  
     public void setDeleteProperties(List<String> deleteProperties)
 254  
     {
 255  0
         this.deleteProperties = deleteProperties;
 256  0
     }
 257  
 
 258  
     public void setDeleteProperties(String... deleteProperties)
 259  
     {
 260  0
         this.deleteProperties = Arrays.asList(deleteProperties);
 261  0
     }
 262  
 
 263  
     public Map<String, Object> getAddProperties()
 264  
     {
 265  0
         return addProperties;
 266  
     }
 267  
 
 268  
     public void setAddProperties(Map<String, Object> addProperties)
 269  
     {
 270  0
         this.addProperties = addProperties;
 271  0
     }
 272  
 
 273  
     /**
 274  
      * @return the renameProperties
 275  
      */
 276  
     public Map<String, String> getRenameProperties()
 277  
     {
 278  0
         return this.renameProperties;
 279  
     }
 280  
 
 281  
     /**
 282  
      * @param renameProperties the renameProperties to set
 283  
      */
 284  
     public void setRenameProperties(Map<String, String> renameProperties)
 285  
     {
 286  0
         this.renameProperties = renameProperties;
 287  0
     }
 288  
 
 289  
     public String getGetProperty()
 290  
     {
 291  0
         return getProperty;
 292  
     }
 293  
 
 294  
     public void setGetProperty(String getProperty)
 295  
     {
 296  0
         this.getProperty = getProperty;
 297  0
     }
 298  
 
 299  
     public boolean isOverwrite()
 300  
     {
 301  0
         return overwrite;
 302  
     }
 303  
 
 304  
     public void setOverwrite(final boolean overwrite)
 305  
     {
 306  0
         this.overwrite = overwrite;
 307  0
     }
 308  
 
 309  
     public PropertyScope getScope()
 310  
     {
 311  0
         return scope;
 312  
     }
 313  
 
 314  
     public void setScope(PropertyScope scope)
 315  
     {
 316  0
         this.scope = scope;
 317  0
     }
 318  
     
 319  
     /**
 320  
      * For XML-based config
 321  
      *
 322  
      * @return The string value name for a {@link org.mule.api.transport.PropertyScope}
 323  
      */
 324  
     public String getScopeName()
 325  
     {
 326  0
         return scope != null ? scope.getScopeName() : null;
 327  
     }
 328  
 
 329  
     /**
 330  
      * For XML-based config
 331  
      * @param scopeName The string value name for a {@link org.mule.api.transport.PropertyScope}
 332  
      */
 333  
     public void setScopeName(String scopeName)
 334  
     {
 335  0
         this.scope = PropertyScope.get(scopeName);
 336  0
     }
 337  
 }