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