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