001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.datadictionary; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.krad.bo.BusinessObject; 020import org.kuali.rice.krad.datadictionary.parse.BeanTag; 021import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 022import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; 023 024/** 025 * The reference element specifies the name of a reference 026 * object that is required to exist in order for the primary 027 * business object to be created or modified on a BO. 028 * 029 * DD: See ReferenceDefinition.java 030 * 031 * JSTL: references are Maps with the following keys: 032 * attributeName (String) 033 * activeIndicatorAttributeName (String) 034 * activeIndicatorReversed (boolean String) 035 * attributeToHighlightOnFail (String) 036 * displayFieldName (String) 037 */ 038@BeanTag(name = "referenceDefinition") 039public class ReferenceDefinition extends DataDictionaryDefinitionBase { 040 private static final long serialVersionUID = 1737968024207302931L; 041 042 protected String attributeName; 043 protected String attributeToHighlightOnFail; 044 protected String displayFieldName; 045 protected String collection; 046 protected Class<?> collectionBusinessObjectClass; 047 protected Class<?> businessObjectClass; 048 049 public ReferenceDefinition() {} 050 051 /** 052 * @return attributeName 053 */ 054 @BeanTagAttribute(name = "attributeName") 055 public String getAttributeName() { 056 return attributeName; 057 } 058 059 /** 060 * attributeName is the name of a reference object that 061 * must exist and not be null. In the case of a collection, 062 * then this is the name of a reference object within the 063 * collection element. 064 * 065 * @throws IllegalArgumentException if the given attributeName is blank 066 */ 067 public void setAttributeName(String attributeName) { 068 if (StringUtils.isBlank(attributeName)) { 069 throw new IllegalArgumentException("invalid (blank) attributeName"); 070 } 071 this.attributeName = attributeName; 072 } 073 074 /** 075 * Gets the attributeToHighlightOnFail attribute. 076 * 077 * @return Returns the attributeToHighlightOnFail. 078 */ 079 @BeanTagAttribute(name = "attributeToHighlightOnFail") 080 public String getAttributeToHighlightOnFail() { 081 return attributeToHighlightOnFail; 082 } 083 084 /** 085 * attributeToHighlightOnFail is the name of the busines 086 * object attribute which will be highlighted when 087 * the default existence check fails. 088 */ 089 public void setAttributeToHighlightOnFail(String attributeToHighlightOnFail) { 090 if (StringUtils.isBlank(attributeToHighlightOnFail)) { 091 throw new IllegalArgumentException("invalid (blank) attributeToHighlightOnFail"); 092 } 093 this.attributeToHighlightOnFail = attributeToHighlightOnFail; 094 } 095 096 /** 097 * Gets the displayFieldName attribute. 098 * 099 * @return Returns the displayFieldName. 100 */ 101 @BeanTagAttribute(name = "displayFieldName") 102 public String getDisplayFieldName() { 103 return displayFieldName; 104 } 105 106 /** 107 * displayFieldName is the name of the field to pull the label as it will 108 * appear in an error message. e.g. "chartOfAccountsCode". 109 */ 110 public void setDisplayFieldName(String displayFieldName) { 111 this.displayFieldName = displayFieldName; 112 } 113 114 /** 115 * This method returns true if the displayFieldName is set, otherwise it returns false. Whether 116 * the displayFieldName is set is defined by whether it has any non-whitespace content in it. 117 * 118 * @return true if the display field name is set 119 */ 120 public boolean isDisplayFieldNameSet() { 121 return StringUtils.isNotBlank(displayFieldName); 122 } 123 124 @BeanTagAttribute(name = "collection") 125 public String getCollection() { 126 return collection; 127 } 128 129 /** 130 * collection is the name of a collection that must exist 131 */ 132 public void setCollection(String collection) { 133 this.collection = collection; 134 } 135 136 public boolean isCollectionReference() { 137 return StringUtils.isNotBlank(getCollection()); 138 } 139 140 @BeanTagAttribute(name = "collectionBusinessObjectClass") 141 public Class<?> getCollectionBusinessObjectClass() { 142 return collectionBusinessObjectClass; 143 } 144 145 /** 146 * Class that the specified collection represents. Does not need to be set. The DD 147 * Will set this attribute through introspection. 148 */ 149 public void setCollectionBusinessObjectClass(Class<?> collectionBusinessObjectClass) { 150 this.collectionBusinessObjectClass = collectionBusinessObjectClass; 151 } 152 153 @Override 154 public void dataDictionaryPostProcessing() { 155 super.dataDictionaryPostProcessing(); 156 if (collectionBusinessObjectClass == null && isCollectionReference()) { 157 collectionBusinessObjectClass = DataDictionary.getCollectionElementClass(businessObjectClass, collection); 158 } 159 } 160 161 @Override 162 public void completeValidation(Class<?> rootBusinessObjectClass, Class<?> otherBusinessObjectClass, ValidationTrace tracer) { 163 String tmpAttributeName = isCollectionReference() ? collection : attributeName; 164 // make sure the attributeName is actually a property of the BO 165 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, tmpAttributeName)) { 166 String currentValues[] = {"rootBusinessObjectClass = " + rootBusinessObjectClass.getName(), 167 "attribute = " + tmpAttributeName}; 168 tracer.createError("ReferenceDefinition attribute does not exist on parent object", 169 currentValues); 170 } 171 // make sure the attributeToHighlightOnFail is actually a property of the BO 172 if (isCollectionReference()) { 173 if (collectionBusinessObjectClass == null) { 174 String currentValues[] = {"rootBusinessObjectClass = " + rootBusinessObjectClass.getName(), 175 "attribute = " + tmpAttributeName}; 176 tracer.createError("ReferenceDefinition: Unable to determine BO class for collection", 177 currentValues); 178 } else { 179 if (!DataDictionary.isPropertyOf(collectionBusinessObjectClass, attributeToHighlightOnFail)) { 180 String currentValues[] = {"collectionBusinessObjectClass = " + collectionBusinessObjectClass.getName(), 181 "attributeToHighlightOnFail = " + attributeToHighlightOnFail}; 182 tracer.createError("ReferenceDefinition: attributeToHighlightOnFail does not exist on collection class", 183 currentValues); 184 } 185 } 186 } else { 187 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, attributeToHighlightOnFail)) { 188 String currentValues[] = {"rootBusinessObjectClass = " + rootBusinessObjectClass.getName(), 189 "attributeToHighlightOnFail = " + attributeToHighlightOnFail}; 190 tracer.createError("ReferenceDefinition: attributeToHighlightOnFail does not exist on parent class", 191 currentValues); 192 } 193 } 194 } 195 196 197 @BeanTagAttribute(name = "businessObjectClass") 198 public Class<?> getBusinessObjectClass() { 199 return businessObjectClass; 200 } 201 202 public void setBusinessObjectClass(Class<?> businessObjectClass) { 203 this.businessObjectClass = businessObjectClass; 204 } 205}