View Javadoc

1   /**
2    * Copyright 2005-2013 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.CoreApiServiceLocator;
20  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
21  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
22  import org.kuali.rice.krad.uif.util.SessionTransient;
23  import org.kuali.rice.krad.util.ObjectUtils;
24  
25  import java.io.Serializable;
26  import java.lang.annotation.Annotation;
27  import java.lang.reflect.Field;
28  import java.util.ArrayList;
29  import java.util.HashMap;
30  import java.util.HashSet;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
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                  CoreApiServiceLocator.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 synchronized 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              // clear all inquiry forms first, temp solution until inquiry forms are not stored in session
85              // TODO: remove once inquiry forms are not required to be in session
86              Set<String> formKeys = new HashSet<String>(sessionForms.keySet());
87              for (String formKey : formKeys) {
88                  UifFormBase sessionForm = sessionForms.get(formKey);
89                  if ((sessionForm instanceof InquiryForm) && (!formKey.equals(form.getFormKey()))) {
90                      sessionForms.remove(formKey);
91                      accessedFormKeys.remove(formKey);
92                  }
93              }
94          }
95  
96          // if we still have too many forms clear the oldest form
97          if (sessionForms.size() > maxNumberOfSessionForms) {
98              // get the oldest form we have
99              String removeFormKey = (String) accessedFormKeys.get(0);
100             if (sessionForms.containsKey(removeFormKey)) {
101                 sessionForms.remove(removeFormKey);
102             }
103             accessedFormKeys.removeElementAt(0);
104         }
105     }
106 
107     /**
108      * Retrieve a form from the session
109      *
110      * @param formKey of the form to retrieve from the session
111      * @return UifFormBase
112      */
113     public UifFormBase getSessionForm(String formKey) {
114         if (sessionForms.containsKey(formKey)) {
115             return sessionForms.get(formKey);
116         }
117 
118         return null;
119     }
120 
121     /**
122      * Removes the stored form data and the forms from the breadcrumb history from the session
123      *
124      * @param form to be removed
125      */
126     public void removeSessionForm(UifFormBase form) {
127         if (form == null || StringUtils.isBlank(form.getFormKey())) {
128             return;
129         }
130 
131         removeSessionFormByKey(form.getFormKey());
132     }
133 
134     /**
135      * Removes the stored form data and the forms from the breadcrumb history from the session
136      *
137      * @param formKey of the form to be removed
138      */
139     public void removeFormWithHistoryFormsByKey(String formKey) {
140         if (sessionForms.containsKey(formKey)) {
141             removeSessionFormByKey(formKey);
142         }
143     }
144 
145     /**
146      * Removes the stored form data from the session
147      *
148      * @param formKey of the form to be removed
149      */
150     public void removeSessionFormByKey(String formKey) {
151         if (accessedFormKeys.contains(formKey)) {
152             accessedFormKeys.removeElement(formKey);
153         }
154 
155         if (sessionForms.containsKey(formKey)) {
156             sessionForms.remove(formKey);
157         }
158     }
159 
160     /**
161      * Indicates whether the form manager has a session form with the given key
162      *
163      * @param formKey key of the form in session to check for
164      * @return true if the manager contains the session form, false if not
165      */
166     public boolean hasSessionForm(String formKey) {
167         return sessionForms.containsKey(formKey);
168     }
169 
170     /**
171      * Retrieves the session form based on the formkey and updates the non session transient
172      * variables on the request form from the session form
173      *
174      * @param requestForm
175      * @param formKey
176      */
177     public void updateFormWithSession(UifFormBase requestForm, String formKey) {
178         UifFormBase sessionForm = sessionForms.get(formKey);
179         if (sessionForm == null) {
180             return;
181         }
182 
183         List<Field> fields = new ArrayList<Field>();
184         fields = ObjectUtils.getAllFields(fields, sessionForm.getClass(), UifFormBase.class);
185         for (Field field : fields) {
186             boolean copyValue = true;
187             for (Annotation an : field.getAnnotations()) {
188                 if (an instanceof SessionTransient) {
189                     copyValue = false;
190                 }
191             }
192 
193             if (copyValue && ObjectPropertyUtils.isReadableProperty(sessionForm, field.getName()) && ObjectPropertyUtils
194                     .isWritableProperty(sessionForm, field.getName())) {
195                 Object fieldValue = ObjectPropertyUtils.getPropertyValue(sessionForm, field.getName());
196                 ObjectPropertyUtils.setPropertyValue(requestForm, field.getName(), fieldValue);
197             }
198         }
199     }
200 
201     /**
202      * Removes the values that are marked @SessionTransient from the form.
203      *
204      * @param form - the form from which the session transient values have been purged
205      */
206     public void purgeForm(UifFormBase form) {
207         List<Field> fields = new ArrayList<Field>();
208         fields = ObjectUtils.getAllFields(fields, form.getClass(), UifFormBase.class);
209         for (Field field : fields) {
210             boolean purgeValue = false;
211 
212             if (!field.getType().isPrimitive()) {
213                 for (Annotation an : field.getAnnotations()) {
214                     if (an instanceof SessionTransient) {
215                         purgeValue = true;
216                     }
217                 }
218             }
219 
220             if (purgeValue && ObjectPropertyUtils.isWritableProperty(form, field.getName())) {
221                 ObjectPropertyUtils.setPropertyValue(form, field.getName(), null);
222             }
223         }
224     }
225 
226     /**
227      * Internal vector maintained to keep track of accessed form and the order in which they were accessed
228      *
229      * <p>
230      * Used for the form clearing process. When forms are added to the manager their key is added to the top of
231      * the vector. When a form needs to be cleared, the form identified by the key at the botton of this vector
232      * is removed
233      * </p>
234      *
235      * @return Vector instance holding form key strings
236      */
237     protected Vector getAccessedFormKeys() {
238         return accessedFormKeys;
239     }
240 
241     /**
242      * Maximum number of forms that can be stored at one time by the manager
243      *
244      * @return int max number of forms
245      */
246     public int getMaxNumberOfSessionForms() {
247         return maxNumberOfSessionForms;
248     }
249 
250     /**
251      * Setter for the maximum number of forms
252      *
253      * @param maxNumberOfSessionForms
254      */
255     public void setMaxNumberOfSessionForms(int maxNumberOfSessionForms) {
256         this.maxNumberOfSessionForms = maxNumberOfSessionForms;
257     }
258 
259 }