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.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  		}
54  	}
55  	
56  	public DictionaryObjectAttributeValueReader(Object object, String entryName, DataDictionaryEntry entry, String attributePath) {
57  		this(object, entryName, entry);
58  		this.attributePath = attributePath;
59  	}
60  	
61  	@Override
62  	public Constrainable getDefinition(String attrName) {
63  		return entry != null ? entry.getAttributeDefinition(attrName) : null;
64  	}
65  	
66  	@Override
67  	public List<Constrainable> getDefinitions() {
68  		if (entry instanceof DataDictionaryEntryBase) {
69  			DataDictionaryEntryBase entryBase = (DataDictionaryEntryBase)entry;
70  			List<Constrainable> definitions = new ArrayList<Constrainable>();
71  			List<AttributeDefinition> attributeDefinitions = entryBase.getAttributes();
72  			definitions.addAll(attributeDefinitions);
73  			return definitions;
74  		}
75  		
76  		return null;
77  	}
78  	
79  	@Override
80  	public Constrainable getEntry() {
81  		if (entry instanceof Constrainable)
82  			return (Constrainable) entry;
83  			
84  		return null;
85  	}
86  	
87  	@Override
88  	public String getLabel(String attrName) {
89  		AttributeDefinition attributeDefinition = entry != null ? entry.getAttributeDefinition(attrName) : null;
90  		return attributeDefinition != null ? attributeDefinition.getLabel()  : attrName;
91  	}
92  
93  	@Override
94  	public Object getObject() {
95  		return this.object;
96  	}
97  	
98  	@Override
99  	public String getPath() {
100 		String path = ValidationUtils.buildPath(attributePath, attributeName);
101 		return path != null ? path : "";
102 	}
103 
104 	@Override
105 	public Class<?> getType(String attrName) {
106 		PropertyDescriptor propertyDescriptor = beanWrapper.getPropertyDescriptor(attrName);
107 		
108 		return propertyDescriptor.getPropertyType();
109 	}
110 
111     @Override
112     public boolean isReadable() {
113         return beanWrapper.isReadableProperty(attributeName);
114     }
115 
116     @SuppressWarnings("unchecked")
117 	@Override
118 	public <X> X getValue() throws AttributeValidationException {
119 		Object value = getValue(attributeName);
120 		return (X) value;
121 	}
122 	
123 	@SuppressWarnings("unchecked")
124 	@Override
125 	public <X> X getValue(String attrName) throws AttributeValidationException {
126 		X attributeValue = null;
127 		
128 		Exception e = null;
129 		try {
130 			attributeValue = (X) beanWrapper.getPropertyValue(attrName);
131 		} catch (IllegalArgumentException iae) {
132 			e = iae;
133 		} catch (InvalidPropertyException ipe){
134 			//just return null
135 		}
136 		
137 		if (e != null)
138 			throw new AttributeValidationException("Unable to lookup attribute value by name (" + attrName + ") using introspection", e);
139 		
140 		
141 		//			JLR : KS has code to handle dynamic attributes -- not sure whether this is really needed anymore if we're actually relying on types
142 		//            // Extract dynamic attributes
143 		//            if(DYNAMIC_ATTRIBUTE.equals(propName)) {
144 		//                dataMap.putAll((Map<String, String>)value);
145 		//            } else {
146 		//				dataMap.put(propName, value);
147 		//            }
148 		
149 		return attributeValue;
150 	}
151 	
152 	/**
153 	 * @return false if parent attribute exists and is not null, otherwise returns true.
154 	 */
155 	public boolean isParentAttributeNull(){
156 	    boolean isParentNull = true;
157 	    
158 	    if (isNestedAttribute()){
159 	        String[] pathTokens = attributeName.split("\\.");
160 
161 	        isParentNull = false;
162             String parentPath = "";
163 	        for (int i=0; (i < pathTokens.length - 1) && !isParentNull;i++){
164                 parentPath += pathTokens[i];
165 	            isParentNull = beanWrapper.getPropertyValue(parentPath) == null;
166 	            parentPath += ".";
167 	        }
168 	    }
169 	    
170 	    return isParentNull;
171 	}
172 	
173 	public boolean isNestedAttribute(){
174 	    return (attributePath != null || attributeName.contains("."));
175 	}
176 
177     @Override
178 	public AttributeValueReader 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 }