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.kns.datadictionary;
18  
19  import java.util.ArrayList;
20  import java.util.LinkedHashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.kuali.rice.kew.docsearch.DocumentSearchGenerator;
26  import org.kuali.rice.kew.doctype.service.DocumentTypeService;
27  import org.kuali.rice.kns.datadictionary.exception.ClassValidationException;
28  import org.kuali.rice.kns.datadictionary.exception.DuplicateEntryException;
29  import org.kuali.rice.kns.document.Document;
30  import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
31  import org.kuali.rice.kns.document.authorization.DocumentPresentationController;
32  import org.kuali.rice.kns.lookup.keyvalues.KeyValuesFinder;
33  import org.kuali.rice.kns.rule.BusinessRule;
34  import org.kuali.rice.kns.rule.PromptBeforeValidation;
35  import org.kuali.rice.kns.web.derviedvaluesetter.DerivedValuesSetter;
36  import org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase;
37  
38  /**
39   * A single Document entry in the DataDictionary, which contains information relating to the display, validation, and general
40   * maintenance of a Document (transactional or maintenance) and its attributes.
41   * 
42   * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process.
43   * 
44   * 
45   */
46  abstract public class DocumentEntry extends DataDictionaryEntryBase {
47  
48  	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentEntry.class);
49  	
50      protected Class<? extends Document> documentClass;
51      protected Class<? extends Document> baseDocumentClass;
52      protected Class<? extends BusinessRule> businessRulesClass;
53      protected Class<? extends PromptBeforeValidation> promptBeforeValidationClass;
54      protected Class<? extends DerivedValuesSetter> derivedValuesSetterClass;
55      protected String documentTypeName;
56  
57      protected boolean allowsNoteAttachments = true;
58      protected boolean allowsNoteFYI = false;
59      protected Class<? extends KeyValuesFinder> attachmentTypesValuesFinderClass;
60      protected boolean displayTopicFieldInNotes = false;
61      protected boolean usePessimisticLocking = false;
62      protected boolean useWorkflowPessimisticLocking = false;
63      protected boolean encryptDocumentDataInPersistentSessionStorage = false;
64  
65      protected List<String> webScriptFiles = new ArrayList<String>( 3 );
66  
67      protected Class<? extends DocumentAuthorizer> documentAuthorizerClass;
68      protected List<HeaderNavigation> headerNavigationList = new ArrayList<HeaderNavigation>();
69  
70      protected boolean allowsCopy = false;
71      protected WorkflowProperties workflowProperties;
72      protected WorkflowAttributes workflowAttributes;
73  
74      protected List<ReferenceDefinition> defaultExistenceChecks = new ArrayList<ReferenceDefinition>();
75      protected Map<String,ReferenceDefinition> defaultExistenceCheckMap = new LinkedHashMap<String, ReferenceDefinition>();
76  
77      protected boolean sessionDocument = false;
78      protected Class<? extends DocumentPresentationController> documentPresentationControllerClass;
79      protected Class<? extends DocumentSearchGenerator> documentSearchGeneratorClass;
80      
81      /**
82       * @see org.kuali.rice.kns.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 documentAuthorizerClass element is the full class name of the
131             java class which will determine what features are available to the
132             user based on the user role and document state.
133      */
134     public void setDocumentAuthorizerClass(Class<? extends DocumentAuthorizer> documentAuthorizerClass) {
135         this.documentAuthorizerClass = documentAuthorizerClass;
136     }
137 
138     /**
139      * Returns the document authorizer class for the document.  Only framework code should be calling this method.
140 	 * Client devs should use {@link DocumentTypeService#getDocumentAuthorizer(Document)} or
141 	 * {@link DocumentTypeService#getDocumentAuthorizer(String)}
142      * 
143      * @return a document authorizer class
144      */
145     public Class<? extends DocumentAuthorizer> getDocumentAuthorizerClass() {
146         return documentAuthorizerClass;
147     }
148 
149     /**
150      * @return Returns the preRulesCheckClass.
151      */
152     public Class<? extends PromptBeforeValidation> getPromptBeforeValidationClass() {
153         return promptBeforeValidationClass;
154     }
155 
156     /**
157      *  The promptBeforeValidationClass element is the full class name of the java
158      *  class which determines whether the user should be asked any questions prior to running validation.
159      *  
160      *   @see KualiDocumentActionBase#promptBeforeValidation(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, String)
161      */
162     public void setPromptBeforeValidationClass(Class<? extends PromptBeforeValidation> preRulesCheckClass) {
163         this.promptBeforeValidationClass = preRulesCheckClass;
164     }
165 
166     /**
167             The documentTypeName element is the name of the document
168             as defined in the workflow system.
169             Example: "AddressTypeMaintenanceDocument"
170      */
171     public void setDocumentTypeName(String documentTypeName) {
172         if (StringUtils.isBlank(documentTypeName)) {
173             throw new IllegalArgumentException("invalid (blank) documentTypeName");
174         }
175         this.documentTypeName = documentTypeName;
176     }
177 
178     public String getDocumentTypeName() {
179         return this.documentTypeName;
180     }
181 
182     /**
183      * Validate common fields for subclass' benefit.
184      * 
185      * @see org.kuali.rice.kns.datadictionary.DataDictionaryEntry#completeValidation()
186      */
187     public void completeValidation() {
188         super.completeValidation();
189 
190     	if (baseDocumentClass != null && !baseDocumentClass.isAssignableFrom(documentClass)) {
191     		throw new ClassValidationException("The baseDocumentClass " + baseDocumentClass.getName() +
192     				" is not a superclass of the documentClass " + documentClass.getName());
193     	}
194         
195         if (workflowProperties != null && workflowAttributes != null) {
196         	throw new DataDictionaryException(documentTypeName + ": workflowProperties and workflowAttributes cannot both be defined for a document");
197         }
198     }
199 
200     /**
201      * @see org.kuali.rice.kns.datadictionary.DataDictionaryEntry#getFullClassName()
202      */
203     public String getFullClassName() {
204     	if ( getBaseDocumentClass() != null) {
205     		return getBaseDocumentClass().getName();
206     	}
207     	if ( getDocumentClass() != null ) {
208     		return getDocumentClass().getName();
209     	}
210     	return "";
211     }
212 
213     /**
214      * @see org.kuali.rice.kns.datadictionary.DataDictionaryEntryBase#getEntryClass()
215      */
216     public Class getEntryClass() {
217         return getDocumentClass();
218     }
219 
220     public String toString() {
221         return "DocumentEntry for documentType " + documentTypeName;
222     }
223 
224     /**
225      * Accessor method for contained displayTopicFieldInNotes
226      * 
227      * @return displayTopicFieldInNotes boolean
228      */
229     public boolean getDisplayTopicFieldInNotes() {
230         return displayTopicFieldInNotes;
231     }
232 
233     /**
234             This field contains a value of true or false.
235             If true, then the "Notes and Attachments" tab will render a column for a note topic.
236      */
237     public void setDisplayTopicFieldInNotes(boolean displayTopicFieldInNotes) {
238         this.displayTopicFieldInNotes = displayTopicFieldInNotes;
239     }
240     
241     /**
242      * Accessor method for contained usePessimisticLocking
243      * 
244      * @return usePessimisticLocking boolean
245      */
246     public boolean getUsePessimisticLocking() {
247         return this.usePessimisticLocking;
248     }
249 
250     /**
251      * @param usePessimisticLocking
252      */
253     public void setUsePessimisticLocking(boolean usePessimisticLocking) {
254         if ( LOG.isDebugEnabled() ) {
255             LOG.debug("calling setUsePessimisticLocking '" + usePessimisticLocking + "'");
256         }
257 
258         this.usePessimisticLocking = usePessimisticLocking;
259     }
260 
261     /**
262      * Accessor method for contained useWorkflowPessimisticLocking
263      * 
264      * @return useWorkflowPessimisticLocking boolean
265      */
266     public boolean getUseWorkflowPessimisticLocking() {
267         return this.useWorkflowPessimisticLocking;
268     }
269 
270     /**
271      * @param useWorkflowPessimisticLocking
272      */
273     public void setUseWorkflowPessimisticLocking(boolean useWorkflowPessimisticLocking) {
274         if ( LOG.isDebugEnabled() ) {
275             LOG.debug("calling setuseWorkflowPessimisticLocking '" + useWorkflowPessimisticLocking + "'");
276         }
277 
278         this.useWorkflowPessimisticLocking = useWorkflowPessimisticLocking;
279     }
280 
281     /**
282         The attachmentTypesValuesFinderClass specifies the name of a values finder
283         class. This is used to determine the set of file types that are allowed
284         to be attached to the document.
285      */
286     public void setAttachmentTypesValuesFinderClass(Class<? extends KeyValuesFinder> attachmentTypesValuesFinderClass) {
287         if (attachmentTypesValuesFinderClass == null) {
288             throw new IllegalArgumentException("invalid (null) attachmentTypesValuesFinderClass");
289         }
290 
291         this.attachmentTypesValuesFinderClass = attachmentTypesValuesFinderClass;
292     }
293 
294     /**
295      * @see org.kuali.rice.kns.datadictionary.control.ControlDefinition#getKeyValuesFinder()
296      */
297     public Class<? extends KeyValuesFinder> getAttachmentTypesValuesFinderClass() {
298         return attachmentTypesValuesFinderClass;
299     }
300 
301     /**
302             The allowsCopy element contains a true or false value.
303             If true, then a user is allowed to make a copy of the
304             record using the maintenance screen.
305      */
306     public void setAllowsCopy(boolean allowsCopy) {
307         this.allowsCopy = allowsCopy;
308     }
309 
310     public boolean getAllowsCopy() {
311         return allowsCopy;
312     }
313     
314     public List<HeaderNavigation> getHeaderNavigationList() {
315         return headerNavigationList;
316     }
317 
318     public List<String> getWebScriptFiles() {
319         return webScriptFiles;
320     }
321 
322     /**
323             The webScriptFile element defines the name of javascript files
324             that are necessary for processing the document.  The specified
325             javascript files will be included in the generated html.
326      */
327     public void setWebScriptFiles(List<String> webScriptFiles) {
328         this.webScriptFiles = webScriptFiles;
329     }
330 
331     /**
332      * @return the allowsNoteAttachments
333      */
334     public boolean getAllowsNoteAttachments() {
335         return this.allowsNoteAttachments;
336     }
337 
338     /**
339             The allowsNoteAttachments element contains a true or false value.
340             If true, then a document screen includes notes with attachments. Otherwise,
341             only notes is displayed.
342      */
343     public void setAllowsNoteAttachments(boolean allowsNoteAttachments) {
344         this.allowsNoteAttachments = allowsNoteAttachments;
345     }
346 
347     /**
348      * @return the allowsNoteFYI
349      */
350     public boolean getAllowsNoteFYI() {
351     	return allowsNoteFYI;
352     }
353     
354     /**
355      * This is an indicator for determining whether to render the AdHoc FYI recipient box and Send FYI button.
356      */
357     public void setAllowsNoteFYI(boolean allowsNoteFYI) {
358     	this.allowsNoteFYI = allowsNoteFYI;
359     }
360     
361     public WorkflowProperties getWorkflowProperties() {
362         return this.workflowProperties;
363     }
364 
365     /**
366             This element is used to define a set of workflowPropertyGroups, which are used to
367             specify which document properties should be serialized during the document serialization
368             process.
369      */
370     public void setWorkflowProperties(WorkflowProperties workflowProperties) {
371         this.workflowProperties = workflowProperties;
372     }
373 
374     public WorkflowAttributes getWorkflowAttributes() {
375 		return this.workflowAttributes;
376 	}
377 
378 	public void setWorkflowAttributes(WorkflowAttributes workflowAttributes) {
379 		this.workflowAttributes = workflowAttributes;
380 	}
381 
382 	/**
383             The headerNavigation element defines a set of additional
384             tabs which will appear on the document.
385      */
386     public void setHeaderNavigationList(List<HeaderNavigation> headerNavigationList) {
387         this.headerNavigationList = headerNavigationList;
388     }
389 
390     /**
391      * 
392      * @return List of all defaultExistenceCheck ReferenceDefinitions associated with this MaintenanceDocument, in the order in
393      *         which they were added
394      * 
395      */
396     public List<ReferenceDefinition> getDefaultExistenceChecks() {
397         return defaultExistenceChecks;
398     }
399 
400 
401     /*
402             The defaultExistenceChecks element contains a list of
403             reference object names which are required to exist when maintaining a BO.
404             Optionally, the reference objects can be required to be active.
405 
406             JSTL: defaultExistenceChecks is a Map of Reference elements,
407             whose entries are keyed by attributeName
408      */
409     public void setDefaultExistenceChecks(List<ReferenceDefinition> defaultExistenceChecks) {
410         this.defaultExistenceChecks = defaultExistenceChecks;
411     }
412     /**
413      * 
414      * @return List of all defaultExistenceCheck reference fieldNames associated with this MaintenanceDocument, in the order in
415      *         which they were added
416      * 
417      */
418     public List<String> getDefaultExistenceCheckFieldNames() {
419         List<String> fieldNames = new ArrayList<String>();
420         fieldNames.addAll(this.defaultExistenceCheckMap.keySet());
421 
422         return fieldNames;
423     }
424 
425 
426 
427 	public boolean isSessionDocument() {
428 		return this.sessionDocument;
429 	}
430 
431 	public void setSessionDocument(boolean sessionDocument) {
432 		this.sessionDocument = sessionDocument;
433 	}
434 
435 	/**
436 	 * Returns the document presentation controller class for the document.  Only framework code should be calling this method.
437 	 * Client devs should use {@link DocumentTypeService#getDocumentPresentationController(Document)} or
438 	 * {@link DocumentTypeService#getDocumentPresentationController(String)}
439 	 * 
440 	 * @return the documentPresentationControllerClass
441 	 */
442 	public Class<? extends DocumentPresentationController> getDocumentPresentationControllerClass() {
443 		return this.documentPresentationControllerClass;
444 	}
445 
446 	/**
447 	 * @param documentPresentationControllerClass the documentPresentationControllerClass to set
448 	 */
449 	public void setDocumentPresentationControllerClass(
450 			Class<? extends DocumentPresentationController> documentPresentationControllerClass) {
451 		this.documentPresentationControllerClass = documentPresentationControllerClass;
452 	}
453 
454 	/**
455 	 * @return the derivedValuesSetter
456 	 */
457 	public Class<? extends DerivedValuesSetter> getDerivedValuesSetterClass() {
458 		return this.derivedValuesSetterClass;
459 	}
460 
461 	/**
462 	 * @param derivedValuesSetter the derivedValuesSetter to set
463 	 */
464 	public void setDerivedValuesSetterClass(
465 			Class<? extends DerivedValuesSetter> derivedValuesSetter) {
466 		this.derivedValuesSetterClass = derivedValuesSetter;
467 	}
468 
469 	public boolean isEncryptDocumentDataInPersistentSessionStorage() {
470 		return this.encryptDocumentDataInPersistentSessionStorage;
471 	}
472 
473 	public void setEncryptDocumentDataInPersistentSessionStorage(
474 			boolean encryptDocumentDataInPersistentSessionStorage) {
475 		this.encryptDocumentDataInPersistentSessionStorage = encryptDocumentDataInPersistentSessionStorage;
476 	}
477 
478     public Class<? extends DocumentSearchGenerator> getDocumentSearchGeneratorClass() {
479         return this.documentSearchGeneratorClass;
480     }
481 
482     public void setDocumentSearchGeneratorClass(
483             Class<? extends DocumentSearchGenerator> documentSearchGeneratorClass) {
484         this.documentSearchGeneratorClass = documentSearchGeneratorClass;
485     }
486 
487     /**
488      * This overridden method ...
489      * 
490      * @see org.kuali.rice.kns.datadictionary.DataDictionaryEntryBase#afterPropertiesSet()
491      */
492     @Override
493     public void afterPropertiesSet() throws Exception {
494     	super.afterPropertiesSet();
495     	if ( defaultExistenceChecks != null) {
496             defaultExistenceCheckMap.clear();
497             for ( ReferenceDefinition reference : defaultExistenceChecks  ) {
498                 if (reference == null) {
499                     throw new IllegalArgumentException("invalid (null) defaultExistenceCheck");
500                 }
501         
502                 String keyName = reference.isCollectionReference()? (reference.getCollection()+"."+reference.getAttributeName()):reference.getAttributeName();
503                 if (defaultExistenceCheckMap.containsKey(keyName)) {
504                     throw new DuplicateEntryException("duplicate defaultExistenceCheck entry for attribute '" + keyName + "'");
505                 }
506                 reference.setBusinessObjectClass(getEntryClass());
507                 defaultExistenceCheckMap.put(keyName, reference);
508             }
509     	}
510     }
511 }