View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.valueChangeNotifier;
20  
21  import java.util.ArrayList;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  
26  import javax.faces.FacesException;
27  import javax.faces.context.FacesContext;
28  import javax.faces.el.MethodBinding;
29  import javax.faces.el.MethodNotFoundException;
30  import javax.faces.event.AbortProcessingException;
31  import javax.faces.event.ValueChangeEvent;
32  
33  /**
34   * Manage valueChange events to be fired after the UPDATE_MODEL phase.
35   * 
36   * @author Mario Ivankovits <imario - at - apache.org>  (latest modification by $Author$)
37   * @version $Revision$ $Date$
38   */
39  public final class ValueChangeManager
40  {
41      public final static Class[] SIGNATURE = new Class[]
42                                                          { ValueChangeEvent.class };
43      private final static String VCL_MANAGER = "_VCL_MANAGER_"
44              + ValueChangeNotifierTag.class.getName();
45  
46      private List events = new ArrayList(10);
47  
48      private static class Entry
49      {
50          private final String method;
51          private final ValueChangeEvent event;
52          private final List restoreStateCommands;
53  
54          public Entry(String method,
55                  ValueChangeEvent event,
56                  List restoreStateCommands)
57          {
58              this.method = method;
59              this.event = event;
60              this.restoreStateCommands = restoreStateCommands;
61          }
62      }
63  
64      private ValueChangeManager()
65      {
66      }
67  
68      /**
69       * add a new event 
70       */
71      public void addEvent(String method,
72              ValueChangeEvent event,
73              List restoreStateCommands)
74      {
75          events.add(new Entry(method, event, restoreStateCommands));
76      }
77  
78      /**
79       * walk through list and fire collected events 
80       */
81      public void fireEvents(FacesContext context)
82      {
83          try
84          {
85              Iterator iterEvents = events.iterator();
86              while (iterEvents.hasNext())
87              {
88                  Entry entry = (Entry) iterEvents.next();
89  
90                  saveCurrentStates(entry.restoreStateCommands);
91                  
92                  try
93                  {
94                      restoreEventStates(entry.restoreStateCommands);
95                      
96                      MethodBinding mb = context.getApplication().createMethodBinding(entry.method, SIGNATURE);
97                      mb.invoke(context, new Object[] { entry.event });
98                  }
99                  catch (MethodNotFoundException e)
100                 {
101                     throw new FacesException(e);
102                 }
103                 catch (AbortProcessingException e)
104                 {
105                     // ignore any other value change event
106                     return;
107                 }
108                 finally
109                 {
110                     restoreCurrentStates(entry.restoreStateCommands);
111                 }
112             }
113         }
114         finally
115         {
116             events.clear();            
117         }
118     }
119 
120     protected void saveCurrentStates(List restoreStateCommands)
121     {
122         for (int i = 0; i<restoreStateCommands.size(); i++)
123         {
124             RestoreStateCommand cmd = (RestoreStateCommand) restoreStateCommands.get(i);
125             cmd.saveCurrentState();
126         }
127     }
128     
129     protected void restoreCurrentStates(List restoreStateCommands)
130     {
131         for (int i = restoreStateCommands.size()-1; i>=0; i--)
132         {
133             RestoreStateCommand cmd = (RestoreStateCommand) restoreStateCommands.get(i);
134             cmd.restoreCurrentState();
135         }
136     }
137 
138     protected void restoreEventStates(List restoreStateCommands)
139     {
140         for (int i = restoreStateCommands.size()-1; i>=0; i--)
141         {
142             RestoreStateCommand cmd = (RestoreStateCommand) restoreStateCommands.get(i);
143             cmd.restoreEventState();
144         }
145     }
146 
147     /**
148      * check if the current request has a manager.<br />
149      * The current request has a manager if, and only if it
150      * collected valueChange events 
151      */
152     public static boolean hasManager(FacesContext context)
153     {
154         Map requestMap = context.getExternalContext().getRequestMap();
155         return requestMap.get(VCL_MANAGER) != null;
156     }
157 
158     /**
159      * get the manager for this request. Create one if needed. 
160      */
161     public static ValueChangeManager getManager(FacesContext context)
162     {
163         Map requestMap = context.getExternalContext().getRequestMap();
164         ValueChangeManager manager = (ValueChangeManager) requestMap
165                 .get(VCL_MANAGER);
166         if (manager == null)
167         {
168             manager = new ValueChangeManager();
169             requestMap.put(VCL_MANAGER, manager);
170         }
171 
172         return manager;
173     }
174 }