View Javadoc

1   /**
2    * Copyright 2005-2011 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.bind;
17  
18  import org.kuali.rice.core.web.format.Formatter;
19  import org.kuali.rice.krad.uif.field.DataField;
20  import org.kuali.rice.krad.web.form.UifFormBase;
21  import org.springframework.beans.BeanWrapperImpl;
22  import org.springframework.beans.BeansException;
23  import org.springframework.beans.InvalidPropertyException;
24  import org.springframework.beans.PropertyValue;
25  
26  import java.beans.PropertyDescriptor;
27  import java.beans.PropertyEditor;
28  import java.util.HashSet;
29  import java.util.Set;
30  
31  /**
32   * This class is a top level BeanWrapper for a UIF View (form).  It will call the
33   * view service to find formatters and check if fields are encrypted.
34   *
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  public class UifViewBeanWrapper extends BeanWrapperImpl {
38      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UifViewBeanWrapper.class);
39  
40      // this is a handle to the target object so we don't
41      // have to cast so often
42      private UifFormBase form;
43  
44      // this stores all properties this wrapper has already checked
45      // with the view so the service isn't called again
46      private Set<String> processedProperties;
47  
48      public UifViewBeanWrapper(Object object) {
49          super(object);
50  
51          form = (UifFormBase) object;
52          processedProperties = new HashSet<String>();
53      }
54  
55      protected void callViewService(String propertyName) {
56          if (LOG.isDebugEnabled()) {
57              LOG.debug("Attempting view service call for property '" + propertyName + "'");
58          }
59          Class<? extends Formatter> formatterClass = null;
60  
61          // viewId should be determined in UifAnnotationMethodHandlerAdapter so
62          // nothing we can do without one here
63          if (form.getView() == null) {
64              return;
65          }
66  
67          // check if we already processed this property for this BeanWrapper instance
68          if (processedProperties.contains(propertyName)) {
69              return;
70          }
71  
72          DataField af = null;
73          if (form.getView().getViewIndex() != null) {
74              af = form.getView().getViewIndex().getDataFieldByPath(propertyName);
75          }
76  
77          if ((af == null) && (form.getPreviousView() != null) && (form.getPreviousView().getViewIndex() != null)) {
78              af = form.getPreviousView().getViewIndex().getDataFieldByPath(propertyName);
79          }
80  
81          boolean requiresEncryption = false;
82          if (af != null) {
83              if (af.getAttributeSecurity() != null) {
84                  if (af.getAttributeSecurity().hasRestrictionThatRemovesValueFromUI()) {
85                      requiresEncryption = true;
86                  }
87              }
88  
89              Formatter formatter = af.getFormatter();
90              if (formatter != null) {
91                  formatterClass = formatter.getClass();
92              }
93          }
94  
95          // really these should be PropertyEditors after we evaluate how many are
96          // needed vs how many spring provides
97          if (formatterClass != null) {
98              if (LOG.isDebugEnabled()) {
99                  LOG.debug("Registering custom editor for property path '" + propertyName + "' and formatter class '" +
100                         formatterClass.getName() + "'");
101             }
102             PropertyEditor customEditor = new UifKnsFormatterPropertyEditor(formatterClass);
103             if (requiresEncryption) {
104                 if (LOG.isDebugEnabled()) {
105                     LOG.debug("Enabling encryption for custom editor '" + propertyName + "' and formatter class '" +
106                             formatterClass.getName() + "'");
107                 }
108                 this.registerCustomEditor(null, propertyName, new UifEncryptionPropertyEditorWrapper(customEditor));
109             } else {
110                 this.registerCustomEditor(null, propertyName, customEditor);
111             }
112         } else if (requiresEncryption) {
113             if (LOG.isDebugEnabled()) {
114                 LOG.debug("No custom formatter for property path '" + propertyName +
115                         "' but property does require encryption");
116             }
117             this.registerCustomEditor(null, propertyName,
118                     new UifEncryptionPropertyEditorWrapper(findEditorForPropertyName(propertyName)));
119         }
120 
121         processedProperties.add(propertyName);
122     }
123 
124     protected PropertyEditor findEditorForPropertyName(String propertyName) {
125         Class<?> clazz = getPropertyType(propertyName);
126         if (LOG.isDebugEnabled()) {
127             LOG.debug("Attempting retrieval of property editor using class '" + clazz + "' and property path '" +
128                     propertyName + "'");
129         }
130         PropertyEditor editor = findCustomEditor(clazz, propertyName);
131         if (editor == null) {
132             if (LOG.isDebugEnabled()) {
133                 LOG.debug("No custom property editor found using class '" + clazz + "' and property path '" +
134                         propertyName + "'. Attempting to find default property editor class.");
135             }
136             editor = getDefaultEditor(clazz);
137         }
138         return editor;
139     }
140 
141     @Override
142     public Class<?> getPropertyType(String propertyName) throws BeansException {
143         try {
144             PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
145             if (pd != null) {
146                 return pd.getPropertyType();
147             }
148 
149             // Maybe an indexed/mapped property...
150             Object value = super.getPropertyValue(propertyName);
151             if (value != null) {
152                 return value.getClass();
153             }
154 
155             // Check to see if there is a custom editor,
156             // which might give an indication on the desired target type.
157             Class<?> editorType = guessPropertyTypeFromEditors(propertyName);
158             if (editorType != null) {
159                 return editorType;
160             }
161         } catch (InvalidPropertyException ex) {
162             // Consider as not determinable.
163         }
164 
165         return null;
166     }
167 
168     @Override
169     public Object getPropertyValue(String propertyName) throws BeansException {
170         callViewService(propertyName);
171         return super.getPropertyValue(propertyName);
172     }
173 
174     @Override
175     public void setPropertyValue(PropertyValue pv) throws BeansException {
176         callViewService(pv.getName());
177         super.setPropertyValue(pv);
178     }
179 
180     @Override
181     public void setPropertyValue(String propertyName, Object value) throws BeansException {
182         callViewService(propertyName);
183         super.setPropertyValue(propertyName, value);
184     }
185 
186     @Override
187     public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
188         //TODO clear cache?
189         form = (UifFormBase) object;
190         super.setWrappedInstance(object, nestedPath, rootObject);
191     }
192 
193     @Override
194     public void setWrappedInstance(Object object) {
195         //TODO clear cache?
196         form = (UifFormBase) object;
197         super.setWrappedInstance(object);
198     }
199 }