1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.change;
20
21 import java.util.HashMap;
22
23 import javax.el.ValueExpression;
24
25 import javax.faces.component.NamingContainer;
26 import javax.faces.component.UIComponent;
27 import javax.faces.context.FacesContext;
28 import javax.faces.el.ValueBinding;
29
30 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
31
32
33
34
35
36
37
38
39 public abstract class ChangeManager
40 {
41 public static void registerDocumentFactory(
42 String targetClassName,
43 String converterClassName)
44 {
45 if ((targetClassName == null) || (targetClassName.length() == 0))
46 throw new IllegalArgumentException(_LOG.getMessage(
47 "TARGET_CLASS_NAME_MUST_BE_PROVIDED"));
48
49 if ((converterClassName == null) || (converterClassName.length() == 0))
50 throw new IllegalArgumentException(_LOG.getMessage(
51 "CONVERTER_CLASS_NAME_MUST_BE_PROVIDED"));
52
53 synchronized (_CLASSNAME_TO_CONVERTER_NAME_MAP)
54 {
55 _CLASSNAME_TO_CONVERTER_NAME_MAP.put(targetClassName, converterClassName);
56 }
57 }
58
59
60
61
62
63
64 protected static DocumentChange createDocumentChange(
65 ComponentChange change)
66 {
67 Class<? extends ComponentChange> changeClass = change.getClass();
68
69 Object converterObject = null;
70 DocumentChangeFactory converter = null;
71
72 synchronized (_CLASS_TO_CONVERTER_MAP)
73 {
74 converterObject = _CLASS_TO_CONVERTER_MAP.get(changeClass);
75 }
76
77 if (converterObject != null)
78 {
79 converter = (DocumentChangeFactory)converterObject;
80 }
81 else
82 {
83 String converterName = null;
84
85 synchronized (_CLASSNAME_TO_CONVERTER_NAME_MAP)
86 {
87 converterName =
88 _CLASSNAME_TO_CONVERTER_NAME_MAP.get(changeClass.getName());
89 }
90
91 if (converterName != null)
92 {
93 try
94 {
95 ClassLoader contextClassLoader =
96 Thread.currentThread().getContextClassLoader();
97
98 Class<?> converterClass = contextClassLoader.loadClass(converterName);
99 if (DocumentChangeFactory.class.isAssignableFrom(converterClass))
100 {
101 converter = (DocumentChangeFactory)converterClass.newInstance();
102
103 synchronized (_CLASS_TO_CONVERTER_MAP)
104 {
105 _CLASS_TO_CONVERTER_MAP.put(changeClass, converter);
106 }
107 }
108 else
109 {
110
111 _LOG.warning("CONVERSION_CLASS_TYPE", new Object[] {converterClass, DocumentChangeFactory.class});
112 }
113 }
114 catch (Throwable e)
115 {
116 _LOG.warning("UNABLE_INSTANTIATE_CONVERTERCLASS", converterName);
117 _LOG.warning(e);
118 }
119
120
121
122 if (converter == null)
123 {
124
125 _CLASSNAME_TO_CONVERTER_NAME_MAP.remove(converterName);
126
127 return null;
128 }
129 }
130 }
131
132
133 if (converter != null)
134 return converter.convert(change);
135
136 return null;
137 }
138
139
140
141
142
143
144
145
146
147 public abstract void addComponentChange(
148 FacesContext facesContext,
149 UIComponent uiComponent,
150 ComponentChange change);
151
152
153
154
155
156
157
158
159
160 public AttributeComponentChange replaceAttributeChangeIfPresent(FacesContext facesContext,
161 UIComponent uiComponent,
162 AttributeComponentChange attributeComponentChange)
163 {
164 _LOG.warning("Must be implemented by subclass");
165 return null;
166 }
167
168
169
170
171
172
173
174
175
176 public void addDocumentChange(
177 FacesContext facesContext,
178 UIComponent uiComponent,
179 DocumentChange change)
180 {
181 if (facesContext == null || uiComponent == null || change == null)
182 throw new IllegalArgumentException(_LOG.getMessage(
183 "CANNOT_ADD_CHANGE_WITH_FACECONTEXT_OR_UICOMPONENT_OR_NULL"));
184 }
185
186
187
188
189
190
191
192 public void applyComponentChangesForCurrentView(FacesContext facesContext)
193 {
194 throw new UnsupportedOperationException("Subclassers must implement");
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209 public void applyComponentChangesForSubtree(
210 FacesContext facesContext,
211 NamingContainer root
212 )
213 {
214 throw new UnsupportedOperationException("Subclassers must implement");
215 }
216
217
218
219
220
221
222
223
224 public void applySimpleComponentChanges(FacesContext context, UIComponent component)
225 {
226 throw new UnsupportedOperationException("Subclassers must implement");
227 }
228
229 private static class AttributeConverter extends DocumentChangeFactory
230 {
231 @Override
232 public DocumentChange convert(ComponentChange compChange)
233 {
234 if (compChange instanceof AttributeComponentChange)
235 {
236 AttributeComponentChange change = (AttributeComponentChange)compChange;
237
238 Object value = change.getAttributeValue();
239
240
241 String valueString = null;
242 if ((value == null) ||
243 (value instanceof CharSequence) ||
244 (value instanceof Number) ||
245 (value instanceof Boolean))
246 {
247 valueString = (value != null)? value.toString() : null;
248 }
249 else if (value instanceof ValueExpression)
250 {
251 valueString = ((ValueExpression)value).getExpressionString();
252 }
253 else if (value instanceof ValueBinding)
254 {
255 valueString = ((ValueBinding)value).getExpressionString();
256 }
257
258 if (valueString != null)
259 return new AttributeDocumentChange(change.getAttributeName(),
260 valueString);
261 }
262
263
264 return null;
265 }
266 }
267
268 private static HashMap<String, String> _CLASSNAME_TO_CONVERTER_NAME_MAP =
269 new HashMap<String, String>();
270
271 private static HashMap<Class<? extends ComponentChange>, DocumentChangeFactory> _CLASS_TO_CONVERTER_MAP =
272 new HashMap<Class<? extends ComponentChange>, DocumentChangeFactory>();
273
274 static private final TrinidadLogger _LOG =
275 TrinidadLogger.createTrinidadLogger(ChangeManager.class);
276
277 static
278 {
279
280 _CLASS_TO_CONVERTER_MAP.put(AttributeComponentChange.class,
281 new AttributeConverter());
282 }
283
284 }