View Javadoc

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