View Javadoc

1   /**
2    * Copyright 2005-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.web.form;
17  
18  import org.apache.commons.beanutils.PropertyUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
21  import org.kuali.rice.krad.service.KRADServiceLocator;
22  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
23  import org.kuali.rice.krad.uif.util.SessionTransient;
24  import org.kuali.rice.krad.uif.view.HistoryEntry;
25  import org.kuali.rice.krad.util.ObjectUtils;
26  
27  import java.io.Serializable;
28  import java.lang.annotation.Annotation;
29  import java.lang.reflect.Field;
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Vector;
35  
36  /**
37   * Manages Uif form objects for a session
38   *
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   */
41  public class UifFormManager implements Serializable {
42      private static final long serialVersionUID = -6323378881342207080L;
43  
44      private int maxNumberOfSessionForms = 5;
45  
46      private Vector accessedFormKeys;
47  
48      private Map<String, UifFormBase> sessionForms;
49  
50      /**
51       * Create a new form manager with an empty list of forms for the session.
52       */
53      public UifFormManager() {
54          this.accessedFormKeys = new Vector();
55          this.sessionForms = new HashMap<String, UifFormBase>();
56  
57          String maxNumberOfSessionFormsConfig =
58                  KRADServiceLocator.getKualiConfigurationService().getPropertyValueAsString("maxNumberOfSessionForms");
59          if (StringUtils.isNotBlank(maxNumberOfSessionFormsConfig)) {
60              maxNumberOfSessionForms = Integer.parseInt(maxNumberOfSessionFormsConfig);
61          }
62      }
63  
64      /**
65       * Add a form to the session
66       *
67       * @param form to be added to the session
68       */
69      public void addSessionForm(UifFormBase form) {
70          if (form == null || StringUtils.isBlank(form.getFormKey())) {
71              throw new RiceIllegalArgumentException("Form or form key was null");
72          }
73  
74          sessionForms.put(form.getFormKey(), form);
75  
76          // add form key to top of vector indicating it is most recent
77          if (accessedFormKeys.contains(form.getFormKey())) {
78              accessedFormKeys.removeElement(form.getFormKey());
79          }
80          accessedFormKeys.add(form.getFormKey());
81  
82          // check if we have too many forms and need to remove an old one
83          if (sessionForms.size() > maxNumberOfSessionForms) {
84              // get the oldest form we have
85              String removeFormKey = (String) accessedFormKeys.get(0);
86              if (sessionForms.containsKey(removeFormKey)) {
87                  sessionForms.remove(removeFormKey);
88              }
89              accessedFormKeys.removeElementAt(0);
90          }
91      }
92  
93      /**
94       * Retrieve a form from the session
95       *
96       * @param formKey of the form to retrieve from the session
97       * @return UifFormBase
98       */
99      public UifFormBase getSessionForm(String formKey) {
100         if (sessionForms.containsKey(formKey)) {
101             return sessionForms.get(formKey);
102         }
103 
104         return null;
105     }
106 
107     /**
108      * Removes the stored form data and the forms from the breadcrumb history from the session
109      *
110      * @param form to be removed
111      */
112     public void removeSessionForm(UifFormBase form) {
113         if (form == null || StringUtils.isBlank(form.getFormKey())) {
114             return;
115         }
116 
117         removeSessionFormByKey(form.getFormKey());
118     }
119 
120     /**
121      * Removes the stored form data and the forms from the breadcrumb history from the session
122      *
123      * @param formKey of the form to be removed
124      */
125     public void removeFormWithHistoryFormsByKey(String formKey) {
126         if (sessionForms.containsKey(formKey)) {
127             // Remove forms from breadcrumb history as well
128             for (HistoryEntry historyEntry : sessionForms.get(formKey).getFormHistory().getHistoryEntries()) {
129                 removeSessionFormByKey(historyEntry.getFormKey());
130             }
131 
132             removeSessionFormByKey(formKey);
133         }
134     }
135 
136     /**
137      * Removes the stored form data from the session
138      *
139      * @param formKey of the form to be removed
140      */
141     public void removeSessionFormByKey(String formKey) {
142         if (accessedFormKeys.contains(formKey)) {
143             accessedFormKeys.removeElement(formKey);
144         }
145 
146         if (sessionForms.containsKey(formKey)) {
147             sessionForms.remove(formKey);
148         }
149     }
150 
151     /**
152      * Retrieves the session form based on the formkey and updates the non session transient
153      * variables on the request form from the session form
154      *
155      * @param requestForm
156      * @param formKey
157      */
158     public void updateFormWithSession(UifFormBase requestForm, String formKey) {
159         UifFormBase sessionForm = sessionForms.get(formKey);
160         if (sessionForm == null) {
161             return;
162         }
163 
164         List<Field> fields = new ArrayList<Field>();
165         fields = ObjectUtils.getAllFields(fields, sessionForm.getClass(), UifFormBase.class);
166         for (Field field : fields) {
167             boolean copyValue = true;
168             for (Annotation an : field.getAnnotations()) {
169                 if (an instanceof SessionTransient) {
170                     copyValue = false;
171                 }
172             }
173 
174             if (copyValue && ObjectPropertyUtils.isReadableProperty(sessionForm, field.getName()) && ObjectPropertyUtils
175                     .isWritableProperty(sessionForm, field.getName())) {
176                 Object fieldValue = ObjectPropertyUtils.getPropertyValue(sessionForm, field.getName());
177                 ObjectPropertyUtils.setPropertyValue(requestForm, field.getName(), fieldValue);
178             }
179         }
180     }
181 
182     /**
183      * Removes the values that are marked @SessionTransient from the form.
184      *
185      * @param form - the form from which the session transient values have been purged
186      */
187     public void purgeForm(UifFormBase form) {
188         List<Field> fields = new ArrayList<Field>();
189         fields = ObjectUtils.getAllFields(fields, form.getClass(), UifFormBase.class);
190         for (Field field : fields) {
191             boolean purgeValue = false;
192 
193             if (!field.getType().isPrimitive()) {
194                 for (Annotation an : field.getAnnotations()) {
195                     if (an instanceof SessionTransient) {
196                         purgeValue = true;
197                     }
198                 }
199             }
200 
201             if (purgeValue && ObjectPropertyUtils.isWritableProperty(form, field.getName())) {
202                 ObjectPropertyUtils.setPropertyValue(form, field.getName(), null);
203             }
204         }
205     }
206 
207     /**
208      * Internal vector maintained to keep track of accessed form and the order in which they were accessed
209      *
210      * <p>
211      * Used for the form clearing process. When forms are added to the manager their key is added to the top of
212      * the vector. When a form needs to be cleared, the form identified by the key at the botton of this vector
213      * is removed
214      * </p>
215      *
216      * @return Vector instance holding form key strings
217      */
218     protected Vector getAccessedFormKeys() {
219         return accessedFormKeys;
220     }
221 
222     /**
223      * Maximum number of forms that can be stored at one time by the manager
224      *
225      * @return int max number of forms
226      */
227     public int getMaxNumberOfSessionForms() {
228         return maxNumberOfSessionForms;
229     }
230 
231     /**
232      * Setter for the maximum number of forms
233      *
234      * @param maxNumberOfSessionForms
235      */
236     public void setMaxNumberOfSessionForms(int maxNumberOfSessionForms) {
237         this.maxNumberOfSessionForms = maxNumberOfSessionForms;
238     }
239 
240 }