2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.test.mock;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.faces.application.Application;
25  import javax.faces.component.StateHolder;
26  import javax.faces.context.ExternalContext;
27  import javax.faces.context.FacesContext;
28  import javax.faces.el.EvaluationException;
29  import javax.faces.el.PropertyNotFoundException;
30  import javax.faces.el.PropertyResolver;
31  import javax.faces.el.ReferenceSyntaxException;
32  import javax.faces.el.ValueBinding;
33  import javax.faces.el.VariableResolver;
34  
35  
36  /***
37   * <p>Mock implementation of <code>ValueBinding</code>.</p>
38   */
39  
40  public class MockValueBinding extends ValueBinding implements StateHolder {
41  
42  
43      // ------------------------------------------------------------ Constructors
44  
45  
46      /***
47       * <p>Construct a default instance.</p>
48       */
49      public MockValueBinding() {
50  
51          this(null, null);
52  
53      }
54  
55  
56      /***
57       * <p>Construct a new value binding for the specified expression.</p>
58       *
59       * @param application Application instance to be wrapped
60       * @param ref Expression to be wrapped
61       */
62      public MockValueBinding(Application application, String ref) {
63  
64          this.application = application;
65          if (ref != null) {
66              if (ref.startsWith("#{") && ref.endsWith("}")) {
67                  ref = ref.substring(2, ref.length() - 1);
68              }
69          }
70          this.ref = ref;
71  
72      }
73  
74  
75      // ----------------------------------------------------- Mock Object Methods
76  
77  
78      /***
79       * <p>Return the expression string for this value binding.</p>
80       */
81      public String ref() {
82  
83          return this.ref;
84  
85      }
86  
87  
88      // ------------------------------------------------------ Instance Variables
89  
90  
91      /***
92       * <p>The <code>Application</code> instance for this application.</p>
93       */
94      private transient Application application; // Restored as necessary
95  
96  
97      /***
98       * <p>The expression this value binding will evaluate.</p>
99       */
100     private String ref;
101 
102 
103     // ---------------------------------------------------- ValueBinding Methods
104 
105 
106     /*** {@inheritDoc} */
107     public Object getValue(FacesContext context)
108         throws EvaluationException, PropertyNotFoundException {
109 
110         if (context == null) {
111             throw new NullPointerException();
112         }
113         List names = parse(ref);
114 
115         // Resolve the variable name
116         VariableResolver vr = application().getVariableResolver();
117         String name = (String) names.get(0);
118         Object base = vr.resolveVariable(context, name);
119         if (names.size() < 2) {
120             return (base);
121         }
122 
123         // Resolve the property names
124         PropertyResolver pr = application().getPropertyResolver();
125         for (int i = 1; i < names.size(); i++) {
126             base = pr.getValue(base, (String) names.get(i));
127         }
128 
129         // Return the resolved value
130         return (base);
131 
132     }
133 
134 
135     /*** {@inheritDoc} */
136     public void setValue(FacesContext context, Object value)
137         throws EvaluationException, PropertyNotFoundException {
138 
139         if (context == null) {
140             throw new NullPointerException();
141         }
142         List names = parse(ref);
143 
144         // Resolve the variable name
145         VariableResolver vr = application().getVariableResolver();
146         String name = (String) names.get(0);
147         Object base = vr.resolveVariable(context, name);
148         if (names.size() < 2) {
149             if ("applicationScope".equals(name)
150                 || "requestScope".equals(name)
151                 || "sessionScope".equals(name)) {
152                 throw new ReferenceSyntaxException("Cannot set '"
153                                                    + name + "'");
154             }
155             Map map = econtext().getRequestMap();
156             if (map.containsKey(name)) {
157                 map.put(name, value);
158                 return;
159             }
160             map = econtext().getSessionMap();
161             if ((map != null) && (map.containsKey(name))) {
162                 map.put(name, value);
163                 return;
164             }
165             map = econtext().getApplicationMap();
166             if (map.containsKey(name)) {
167                 map.put(name, value);
168                 return;
169             }
170             econtext().getRequestMap().put(name, value);
171             return;
172         }
173 
174         // Resolve the property names
175         PropertyResolver pr = application().getPropertyResolver();
176         for (int i = 1; i < (names.size() - 1); i++) {
177             // System.out.println("  property=" + names.get(i));
178             base = pr.getValue(base, (String) names.get(i));
179         }
180 
181         // Update the last property
182         pr.setValue(base, (String) names.get(names.size() - 1), value);
183 
184     }
185 
186 
187     /*** {@inheritDoc} */
188     public boolean isReadOnly(FacesContext context)
189         throws PropertyNotFoundException {
190 
191         if (context == null) {
192             throw new NullPointerException();
193         }
194         List names = parse(ref);
195 
196         // Resolve the variable name
197         VariableResolver vr = application().getVariableResolver();
198         String name = (String) names.get(0);
199         Object base = vr.resolveVariable(context, name);
200         if (names.size() < 2) {
201             return true;
202         }
203 
204         // Resolve the property names
205         PropertyResolver pr = application().getPropertyResolver();
206         for (int i = 1; i < names.size() - 1; i++) {
207             base = pr.getValue(base, (String) names.get(i));
208         }
209 
210         // Return the read only state of the final property
211         return pr.isReadOnly(base, (String) names.get(names.size() - 1));
212 
213     }
214 
215 
216     /*** {@inheritDoc} */
217     public Class getType(FacesContext context)
218         throws PropertyNotFoundException {
219 
220         if (context == null) {
221             throw new NullPointerException();
222         }
223         List names = parse(ref);
224 
225         // Resolve the variable name
226         VariableResolver vr = application().getVariableResolver();
227         String name = (String) names.get(0);
228         Object base = vr.resolveVariable(context, name);
229         if (names.size() < 2) {
230             return base.getClass();
231         }
232 
233         // Resolve the property names
234         PropertyResolver pr = application().getPropertyResolver();
235         for (int i = 1; i < names.size() - 1; i++) {
236             base = pr.getValue(base, (String) names.get(i));
237         }
238 
239         // Return the type of the final property
240         return pr.getType(base, (String) names.get(names.size() - 1));
241 
242     }
243 
244     /*** {@inheritDoc} */
245     public String getExpressionString() {
246 
247         return "#{" + ref + "}";
248 
249     }
250 
251 
252     // ----------------------------------------------------- StateHolder Methods
253 
254 
255     /*** {@inheritDoc} */
256     public Object saveState(FacesContext context) {
257 
258         Object[] values = new Object[1];
259         values[0] = ref;
260         return values;
261 
262     }
263 
264 
265     /*** {@inheritDoc} */
266     public void restoreState(FacesContext context, Object state) {
267 
268         Object[] values = (Object[]) state;
269         ref = (String) values[0];
270 
271     }
272 
273 
274     /***
275      * <p>Flag indicating that this value is transient.</p>
276      */
277     private boolean transientFlag = false;
278 
279 
280     /*** {@inheritDoc} */
281     public boolean isTransient() {
282 
283         return this.transientFlag;
284 
285     }
286 
287 
288     /*** {@inheritDoc} */
289     public void setTransient(boolean transientFlag) {
290 
291         this.transientFlag = transientFlag;
292 
293     }
294 
295 
296     // --------------------------------------------------------- Private Methods
297 
298 
299     /***
300      * <p>Return the relevant <code>Application</code> instance.</p>
301      */
302     private Application application() {
303 
304         if (application == null) {
305             application = FacesContext.getCurrentInstance().getApplication();
306         }
307         return (application);
308 
309     }
310 
311 
312     /***
313      * <p>Return the relevant <code>ExternalContext</code> instance.</p>
314      */
315     private ExternalContext econtext() {
316 
317         return (FacesContext.getCurrentInstance().getExternalContext());
318 
319     }
320 
321 
322     /***
323      * <p>Return a list of the expression elements in this expression.</p>
324      *
325      * @param ref Expression to be parsed
326      */
327     private List parse(String ref) {
328 
329         List names = new ArrayList();
330         StringBuffer expr = new StringBuffer(ref);
331         boolean isBlockOn = false;
332         for (int i = expr.length() - 1; i > -1; i--) {
333             if (expr.charAt(i) == ' ') {
334                 expr.deleteCharAt(i);
335             } else if (expr.charAt(i) == ']') {
336                 expr.deleteCharAt(i);
337             } else if (expr.charAt(i) == '[') {
338                 expr.deleteCharAt(i);
339             } else if (expr.charAt(i) == '\'') {
340                 if (!isBlockOn) {
341                     expr.deleteCharAt(i);
342                 } else {
343                     names.add(0, expr.substring(i + 1));
344                     expr.delete(i, expr.length());
345                 }
346                 isBlockOn = !isBlockOn;
347             } else if (expr.charAt(i) == '.' && !isBlockOn) {
348                 names.add(0, expr.substring(i + 1));
349                 expr.delete(i, expr.length());
350             }
351         }
352 
353         if (expr.length() > 0) {
354             names.add(0, expr.toString());
355         }
356 
357         if (names.size() < 1) {
358             throw new ReferenceSyntaxException("No expression in '"
359                     + ref + "'");
360         }
361         for (int i = 0; i < names.size(); i++) {
362             String name = (String) names.get(i);
363             if (name.length() < 1) {
364                 throw new ReferenceSyntaxException("Invalid expression '"
365                         + ref + "'");
366             }
367         }
368         return (names);
369 
370     }
371 
372 
373 }