View Javadoc

1   /*
2    * Copyright 2004-2005, 2007-2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package net.sf.morph.lang.languages;
17  
18  import java.util.Locale;
19  
20  import net.sf.composite.util.ObjectUtils;
21  import net.sf.morph.Defaults;
22  import net.sf.morph.lang.DecoratedLanguage;
23  import net.sf.morph.lang.LanguageException;
24  import net.sf.morph.transform.Converter;
25  import net.sf.morph.transform.TransformationException;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  /**
31   * A convenient base class for Languages that takes care of exception
32   * handling and logging.  Also exposes the
33   * {@link net.sf.morph.lang.DecoratedLanguage} interface while only requiring
34   * subclasses to implement the methods in {@link net.sf.morph.lang.Language}.
35   *
36   * @author Matt Sgarlata
37   * @since Nov 28, 2004
38   */
39  public abstract class BaseLanguage implements DecoratedLanguage {
40  
41  	private Converter converter;
42  	private String languageName;
43  
44  	private transient Log log;
45  
46  	/**
47  	 * Create a new BaseLanguage.
48  	 */
49  	public BaseLanguage() {
50  		super();
51  		establishLog(null);
52  	}
53  
54  	/**
55  	 * Implement <code>isProperty(expression)</code>.
56  	 * @param expression
57  	 * @return boolean
58  	 * @throws Exception
59  	 */
60  	protected abstract boolean isPropertyImpl(String expression) throws Exception;
61  
62  	/**
63  	 * Implement <code>getType(target, expression)</code>.
64  	 * @param target bean
65  	 * @param expression to read
66  	 * @return Class
67  	 * @throws Exception
68  	 */
69  	protected abstract Class getTypeImpl(Object target, String expression)
70  			throws Exception;
71  
72  	/**
73  	 * Implement <code>get(target, expression)</code>.
74  	 * @param target bean
75  	 * @param expression to get
76  	 * @return Object
77  	 * @throws Exception
78  	 */
79  	protected abstract Object getImpl(Object target, String expression) throws Exception;
80  
81  	/**
82  	 * Implement <code>set(target, expression, value)</code>.
83  	 * @param target bean
84  	 * @param expression to set
85  	 * @param value to set
86  	 * @throws Exception
87  	 */
88  	protected abstract void setImpl(Object target, String expression, Object value)
89  			throws Exception;
90  
91  	/**
92  	 * {@inheritDoc}
93  	 */
94  	public final boolean isProperty(String expression) throws LanguageException {
95  		try {
96  			boolean isProperty = isPropertyImpl(expression);
97  
98  			if (log.isTraceEnabled()) {
99  				log.trace("Expression '"
100 					+ expression
101 					+ "' denotes a"
102 					+ (isProperty ? " simple property of an object"
103 						: "n expression that involves traversal of an object graph"));
104 			}
105 			return isProperty;
106 		}
107 		catch (LanguageException e) {
108 			throw e;
109 		}
110 		catch (Exception e) {
111 			throw new LanguageException("Could not determine if expression '"
112 				+ expression + "' references a nested property", e);
113 		}
114 	}
115 
116 	/**
117 	 * {@inheritDoc}
118 	 */
119 	public final Class getType(Object target, String expression) throws LanguageException {
120 		if (target == null) {
121 			throw new LanguageException("The target object cannot be null");
122 		}
123 		if (log.isTraceEnabled()) {
124 			log.trace("Retrieving type of '" + expression + "' from target "
125 					+ ObjectUtils.getObjectDescription(target));
126 		}
127 		try {
128 			Class type = getTypeImpl(target, expression);
129 			return type == null ? Object.class : type;
130 		}
131 		catch (LanguageException e) {
132 			throw e;
133 		}
134 		catch (Exception e) {
135 			throw new LanguageException("Could not retrieve type of '"
136 					+ expression + "' from target "
137 					+ ObjectUtils.getObjectDescription(target), e);
138 		}
139 	}
140 
141 	/**
142 	 * {@inheritDoc}
143 	 */
144 	public final Object get(Object target, String expression) throws LanguageException {
145 		if (target == null) {
146 			throw new LanguageException("The target object cannot be null");
147 		}
148 		if (log.isTraceEnabled()) {
149 			log.trace("Retrieving '" + expression + "' from target "
150 					+ ObjectUtils.getObjectDescription(target));
151 		}
152 		try {
153 			return getImpl(target, expression);
154 		}
155 		catch (LanguageException e) {
156 			throw e;
157 		}
158 		catch (Exception e) {
159 			throw new LanguageException("Could not retrieve '" + expression
160 					+ "' from target "
161 					+ ObjectUtils.getObjectDescription(target), e);
162 		}
163 	}
164 
165 	/**
166 	 * {@inheritDoc}
167 	 */
168 	public final void set(Object target, String expression, Object value)
169 			throws LanguageException {
170 		set(target, expression, value, null);
171 	}
172 
173 	/**
174 	 * {@inheritDoc}
175 	 */
176 	public final Object get(Object target, String expression, Class destinationClass)
177 			throws LanguageException, TransformationException {
178 		return get(target, expression, destinationClass, null);
179 	}
180 
181 	/**
182 	 * {@inheritDoc}
183 	 */
184 	public final Object get(Object target, String expression, Class destinationClass,
185 			Locale locale) throws LanguageException, TransformationException {
186 		Object object = get(target, expression);
187 		return getConverter().convert(destinationClass, object, locale);
188 	}
189 
190 	/**
191 	 * {@inheritDoc}
192 	 */
193 	public final Object get(Object target, String expression, Locale locale,
194 			Class destinationClass) throws LanguageException, TransformationException {
195 		return get(target, expression, destinationClass, locale);
196 	}
197 
198 	/**
199 	 * {@inheritDoc}
200 	 */
201 	public void set(Object target, String expression, Object value, Locale locale)
202 			throws LanguageException, TransformationException {
203 
204 		if (target == null) {
205 			throw new LanguageException("The target object cannot be null");
206 		}
207 		if (log.isTraceEnabled()) {
208 			log.trace("Setting '" + expression + "' to "
209 				+ ObjectUtils.getObjectDescription(value) + " on target "
210 				+ ObjectUtils.getObjectDescription(target));
211 		}
212 		// first do any needed type conversion
213 		Class type = getType(target, expression);
214 		Object converted = type.isInstance(value) ? value : getConverter()
215 				.convert(type, value, locale);
216 
217 		try {
218 			setImpl(target, expression, converted);
219 		}
220 		catch (LanguageException e) {
221 			throw e;
222 		}
223 		catch (Exception e) {
224 			throw new LanguageException("Could not set '" + expression
225 					+ "' to " + ObjectUtils.getObjectDescription(value)
226 					+ " on target " + ObjectUtils.getObjectDescription(target),
227 					e);
228 		}
229 	}
230 
231 	/**
232 	 * Get the Converter.
233 	 * @return Converter
234 	 */
235 	public Converter getConverter() {
236 		if (converter == null) {
237 			setConverter(Defaults.createConverter());
238 		}
239 		return converter;
240 	}
241 
242 	/**
243 	 * Set the Converter.
244 	 * @param converter to set
245 	 */
246 	public void setConverter(Converter converter) {
247 		this.converter = converter;
248 	}
249 
250 	/**
251 	 * Get the languageName.
252 	 * @return String
253 	 */
254 	public String getLanguageName() {
255 		return languageName;
256 	}
257 
258 	/**
259 	 * Set the languageName.
260 	 * @param languageName the String to set
261 	 */
262 	public void setLanguageName(String languageName) {
263 		if (ObjectUtils.equals(languageName, this.languageName)) {
264 			return;
265 		}
266 		this.languageName = languageName;
267 		establishLog(languageName);
268 	}
269 
270 	private void establishLog(String name) {
271 		log = name == null ? LogFactory.getLog(getClass()) : LogFactory.getLog(name);
272 	}
273 
274 	/**
275 	 * {@inheritDoc}
276 	 */
277 	public String toString() {
278 		String name = getLanguageName();
279 		return name == null ? super.toString() : name;
280 	}
281 }