View Javadoc

1   /**
2    * Copyright 2005-2012 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 superclass
106      * associated with the document. This gives the data dictionary the ability
107      * to index by the superclass 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 (baseDocumentClass != null && !baseDocumentClass.isAssignableFrom(documentClass)) {
154             throw new ClassValidationException("The baseDocumentClass " + baseDocumentClass.getName() +
155                     " is not a superclass of the documentClass " + documentClass.getName());
156         }
157 
158         if (workflowProperties != null && workflowAttributes != null) {
159             throw new DataDictionaryException(documentTypeName +
160                     ": workflowProperties and workflowAttributes cannot both be defined for a document");
161         }
162     }
163 
164     /**
165      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntry#getFullClassName()
166      */
167     public String getFullClassName() {
168         if (getBaseDocumentClass() != null) {
169             return getBaseDocumentClass().getName();
170         }
171         if (getDocumentClass() != null) {
172             return getDocumentClass().getName();
173         }
174         return "";
175     }
176 
177     /**
178      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase#getEntryClass()
179      */
180     public Class getEntryClass() {
181         return getDocumentClass();
182     }
183 
184     public String toString() {
185         return "DocumentEntry for documentType " + documentTypeName;
186     }
187 
188     /**
189      * Accessor method for contained displayTopicFieldInNotes
190      *
191      * @return displayTopicFieldInNotes boolean
192      */
193     public boolean getDisplayTopicFieldInNotes() {
194         return displayTopicFieldInNotes;
195     }
196 
197     /**
198      * This field contains a value of true or false.
199      * If true, then the "Notes and Attachments" tab will render a column for a note topic.
200      */
201     public void setDisplayTopicFieldInNotes(boolean displayTopicFieldInNotes) {
202         this.displayTopicFieldInNotes = displayTopicFieldInNotes;
203     }
204 
205     /**
206      * Accessor method for contained usePessimisticLocking
207      *
208      * @return usePessimisticLocking boolean
209      */
210     public boolean getUsePessimisticLocking() {
211         return this.usePessimisticLocking;
212     }
213 
214     /**
215      * @param usePessimisticLocking
216      */
217     public void setUsePessimisticLocking(boolean usePessimisticLocking) {
218         if (LOG.isDebugEnabled()) {
219             LOG.debug("calling setUsePessimisticLocking '" + usePessimisticLocking + "'");
220         }
221 
222         this.usePessimisticLocking = usePessimisticLocking;
223     }
224 
225     /**
226      * Accessor method for contained useWorkflowPessimisticLocking
227      *
228      * @return useWorkflowPessimisticLocking boolean
229      */
230     public boolean getUseWorkflowPessimisticLocking() {
231         return this.useWorkflowPessimisticLocking;
232     }
233 
234     /**
235      * @param useWorkflowPessimisticLocking
236      */
237     public void setUseWorkflowPessimisticLocking(boolean useWorkflowPessimisticLocking) {
238         if (LOG.isDebugEnabled()) {
239             LOG.debug("calling setuseWorkflowPessimisticLocking '" + useWorkflowPessimisticLocking + "'");
240         }
241 
242         this.useWorkflowPessimisticLocking = useWorkflowPessimisticLocking;
243     }
244 
245     /**
246      * The attachmentTypesValuesFinderClass specifies the name of a values finder
247      * class. This is used to determine the set of file types that are allowed
248      * to be attached to the document.
249      */
250     public void setAttachmentTypesValuesFinderClass(Class<? extends KeyValuesFinder> attachmentTypesValuesFinderClass) {
251         if (attachmentTypesValuesFinderClass == null) {
252             throw new IllegalArgumentException("invalid (null) attachmentTypesValuesFinderClass");
253         }
254 
255         this.attachmentTypesValuesFinderClass = attachmentTypesValuesFinderClass;
256     }
257 
258     /**
259      * @see org.kuali.rice.krad.datadictionary.control.ControlDefinition#getKeyValuesFinder()
260      */
261     public Class<? extends KeyValuesFinder> getAttachmentTypesValuesFinderClass() {
262         return attachmentTypesValuesFinderClass;
263     }
264 
265     /**
266      * The allowsCopy element contains a true or false value.
267      * If true, then a user is allowed to make a copy of the
268      * record using the maintenance screen.
269      */
270     public void setAllowsCopy(boolean allowsCopy) {
271         this.allowsCopy = allowsCopy;
272     }
273 
274     public boolean getAllowsCopy() {
275         return allowsCopy;
276     }
277 
278     /**
279      * @return the allowsNoteAttachments
280      */
281     public boolean getAllowsNoteAttachments() {
282         return this.allowsNoteAttachments;
283     }
284 
285     /**
286      * The allowsNoteAttachments element contains a true or false value.
287      * If true, then a document screen includes notes with attachments. Otherwise,
288      * only notes is displayed.
289      */
290     public void setAllowsNoteAttachments(boolean allowsNoteAttachments) {
291         this.allowsNoteAttachments = allowsNoteAttachments;
292     }
293 
294     /**
295      * @return the allowsNoteFYI
296      */
297     public boolean getAllowsNoteFYI() {
298         return allowsNoteFYI;
299     }
300 
301     /**
302      * This is an indicator for determining whether to render the AdHoc FYI recipient box and Send FYI button.
303      */
304     public void setAllowsNoteFYI(boolean allowsNoteFYI) {
305         this.allowsNoteFYI = allowsNoteFYI;
306     }
307 
308     public WorkflowProperties getWorkflowProperties() {
309         return this.workflowProperties;
310     }
311 
312     /**
313      * This element is used to define a set of workflowPropertyGroups, which are used to
314      * specify which document properties should be serialized during the document serialization
315      * process.
316      */
317     public void setWorkflowProperties(WorkflowProperties workflowProperties) {
318         this.workflowProperties = workflowProperties;
319     }
320 
321     public WorkflowAttributes getWorkflowAttributes() {
322         return this.workflowAttributes;
323     }
324 
325     public void setWorkflowAttributes(WorkflowAttributes workflowAttributes) {
326         this.workflowAttributes = workflowAttributes;
327     }
328 
329     /**
330      * Full class name for the {@link DocumentAuthorizer} that will authorize actions for this document
331      *
332      * @return class name for document authorizer
333      */
334     public Class<? extends DocumentAuthorizer> getDocumentAuthorizerClass() {
335         return documentAuthorizerClass;
336     }
337 
338     /**
339      * Setter for the document authorizer class name
340      *
341      * @param documentAuthorizerClass
342      */
343     public void setDocumentAuthorizerClass(Class<? extends DocumentAuthorizer> documentAuthorizerClass) {
344         this.documentAuthorizerClass = documentAuthorizerClass;
345     }
346 
347     /**
348      * Full class name for the {@link DocumentPresentationController} that will be invoked to implement presentation
349      * logic for the document
350      *
351      * @return class name for document presentation controller
352      */
353     public Class<? extends DocumentPresentationController> getDocumentPresentationControllerClass() {
354         return documentPresentationControllerClass;
355     }
356 
357     /**
358      * Setter for the document presentation controller class name
359      *
360      * @param documentPresentationControllerClass
361      */
362     public void setDocumentPresentationControllerClass(
363             Class<? extends DocumentPresentationController> documentPresentationControllerClass) {
364         this.documentPresentationControllerClass = documentPresentationControllerClass;
365     }
366 
367     /**
368      * @return List of all defaultExistenceCheck ReferenceDefinitions associated with this MaintenanceDocument, in the
369      *         order in
370      *         which they were added
371      */
372     public List<ReferenceDefinition> getDefaultExistenceChecks() {
373         return defaultExistenceChecks;
374     }
375 
376     /*
377            The defaultExistenceChecks element contains a list of
378            reference object names which are required to exist when maintaining a BO.
379            Optionally, the reference objects can be required to be active.
380 
381            JSTL: defaultExistenceChecks is a Map of Reference elements,
382            whose entries are keyed by attributeName
383     */
384     public void setDefaultExistenceChecks(List<ReferenceDefinition> defaultExistenceChecks) {
385         this.defaultExistenceChecks = defaultExistenceChecks;
386     }
387 
388     /**
389      * @return List of all defaultExistenceCheck reference fieldNames associated with this MaintenanceDocument, in the
390      *         order in
391      *         which they were added
392      */
393     public List<String> getDefaultExistenceCheckFieldNames() {
394         List<String> fieldNames = new ArrayList<String>();
395         fieldNames.addAll(this.defaultExistenceCheckMap.keySet());
396 
397         return fieldNames;
398     }
399 
400     public boolean isEncryptDocumentDataInPersistentSessionStorage() {
401         return this.encryptDocumentDataInPersistentSessionStorage;
402     }
403 
404     public void setEncryptDocumentDataInPersistentSessionStorage(
405             boolean encryptDocumentDataInPersistentSessionStorage) {
406         this.encryptDocumentDataInPersistentSessionStorage = encryptDocumentDataInPersistentSessionStorage;
407     }
408 
409     /**
410      * This overridden method ...
411      *
412      * @see org.kuali.rice.krad.datadictionary.DataDictionaryEntryBase#afterPropertiesSet()
413      */
414     @Override
415     public void afterPropertiesSet() throws Exception {
416         super.afterPropertiesSet();
417         if (defaultExistenceChecks != null) {
418             defaultExistenceCheckMap.clear();
419             for (ReferenceDefinition reference : defaultExistenceChecks) {
420                 if (reference == null) {
421                     throw new IllegalArgumentException("invalid (null) defaultExistenceCheck");
422                 }
423 
424                 String keyName = reference.isCollectionReference() ?
425                         (reference.getCollection() + "." + reference.getAttributeName()) : reference.getAttributeName();
426                 if (defaultExistenceCheckMap.containsKey(keyName)) {
427                     throw new DuplicateEntryException(
428                             "duplicate defaultExistenceCheck entry for attribute '" + keyName + "'");
429                 }
430                 reference.setBusinessObjectClass(getEntryClass());
431                 defaultExistenceCheckMap.put(keyName, reference);
432             }
433         }
434     }
435 }