View Javadoc

1   /*
2    * $Id: BasicDeltaPropertiesAccessor.java,v 1.17 2011/06/16 09:29:40 jbmeslin Exp $
3    * 
4    */
5   package org.rcfaces.core.internal.component;
6   
7   import java.util.ArrayList;
8   import java.util.HashMap;
9   import java.util.HashSet;
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.Set;
14  
15  import javax.el.ValueExpression;
16  import javax.faces.FacesException;
17  import javax.faces.component.UIComponentBase;
18  import javax.faces.context.FacesContext;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.rcfaces.core.internal.util.ClassLocator;
23  import org.rcfaces.core.internal.util.StateHolderTools;
24  
25  /**
26   * 
27   * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
28   * @version $Revision: 1.17 $ $Date: 2011/06/16 09:29:40 $
29   */
30  public class BasicDeltaPropertiesAccessor extends AbstractPropertiesAccessor
31          implements IDeltaPropertiesAccessor {
32      private static final String REVISION = "$Revision: 1.17 $";
33  
34      private static final Log LOG = LogFactory
35              .getLog(BasicDeltaPropertiesAccessor.class);
36  
37      private static final int PROPERTY_INITIAL_SIZE = 8;
38  
39      private static final boolean CLONE_VALUE = true;
40  
41      private static final Object UNDEFINED = new Object();
42  
43      private final IPropertiesAccessor parent;
44  
45      private Map properties;
46      
47      
48      private static IUnproxifyValueExpression unproxifyValueExpression = null;
49      
50      static {
51      	try {
52      		ClassLocator.load("org.apache.jasper.el.JspValueExpression", BasicDeltaPropertiesAccessor.class, null);
53      		
54      		Class cl =ClassLocator.load("org.rcfaces.core.internal.jasper.JasperUnproxifyValueExpression", BasicDeltaPropertiesAccessor.class, null);
55      		unproxifyValueExpression= (IUnproxifyValueExpression) cl.newInstance();
56      	
57      	} catch (ClassNotFoundException ex) {
58      		LOG.error(ex.getMessage());
59      	} catch (Throwable ex) {
60      		 LOG.error(ex.getMessage());
61      	}
62      }
63      
64  
65      public BasicDeltaPropertiesAccessor(IPropertiesAccessor parent) {
66          this.parent = parent;
67      }
68  
69      public void commitProperties(FacesContext context) {
70          if (hasModifiedProperties() == false) {
71              return;
72          }
73  
74          parent.putAll(context, properties.entrySet(), UNDEFINED);
75      }
76  
77      public boolean isPropertySetted(String propertyName) {
78          if (properties != null) {
79              Object value = properties.get(propertyName);
80              if (value != null) {
81                  if (value == UNDEFINED) {
82                      return false;
83                  }
84  
85                  return true;
86              }
87          }
88  
89          return parent.isPropertySetted(propertyName);
90      }
91  
92      public Object getProperty(String propertyName) {
93          if (properties != null && properties.isEmpty() == false) {
94              Object ret = properties.get(propertyName);
95              if (ret != null) {
96                  if (ret == UNDEFINED) {
97                      return null;
98                  }
99  
100                 return ret;
101             }
102         }
103 
104         Object value = parent.getProperty(propertyName);
105 
106         if (CLONE_VALUE && value != null) {
107             Object original = value;
108 
109             if (value instanceof Map) {
110                 value = new HashMap((Map) value);
111 
112             } else if (value instanceof List) {
113                 value = new ArrayList((List) value);
114 
115             } else if (value instanceof Set) {
116                 value = new HashSet((Set) value);
117             }
118 
119             if (original != value) {
120                 setProperty(null, propertyName, value);
121             }
122         }
123 
124         return value;
125     }
126 
127     public Object setProperty(FacesContext facesContext, String propertyName,
128             Object value) {
129 
130         Object initialValue = parent.getProperty(propertyName);
131 
132         // La propriété est identique au model ?
133         if (initialValue == value
134                 || (initialValue != null && initialValue.equals(value))) {
135 
136             if (properties != null) {
137                 return properties.remove(propertyName);
138             }
139 
140             // On remet l'ancienne valeur !
141             return initialValue;
142         }
143 
144         // On doit gérer le NULL !
145         if (value == null) {
146             value = UNDEFINED;
147         }
148 
149         if (properties == null) {
150             properties = createMap(PROPERTY_INITIAL_SIZE);
151         }
152 
153         Object old = properties.put(propertyName, value);
154         if (old == UNDEFINED) {
155             return initialValue;
156         }
157 
158         return old;
159     }
160 
161     public void setProperty(FacesContext facesContext, String propertyName,
162             ValueExpression valueExpression) {
163     	
164         Object initialValue = parent.getProperty(propertyName);
165         
166         if (unproxifyValueExpression!=null) {
167         	valueExpression = unproxifyValueExpression.process(valueExpression);
168         }
169         
170         if (initialValue != null && initialValue.equals(valueExpression)) {
171             return;
172         }
173 
174         LOG.error("Can not change a ValueExpression property '" + propertyName
175                 + "' valueExpression=" + valueExpression + " original='"
176                 + initialValue + "'.");
177 
178         throw new FacesException(
179                 "Can not set a ValueExpression while a delta phase.");
180     }
181 
182 	public Object removeProperty(FacesContext facesContext, String propertyName) {
183 
184         Object initialValue = parent.getProperty(propertyName);
185         if (initialValue != null) {
186             // Un model existe !
187 
188             if (properties == null) {
189                 properties = createMap(PROPERTY_INITIAL_SIZE);
190             }
191 
192             // On positionne donc un UNDEFINED dans le delta !
193             Object old = properties.put(propertyName, UNDEFINED);
194 
195             if (old == UNDEFINED) {
196                 // L'ancien est deja UNDEFINED => retourne null;
197                 return null;
198             }
199 
200             if (old != null) {
201                 // Il y a avait deja une valeur dans le delta
202                 return old;
203             }
204 
205             // Sinon on retourne la valeur initiale
206             return initialValue;
207         }
208 
209         // Pas de valeur initiale !
210 
211         // On positionne donc un UNDEFINED dans le delta !
212         Object old = properties.put(propertyName, UNDEFINED);
213         if (old == UNDEFINED) {
214             // L'ancien est deja UNDEFINED => retourne null;
215             return null;
216         }
217 
218         return old;
219     }
220 
221     public Object saveState(FacesContext context) {
222         if (hasModifiedProperties() == false) {
223             return null;
224         }
225 
226         Object rets[] = new Object[properties.size() * 2];
227         int i = 0;
228         for (Iterator it = properties.entrySet().iterator(); it.hasNext();) {
229             Map.Entry entry = (Map.Entry) it.next();
230 
231             rets[i++] = entry.getKey();
232 
233             Object value = entry.getValue();
234             if (value == UNDEFINED || value == null) {
235                 i++;
236                 continue;
237             }
238 
239             if (StateHolderTools.isPrimitive(value) == false) {
240                 rets[i++] = UIComponentBase.saveAttachedState(context, value);
241 
242                 continue;
243             }
244 
245             rets[i++] = value;
246         }
247 
248         return rets;
249     }
250 
251     public void restoreState(FacesContext context, Object state) {
252         if (state == null) {
253             return;
254         }
255 
256         if ((state instanceof Object[]) == false) {
257             throw new FacesException(
258                     "Bad serialized format ! (not an objects array !)");
259         }
260 
261         Object datas[] = (Object[]) state;
262 
263         properties = new HashMap(datas.length / 2);
264 
265         for (int i = 0; i < datas.length;) {
266             String key = (String) datas[i++];
267             Object value = datas[i++];
268 
269             if (StateHolderTools.isPrimitive(value) == false) {
270                 value = UIComponentBase.restoreAttachedState(context, value);
271             }
272 
273             setProperty(context, key, value);
274         }
275     }
276 
277     public void release() {
278         properties = null;
279     }
280 
281     public Set keySet() {
282         Set l = parent.keySet();
283         if (properties == null || properties.isEmpty()) {
284             // Pas de propriétés locales !
285             return l;
286         }
287 
288         Set v = new HashSet(l.size() + properties.size());
289         v.addAll(l);
290 
291         for (Iterator it = properties.entrySet().iterator(); it.hasNext();) {
292             Map.Entry entry = (Map.Entry) it.next();
293 
294             String key = (String) entry.getKey();
295             Object value = entry.getValue();
296 
297             if (value == UNDEFINED) {
298                 v.remove(key);
299                 continue;
300             }
301 
302             v.add(key);
303         }
304 
305         return v;
306     }
307 
308     public boolean hasModifiedProperties() {
309         return properties != null && properties.size() > 0;
310     }
311 
312     public int size() {
313         if (hasModifiedProperties() == false) {
314             return parent.size();
315         }
316 
317         Set l = parent.keySet();
318 
319         int cnt = l.size();
320         for (Iterator it = properties.entrySet().iterator(); it.hasNext();) {
321             Map.Entry entry = (Map.Entry) it.next();
322 
323             String key = (String) entry.getKey();
324             Object value = entry.getValue();
325 
326             boolean contains = l.contains(key);
327             if (contains) {
328                 if (value == UNDEFINED) {
329                     // Valeur connue mais mise à NULL
330                     cnt--;
331                 }
332 
333                 continue;
334             }
335 
336             if (value == UNDEFINED) {
337                 // Valeur à NULL, mais inconnue
338                 continue;
339             }
340 
341             // Valeur ajoutée
342             cnt++;
343         }
344 
345         return cnt;
346     }
347 
348     public String toString() {
349         if (hasModifiedProperties() == false) {
350             return "{Delta: NONE}";
351         }
352 
353         Set keys = keySet();
354 
355         String s = "{Delta: ";
356 
357         boolean first = true;
358         for (Iterator it = keys.iterator(); it.hasNext();) {
359             String key = (String) it.next();
360 
361             if (first) {
362                 first = false;
363             } else {
364                 s += ",";
365             }
366 
367             if (properties.containsKey(key)) {
368                 s += "(D)";
369             }
370             s += key + "=";
371 
372             Object obj = getProperty(key);
373             if (obj instanceof ValueExpression) {
374                 s += "'" + ((ValueExpression) obj).getExpressionString() + "'";
375 
376             } else if (obj != null) {
377                 s += "'" + obj + "'";
378 
379             } else {
380                 s += obj;
381             }
382         }
383 
384         s += "}";
385 
386         return s;
387     }
388 }