View Javadoc

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