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.datadictionary.validation;
17  
18  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
19  import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
20  import org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase;
21  import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
22  import org.kuali.rice.krad.datadictionary.validation.capability.Constrainable;
23  import org.springframework.beans.BeanWrapper;
24  import org.springframework.beans.BeanWrapperImpl;
25  import org.springframework.beans.InvalidPropertyException;
26  
27  import java.beans.PropertyDescriptor;
28  import java.util.ArrayList;
29  import java.util.List;
30  
31  /**
32   * This class allows a dictionary object to expose information about its fields / attributes, including the values of
33   * those fields, with some guidance from the DataDictionaryEntry object.
34   *
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  public class DictionaryObjectAttributeValueReader extends BaseAttributeValueReader {
38  
39      protected Object object;
40      protected DataDictionaryEntry entry;
41  
42      protected BeanWrapper beanWrapper;
43  
44      private String attributePath;
45  
46      public DictionaryObjectAttributeValueReader(Object object, String entryName, DataDictionaryEntry entry) {
47          this.object = object;
48          this.entry = entry;
49          this.entryName = entryName;
50  
51          if (object != null) {
52              beanWrapper = new BeanWrapperImpl(object);
53          }
54      }
55  
56      public DictionaryObjectAttributeValueReader(Object object, String entryName, DataDictionaryEntry entry,
57              String attributePath) {
58          this(object, entryName, entry);
59          this.attributePath = attributePath;
60      }
61  
62      @Override
63      public Constrainable getDefinition(String attrName) {
64          return entry != null ? entry.getAttributeDefinition(attrName) : null;
65      }
66  
67      @Override
68      public List<Constrainable> getDefinitions() {
69          if (entry instanceof DataDictionaryEntryBase) {
70              DataDictionaryEntryBase entryBase = (DataDictionaryEntryBase) entry;
71              List<Constrainable> definitions = new ArrayList<Constrainable>();
72              List<AttributeDefinition> attributeDefinitions = entryBase.getAttributes();
73              definitions.addAll(attributeDefinitions);
74              return definitions;
75          }
76  
77          return null;
78      }
79  
80      @Override
81      public Constrainable getEntry() {
82          if (entry instanceof Constrainable) {
83              return (Constrainable) entry;
84          }
85  
86          return null;
87      }
88  
89      @Override
90      public String getLabel(String attrName) {
91          AttributeDefinition attributeDefinition = entry != null ? entry.getAttributeDefinition(attrName) : null;
92          return attributeDefinition != null ? attributeDefinition.getLabel() : attrName;
93      }
94  
95      @Override
96      public Object getObject() {
97          return this.object;
98      }
99  
100     @Override
101     public String getPath() {
102         String path = ValidationUtils.buildPath(attributePath, attributeName);
103         return path != null ? path : "";
104     }
105 
106     @Override
107     public Class<?> getType(String attrName) {
108         PropertyDescriptor propertyDescriptor = beanWrapper.getPropertyDescriptor(attrName);
109 
110         return propertyDescriptor.getPropertyType();
111     }
112 
113     @Override
114     public boolean isReadable() {
115         return beanWrapper.isReadableProperty(attributeName);
116     }
117 
118     @SuppressWarnings("unchecked")
119     @Override
120     public <X> X getValue() throws AttributeValidationException {
121         Object value = getValue(attributeName);
122         return (X) value;
123     }
124 
125     @SuppressWarnings("unchecked")
126     @Override
127     public <X> X getValue(String attrName) throws AttributeValidationException {
128         X attributeValue = null;
129 
130         Exception e = null;
131         try {
132             attributeValue = (X) beanWrapper.getPropertyValue(attrName);
133         } catch (IllegalArgumentException iae) {
134             e = iae;
135         } catch (InvalidPropertyException ipe) {
136             //just return null
137         }
138 
139         if (e != null) {
140             throw new AttributeValidationException(
141                     "Unable to lookup attribute value by name (" + attrName + ") using introspection", e);
142         }
143 
144         //			JLR : KS has code to handle dynamic attributes -- not sure whether this is really needed anymore if we're actually relying on types
145         //            // Extract dynamic attributes
146         //            if(DYNAMIC_ATTRIBUTE.equals(propName)) {
147         //                dataMap.putAll((Map<String, String>)value);
148         //            } else {
149         //				dataMap.put(propName, value);
150         //            }
151 
152         return attributeValue;
153     }
154 
155     /**
156      * @return false if parent attribute exists and is not null, otherwise returns true.
157      */
158     public boolean isParentAttributeNull() {
159         boolean isParentNull = true;
160 
161         if (isNestedAttribute()) {
162             String[] pathTokens = attributeName.split("\\.");
163 
164             isParentNull = false;
165             String parentPath = "";
166             for (int i = 0; (i < pathTokens.length - 1) && !isParentNull; i++) {
167                 parentPath += pathTokens[i];
168                 isParentNull = beanWrapper.getPropertyValue(parentPath) == null;
169                 parentPath += ".";
170             }
171         }
172 
173         return isParentNull;
174     }
175 
176     public boolean isNestedAttribute() {
177         return (attributePath != null || attributeName.contains("."));
178     }
179 
180     @Override
181     public AttributeValueReader clone() {
182         DictionaryObjectAttributeValueReader readerClone = new DictionaryObjectAttributeValueReader(this.object,
183                 this.entryName, this.entry, this.attributePath);
184         readerClone.setAttributeName(this.attributeName);
185 
186         return readerClone;
187     }
188 
189 }