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.datadictionary.validation;
17  
18  import java.beans.PropertyDescriptor;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
23  import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
24  import org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase;
25  import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
26  import org.kuali.rice.krad.datadictionary.validation.capability.Constrainable;
27  import org.springframework.beans.BeanWrapper;
28  import org.springframework.beans.BeanWrapperImpl;
29  import org.springframework.beans.InvalidPropertyException;
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              beanWrapper.setAutoGrowNestedPaths(true);
54  		}
55  	}
56  	
57  	public DictionaryObjectAttributeValueReader(Object object, String entryName, DataDictionaryEntry entry, 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  		return null;
86  	}
87  	
88  	@Override
89  	public String getLabel(String attrName) {
90  		AttributeDefinition attributeDefinition = entry != null ? entry.getAttributeDefinition(attrName) : null;
91  		return attributeDefinition != null ? attributeDefinition.getLabel()  : attrName;
92  	}
93  
94  	@Override
95  	public Object getObject() {
96  		return this.object;
97  	}
98  	
99  	@Override
100 	public String getPath() {
101 		String path = ValidationUtils.buildPath(attributePath, attributeName);
102 		return path != null ? path : "";
103 	}
104 
105 	@Override
106 	public Class<?> getType(String attrName) {
107 		PropertyDescriptor propertyDescriptor = beanWrapper.getPropertyDescriptor(attrName);
108 		
109 		return propertyDescriptor.getPropertyType();
110 	}
111 
112     @Override
113     public boolean isReadable() {
114         return beanWrapper.isReadableProperty(attributeName);
115     }
116 
117     @SuppressWarnings("unchecked")
118 	@Override
119 	public <X> X getValue() throws AttributeValidationException {
120 		Object value = getValue(attributeName);
121 		return (X) value;
122 	}
123 	
124 	@SuppressWarnings("unchecked")
125 	@Override
126 	public <X> X getValue(String attrName) throws AttributeValidationException {
127 		X attributeValue = null;
128 		
129 		Exception e = null;
130 		try {
131 			attributeValue = (X) beanWrapper.getPropertyValue(attrName);
132 		} catch (IllegalArgumentException iae) {
133 			e = iae;
134 		} catch (InvalidPropertyException ipe){
135 			//just return null
136 		}
137 		
138 		if (e != null)
139 			throw new AttributeValidationException("Unable to lookup attribute value by name (" + attrName + ") using introspection", e);
140 		
141 		
142 		//			JLR : KS has code to handle dynamic attributes -- not sure whether this is really needed anymore if we're actually relying on types
143 		//            // Extract dynamic attributes
144 		//            if(DYNAMIC_ATTRIBUTE.equals(propName)) {
145 		//                dataMap.putAll((Map<String, String>)value);
146 		//            } else {
147 		//				dataMap.put(propName, value);
148 		//            }
149 		
150 		return attributeValue;
151 	}
152 	
153 	/**
154 	 * @return false if parent attribute exists and is not null, otherwise returns true.
155 	 */
156 	public boolean isParentAttributeNull(){
157 	    boolean isParentNull = true;
158 	    
159 	    if (isNestedAttribute()){
160 	        String[] pathTokens = attributeName.split("\\.");
161 
162 	        isParentNull = false;
163             String parentPath = "";
164 	        for (int i=0; (i < pathTokens.length - 1) && !isParentNull;i++){
165                 parentPath += pathTokens[i];
166 	            isParentNull = beanWrapper.getPropertyValue(parentPath) == null;
167 	            parentPath += ".";
168 	        }
169 	    }
170 	    
171 	    return isParentNull;
172 	}
173 	
174 	public boolean isNestedAttribute(){
175 	    return (attributePath != null || attributeName.contains("."));
176 	}
177 	
178 	public DictionaryObjectAttributeValueReader clone(){
179 	    DictionaryObjectAttributeValueReader readerClone = 
180 	        new DictionaryObjectAttributeValueReader(this.object, this.entryName, this.entry, this.attributePath);
181 	    readerClone.setAttributeName(this.attributeName);
182 	    
183 	    
184 	    return readerClone;	    
185 	}
186 	
187 }