View Javadoc

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  
17  package org.kuali.rice.krad.datadictionary;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.krad.datadictionary.exception.ClassValidationException;
21  import org.kuali.rice.krad.datadictionary.exception.DuplicateEntryException;
22  import org.kuali.rice.krad.document.Document;
23  import org.kuali.rice.krad.document.authorization.DocumentAuthorizer;
24  import org.kuali.rice.krad.document.authorization.DocumentPresentationController;
25  import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
26  import org.kuali.rice.krad.rule.BusinessRule;
27  
28  import java.util.ArrayList;
29  import java.util.LinkedHashMap;
30  import java.util.List;
31  import java.util.Map;
32  
33  /**
34   * A single Document entry in the DataDictionary, which contains information relating to the display, validation, and
35   * general
36   * maintenance of a Document (transactional or maintenance) and its attributes.
37   * <p/>
38   * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process
39   *
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   */
42  abstract public class DocumentEntry extends DataDictionaryEntryBase {
43      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentEntry.class);
44      private static final long serialVersionUID = 8231730871830055356L;
45  
46      protected String documentTypeName;
47  
48      protected Class<? extends Document> documentClass;
49      protected Class<? extends Document> baseDocumentClass;
50      protected Class<? extends BusinessRule> businessRulesClass;
51  
52      protected boolean allowsNoteAttachments = true;
53      protected boolean allowsNoteFYI = false;
54      protected Class<? extends KeyValuesFinder> attachmentTypesValuesFinderClass;
55      protected boolean displayTopicFieldInNotes = false;
56      protected boolean usePessimisticLocking = false;
57      protected boolean useWorkflowPessimisticLocking = false;
58      protected boolean encryptDocumentDataInPersistentSessionStorage = false;
59  
60      protected boolean allowsCopy = false;
61      protected WorkflowProperties workflowProperties;
62      protected WorkflowAttributes workflowAttributes;
63  
64      protected List<ReferenceDefinition> defaultExistenceChecks = new ArrayList<ReferenceDefinition>();
65      protected Map<String, ReferenceDefinition> defaultExistenceCheckMap =
66              new LinkedHashMap<String, ReferenceDefinition>();
67  
68      protected Class<? extends DocumentAuthorizer> documentAuthorizerClass;
69      protected Class<? extends DocumentPresentationController> documentPresentationControllerClass;
70  
71      /**
72       * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#getJstlKey()
73       */
74      public String getJstlKey() {
75          return documentTypeName;
76      }
77  
78      /**
79       * The documentClass element is the name of the java class
80       * associated with the document.
81       */
82      public void setDocumentClass(Class<? extends Document> documentClass) {
83          if (documentClass == null) {
84              throw new IllegalArgumentException("invalid (null) documentClass");
85          }
86  
87          this.documentClass = documentClass;
88      }
89  
90      public Class<? extends Document> getDocumentClass() {
91          return documentClass;
92      }
93  
94      /**
95       * The optional baseDocumentClass element is the name of the java superclass
96       * associated with the document. This gives the data dictionary the ability
97       * to index by the superclass in addition to the current class.
98       */
99      public void setBaseDocumentClass(Class<? extends Document> baseDocumentClass) {
100         this.baseDocumentClass = baseDocumentClass;
101     }
102 
103     public Class<? extends Document> getBaseDocumentClass() {
104         return baseDocumentClass;
105     }
106 
107     /**
108      * The businessRulesClass element is the full class name of the java
109      * class which contains the business rules for a document.
110      */
111     public void setBusinessRulesClass(Class<? extends BusinessRule> businessRulesClass) {
112         this.businessRulesClass = businessRulesClass;
113     }
114 
115     public Class<? extends BusinessRule> getBusinessRulesClass() {
116         return businessRulesClass;
117     }
118 
119     /**
120      * The documentTypeName element is the name of the document
121      * as defined in the workflow system.
122      * Example: "AddressTypeMaintenanceDocument"
123      */
124     public void setDocumentTypeName(String documentTypeName) {
125         if (StringUtils.isBlank(documentTypeName)) {
126             throw new IllegalArgumentException("invalid (blank) documentTypeName");
127         }
128         this.documentTypeName = documentTypeName;
129     }
130 
131     public String getDocumentTypeName() {
132         return this.documentTypeName;
133     }
134 
135     /**
136      * Validate common fields for subclass' benefit.
137      *
138      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#completeValidation()
139      */
140     public void completeValidation() {
141         super.completeValidation();
142 
143         if (baseDocumentClass != null && !baseDocumentClass.isAssignableFrom(documentClass)) {
144             throw new ClassValidationException("The baseDocumentClass " + baseDocumentClass.getName() +
145                     " is not a superclass of the documentClass " + documentClass.getName());
146         }
147 
148         if (workflowProperties != null && workflowAttributes != null) {
149             throw new DataDictionaryException(documentTypeName +
150                     ": workflowProperties and workflowAttributes cannot both be defined for a document");
151         }
152     }
153 
154     /**
155      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#getFullClassName()
156      */
157     public String getFullClassName() {
158         if (getBaseDocumentClass() != null) {
159             return getBaseDocumentClass().getName();
160         }
161         if (getDocumentClass() != null) {
162             return getDocumentClass().getName();
163         }
164         return "";
165     }
166 
167     /**
168      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase#getEntryClass()
169      */
170     public Class getEntryClass() {
171         return getDocumentClass();
172     }
173 
174     public String toString() {
175         return "DocumentEntry for documentType " + documentTypeName;
176     }
177 
178     /**
179      * Accessor method for contained displayTopicFieldInNotes
180      *
181      * @return displayTopicFieldInNotes boolean
182      */
183     public boolean getDisplayTopicFieldInNotes() {
184         return displayTopicFieldInNotes;
185     }
186 
187     /**
188      * This field contains a value of true or false.
189      * If true, then the "Notes and Attachments" tab will render a column for a note topic.
190      */
191     public void setDisplayTopicFieldInNotes(boolean displayTopicFieldInNotes) {
192         this.displayTopicFieldInNotes = displayTopicFieldInNotes;
193     }
194 
195     /**
196      * Accessor method for contained usePessimisticLocking
197      *
198      * @return usePessimisticLocking boolean
199      */
200     public boolean getUsePessimisticLocking() {
201         return this.usePessimisticLocking;
202     }
203 
204     /**
205      * @param usePessimisticLocking
206      */
207     public void setUsePessimisticLocking(boolean usePessimisticLocking) {
208         if (LOG.isDebugEnabled()) {
209             LOG.debug("calling setUsePessimisticLocking '" + usePessimisticLocking + "'");
210         }
211 
212         this.usePessimisticLocking = usePessimisticLocking;
213     }
214 
215     /**
216      * Accessor method for contained useWorkflowPessimisticLocking
217      *
218      * @return useWorkflowPessimisticLocking boolean
219      */
220     public boolean getUseWorkflowPessimisticLocking() {
221         return this.useWorkflowPessimisticLocking;
222     }
223 
224     /**
225      * @param useWorkflowPessimisticLocking
226      */
227     public void setUseWorkflowPessimisticLocking(boolean useWorkflowPessimisticLocking) {
228         if (LOG.isDebugEnabled()) {
229             LOG.debug("calling setuseWorkflowPessimisticLocking '" + useWorkflowPessimisticLocking + "'");
230         }
231 
232         this.useWorkflowPessimisticLocking = useWorkflowPessimisticLocking;
233     }
234 
235     /**
236      * The attachmentTypesValuesFinderClass specifies the name of a values finder
237      * class. This is used to determine the set of file types that are allowed
238      * to be attached to the document.
239      */
240     public void setAttachmentTypesValuesFinderClass(Class<? extends KeyValuesFinder> attachmentTypesValuesFinderClass) {
241         if (attachmentTypesValuesFinderClass == null) {
242             throw new IllegalArgumentException("invalid (null) attachmentTypesValuesFinderClass");
243         }
244 
245         this.attachmentTypesValuesFinderClass = attachmentTypesValuesFinderClass;
246     }
247 
248     /**
249      * @see org.kuali.rice.krad.datadictionary.control.ControlDefinition#getKeyValuesFinder()
250      */
251     public Class<? extends KeyValuesFinder> getAttachmentTypesValuesFinderClass() {
252         return attachmentTypesValuesFinderClass;
253     }
254 
255     /**
256      * The allowsCopy element contains a true or false value.
257      * If true, then a user is allowed to make a copy of the
258      * record using the maintenance screen.
259      */
260     public void setAllowsCopy(boolean allowsCopy) {
261         this.allowsCopy = allowsCopy;
262     }
263 
264     public boolean getAllowsCopy() {
265         return allowsCopy;
266     }
267 
268     /**
269      * @return the allowsNoteAttachments
270      */
271     public boolean getAllowsNoteAttachments() {
272         return this.allowsNoteAttachments;
273     }
274 
275     /**
276      * The allowsNoteAttachments element contains a true or false value.
277      * If true, then a document screen includes notes with attachments. Otherwise,
278      * only notes is displayed.
279      */
280     public void setAllowsNoteAttachments(boolean allowsNoteAttachments) {
281         this.allowsNoteAttachments = allowsNoteAttachments;
282     }
283 
284     /**
285      * @return the allowsNoteFYI
286      */
287     public boolean getAllowsNoteFYI() {
288         return allowsNoteFYI;
289     }
290 
291     /**
292      * This is an indicator for determining whether to render the AdHoc FYI recipient box and Send FYI button.
293      */
294     public void setAllowsNoteFYI(boolean allowsNoteFYI) {
295         this.allowsNoteFYI = allowsNoteFYI;
296     }
297 
298     public WorkflowProperties getWorkflowProperties() {
299         return this.workflowProperties;
300     }
301 
302     /**
303      * This element is used to define a set of workflowPropertyGroups, which are used to
304      * specify which document properties should be serialized during the document serialization
305      * process.
306      */
307     public void setWorkflowProperties(WorkflowProperties workflowProperties) {
308         this.workflowProperties = workflowProperties;
309     }
310 
311     public WorkflowAttributes getWorkflowAttributes() {
312         return this.workflowAttributes;
313     }
314 
315     public void setWorkflowAttributes(WorkflowAttributes workflowAttributes) {
316         this.workflowAttributes = workflowAttributes;
317     }
318 
319     /**
320      * @return List of all defaultExistenceCheck ReferenceDefinitions associated with this MaintenanceDocument, in the
321      *         order in
322      *         which they were added
323      */
324     public List<ReferenceDefinition> getDefaultExistenceChecks() {
325         return defaultExistenceChecks;
326     }
327 
328     /*
329            The defaultExistenceChecks element contains a list of
330            reference object names which are required to exist when maintaining a BO.
331            Optionally, the reference objects can be required to be active.
332 
333            JSTL: defaultExistenceChecks is a Map of Reference elements,
334            whose entries are keyed by attributeName
335     */
336     public void setDefaultExistenceChecks(List<ReferenceDefinition> defaultExistenceChecks) {
337         this.defaultExistenceChecks = defaultExistenceChecks;
338     }
339 
340     /**
341      * @return List of all defaultExistenceCheck reference fieldNames associated with this MaintenanceDocument, in the
342      *         order in
343      *         which they were added
344      */
345     public List<String> getDefaultExistenceCheckFieldNames() {
346         List<String> fieldNames = new ArrayList<String>();
347         fieldNames.addAll(this.defaultExistenceCheckMap.keySet());
348 
349         return fieldNames;
350     }
351 
352     public boolean isEncryptDocumentDataInPersistentSessionStorage() {
353         return this.encryptDocumentDataInPersistentSessionStorage;
354     }
355 
356     public void setEncryptDocumentDataInPersistentSessionStorage(
357             boolean encryptDocumentDataInPersistentSessionStorage) {
358         this.encryptDocumentDataInPersistentSessionStorage = encryptDocumentDataInPersistentSessionStorage;
359     }
360 
361     /**
362      * The documentAuthorizerClass element is the full class name of the
363      * java class which will determine what features are available to the
364      * user based on the user role and document state.
365      */
366     public void setDocumentAuthorizerClass(Class<? extends DocumentAuthorizer> documentAuthorizerClass) {
367         this.documentAuthorizerClass = documentAuthorizerClass;
368     }
369 
370     /**
371      * Returns the document authorizer class for the document.  Only framework code should be calling this method.
372      * Client devs should use {@link DocumentTypeService#getDocumentAuthorizer(org.kuali.rice.krad.document.Document)}
373      * or
374      * {@link DocumentTypeService#getDocumentAuthorizer(String)}
375      *
376      * @return a document authorizer class
377      */
378     public Class<? extends DocumentAuthorizer> getDocumentAuthorizerClass() {
379         return documentAuthorizerClass;
380     }
381 
382     /**
383      * Returns the document presentation controller class for the document.  Only framework code should be calling this
384      * method.
385      * Client devs should use {@link DocumentTypeService#getDocumentPresentationController(org.kuali.rice.krad.document.Document)}
386      * or
387      * {@link DocumentTypeService#getDocumentPresentationController(String)}
388      *
389      * @return the documentPresentationControllerClass
390      */
391     public Class<? extends DocumentPresentationController> getDocumentPresentationControllerClass() {
392         return this.documentPresentationControllerClass;
393     }
394 
395     /**
396      * @param documentPresentationControllerClass the documentPresentationControllerClass to set
397      */
398     public void setDocumentPresentationControllerClass(
399             Class<? extends DocumentPresentationController> documentPresentationControllerClass) {
400         this.documentPresentationControllerClass = documentPresentationControllerClass;
401     }
402 
403     /**
404      * This overridden method ...
405      *
406      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase#afterPropertiesSet()
407      */
408     @Override
409     public void afterPropertiesSet() throws Exception {
410         super.afterPropertiesSet();
411         if (defaultExistenceChecks != null) {
412             defaultExistenceCheckMap.clear();
413             for (ReferenceDefinition reference : defaultExistenceChecks) {
414                 if (reference == null) {
415                     throw new IllegalArgumentException("invalid (null) defaultExistenceCheck");
416                 }
417 
418                 String keyName = reference.isCollectionReference() ?
419                         (reference.getCollection() + "." + reference.getAttributeName()) : reference.getAttributeName();
420                 if (defaultExistenceCheckMap.containsKey(keyName)) {
421                     throw new DuplicateEntryException(
422                             "duplicate defaultExistenceCheck entry for attribute '" + keyName + "'");
423                 }
424                 reference.setBusinessObjectClass(getEntryClass());
425                 defaultExistenceCheckMap.put(keyName, reference);
426             }
427         }
428     }
429 }