1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.transform.copiers;
17
18 import java.util.Arrays;
19 import java.util.Locale;
20 import java.util.Set;
21
22 import net.sf.morph.transform.Converter;
23 import net.sf.morph.transform.DecoratedConverter;
24 import net.sf.morph.transform.DecoratedCopier;
25 import net.sf.morph.transform.ExplicitTransformer;
26 import net.sf.morph.transform.TransformationException;
27 import net.sf.morph.transform.Transformer;
28 import net.sf.morph.transform.converters.DefaultToBooleanConverter;
29 import net.sf.morph.transform.transformers.BaseTransformer;
30 import net.sf.morph.util.Assert;
31 import net.sf.morph.util.ClassUtils;
32 import net.sf.morph.util.ContainerUtils;
33 import net.sf.morph.util.TransformerUtils;
34
35 /**
36 * This copier uses an <code>if</code> <code>Converter</code> to convert an incoming object to a Boolean.
37 * If this results in a Boolean object corresponding to boolean true, the then
38 * Transformer is invoked; otherwise the optional else Transformer is invoked if present.
39 *
40 * @author Matt Benson
41 * @since Morph 1.1
42 */
43 public class ConditionalCopier extends BaseTransformer implements DecoratedConverter,
44 DecoratedCopier, ExplicitTransformer {
45 private static final Converter DEFAULT_IF = new DefaultToBooleanConverter();
46
47 private Converter ifConverter;
48 private Transformer thenTransformer;
49 private Transformer elseTransformer;
50
51 /**
52 * {@inheritDoc}
53 */
54 protected Class[] getDestinationClassesImpl() throws Exception {
55 Transformer tt = getThenTransformer();
56 Transformer et = getElseTransformer();
57 return et == null ? tt.getDestinationClasses() : tt == null ? et
58 .getDestinationClasses() : merge(tt.getDestinationClasses(), et
59 .getDestinationClasses());
60 }
61
62 /**
63 * {@inheritDoc}
64 */
65 protected Class[] getSourceClassesImpl() throws Exception {
66 Transformer tt = getThenTransformer();
67 Transformer et = getElseTransformer();
68 return et == null ? tt.getSourceClasses() : tt == null ? et.getSourceClasses()
69 : merge(tt.getSourceClasses(), et.getSourceClasses());
70 }
71
72 /**
73 * {@inheritDoc}
74 */
75 protected boolean isAutomaticallyHandlingNulls() {
76 return false;
77 }
78
79 /**
80 * {@inheritDoc}
81 */
82 protected boolean isTransformableImpl(Class destinationType, Class sourceType)
83 throws Exception {
84 return TransformerUtils.isTransformable(getIfConverter(), Boolean.class,
85 sourceType)
86 && (TransformerUtils.isTransformable(getThenTransformer(),
87 destinationType, sourceType) || TransformerUtils.isTransformable(
88 getElseTransformer(), destinationType, sourceType));
89 }
90
91 /**
92 * {@inheritDoc}
93 */
94 public synchronized void setDestinationClasses(Class[] destinationClasses) {
95 super.setDestinationClasses(destinationClasses);
96 }
97
98 /**
99 * {@inheritDoc}
100 */
101 public synchronized void setSourceClasses(Class[] sourceClasses) {
102 super.setSourceClasses(sourceClasses);
103 }
104
105 /**
106 * {@inheritDoc}
107 */
108 protected Object convertImpl(Class destinationClass, Object source, Locale locale)
109 throws Exception {
110
111 return transform(destinationClass, source, source, locale,
112 TRANSFORMATION_TYPE_CONVERT);
113 }
114
115 /**
116 * {@inheritDoc}
117 */
118 protected void copyImpl(Object destination, Object source, Locale locale,
119 Integer preferredTransformationType) throws Exception {
120 transform(ClassUtils.getClass(destination), destination, source, locale,
121 TRANSFORMATION_TYPE_COPY);
122 }
123
124 /**
125 * Do the transformation.
126 * @param destinationType
127 * @param destination
128 * @param source
129 * @param locale
130 * @param preferredTransformationType
131 * @return
132 * @throws TransformationException
133 */
134 protected Object transform(Class destinationType, Object destination, Object source,
135 Locale locale, Integer preferredTransformationType)
136 throws TransformationException {
137 Transformer t;
138 if (evaluateIf(source, locale)) {
139 t = getThenTransformer();
140
141 Assert.notNull(t, "thenTransformer");
142 }
143 else {
144 t = getElseTransformer();
145 }
146 return t == null ? destination : TransformerUtils.transform(t, destinationType,
147 destination, source, locale, preferredTransformationType);
148 }
149
150 /**
151 * Evaluate the source object against the ifConverter.
152 * @param source
153 * @param locale
154 * @return boolean result
155 */
156 private boolean evaluateIf(Object source, Locale locale) {
157 Boolean b = (Boolean) getIfConverter().convert(Boolean.class, source, locale);
158 return Boolean.TRUE.equals(b);
159 }
160
161 /**
162 * Get the ifConverter.
163 * @return Converter.
164 */
165 public Converter getIfConverter() {
166 return ifConverter == null ? DEFAULT_IF : ifConverter;
167 }
168
169 /**
170 * Set the ifConverter. By default it will be an instance of {@link DefaultToBooleanConverter}.
171 * @param ifConverter the Converter ifConverter to set.
172 */
173 public void setIfConverter(Converter ifConverter) {
174 this.ifConverter = ifConverter;
175 }
176
177 /**
178 * Get the thenTransformer.
179 * @return Transformer.
180 */
181 public Transformer getThenTransformer() {
182 return thenTransformer;
183 }
184
185 /**
186 * Set the thenTransformer.
187 * @param thenTransformer the Transformer thenTransformer to set.
188 */
189 public void setThenTransformer(Transformer thenTransformer) {
190 this.thenTransformer = thenTransformer;
191 setInitialized(false);
192 }
193
194 /**
195 * Get the elseTransformer.
196 * @return Transformer.
197 */
198 public Transformer getElseTransformer() {
199 return elseTransformer;
200 }
201
202 /**
203 * Set the elseTransformer.
204 * @param elseTransformer the Transformer elseTransformer to set.
205 */
206 public void setElseTransformer(Transformer elseTransformer) {
207 this.elseTransformer = elseTransformer;
208 setInitialized(false);
209 }
210
211 /**
212 * Merge two Class[]s.
213 * @param a
214 * @param b
215 * @return Class[]
216 */
217 private static Class[] merge(Class[] a, Class[] b) {
218 Set s = ContainerUtils.createOrderedSet();
219 s.addAll(Arrays.asList(a));
220 s.addAll(Arrays.asList(b));
221 return (Class[]) s.toArray(new Class[s.size()]);
222 }
223
224 }
225