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.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.ComplexAttributeDefinition;
24  import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
25  import org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase;
26  import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
27  import org.kuali.rice.krad.datadictionary.validation.capability.Constrainable;
28  import org.springframework.beans.BeanWrapper;
29  import org.springframework.beans.BeanWrapperImpl;
30  import org.springframework.beans.NullValueInNestedPathException;
31  
32  /**
33   * This class allows a dictionary object to expose information about its fields / attributes, including the values of
34   * those fields, with some guidance from the DataDictionaryEntry object. 
35   * 
36   * @author Kuali Rice Team (rice.collab@kuali.org) 
37   */
38  public class DictionaryObjectAttributeValueReader extends BaseAttributeValueReader {
39  
40  	protected Object object;
41  	protected DataDictionaryEntry entry;
42  
43  	protected BeanWrapper beanWrapper;
44  	
45  	private String attributePath;
46  	
47  	public DictionaryObjectAttributeValueReader(Object object, String entryName, DataDictionaryEntry entry) {
48  		this.object = object;
49  		this.entry = entry;
50  		this.entryName = entryName;
51  
52  		if (object != null){
53  			beanWrapper = new BeanWrapperImpl(object);
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 	@SuppressWarnings("unchecked")
113 	@Override
114 	public <X> X getValue() throws AttributeValidationException {
115 		Object value = getValue(attributeName);
116 		return (X) value;
117 	}
118 	
119 	@SuppressWarnings("unchecked")
120 	@Override
121 	public <X> X getValue(String attrName) throws AttributeValidationException {
122 		X attributeValue = null;
123 		
124 		Exception e = null;
125 		try {
126 			attributeValue = (X) beanWrapper.getPropertyValue(attrName);
127 
128 		} catch (IllegalArgumentException iae) {
129 			e = iae;
130 		} catch (NullValueInNestedPathException nvinp){
131 			//just return null
132 		}
133 		
134 		if (e != null)
135 			throw new AttributeValidationException("Unable to lookup attribute value by name (" + attrName + ") using introspection", e);
136 		
137 		
138 		//			JLR : KS has code to handle dynamic attributes -- not sure whether this is really needed anymore if we're actually relying on types
139 		//            // Extract dynamic attributes
140 		//            if(DYNAMIC_ATTRIBUTE.equals(propName)) {
141 		//                dataMap.putAll((Map<String, String>)value);
142 		//            } else {
143 		//				dataMap.put(propName, value);
144 		//            }
145 		
146 		return attributeValue;
147 	}
148 	
149 	/**
150 	 * @return false if parent attribute exists and is not null, otherwise returns true.
151 	 */
152 	public boolean isParentAttributeNull(){
153 	    boolean isParentNull = true;
154 	    
155 	    if (isNestedAttribute()){
156 	        String[] pathTokens = attributeName.split("\\.");
157 
158 	        isParentNull = false;
159             String parentPath = "";
160 	        for (int i=0; (i < pathTokens.length - 1) && !isParentNull;i++){
161                 parentPath += pathTokens[i];
162 	            isParentNull = beanWrapper.getPropertyValue(parentPath) == null;
163 	            parentPath += ".";
164 	        }
165 	    }
166 	    
167 	    return isParentNull;
168 	}
169 	
170 	public boolean isNestedAttribute(){
171 	    return (attributePath != null || attributeName.contains("."));
172 	}
173 	
174 	public DictionaryObjectAttributeValueReader clone(){
175 	    DictionaryObjectAttributeValueReader readerClone = 
176 	        new DictionaryObjectAttributeValueReader(this.object, this.entryName, this.entry, this.attributePath);
177 	    readerClone.setAttributeName(this.attributeName);
178 	    
179 	    
180 	    return readerClone;	    
181 	}
182 	
183 }