View Javadoc

1   /*
2    * $Id: OgnlConverterWrapper.java,v 1.2 2004/04/08 20:56:11 eelco12 Exp $
3    * $Revision: 1.2 $
4    * $Date: 2004/04/08 20:56:11 $
5    *
6    * ====================================================================
7    * Copyright (c) 2003, Open Edge B.V.
8    * All rights reserved.
9    * Redistribution and use in source and binary forms, with or without 
10   * modification, are permitted provided that the following conditions are met:
11   * Redistributions of source code must retain the above copyright notice, 
12   * this list of conditions and the following disclaimer. Redistributions 
13   * in binary form must reproduce the above copyright notice, this list of 
14   * conditions and the following disclaimer in the documentation and/or other 
15   * materials provided with the distribution. Neither the name of OpenEdge B.V. 
16   * nor the names of its contributors may be used to endorse or promote products 
17   * derived from this software without specific prior written permission.
18   * 
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
20   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
22   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
23   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
24   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
25   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
26   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
27   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
28   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
29   * THE POSSIBILITY OF SUCH DAMAGE.
30   */
31  package nl.openedge.baritus.population;
32  
33  import java.lang.reflect.Member;
34  import java.util.Locale;
35  import java.util.Map;
36  
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  import nl.openedge.baritus.ConverterRegistry;
41  import nl.openedge.baritus.ExecutionParams;
42  import nl.openedge.baritus.LogConstants;
43  import nl.openedge.baritus.converters.ConversionException;
44  import nl.openedge.baritus.converters.Converter;
45  
46  import ognl.DefaultTypeConverter;
47  import ognl.OgnlOps;
48  
49  /***
50   * This class should be registered with the Ognl context before parsing
51   * in order to be abel to use our converters. It implements Ognl TypeConverter
52   * and uses the ConverterRegistry to lookup converters. If no converter is found
53   * for a given type, the default conversion of Ognl is used.
54   * 
55   * @author Eelco Hillenius
56   */
57  public class OgnlConverterWrapper extends DefaultTypeConverter
58  {
59  	
60  	private static Log populationLog = LogFactory.getLog(LogConstants.POPULATION_LOG);
61  
62  	/***
63  	 * Convert the provided value to provided type using provided context.
64  	 * @param context Ognl context
65  	 * @param value the current, unconverted value
66  	 * @param toType the type that should be converted to
67  	 * @return Object the converted value
68  	 * @see ognl.DefaultTypeConverter#convertValue(java.util.Map, java.lang.Object, java.lang.Class)
69  	 */
70  	public Object convertValue(Map context, Object value, Class toType)
71  	{
72  
73  		if(value == null) return null;
74  
75  		Object converted = null;
76  		
77  		Locale locale = (Locale)context.get(OgnlFieldPopulator.CTX_KEY_CURRENT_LOCALE);
78  		ExecutionParams executionParams = (ExecutionParams)
79  			context.get(OgnlFieldPopulator.CTX_KEY_CURRENT_EXEC_PARAMS);
80  		
81  		if((!toType.isArray()) && value instanceof String[] && ((String[])value).length == 1)
82  		{
83  			value = ((String[])value)[0];	
84  		}
85  		
86  		if( (value instanceof String) && ((String)value).trim().equals("") 
87  			&& executionParams.isSetNullForEmptyString())
88  		{
89  			if(populationLog.isDebugEnabled())
90  			{
91  				String name = (String)context.get(
92  					OgnlFieldPopulator.CTX_KEY_CURRENT_FIELD_NAME);
93  				populationLog.debug("empty input for property " + name + " converted to null");
94  			}
95  			return null;
96  		}
97  		
98  		context.put(OgnlFieldPopulator.CTX_KEY_CURRENT_TRIED_VALUE, value);
99  		
100 		try
101 		{
102 			ConverterRegistry reg = ConverterRegistry.getInstance();
103 			Converter converter = reg.lookup(toType, locale);
104 			
105 			if(converter != null) // we found a converter
106 			{
107 				context.put(OgnlFieldPopulator.CTX_KEY_CURRENT_CONVERTER, converter);
108 				
109 				if(populationLog.isDebugEnabled())
110 				{
111 					String name = (String)context.get(
112 						OgnlFieldPopulator.CTX_KEY_CURRENT_FIELD_NAME);
113 					populationLog.debug("using converter " 
114 						+ converter + " for property " + name +
115 						" (type " + toType + ")");
116 				}
117 				
118 				if(!toType.isArray()) // a common case with request parameters is that
119 					// they are send as a string array instead of a plain string
120 				{
121 					if(value instanceof String[] && ((String[])value).length == 1) 
122 					{
123 						value = ((String[])value)[0];
124 					}					
125 				}
126 				
127 				converted = converter.convert(toType, value);	
128 			}
129 			else // no converter was found
130 			{
131 				converted = OgnlOps.convertValue(value, toType);
132 			}
133 		}
134 		catch(ConversionException e)
135 		{
136 			context.put(OgnlFieldPopulator.CTX_KEY_CURRENT_TARGET_TYPE, toType);
137 			throw e;
138 		}
139 		catch(Exception e)
140 		{
141 			context.put(OgnlFieldPopulator.CTX_KEY_CURRENT_TARGET_TYPE, toType);
142 			throw new ConversionException(e);
143 		}
144 		
145 		return converted;
146 	}
147 
148 	/***
149 	 * This method is only here to satisfy the interface. Method convertValue(Map, Object, Class)
150 	 * is called, so parameters member and propertyName are ignored.
151 	 * @see ognl.DefaultTypeConverter#convertValue(java.util.Map, java.lang.Object, java.lang.Class)
152 	 */
153 	public Object convertValue(
154 		Map context,
155 		Object target,
156 		Member member,
157 		String propertyName,
158 		Object value,
159 		Class toType)
160 	{
161 		return convertValue(context, value, toType);
162 	}
163 
164 }