Coverage Report - org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase
 
Classes in this File Line Coverage Branch Coverage Complexity
DataDictionaryEntryBase
32%
32/100
25%
13/52
3
 
 1  
 /*
 2  
  * Copyright 2005-2007 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;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.krad.datadictionary.exception.DuplicateEntryException;
 20  
 import org.kuali.rice.krad.exception.ValidationException;
 21  
 import org.springframework.beans.BeanUtils;
 22  
 import org.springframework.beans.factory.InitializingBean;
 23  
 
 24  
 import java.util.ArrayList;
 25  
 import java.util.LinkedHashMap;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 import java.util.Set;
 29  
 
 30  
 /**
 31  
  * Contains common properties and methods for data dictionary entries.
 32  
  * 
 33  
  * 
 34  
  */
 35  
 abstract public class DataDictionaryEntryBase implements DataDictionaryEntry, InitializingBean {
 36  
 
 37  
     protected List<AttributeDefinition> attributes;
 38  
     protected List<ComplexAttributeDefinition> complexAttributes;
 39  
     protected List<CollectionDefinition> collections;
 40  
     protected List<RelationshipDefinition> relationships;
 41  
     protected Map<String, AttributeDefinition> attributeMap;
 42  
     protected Map<String, ComplexAttributeDefinition> complexAttributeMap;
 43  
     protected Map<String, CollectionDefinition> collectionMap;
 44  
     protected Map<String, RelationshipDefinition> relationshipMap;
 45  
     
 46  33
     public DataDictionaryEntryBase() {
 47  33
         this.attributes = new ArrayList<AttributeDefinition>();
 48  33
         this.collections = new ArrayList<CollectionDefinition>();
 49  33
         this.relationships = new ArrayList<RelationshipDefinition>();
 50  33
         this.attributeMap = new LinkedHashMap<String, AttributeDefinition>();
 51  33
         this.collectionMap = new LinkedHashMap<String, CollectionDefinition>();
 52  33
         this.relationshipMap = new LinkedHashMap<String, RelationshipDefinition>();
 53  33
     }
 54  
     
 55  
     /* Returns the given entry class (bo class or document class) */
 56  
     public abstract Class<?> getEntryClass();
 57  
     
 58  
     /**
 59  
      * @param attributeName
 60  
      * @return AttributeDefinition with the given name, or null if none with that name exists
 61  
      */
 62  
     public AttributeDefinition getAttributeDefinition(String attributeName) {
 63  15
         if (StringUtils.isBlank(attributeName)) {
 64  0
             throw new IllegalArgumentException("invalid (blank) attributeName");
 65  
         }
 66  15
         return attributeMap.get(attributeName);
 67  
     }
 68  
 
 69  
     /**
 70  
      * @return a Map containing all AttributeDefinitions associated with this BusinessObjectEntry, indexed by attributeName
 71  
      */
 72  
     public List<AttributeDefinition> getAttributes() {
 73  0
         return this.attributes;
 74  
     }
 75  
     
 76  
     /**
 77  
          * @return the complexAttributes
 78  
          */
 79  
         public List<ComplexAttributeDefinition> getComplexAttributes() {
 80  0
                 return this.complexAttributes;
 81  
         }
 82  
 
 83  
         /**
 84  
          * @param complexAttributes the complexAttributes to set
 85  
          */
 86  
         public void setComplexAttributes(
 87  
                         List<ComplexAttributeDefinition> complexAttributes) {
 88  0
                 this.complexAttributes = complexAttributes;
 89  0
         }
 90  
 
 91  
     /**
 92  
      * @param collectionName
 93  
      * @return CollectionDefinition with the given name, or null if none with that name exists
 94  
      */
 95  
     public CollectionDefinition getCollectionDefinition(String collectionName) {
 96  0
         if (StringUtils.isBlank(collectionName)) {
 97  0
             throw new IllegalArgumentException("invalid (blank) collectionName");
 98  
         }
 99  0
         return collectionMap.get(collectionName);
 100  
     }
 101  
 
 102  
     /**
 103  
      * @return a Map containing all CollectionDefinitions associated with this BusinessObjectEntry, indexed by collectionName
 104  
      */
 105  
     public List<CollectionDefinition> getCollections() {
 106  0
         return this.collections;
 107  
     }
 108  
 
 109  
     /**
 110  
      * @param relationshipName
 111  
      * @return RelationshipDefinition with the given name, or null if none with that name exists
 112  
      */
 113  
     public RelationshipDefinition getRelationshipDefinition(String relationshipName) {
 114  0
         if (StringUtils.isBlank(relationshipName)) {
 115  0
             throw new IllegalArgumentException("invalid (blank) relationshipName");
 116  
         }
 117  0
         return relationshipMap.get(relationshipName);
 118  
     }
 119  
 
 120  
     /**
 121  
      * @return a Map containing all RelationshipDefinitions associated with this BusinessObjectEntry, indexed by relationshipName
 122  
      */
 123  
     public List<RelationshipDefinition> getRelationships() {
 124  0
         return this.relationships;
 125  
     }
 126  
 
 127  
 
 128  
     /**
 129  
      * Directly validate simple fields, call completeValidation on Definition fields.
 130  
      */
 131  
     public void completeValidation() {
 132  
         
 133  0
         for ( AttributeDefinition attributeDefinition : attributes ) {
 134  0
             attributeDefinition.completeValidation(getEntryClass(), null);
 135  
         }
 136  
 
 137  0
         for ( CollectionDefinition collectionDefinition : collections ) {
 138  0
             collectionDefinition.completeValidation(getEntryClass(), null);
 139  
         }
 140  
 
 141  0
         for ( RelationshipDefinition relationshipDefinition : relationships ) {
 142  0
             relationshipDefinition.completeValidation(getEntryClass(), null);
 143  
         }
 144  0
     }
 145  
 
 146  
     /**
 147  
             The attributes element contains attribute 
 148  
             elements.  These define the specifications for business object fields.
 149  
 
 150  
             JSTL: attributes is a Map which is accessed by a key of "attributes".
 151  
             This map contains entries with the following keys:
 152  
                 * attributeName of first attribute
 153  
                 * attributeName of second attribute
 154  
                 etc.
 155  
 
 156  
             The corresponding value for each entry is an attribute ExportMap.
 157  
             By the time the JSTL export happens, all attributeReferences will be
 158  
             indistinguishable from attributes.
 159  
 
 160  
             See AttributesMapBuilder.java
 161  
 
 162  
                 The attribute element specifies the way in which a business object
 163  
                 field appears on a screen for data entry or display purposes.  These
 164  
                 specifications include the following:
 165  
                 * The title and formatting of the field
 166  
                 * Descriptive information about the field
 167  
                 * The edits used at time of data-entry
 168  
 
 169  
                 DD: See AttributeDefinition.java
 170  
 
 171  
                 JSTL: attribute is a Map which is accessed using a key which is the attributeName
 172  
                 of an attribute.  Each entry contains the following keys:
 173  
                     * name (String)
 174  
                     * forceUppercase (boolean String)
 175  
                     * label (String)
 176  
                     * shortLabel (String, copied from label if not present)
 177  
                     * maxLength (String)
 178  
                     * exclusiveMin (bigdecimal String)
 179  
                     * exclusiveMax (bigdecimal String)
 180  
                     * validationPattern (Map, optional)
 181  
                     * required (boolean String)
 182  
                     * control (Map)
 183  
                     * summary (String)
 184  
                     * description (String)
 185  
                     * formatterClass (String, optional)
 186  
                     * fullClassName (String)
 187  
                     * displayWorkgroup(String, optional)
 188  
                     * displayMaskClass(String, optional)
 189  
 
 190  
                 See AttributesMapBuilder.java
 191  
                 Note: exclusiveMax is mapped from the inclusiveMax element!
 192  
                 The validation logic seems to be assuming inclusiveMax.
 193  
      *
 194  
      */
 195  
     public void setAttributes(List<AttributeDefinition> attributes) {
 196  27
         attributeMap.clear();
 197  27
         for ( AttributeDefinition attribute : attributes ) {
 198  132
             if (attribute == null) {
 199  0
                 throw new IllegalArgumentException("invalid (null) attributeDefinition");
 200  
             }
 201  132
             String attributeName = attribute.getName();
 202  132
             if (StringUtils.isBlank(attributeName)) {
 203  0
                 throw new ValidationException("invalid (blank) attributeName");
 204  
             }
 205  
 
 206  132
             if (attributeMap.containsKey(attributeName)) {
 207  0
                 throw new DuplicateEntryException("collection '" + attributeName + "' already defined as an Attribute for class '" + getEntryClass().getName() + "'");
 208  132
             } else if (collectionMap.containsKey(attributeName)) {
 209  0
                 throw new DuplicateEntryException("attribute '" + attributeName + "' already defined as a Collection for class '" + getEntryClass().getName() + "'");
 210  
             }
 211  
 
 212  132
             attributeMap.put(attributeName, attribute);            
 213  132
         }
 214  27
         this.attributes = attributes;
 215  27
     }
 216  
 
 217  
     /**
 218  
             The collections element contains collection elements.  These define
 219  
             the lists of other business objects which are related to and
 220  
             defined in the business objects.
 221  
 
 222  
             JSTL: collections is a Map which is accessed by a key of "collections".
 223  
             This map contains entries with the following keys:
 224  
                 * name of first collection
 225  
                 * name of second collection
 226  
                 etc.
 227  
             The corresponding value for each entry is a collection ExportMap.
 228  
 
 229  
             The collection element defines the name and description a
 230  
             list of objects related to the business object.
 231  
 
 232  
             DD: See CollectionDefinition.java.
 233  
 
 234  
             JSTL: collection is a Map which is accessed using a key which is the
 235  
             name of the collection.  Each entry contains the following keys:
 236  
                 * name (String)
 237  
                 * label (String)
 238  
                 * shortLabel (String, copied from label if missing)
 239  
                 * elementLabel (String, copied from contained class if missing)
 240  
                 * summary (String)
 241  
                 * description (String)
 242  
 
 243  
             See CollectionsMapBuilder.java.
 244  
      */
 245  
     public void setCollections(List<CollectionDefinition> collections) {
 246  6
         collectionMap.clear();
 247  6
         for ( CollectionDefinition collection : collections ) {
 248  6
             if (collection == null) {
 249  0
                 throw new IllegalArgumentException("invalid (null) collectionDefinition");
 250  
             }
 251  6
             String collectionName = collection.getName();
 252  6
             if (StringUtils.isBlank(collectionName)) {
 253  0
                 throw new ValidationException("invalid (blank) collectionName");
 254  
             }
 255  
 
 256  6
             if (collectionMap.containsKey(collectionName)) {
 257  0
                 throw new DuplicateEntryException("collection '" + collectionName + "' already defined for class '" + getEntryClass().getName() + "'");
 258  6
             } else if (attributeMap.containsKey(collectionName)) {
 259  0
                 throw new DuplicateEntryException("collection '" + collectionName + "' already defined as an Attribute for class '" + getEntryClass().getName() + "'");
 260  
             }
 261  
 
 262  6
             collectionMap.put(collectionName, collection);
 263  
             
 264  6
         }
 265  6
         this.collections = collections;
 266  6
     }
 267  
 
 268  
     /**
 269  
             The relationships element contains relationship elements.
 270  
             These are used to map attribute names to fields in a reference object.
 271  
 
 272  
             JSTL: relationships is a Map which is accessed by a key of "relationships".
 273  
             This map contains entries with the following keys:
 274  
                 * objectAttributeName of first relationship
 275  
                 * objectAttributeName of second relationship
 276  
                 etc.
 277  
             The corresponding value for each entry is a relationship ExportMap.
 278  
 
 279  
             The relationship element defines how primitive attributes of this
 280  
             class can be used to retrieve an instance of some related Object instance
 281  
             DD: See RelationshipDefinition.java.
 282  
 
 283  
             JSTL: relationship is a Map which is accessed using a key which is the
 284  
             objectAttributeName of a relationship.  The map contains a single entry
 285  
             with a key of "primitiveAttributes" and value which is an attributesMap ExportMap.
 286  
 
 287  
             The attributesMap ExportMap contains the following keys:
 288  
                 * 0   (for first primitiveAttribute)
 289  
                 * 1   (for second primitiveAttribute)
 290  
                 etc.
 291  
             The corresponding value for each entry is an primitiveAttribute ExportMap
 292  
             which contains the following keys:
 293  
                 * "sourceName"
 294  
                 * "targetName"
 295  
 
 296  
             See RelationshipsMapBuilder.java.
 297  
             
 298  
      */
 299  
     public void setRelationships(List<RelationshipDefinition> relationships) {
 300  0
         this.relationships = relationships;
 301  0
     }
 302  
 
 303  
     public Set<String> getCollectionNames() {
 304  0
         return collectionMap.keySet();
 305  
     }
 306  
     
 307  
     public Set<String> getAttributeNames() {
 308  0
         return attributeMap.keySet();
 309  
     }
 310  
 
 311  
     public Set<String> getRelationshipNames() {
 312  0
         return relationshipMap.keySet();
 313  
     }
 314  
     
 315  
     /**
 316  
      * This overridden method ...
 317  
      * 
 318  
      * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 319  
      */
 320  
     public void afterPropertiesSet() throws Exception {
 321  0
             if ( relationships != null ) {
 322  0
             relationshipMap.clear();
 323  0
             for ( RelationshipDefinition relationship : relationships ) {            
 324  0
                 if (relationship == null) {
 325  0
                     throw new IllegalArgumentException("invalid (null) relationshipDefinition");
 326  
                 }
 327  0
                 String relationshipName = relationship.getObjectAttributeName();
 328  0
                 if (StringUtils.isBlank(relationshipName)) {
 329  0
                     throw new ValidationException("invalid (blank) relationshipName");
 330  
                 }
 331  0
                 relationship.setSourceClass(getEntryClass());
 332  0
                 relationshipMap.put(relationshipName, relationship);
 333  0
             }
 334  
             }
 335  
             
 336  
             //Populate attributes with nested attribute definitions
 337  0
             if (complexAttributes != null){
 338  0
                     for (ComplexAttributeDefinition complexAttribute:complexAttributes){
 339  0
                             addNestedAttributes(complexAttribute, complexAttribute.getName());
 340  
                     }
 341  
             }
 342  0
            }
 343  
     
 344  
     private void addNestedAttributes(ComplexAttributeDefinition complexAttribute, String attrPath){
 345  0
             DataDictionaryEntryBase dataDictionaryEntry = (DataDictionaryEntryBase)complexAttribute.getDataObjectEntry();
 346  
             
 347  
             //Add attributes for the complex attibutes
 348  0
             for (AttributeDefinition attribute:dataDictionaryEntry.getAttributes()){
 349  0
                     String nestedAttributeName = attrPath + "." + attribute.getName();
 350  0
                     AttributeDefinition nestedAttribute = copyAttributeDefinition(attribute);
 351  0
                     nestedAttribute.setName(nestedAttributeName);
 352  
                     
 353  0
                     if (!attributeMap.containsValue(nestedAttributeName)){
 354  0
                             this.attributes.add(nestedAttribute);
 355  0
                             this.attributeMap.put(nestedAttributeName, nestedAttribute);
 356  
                     }
 357  0
             }            
 358  
             
 359  
             //Recursively add complex attributes
 360  0
             List<ComplexAttributeDefinition> nestedComplexAttributes = dataDictionaryEntry.getComplexAttributes();
 361  0
             if (nestedComplexAttributes != null){
 362  0
                     for (ComplexAttributeDefinition nestedComplexAttribute:nestedComplexAttributes){
 363  0
                             addNestedAttributes(nestedComplexAttribute, attrPath);
 364  
                     }
 365  
             }
 366  0
     }
 367  
     
 368  
     private AttributeDefinition copyAttributeDefinition(AttributeDefinition attrDefToCopy){
 369  0
             AttributeDefinition attrDefCopy = new AttributeDefinition();
 370  
             
 371  
             try {
 372  
                     
 373  0
                         BeanUtils.copyProperties(attrDefToCopy, attrDefToCopy, new String[] { "formatterClass" });
 374  0
                 } catch (Exception e) {
 375  0
                         e.printStackTrace();
 376  0
                 }
 377  
                 
 378  0
                 return attrDefCopy;
 379  
     }
 380  
 }