001/** 002 * Copyright 2005-2018 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.datadictionary.parse.BeanTag; 020import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 021import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; 022 023/** 024 * The primitiveAttribute element identifies one pair of 025 * corresponding fields in the primary business object and 026 * the related business object. 027 * 028 * JSTL: primitiveAttribute is a Map which is accessed by the 029 * sequential key of "0", "1", etc. Each entry contains the following 030 * keys: 031 * sourceName (String) 032 * targetName (String) 033 * The value corresponding to the sourceName key is the attribute name defined 034 * for the primary business object. 035 * The value corresponding to the targetName key is the attribute name for 036 * the object being referenced by objectAttributeName. 037 */ 038@BeanTag(name = "primitiveAttributeDefinition") 039public class PrimitiveAttributeDefinition extends DataDictionaryDefinitionBase { 040 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PrimitiveAttributeDefinition.class); 041 private static final long serialVersionUID = -715128943756700821L; 042 043 protected String sourceName; 044 protected String targetName; 045 046 public PrimitiveAttributeDefinition() {} 047 048 @BeanTagAttribute(name = "sourceName") 049 public String getSourceName() { 050 return sourceName; 051 } 052 053 /** 054 * sourceName is the name of the POJO property of the business object 055 * 056 * @throws IllegalArgumentException if the given sourceName is blank 057 */ 058 public void setSourceName(String sourceName) { 059 if (StringUtils.isBlank(sourceName)) { 060 throw new IllegalArgumentException("invalid (blank) sourceName"); 061 } 062 063 this.sourceName = sourceName; 064 } 065 066 @BeanTagAttribute(name = "targetName") 067 public String getTargetName() { 068 return targetName; 069 } 070 071 /** 072 * targetName is the name of attribute that corresponds to the sourceName in the looked up BO 073 * 074 * @throws IllegalArgumentException if the given targetName is blank 075 */ 076 public void setTargetName(String targetName) { 077 if (StringUtils.isBlank(targetName)) { 078 throw new IllegalArgumentException("invalid (blank) targetName"); 079 } 080 081 this.targetName = targetName; 082 } 083 084 /** 085 * Directly validate simple fields. 086 * 087 * @see org.kuali.rice.krad.datadictionary.DataDictionaryDefinition#completeValidation(java.lang.Class, 088 * java.lang.Class) 089 */ 090 @Override 091 public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass) { 092 completeValidation(rootBusinessObjectClass, otherBusinessObjectClass, new ValidationTrace()); 093 } 094 095 /** 096 * Directly validate simple fields 097 * 098 * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#completeValidation(org.kuali.rice.krad.datadictionary.validator.ValidationTrace) 099 */ 100 @Override 101 public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass, 102 ValidationTrace tracer) { 103 tracer.addBean(this.getClass().getSimpleName(), ValidationTrace.NO_BEAN_ID); 104 105 try { 106 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, sourceName)) { 107 String currentValues[] = {"attribute = " + getSourceName(), "class = " + rootBusinessObjectClass}; 108 tracer.createError("Unable to find attribute on class", currentValues); 109 } 110 } catch (RuntimeException ex) { 111 String currentValues[] = {"attribute = " + getSourceName(), "class = " + rootBusinessObjectClass, 112 "Exception = " + ex.getMessage()}; 113 tracer.createError("Unable to find attribute on class", currentValues); 114 LOG.error( "Exception while validating PrimitiveAttributeDefintion on " + rootBusinessObjectClass + ": " + this, ex); 115 } 116 try { 117 if (!DataDictionary.isPropertyOf(otherBusinessObjectClass, targetName)) { 118 String currentValues[] = {"attribute = " + getTargetName(), "class = " + otherBusinessObjectClass}; 119 tracer.createError("Unable to find attribute on class", currentValues); 120 } 121 } catch (RuntimeException ex) { 122 String currentValues[] = {"attribute = " + getTargetName(), "class = " + otherBusinessObjectClass, 123 "Exception = " + ex.getMessage()}; 124 tracer.createError("Unable to find attribute on class", currentValues); 125 LOG.error( "Exception while validating PrimitiveAttributeDefintion on " + rootBusinessObjectClass + ": " + this, ex); 126 } 127 try { 128 Class sourceClass = DataDictionary.getAttributeClass(rootBusinessObjectClass, sourceName); 129 Class targetClass = DataDictionary.getAttributeClass(otherBusinessObjectClass, targetName); 130 if ((null == sourceClass && null != targetClass) 131 || (null != sourceClass && null == targetClass) 132 || !StringUtils.equals(sourceClass.getName(), targetClass.getName())) { 133 String sourceClassName = rootBusinessObjectClass.getName(); 134 String targetClassName = otherBusinessObjectClass.getName(); 135 String sourcePath = sourceClassName + "." + sourceName; 136 String targetPath = targetClassName + "." + targetName; 137 138 // Just a temp hack to ignore null Person objects 139 if ((sourcePath != null && !StringUtils.contains(sourcePath, ".principalId")) 140 && (targetPath != null && !StringUtils.contains(targetPath, ".principalId")) ) { 141 String currentValues[] = {"source = " + sourcePath + "' (" + sourceClass + ")", 142 "target = " + targetPath + "' (" + targetClass + ")"}; 143 tracer.createError("Source and target of different types", currentValues); 144 } 145 } 146 } catch (RuntimeException ex) { 147 String currentValues[] = {"Exception = " + ex.getMessage()}; 148 tracer.createError("Unable to validate property", currentValues); 149 LOG.error( "Exception while validating PrimitiveAttributeDefintion on " + rootBusinessObjectClass + ": " + this, ex); 150 } 151 } 152 153 @Override 154 public String toString() { 155 StringBuilder builder = new StringBuilder(); 156 builder.append("PrimitiveAttributeDefinition [sourceName=").append(this.sourceName).append(", targetName=") 157 .append(this.targetName).append("]"); 158 return builder.toString(); 159 } 160 161}