Coverage Report - org.kuali.rice.kew.doctype.bo.DocumentType
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentType
0%
0/527
0%
0/282
2.459
 
 1  
 /*
 2  
  * Copyright 2006-2011 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.kew.doctype.bo;
 18  
 
 19  
 import java.lang.reflect.InvocationTargetException;
 20  
 import java.util.ArrayList;
 21  
 import java.util.Collection;
 22  
 import java.util.Collections;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.Set;
 26  
 
 27  
 import javax.persistence.Basic;
 28  
 import javax.persistence.CascadeType;
 29  
 import javax.persistence.Column;
 30  
 import javax.persistence.Entity;
 31  
 import javax.persistence.FetchType;
 32  
 import javax.persistence.GeneratedValue;
 33  
 import javax.persistence.Id;
 34  
 import javax.persistence.Lob;
 35  
 import javax.persistence.NamedQueries;
 36  
 import javax.persistence.NamedQuery;
 37  
 import javax.persistence.OneToMany;
 38  
 import javax.persistence.OrderBy;
 39  
 import javax.persistence.Table;
 40  
 import javax.persistence.Transient;
 41  
 
 42  
 import org.apache.commons.lang.StringUtils;
 43  
 import org.hibernate.annotations.Fetch;
 44  
 import org.hibernate.annotations.FetchMode;
 45  
 import org.hibernate.annotations.GenericGenerator;
 46  
 import org.hibernate.annotations.Parameter;
 47  
 import org.kuali.rice.core.api.config.CoreConfigHelper;
 48  
 import org.kuali.rice.core.api.config.property.ConfigContext;
 49  
 import org.kuali.rice.core.api.exception.RiceRemoteServiceConnectionException;
 50  
 import org.kuali.rice.core.api.reflect.ObjectDefinition;
 51  
 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
 52  
 import org.kuali.rice.core.web.format.FormatException;
 53  
 import org.kuali.rice.kew.actionlist.CustomActionListAttribute;
 54  
 import org.kuali.rice.kew.docsearch.DocumentSearchCriteriaProcessor;
 55  
 import org.kuali.rice.kew.docsearch.DocumentSearchGenerator;
 56  
 import org.kuali.rice.kew.docsearch.DocumentSearchResultProcessor;
 57  
 import org.kuali.rice.kew.docsearch.SearchableAttribute;
 58  
 import org.kuali.rice.kew.docsearch.StandardDocumentSearchCriteriaProcessor;
 59  
 import org.kuali.rice.kew.docsearch.xml.DocumentSearchXMLResultProcessor;
 60  
 import org.kuali.rice.kew.docsearch.xml.GenericXMLSearchableAttribute;
 61  
 import org.kuali.rice.kew.doctype.ApplicationDocumentStatus;
 62  
 import org.kuali.rice.kew.doctype.DocumentTypeAttribute;
 63  
 import org.kuali.rice.kew.doctype.DocumentTypePolicy;
 64  
 import org.kuali.rice.kew.doctype.DocumentTypePolicyEnum;
 65  
 import org.kuali.rice.kew.doctype.DocumentTypeSecurity;
 66  
 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
 67  
 import org.kuali.rice.kew.engine.node.Process;
 68  
 import org.kuali.rice.kew.exception.ResourceUnavailableException;
 69  
 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
 70  
 import org.kuali.rice.kew.mail.CustomEmailAttribute;
 71  
 import org.kuali.rice.kew.notes.CustomNoteAttribute;
 72  
 import org.kuali.rice.kew.postprocessor.DefaultPostProcessor;
 73  
 import org.kuali.rice.kew.postprocessor.PostProcessor;
 74  
 import org.kuali.rice.kew.postprocessor.PostProcessorRemote;
 75  
 import org.kuali.rice.kew.postprocessor.PostProcessorRemoteAdapter;
 76  
 import org.kuali.rice.kew.rule.bo.RuleAttribute;
 77  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 78  
 import org.kuali.rice.kew.util.CodeTranslator;
 79  
 import org.kuali.rice.kew.util.KEWConstants;
 80  
 import org.kuali.rice.kew.util.KEWPropertyConstants;
 81  
 import org.kuali.rice.kew.util.Utilities;
 82  
 import org.kuali.rice.kim.api.group.Group;
 83  
 import org.kuali.rice.kim.api.services.IdentityManagementService;
 84  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 85  
 import org.kuali.rice.kns.bo.Inactivateable;
 86  
 import org.kuali.rice.kns.bo.PersistableBusinessObjectBase;
 87  
 import org.kuali.rice.kns.util.ObjectUtils;
 88  
 
 89  
 /**
 90  
  * Model bean mapped to ojb representing a document type.  Provides component lookup behavior that
 91  
  * can construct {@link ObjectDefinition} objects correctly to account for application id inheritance.
 92  
  * Can also navigate parent hierarchy when getting data/components.
 93  
  *
 94  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 95  
  */
 96  
 @Entity
 97  
 //@Sequence(name="KREW_DOC_HDR_S", property="documentTypeId")
 98  
 @Table(name = "KREW_DOC_TYP_T")
 99  
 @NamedQueries({
 100  
         @NamedQuery(name = "DocumentType.QuickLinks.FindLabelByTypeName", query = "SELECT label FROM DocumentType WHERE name = :docTypeName AND currentInd = 1"),
 101  
         @NamedQuery(name = "DocumentType.QuickLinks.FindInitiatedDocumentTypesListByInitiatorWorkflowId", query = "SELECT DISTINCT dt.name, dt.label FROM DocumentType dt, DocumentRouteHeaderValue drhv " +
 102  
                 "WHERE drhv.initiatorWorkflowId = :initiatorWorkflowId AND drhv.documentTypeId = dt.documentTypeId AND dt.active = 1 AND dt.currentInd = 1 " +
 103  
                 "ORDER BY UPPER(dt.label)")
 104  
 })
 105  
 public class DocumentType extends PersistableBusinessObjectBase implements Inactivateable, DocumentTypeEBO {
 106  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentType.class);
 107  
 
 108  
     private static final long serialVersionUID = 1312830153583125069L;
 109  
 
 110  
     @Id
 111  
     @GeneratedValue(generator = "KREW_DOC_HDR_S")
 112  
     @GenericGenerator(name = "KREW_DOC_HDR_S", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
 113  
             @Parameter(name = "sequence_name", value = "KREW_DOC_HDR_S"),
 114  
             @Parameter(name = "value_column", value = "id")
 115  
     })
 116  
     @Column(name = "DOC_TYP_ID")
 117  
     private Long documentTypeId;
 118  
     @Column(name = "PARNT_ID")
 119  
     private Long docTypeParentId;
 120  
     @Column(name = "DOC_TYP_NM")
 121  
     private String name;
 122  0
     @Column(name = "DOC_TYP_VER_NBR")
 123  
     private Integer version = new Integer(0);
 124  
     @Column(name = "ACTV_IND")
 125  
     private Boolean active;
 126  
     @Column(name = "CUR_IND")
 127  
     private Boolean currentInd;
 128  
     @Column(name = "DOC_TYP_DESC")
 129  
     private String description;
 130  
     @Column(name = "LBL")
 131  
     private String label;
 132  
     @Column(name = "PREV_DOC_TYP_VER_NBR")
 133  
     private Long previousVersionId;
 134  
     @Column(name = "DOC_HDR_ID")
 135  
     private String documentId;
 136  
 
 137  
     @Column(name = "HELP_DEF_URL")
 138  
     private String unresolvedHelpDefinitionUrl;
 139  
 
 140  
     @Column(name = "DOC_SEARCH_HELP_URL")
 141  
     private String unresolvedDocSearchHelpUrl;
 142  
 
 143  
     @Column(name = "DOC_HDLR_URL")
 144  
     private String unresolvedDocHandlerUrl;
 145  
     @Column(name = "POST_PRCSR")
 146  
     private String postProcessorName;
 147  
     @Column(name = "GRP_ID")
 148  
     //private Long superUserWorkgroupId;
 149  
     private String workgroupId;
 150  
     @Column(name = "BLNKT_APPR_GRP_ID")
 151  
     private String blanketApproveWorkgroupId;
 152  
     @Column(name = "BLNKT_APPR_PLCY")
 153  
     private String blanketApprovePolicy;
 154  
     @Column(name = "RPT_GRP_ID")
 155  
     private String reportingWorkgroupId;
 156  
     @Column(name = "APPL_ID")
 157  
     private String actualApplicationId;
 158  
 
 159  
 
 160  
     /* these two fields are for the web tier lookupable
 161  
      * DocumentType is doing double-duty as a web/business tier object
 162  
      */
 163  
     @Transient
 164  
     private String returnUrl;
 165  
     @Transient
 166  
     private String actionsUrl;
 167  0
     @Transient
 168  
     private Boolean applyRetroactively = Boolean.FALSE;
 169  
 
 170  
     /* The default exception workgroup to apply to nodes that lack an exception workgroup definition.
 171  
      * Used at parse-time only; not stored in db.
 172  
      */
 173  
     @Transient
 174  
     private Group defaultExceptionWorkgroup;
 175  
 
 176  
     @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}, mappedBy = "documentType")
 177  
     @Fetch(value = FetchMode.SELECT)
 178  
     private Collection<DocumentTypePolicy> policies;
 179  
 
 180  
     /* This property contains the list of valid ApplicationDocumentStatus values, 
 181  
     * if defined, for the document type.  If these status values are defined, only these
 182  
     * values may be assigned as the status.  If not valid values are defined, the status may
 183  
     * be set to any value by the client.
 184  
     */
 185  
     @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}, mappedBy = "documentType")
 186  
     @Fetch(value = FetchMode.SELECT)
 187  
     private List<ApplicationDocumentStatus> validApplicationStatuses;
 188  
 
 189  
     @Transient
 190  
     private List routeLevels;
 191  
     @Transient
 192  
     private Collection childrenDocTypes;
 193  
     @Fetch(value = FetchMode.SELECT)
 194  
     @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}, mappedBy = "documentType")
 195  
     @OrderBy("orderIndex ASC")
 196  
     private List<DocumentTypeAttribute> documentTypeAttributes;
 197  
 
 198  
     /* New Workflow 2.1 Field */
 199  0
     @Fetch(value = FetchMode.SELECT)
 200  
     @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, mappedBy = "documentType")
 201  
     private List<Process> processes = new ArrayList();
 202  0
     @Column(name = "RTE_VER_NBR")
 203  
     private String routingVersion = KEWConstants.CURRENT_ROUTING_VERSION;
 204  
 
 205  
     /* Workflow 2.2 Fields */
 206  
     @Column(name = "NOTIFY_ADDR")
 207  
     private String actualNotificationFromAddress;
 208  
     @Lob
 209  
     @Basic(fetch = FetchType.LAZY)
 210  
     @Column(name = "SEC_XML")
 211  
     private String documentTypeSecurityXml;
 212  
     @Transient
 213  
     private DocumentTypeSecurity documentTypeSecurity;
 214  
 
 215  
     /* Workflow 2.4 XSLT-based email message customization */
 216  
     @Column(name = "EMAIL_XSL")
 217  
     private String customEmailStylesheet;
 218  
 
 219  0
     public DocumentType() {
 220  0
         routeLevels = new ArrayList();
 221  0
         documentTypeAttributes = new ArrayList<DocumentTypeAttribute>();
 222  0
         policies = new ArrayList<DocumentTypePolicy>();
 223  0
         version = new Integer(0);
 224  0
         label = null;
 225  0
     }
 226  
 
 227  
     public void populateDataDictionaryEditableFields(Set<String> propertyNamesEditableViaUI, DocumentType dataDictionaryEditedType) {
 228  0
         String currentPropertyName = "";
 229  
         try {
 230  0
             for (String propertyName : propertyNamesEditableViaUI) {
 231  0
                 currentPropertyName = propertyName;
 232  0
                 if (KEWPropertyConstants.PARENT_DOC_TYPE_NAME.equals(propertyName)) {
 233  
                     // this is trying to set the parent document type name so lets set the entire parent document
 234  0
                     String parentDocumentTypeName = (String) ObjectUtils.getPropertyValue(dataDictionaryEditedType, propertyName);
 235  0
                     if (StringUtils.isNotBlank(parentDocumentTypeName)) {
 236  0
                         DocumentType parentDocType = KEWServiceLocator.getDocumentTypeService().findByName(parentDocumentTypeName);
 237  0
                         if (ObjectUtils.isNull(parentDocType)) {
 238  0
                             throw new WorkflowRuntimeException("Could not find valid document type for document type name '" + parentDocumentTypeName + "' to set as Parent Document Type");
 239  
                         }
 240  0
                         setDocTypeParentId(parentDocType.getDocumentTypeId());
 241  
                     }
 242  0
                 }
 243  
 //                else if (!FIELD_PROPERTY_NAME_DOCUMENT_TYPE_ID.equals(propertyName)) {
 244  
                 else {
 245  0
                     LOG.info("*** COPYING PROPERTY NAME FROM OLD BO TO NEW BO: " + propertyName);
 246  0
                     ObjectUtils.setObjectProperty(this, propertyName, ObjectUtils.getPropertyValue(dataDictionaryEditedType, propertyName));
 247  
                 }
 248  
             }
 249  0
         } catch (FormatException e) {
 250  0
             throw new WorkflowRuntimeException("Error setting property '" + currentPropertyName + "' in Document Type", e);
 251  0
         } catch (IllegalAccessException e) {
 252  0
             throw new WorkflowRuntimeException("Error setting property '" + currentPropertyName + "' in Document Type", e);
 253  0
         } catch (InvocationTargetException e) {
 254  0
             throw new WorkflowRuntimeException("Error setting property '" + currentPropertyName + "' in Document Type", e);
 255  0
         } catch (NoSuchMethodException e) {
 256  0
             throw new WorkflowRuntimeException("Error setting property '" + currentPropertyName + "' in Document Type", e);
 257  0
         } catch (Exception e) {
 258  0
             throw new WorkflowRuntimeException("Error setting property '" + currentPropertyName + "' in Document Type", e);
 259  0
         }
 260  0
     }
 261  
 
 262  
     public DocumentTypePolicy getAllowUnrequestedActionPolicy() {
 263  0
         return getPolicyByName(DocumentTypePolicyEnum.ALLOW_UNREQUESTED_ACTION.getName(), Boolean.TRUE);
 264  
     }
 265  
 
 266  
     public DocumentTypePolicy getDefaultApprovePolicy() {
 267  0
         return getPolicyByName(DocumentTypePolicyEnum.DEFAULT_APPROVE.getName(), Boolean.TRUE);
 268  
     }
 269  
 
 270  
     public DocumentTypePolicy getUseWorkflowSuperUserDocHandlerUrl() {
 271  0
         return getPolicyByName(DocumentTypePolicyEnum.USE_KEW_SUPERUSER_DOCHANDLER.getName(), Boolean.TRUE);
 272  
     }
 273  
 
 274  
     public DocumentTypePolicy getInitiatorMustRoutePolicy() {
 275  0
         return getPolicyByName(DocumentTypePolicyEnum.INITIATOR_MUST_ROUTE.getName(), Boolean.TRUE);
 276  
     }
 277  
 
 278  
     public DocumentTypePolicy getInitiatorMustSavePolicy() {
 279  0
         return getPolicyByName(DocumentTypePolicyEnum.INITIATOR_MUST_SAVE.getName(), Boolean.TRUE);
 280  
     }
 281  
 
 282  
     public DocumentTypePolicy getInitiatorMustCancelPolicy() {
 283  0
         return getPolicyByName(DocumentTypePolicyEnum.INITIATOR_MUST_CANCEL.getName(), Boolean.TRUE);
 284  
     }
 285  
 
 286  
     public DocumentTypePolicy getInitiatorMustBlanketApprovePolicy() {
 287  0
         return getPolicyByName(DocumentTypePolicyEnum.INITIATOR_MUST_BLANKET_APPROVE.getName(), Boolean.TRUE);
 288  
     }
 289  
 
 290  
     public DocumentTypePolicy getLookIntoFuturePolicy() {
 291  0
         return getPolicyByName(DocumentTypePolicyEnum.LOOK_FUTURE.getName(), Boolean.FALSE);
 292  
     }
 293  
 
 294  
     public DocumentTypePolicy getSuperUserApproveNotificationPolicy() {
 295  0
         return getPolicyByName(DocumentTypePolicyEnum.SEND_NOTIFICATION_ON_SU_APPROVE.getName(), Boolean.FALSE);
 296  
     }
 297  
 
 298  
     public DocumentTypePolicy getSupportsQuickInitiatePolicy() {
 299  0
         return getPolicyByName(DocumentTypePolicyEnum.SUPPORTS_QUICK_INITIATE.getName(), Boolean.TRUE);
 300  
     }
 301  
 
 302  
     public DocumentTypePolicy getNotifyOnSavePolicy() {
 303  0
         return getPolicyByName(DocumentTypePolicyEnum.NOTIFY_ON_SAVE.getName(), Boolean.FALSE);
 304  
     }
 305  
 
 306  
     /**
 307  
      * This method returns a DocumentTypePolicy object related to the DocumentStatusPolicy defined for this document type.
 308  
      */
 309  
     public DocumentTypePolicy getDocumentStatusPolicy() {
 310  0
         return getPolicyByName(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY.getName(), KEWConstants.DOCUMENT_STATUS_POLICY_KEW_STATUS);
 311  
     }
 312  
 
 313  
     /**
 314  
      * This method returns a DocumentTypePolicy object related to the DocumentStatusPolicy defined for this document type.
 315  
      */
 316  
     public DocumentTypePolicy getSuPostprocessorOverridePolicy() {
 317  0
         return getPolicyByName(DocumentTypePolicyEnum.ALLOW_SU_POSTPROCESSOR_OVERRIDE_POLICY.getName(), Boolean.TRUE);
 318  
     }
 319  
 
 320  
     /**
 321  
      * This method returns a boolean denoting whether the KEW Route Status is to be displayed.
 322  
      * The KEW Route Status is updated by the workflow engine regardless of whether it is to be displayed or not.
 323  
      *
 324  
      * @return true  - if the status is to be displayed  (Policy is set to either use KEW (default) or both)
 325  
      *         false - if the KEW Route Status is not to be displayed
 326  
      */
 327  
     public Boolean isKEWStatusInUse() {
 328  0
         if (isPolicyDefined(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY)) {
 329  0
             String policyValue = getPolicyByName(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY.getName(), KEWConstants.DOCUMENT_STATUS_POLICY_KEW_STATUS).getPolicyStringValue();
 330  0
             return (policyValue == null || "".equals(policyValue)
 331  
                     || KEWConstants.DOCUMENT_STATUS_POLICY_KEW_STATUS.equalsIgnoreCase(policyValue)
 332  
                     || KEWConstants.DOCUMENT_STATUS_POLICY_BOTH.equalsIgnoreCase(policyValue)) ? Boolean.TRUE : Boolean.FALSE;
 333  
         } else {
 334  0
             return Boolean.TRUE;
 335  
         }
 336  
     }
 337  
 
 338  
     /**
 339  
      * This method returns a boolean denoting whether the Application Document Status is to be used for this document type.
 340  
      *
 341  
      * @return true  - if the status is to be displayed  (Policy is set to either use the application document status or both)
 342  
      *         false - if only the KEW Route Status is to be displayed (default)
 343  
      */
 344  
     public Boolean isAppDocStatusInUse() {
 345  0
         if (isPolicyDefined(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY)) {
 346  0
             String policyValue = getPolicyByName(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY.getName(), KEWConstants.DOCUMENT_STATUS_POLICY_KEW_STATUS).getPolicyStringValue();
 347  0
             return (KEWConstants.DOCUMENT_STATUS_POLICY_APP_DOC_STATUS.equalsIgnoreCase(policyValue)
 348  
                     || KEWConstants.DOCUMENT_STATUS_POLICY_BOTH.equalsIgnoreCase(policyValue)) ? Boolean.TRUE : Boolean.FALSE;
 349  
         } else {
 350  0
             return Boolean.FALSE;
 351  
         }
 352  
     }
 353  
 
 354  
     /**
 355  
      * This method returns a boolean denoting if both the KEW Route Status and the Application Document Status
 356  
      * are to be used in displays.
 357  
      *
 358  
      * @return true  - if both the KEW Route Status and Application Document Status are to be displayed.
 359  
      *         false - if only one status is to be displayed.
 360  
      */
 361  
     public Boolean areBothStatusesInUse() {
 362  0
         if (isPolicyDefined(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY)) {
 363  0
             String policyValue = getPolicyByName(DocumentTypePolicyEnum.DOCUMENT_STATUS_POLICY.getName(), KEWConstants.DOCUMENT_STATUS_POLICY_KEW_STATUS).getPolicyStringValue();
 364  0
             return (KEWConstants.DOCUMENT_STATUS_POLICY_BOTH.equalsIgnoreCase(policyValue)) ? Boolean.TRUE : Boolean.FALSE;
 365  
         } else {
 366  0
             return Boolean.FALSE;
 367  
         }
 368  
     }
 369  
 
 370  
     public String getUseWorkflowSuperUserDocHandlerUrlValue() {
 371  0
         if (getUseWorkflowSuperUserDocHandlerUrl() != null) {
 372  0
             return getUseWorkflowSuperUserDocHandlerUrl().getPolicyDisplayValue();
 373  
         }
 374  0
         return null;
 375  
     }
 376  
 
 377  
     public String getAllowUnrequestedActionPolicyDisplayValue() {
 378  0
         if (getAllowUnrequestedActionPolicy() != null) {
 379  0
             return getAllowUnrequestedActionPolicy().getPolicyDisplayValue();
 380  
         }
 381  0
         return null;
 382  
     }
 383  
 
 384  
     public String getDefaultApprovePolicyDisplayValue() {
 385  0
         if (getDefaultApprovePolicy() != null) {
 386  0
             return getDefaultApprovePolicy().getPolicyDisplayValue();
 387  
         }
 388  0
         return null;
 389  
     }
 390  
 
 391  
     public String getInitiatorMustRouteDisplayValue() {
 392  0
         if (getInitiatorMustRoutePolicy() != null) {
 393  0
             return getInitiatorMustRoutePolicy().getPolicyDisplayValue();
 394  
         }
 395  0
         return null;
 396  
     }
 397  
 
 398  
     public String getInitiatorMustSaveDisplayValue() {
 399  0
         if (getInitiatorMustSavePolicy() != null) {
 400  0
             return getInitiatorMustSavePolicy().getPolicyDisplayValue();
 401  
         }
 402  0
         return null;
 403  
     }
 404  
 
 405  
     public boolean isPolicyDefined(DocumentTypePolicyEnum policyToCheck) {
 406  0
         Iterator<DocumentTypePolicy> policyIter = getPolicies().iterator();
 407  0
         while (policyIter.hasNext()) {
 408  0
             DocumentTypePolicy policy = policyIter.next();
 409  0
             if (policyToCheck.getName().equals(policy.getPolicyName())) {
 410  0
                 return true;
 411  
             }
 412  0
         }
 413  0
         return getParentDocType() != null && getParentDocType().isPolicyDefined(policyToCheck);
 414  
     }
 415  
 
 416  
     public void addSearchableAttribute(DocumentTypeAttribute searchableAttribute) {
 417  0
         documentTypeAttributes.add(searchableAttribute);
 418  0
     }
 419  
 
 420  
     public boolean hasSearchableAttributes() {
 421  0
         return !getSearchableAttributes().isEmpty();
 422  
     }
 423  
 
 424  
     public List<SearchableAttribute> getSearchableAttributes() {
 425  0
         List<SearchableAttribute> searchAtts = new ArrayList<SearchableAttribute>();
 426  0
         if ((documentTypeAttributes == null || documentTypeAttributes.isEmpty())) {
 427  0
             if (getParentDocType() != null) {
 428  0
                 return getParentDocType().getSearchableAttributes();
 429  
             } else {
 430  0
                 return searchAtts;
 431  
             }
 432  
         }
 433  
 
 434  0
         for (Iterator iterator = documentTypeAttributes.iterator(); iterator.hasNext();) {
 435  0
             DocumentTypeAttribute attribute = (DocumentTypeAttribute) iterator.next();
 436  
 //                        String attributeType = attribute.getRuleAttribute().getType();
 437  0
             RuleAttribute ruleAttribute = attribute.getRuleAttribute();
 438  0
             SearchableAttribute searchableAttribute = null;
 439  0
             if (KEWConstants.SEARCHABLE_ATTRIBUTE_TYPE.equals(ruleAttribute.getType())) {
 440  0
                 ObjectDefinition objDef = getAttributeObjectDefinition(ruleAttribute);
 441  
                 try {
 442  0
                     searchableAttribute = (SearchableAttribute) GlobalResourceLoader.getObject(objDef);
 443  0
                 } catch (RiceRemoteServiceConnectionException e) {
 444  0
                     LOG.warn("Unable to connect to load searchable attributes for " + this.getName());
 445  0
                     LOG.warn(e.getMessage());
 446  0
                     searchableAttribute = null;
 447  0
                 }
 448  0
             } else if (KEWConstants.SEARCHABLE_XML_ATTRIBUTE_TYPE.equals(ruleAttribute.getType())) {
 449  0
                 ObjectDefinition objDef = getAttributeObjectDefinition(ruleAttribute);
 450  0
                 searchableAttribute = (SearchableAttribute) GlobalResourceLoader.getObject(objDef);
 451  
                 //required to make it work because ruleAttribute XML is required to construct fields
 452  0
                 ((GenericXMLSearchableAttribute) searchableAttribute).setRuleAttribute(ruleAttribute);
 453  
             }
 454  0
             if (searchableAttribute != null) {
 455  0
                 searchAtts.add(searchableAttribute);
 456  
             }
 457  0
         }
 458  0
         return searchAtts;
 459  
     }
 460  
 
 461  
     public DocumentTypeAttribute getDocumentTypeAttribute(int index) {
 462  0
         while (getDocumentTypeAttributes().size() <= index) {
 463  0
             DocumentTypeAttribute attribute = new DocumentTypeAttribute();
 464  
             //attribute.setDocumentTypeId(this.documentTypeId);
 465  0
             getDocumentTypeAttributes().add(attribute);
 466  0
         }
 467  0
         return (DocumentTypeAttribute) getDocumentTypeAttributes().get(index);
 468  
     }
 469  
 
 470  
     public void setDocumentTypeAttribute(int index, DocumentTypeAttribute documentTypeAttribute) {
 471  0
         documentTypeAttributes.set(index, documentTypeAttribute);
 472  0
     }
 473  
 
 474  
     public String getDocTypeActiveIndicatorDisplayValue() {
 475  0
         if (getActive() == null) {
 476  0
             return KEWConstants.INACTIVE_LABEL_LOWER;
 477  
         }
 478  0
         return CodeTranslator.getActiveIndicatorLabel(getActive());
 479  
     }
 480  
 
 481  
     public Collection getChildrenDocTypes() {
 482  0
         if (this.childrenDocTypes == null) {
 483  0
             this.childrenDocTypes = KEWServiceLocator.getDocumentTypeService().getChildDocumentTypes(getDocumentTypeId());
 484  
         }
 485  0
         return childrenDocTypes;
 486  
     }
 487  
 
 488  
     public java.lang.Long getDocTypeParentId() {
 489  0
         return docTypeParentId;
 490  
     }
 491  
 
 492  
     public void setDocTypeParentId(java.lang.Long docTypeParentId) {
 493  0
         this.docTypeParentId = docTypeParentId;
 494  0
     }
 495  
 
 496  
     public DocumentType getParentDocType() {
 497  0
         return KEWServiceLocator.getDocumentTypeService().findById(this.docTypeParentId);
 498  
     }
 499  
 
 500  
     public Collection<DocumentTypePolicy> getPolicies() {
 501  0
         return policies;
 502  
     }
 503  
 
 504  
     public void setPolicies(Collection<DocumentTypePolicy> policies) {
 505  0
         this.policies = policies;
 506  0
     }
 507  
 
 508  
     public List<ApplicationDocumentStatus> getValidApplicationStatuses() {
 509  0
         return this.validApplicationStatuses;
 510  
     }
 511  
 
 512  
     public void setValidApplicationStatuses(
 513  
             List<ApplicationDocumentStatus> validApplicationStatuses) {
 514  0
         this.validApplicationStatuses = validApplicationStatuses;
 515  0
     }
 516  
 
 517  
     public String getDocumentTypeSecurityXml() {
 518  0
         return documentTypeSecurityXml;
 519  
     }
 520  
 
 521  
     public void setDocumentTypeSecurityXml(String documentTypeSecurityXml) {
 522  0
         this.documentTypeSecurityXml = documentTypeSecurityXml;
 523  0
         if (!org.apache.commons.lang.StringUtils.isEmpty(documentTypeSecurityXml.trim())) {
 524  0
             this.documentTypeSecurity = new DocumentTypeSecurity(this.getApplicationId(), documentTypeSecurityXml);
 525  
         } else {
 526  0
             this.documentTypeSecurity = null;
 527  
         }
 528  0
     }
 529  
 
 530  
     public DocumentTypeSecurity getDocumentTypeSecurity() {
 531  0
         if (this.documentTypeSecurity == null &&
 532  
                 this.documentTypeSecurityXml != null &&
 533  
                 !org.apache.commons.lang.StringUtils.isEmpty(documentTypeSecurityXml.trim())) {
 534  0
             this.documentTypeSecurity = new DocumentTypeSecurity(this.getApplicationId(), documentTypeSecurityXml);
 535  
         }
 536  0
         if ((this.documentTypeSecurity == null) && (getParentDocType() != null)) {
 537  0
             return getParentDocType().getDocumentTypeSecurity();
 538  
         }
 539  0
         return this.documentTypeSecurity;
 540  
     }
 541  
 
 542  
 
 543  
     public List getRouteLevels() {
 544  0
         if (routeLevels.isEmpty() && getParentDocType() != null) {
 545  0
             return getParentRouteLevels(getParentDocType());
 546  
         }
 547  0
         return routeLevels;
 548  
     }
 549  
 
 550  
     private List getParentRouteLevels(DocumentType parent) {
 551  0
         if (parent.getRouteLevels() == null) {
 552  0
             return getParentRouteLevels(parent.getParentDocType());
 553  
         } else {
 554  0
             return parent.getRouteLevels();
 555  
         }
 556  
     }
 557  
 
 558  
     public void setRouteLevels(List routeLevels) {
 559  0
         this.routeLevels = routeLevels;
 560  0
     }
 561  
 
 562  
     public String getActionsUrl() {
 563  0
         return actionsUrl;
 564  
     }
 565  
 
 566  
     public void setActionsUrl(String actions) {
 567  0
         this.actionsUrl = actions;
 568  0
     }
 569  
 
 570  
     public Boolean getActive() {
 571  0
         return active;
 572  
     }
 573  
 
 574  
     public void setActive(java.lang.Boolean activeInd) {
 575  0
         this.active = activeInd;
 576  0
     }
 577  
 
 578  
     public java.lang.Boolean getCurrentInd() {
 579  0
         return currentInd;
 580  
     }
 581  
 
 582  
     public void setCurrentInd(java.lang.Boolean currentInd) {
 583  0
         this.currentInd = currentInd;
 584  0
     }
 585  
 
 586  
     public java.lang.String getDescription() {
 587  0
         return description;
 588  
     }
 589  
 
 590  
     public void setDescription(java.lang.String description) {
 591  0
         this.description = description;
 592  0
     }
 593  
 
 594  
     /**
 595  
      * This method gets the document handler url from this object or from a parent document type and resolves any
 596  
      * potential variables that may be in use
 597  
      */
 598  
     public String getDocHandlerUrl() {
 599  0
         return resolveDocHandlerUrl(getUnresolvedInheritedDocHandlerUrl(false));
 600  
     }
 601  
 
 602  
     /**
 603  
      * This method retrieves the unresolved document handler URL either from this object or from a parent document type
 604  
      * object. If the forDisplayPurposes value is true the value returned will be invalid for system use.
 605  
      * <p/>
 606  
      * This method will first call the {@link #getUnresolvedDocHandlerUrl()} method to check for a value on this object.
 607  
      * If none is found a parent document type must exist because the document handler URL is required and is used. The
 608  
      * system will use inheritance to find the document handler url from a document type somewhere in the hierarchy.
 609  
      *
 610  
      * @param forDisplayPurposes - if true then the string returned will have a label explaining where the value came from
 611  
      * @return the unresolved document handler URL value or a displayable value with sourcing information
 612  
      */
 613  
     protected String getUnresolvedInheritedDocHandlerUrl(boolean forDisplayPurposes) {
 614  0
         if (StringUtils.isNotBlank(getUnresolvedDocHandlerUrl())) {
 615  
             // this object has a direct value set, so return it
 616  0
             return getUnresolvedDocHandlerUrl();
 617  
         }
 618  
         // check for a parent document to see if the doc handler url can be inherited
 619  0
         DocumentType docType = getParentDocType();
 620  0
         if (ObjectUtils.isNotNull(docType)) {
 621  0
             String parentValue = docType.getUnresolvedDocHandlerUrl();
 622  0
             if (StringUtils.isNotBlank(parentValue)) {
 623  
                 // found a parent value set on the immediate parent object so return it
 624  0
                 if (forDisplayPurposes) {
 625  0
                     parentValue += " " + KEWConstants.DOCUMENT_TYPE_INHERITED_VALUE_INDICATOR;
 626  
                 }
 627  0
                 return parentValue;
 628  
             }
 629  
             // no valid value exists on the immediate parent, so check the hierarchy
 630  0
             return docType.getUnresolvedInheritedDocHandlerUrl(forDisplayPurposes);
 631  
         }
 632  0
         return null;
 633  
     }
 634  
 
 635  
     /**
 636  
      * Returns the same value as the {@link #getUnresolvedInheritedDocHandlerUrl(boolean)} method but will also have label
 637  
      * information about whether the value returned came from this object or the parent document type associated with this object
 638  
      */
 639  
     public String getDisplayableUnresolvedDocHandlerUrl() {
 640  0
         return getUnresolvedInheritedDocHandlerUrl(true);
 641  
     }
 642  
 
 643  
     /**
 644  
      * EMPTY METHOD. Use {@link #setUnresolvedDocHandlerUrl(String)} instead.
 645  
      *
 646  
      * @deprecated
 647  
      */
 648  
     public void setDisplayableUnresolvedDocHandlerUrl(String displayableUnresolvedDocHandlerUrl) {
 649  
         // do nothing
 650  0
     }
 651  
 
 652  
     /**
 653  
      * @return the unresolvedDocHandlerUrl
 654  
      */
 655  
     public String getUnresolvedDocHandlerUrl() {
 656  0
         return this.unresolvedDocHandlerUrl;
 657  
     }
 658  
 
 659  
     /**
 660  
      * @param unresolvedDocHandlerUrl the unresolvedDocHandlerUrl to set
 661  
      */
 662  
     public void setUnresolvedDocHandlerUrl(String unresolvedDocHandlerUrl) {
 663  0
         this.unresolvedDocHandlerUrl = unresolvedDocHandlerUrl;
 664  0
     }
 665  
 
 666  
     /**
 667  
      * If the doc handler URL has variables in it that need to be replaced, this will look up the values
 668  
      * for those variables and replace them in the doc handler URL.
 669  
      */
 670  
     protected String resolveDocHandlerUrl(String docHandlerUrl) {
 671  0
         if (StringUtils.isBlank(docHandlerUrl)) {
 672  0
             return "";
 673  
         }
 674  0
         return Utilities.substituteConfigParameters(getApplicationId(), docHandlerUrl);
 675  
     }
 676  
 
 677  
     /**
 678  
      * Use {@link #setDocHandlerUrl(String)} to add a document handler url to this object.
 679  
      *
 680  
      * @deprecated
 681  
      */
 682  
     public void setDocHandlerUrl(java.lang.String docHandlerUrl) {
 683  0
         setUnresolvedDocHandlerUrl(docHandlerUrl);
 684  0
     }
 685  
 
 686  
     /**
 687  
      * @return the unresolvedHelpDefinitionUrl
 688  
      */
 689  
     public String getUnresolvedHelpDefinitionUrl() {
 690  0
         return this.unresolvedHelpDefinitionUrl;
 691  
     }
 692  
 
 693  
     /**
 694  
      * @param unresolvedHelpDefinitionUrl the unresolvedHelpDefinitionUrl to set
 695  
      */
 696  
     public void setUnresolvedHelpDefinitionUrl(String unresolvedHelpDefinitionUrl) {
 697  0
         this.unresolvedHelpDefinitionUrl = unresolvedHelpDefinitionUrl;
 698  0
     }
 699  
 
 700  
     /**
 701  
      * This method gets the help definition url from this object and resolves any
 702  
      * potential variables that may be in use
 703  
      */
 704  
     public String getHelpDefinitionUrl() {
 705  0
         return resolveHelpUrl(getUnresolvedHelpDefinitionUrl());
 706  
     }
 707  
 
 708  
     /**
 709  
      * If a help URL has variables in it that need to be replaced, this will look up the values
 710  
      * for those variables and replace them.
 711  
      */
 712  
     protected String resolveHelpUrl(String helpDefinitionUrl) {
 713  0
         if (StringUtils.isBlank(helpDefinitionUrl)) {
 714  0
             return "";
 715  
         }
 716  0
         return Utilities.substituteConfigParameters(helpDefinitionUrl);
 717  
     }
 718  
 
 719  
     /**
 720  
      * @return the unresolvedDocSearchHelpUrl
 721  
      */
 722  
     public String getUnresolvedDocSearchHelpUrl() {
 723  0
         return this.unresolvedDocSearchHelpUrl;
 724  
     }
 725  
 
 726  
     /**
 727  
      * @param unresolvedDocSearchHelpUrl the unresolvedDocSearchHelpUrl to set
 728  
      */
 729  
     public void setUnresolvedDocSearchHelpUrl(String unresolvedDocSearchHelpUrl) {
 730  0
         this.unresolvedDocSearchHelpUrl = unresolvedDocSearchHelpUrl;
 731  0
     }
 732  
 
 733  
     /**
 734  
      * This method gets the doc search help url from this object and resolves any
 735  
      * potential variables that may be in use
 736  
      */
 737  
     public String getDocSearchHelpUrl() {
 738  0
         return resolveHelpUrl(getUnresolvedDocSearchHelpUrl());
 739  
     }
 740  
 
 741  
     public java.lang.String getLabel() {
 742  0
         return label;
 743  
     }
 744  
 
 745  
     public void setLabel(java.lang.String label) {
 746  0
         this.label = label;
 747  0
     }
 748  
 
 749  
     public java.lang.String getName() {
 750  0
         return name;
 751  
     }
 752  
 
 753  
     public void setName(java.lang.String name) {
 754  0
         this.name = name;
 755  0
     }
 756  
 
 757  
     public PostProcessor getPostProcessor() {
 758  0
         String pname = getPostProcessorName();
 759  
 
 760  0
         if (StringUtils.equals(pname, KEWConstants.POST_PROCESSOR_NON_DEFINED_VALUE)) {
 761  0
             return new DefaultPostProcessor();
 762  
         }
 763  0
         if (StringUtils.isBlank(pname)) {
 764  0
             if (getParentDocType() != null) {
 765  0
                 return getParentDocType().getPostProcessor();
 766  
             } else {
 767  0
                 return new DefaultPostProcessor();
 768  
             }
 769  
         }
 770  
 
 771  0
         ObjectDefinition objDef = getObjectDefinition(pname);
 772  0
         Object postProcessor = GlobalResourceLoader.getObject(objDef);
 773  
 
 774  0
         if (postProcessor == null) {
 775  0
             throw new WorkflowRuntimeException("Could not locate PostProcessor in this JVM or at application id " + getApplicationId() + ": " + pname);
 776  
         }
 777  0
         if (postProcessor instanceof PostProcessorRemote) {
 778  0
             postProcessor = new PostProcessorRemoteAdapter((PostProcessorRemote) postProcessor);
 779  
         }
 780  
 
 781  0
         return (PostProcessor) postProcessor;
 782  
     }
 783  
 
 784  
     /**
 785  
      * This method gets the post processor class value. If the forDisplayPurposes value is true
 786  
      * the value will be invalid for system use.
 787  
      * <p/>
 788  
      * This method will first call the {@link #getPostProcessorName()} method to check the value on this object.
 789  
      * If none is found the system checks for a parent document type.  If a valid parent type exists for this document type
 790  
      * then the system will use inheritance from that parent document type as long as at least one document type in the
 791  
      * hierarchy has a value set.  If no value is set on any parent document type or if no parent document type exists the
 792  
      * system will return null.
 793  
      *
 794  
      * @param forDisplayPurposes - if true then the string returned will have a label explaining where the value came from
 795  
      * @return the post processor class value or a displayable value with sourcing information
 796  
      */
 797  
     protected String getInheritedPostProcessorName(boolean forDisplayPurposes) {
 798  0
         if (StringUtils.isNotBlank(getPostProcessorName())) {
 799  
             // this object has a post processor class so return it
 800  0
             return getPostProcessorName();
 801  
         }
 802  0
         if (ObjectUtils.isNotNull(getParentDocType())) {
 803  
             // direct parent document type exists
 804  0
             String parentValue = getParentDocType().getPostProcessorName();
 805  0
             if (StringUtils.isNotBlank(parentValue)) {
 806  
                 // found a post processor class set on the immediate parent object so return it
 807  0
                 if (forDisplayPurposes) {
 808  0
                     parentValue += " " + KEWConstants.DOCUMENT_TYPE_INHERITED_VALUE_INDICATOR;
 809  
                 }
 810  0
                 return parentValue;
 811  
             }
 812  
             // did not find a valid value on the immediate parent, so use hierarchy
 813  0
             return getParentDocType().getInheritedPostProcessorName(forDisplayPurposes);
 814  
         }
 815  0
         return null;
 816  
     }
 817  
 
 818  
     public java.lang.String getPostProcessorName() {
 819  0
         return postProcessorName;
 820  
     }
 821  
 
 822  
     public void setPostProcessorName(java.lang.String postProcessorName) {
 823  0
         this.postProcessorName = postProcessorName;
 824  0
     }
 825  
 
 826  
     public String getDisplayablePostProcessorName() {
 827  0
         return getInheritedPostProcessorName(true);
 828  
     }
 829  
 
 830  
     /**
 831  
      * EMPTY METHOD. Use {@link #setPostProcessorName(String)} instead.
 832  
      *
 833  
      * @deprecated
 834  
      */
 835  
     public void setDisplayablePostProcessorName(String displayablePostProcessorName) {
 836  
         // do nothing
 837  0
     }
 838  
 
 839  
     public java.lang.Long getPreviousVersionId() {
 840  0
         return previousVersionId;
 841  
     }
 842  
 
 843  
     public void setPreviousVersionId(java.lang.Long previousVersionId) {
 844  0
         this.previousVersionId = previousVersionId;
 845  0
     }
 846  
 
 847  
     public java.lang.String getDocumentId() {
 848  0
         return documentId;
 849  
     }
 850  
 
 851  
     public void setDocumentId(java.lang.String documentId) {
 852  0
         this.documentId = documentId;
 853  0
     }
 854  
 
 855  
     public java.lang.Integer getVersion() {
 856  0
         return version;
 857  
     }
 858  
 
 859  
     public void setVersion(java.lang.Integer version) {
 860  0
         this.version = version;
 861  0
     }
 862  
 
 863  
     public java.lang.Long getDocumentTypeId() {
 864  0
         return documentTypeId;
 865  
     }
 866  
 
 867  
     public void setDocumentTypeId(java.lang.Long docTypeGrpId) {
 868  0
         this.documentTypeId = docTypeGrpId;
 869  0
     }
 870  
 
 871  
     public Object copy(boolean preserveKeys) {
 872  0
         throw new UnsupportedOperationException("The copy method is deprecated and unimplemented!");
 873  
     }
 874  
 
 875  
     public java.lang.String getReturnUrl() {
 876  0
         return returnUrl;
 877  
     }
 878  
 
 879  
     public void setReturnUrl(java.lang.String returnUrl) {
 880  0
         this.returnUrl = returnUrl;
 881  0
     }
 882  
 
 883  
     private DocumentTypePolicy getPolicyByName(String policyName, Boolean defaultValue) {
 884  
 
 885  0
         Iterator policyIter = getPolicies().iterator();
 886  0
         while (policyIter.hasNext()) {
 887  0
             DocumentTypePolicy policy = (DocumentTypePolicy) policyIter.next();
 888  0
             if (policyName.equals(policy.getPolicyName())) {
 889  0
                 policy.setInheritedFlag(Boolean.FALSE);
 890  0
                 return policy;
 891  
             }
 892  0
         }
 893  
 
 894  0
         if (getParentDocType() != null) {
 895  0
             DocumentTypePolicy policy = getParentDocType().getPolicyByName(policyName, defaultValue);
 896  0
             policy.setInheritedFlag(Boolean.TRUE);
 897  0
             if (policy.getPolicyValue() == null) {
 898  0
                 policy.setPolicyValue(Boolean.TRUE);
 899  
             }
 900  0
             return policy;
 901  
         }
 902  0
         DocumentTypePolicy policy = new DocumentTypePolicy();
 903  0
         policy.setPolicyName(policyName);
 904  0
         policy.setInheritedFlag(Boolean.FALSE);
 905  0
         policy.setPolicyValue(defaultValue);
 906  0
         return policy;
 907  
     }
 908  
 
 909  
     private DocumentTypePolicy getPolicyByName(String policyName, String defaultValue) {
 910  
 
 911  0
         Iterator policyIter = getPolicies().iterator();
 912  0
         while (policyIter.hasNext()) {
 913  0
             DocumentTypePolicy policy = (DocumentTypePolicy) policyIter.next();
 914  0
             if (policyName.equals(policy.getPolicyName())) {
 915  0
                 policy.setInheritedFlag(Boolean.FALSE);
 916  0
                 return policy;
 917  
             }
 918  0
         }
 919  
 
 920  0
         if (getParentDocType() != null) {
 921  0
             DocumentTypePolicy policy = getParentDocType().getPolicyByName(policyName, defaultValue);
 922  0
             policy.setInheritedFlag(Boolean.TRUE);
 923  0
             if (policy.getPolicyValue() == null) {
 924  0
                 policy.setPolicyValue(Boolean.TRUE);
 925  
             }
 926  0
             return policy;
 927  
         }
 928  0
         DocumentTypePolicy policy = new DocumentTypePolicy();
 929  0
         policy.setPolicyName(policyName);
 930  0
         policy.setInheritedFlag(Boolean.FALSE);
 931  0
         policy.setPolicyValue(Boolean.TRUE);
 932  0
         policy.setPolicyStringValue(defaultValue);
 933  0
         return policy;
 934  
     }
 935  
 
 936  
     private DocumentTypeService getDocumentTypeService() {
 937  0
         return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
 938  
     }
 939  
 
 940  
     public Group getSuperUserWorkgroup() {
 941  0
         Group superUserWorkgroup = getSuperUserWorkgroupNoInheritence();
 942  0
         if (superUserWorkgroup == null && getParentDocType() != null) {
 943  0
             return getParentDocType().getSuperUserWorkgroup();
 944  
         }
 945  0
         return superUserWorkgroup;
 946  
     }
 947  
 
 948  
     public Group getSuperUserWorkgroupNoInheritence() {
 949  0
         if (workgroupId == null) {
 950  0
             return null;
 951  
         }
 952  0
         return getIdentityManagementService().getGroup(this.workgroupId);
 953  
     }
 954  
 
 955  
     public void setSuperUserWorkgroupNoInheritence(Group suWorkgroup) {
 956  0
         this.workgroupId = null;
 957  0
         if (ObjectUtils.isNotNull(suWorkgroup)) {
 958  0
             this.workgroupId = suWorkgroup.getId();
 959  
         }
 960  0
     }
 961  
 
 962  
     /**
 963  
      * Returns true if this DocumentType has a super user group defined.
 964  
      */
 965  
     public boolean isSuperUserGroupDefined() {
 966  0
         if (this.workgroupId == null) {
 967  0
             return getParentDocType() != null && getParentDocType().isSuperUserGroupDefined();
 968  
         }
 969  0
         return true;
 970  
     }
 971  
 
 972  
     public DocumentType getPreviousVersion() {
 973  0
         return getDocumentTypeService().findById(previousVersionId);
 974  
     }
 975  
 
 976  
     public Group getBlanketApproveWorkgroup() {
 977  0
         if (StringUtils.isBlank(blanketApproveWorkgroupId)) {
 978  0
             return null;
 979  
         }
 980  0
         return getIdentityManagementService().getGroup(blanketApproveWorkgroupId);
 981  
     }
 982  
 
 983  
     public void setBlanketApproveWorkgroup(Group blanketApproveWorkgroup) {
 984  0
         this.blanketApproveWorkgroupId = null;
 985  0
         if (ObjectUtils.isNotNull(blanketApproveWorkgroup)) {
 986  0
             this.blanketApproveWorkgroupId = blanketApproveWorkgroup.getId();
 987  
         }
 988  0
     }
 989  
 
 990  
     public String getBlanketApprovePolicy() {
 991  0
         return this.blanketApprovePolicy;
 992  
     }
 993  
 
 994  
     public void setBlanketApprovePolicy(String blanketApprovePolicy) {
 995  0
         this.blanketApprovePolicy = blanketApprovePolicy;
 996  0
     }
 997  
 
 998  
     public Group getBlanketApproveWorkgroupWithInheritance() {
 999  0
         if (getParentDocType() != null && this.blanketApproveWorkgroupId == null) {
 1000  0
             return getParentDocType().getBlanketApproveWorkgroupWithInheritance();
 1001  
         }
 1002  0
         return getIdentityManagementService().getGroup(blanketApproveWorkgroupId);
 1003  
     }
 1004  
 
 1005  
     public boolean isBlanketApprover(String principalId) {
 1006  0
         if (KEWConstants.DOCUMENT_TYPE_BLANKET_APPROVE_POLICY_NONE.equalsIgnoreCase(getBlanketApprovePolicy())) {
 1007  
             // no one can blanket approve this doc type
 1008  0
             return false;
 1009  0
         } else if (KEWConstants.DOCUMENT_TYPE_BLANKET_APPROVE_POLICY_ANY.equalsIgnoreCase(getBlanketApprovePolicy())) {
 1010  
             // anyone can blanket approve this doc type
 1011  0
             return true;
 1012  
         }
 1013  0
         if (blanketApproveWorkgroupId != null) {
 1014  0
             return getIdentityManagementService().isMemberOfGroup(principalId, blanketApproveWorkgroupId);
 1015  
         }
 1016  0
         DocumentType parentDoc = getParentDocType();
 1017  0
         if (parentDoc != null) {
 1018  
             // found parent doc so try to get blanket approver info from it
 1019  0
             return parentDoc.isBlanketApprover(principalId);
 1020  
         }
 1021  0
         return false;
 1022  
     }
 1023  
 
 1024  
     /**
 1025  
      * Returns true if either a blanket approve group or blanket approve policy is defined
 1026  
      * on this Document Type.
 1027  
      */
 1028  
     public boolean isBlanketApproveGroupDefined() {
 1029  0
         if (StringUtils.isBlank(getBlanketApprovePolicy()) && this.blanketApproveWorkgroupId == null) {
 1030  0
             return getParentDocType() != null && getParentDocType().isBlanketApproveGroupDefined();
 1031  
         }
 1032  0
         return true;
 1033  
     }
 1034  
 
 1035  
     /**
 1036  
      * @return the reportingWorkgroupId
 1037  
      */
 1038  
     public String getReportingWorkgroupId() {
 1039  0
         return this.reportingWorkgroupId;
 1040  
     }
 1041  
 
 1042  
     /**
 1043  
      * @param reportingWorkgroupId the reportingWorkgroupId to set
 1044  
      */
 1045  
     public void setReportingWorkgroupId(String reportingWorkgroupId) {
 1046  0
         this.reportingWorkgroupId = reportingWorkgroupId;
 1047  0
     }
 1048  
 
 1049  
     public Group getReportingWorkgroup() {
 1050  0
             if (StringUtils.isBlank(this.reportingWorkgroupId)) {
 1051  0
                     return null;
 1052  
             }
 1053  0
         return getIdentityManagementService().getGroup(this.reportingWorkgroupId);
 1054  
     }
 1055  
 
 1056  
     public void setReportingWorkgroup(Group reportingWorkgroup) {
 1057  0
         this.reportingWorkgroupId = null;
 1058  0
         if (ObjectUtils.isNotNull(reportingWorkgroup)) {
 1059  0
             this.reportingWorkgroupId = reportingWorkgroup.getId();
 1060  
         }
 1061  0
     }
 1062  
 
 1063  
     public Group getDefaultExceptionWorkgroup() {
 1064  0
         return defaultExceptionWorkgroup;
 1065  
     }
 1066  
 
 1067  
     public void setDefaultExceptionWorkgroup(Group defaultExceptionWorkgroup) {
 1068  0
         this.defaultExceptionWorkgroup = defaultExceptionWorkgroup;
 1069  0
     }
 1070  
 
 1071  
 
 1072  
     public DocumentSearchGenerator getDocumentSearchGenerator() {
 1073  0
         ObjectDefinition objDef = getAttributeObjectDefinition(KEWConstants.SEARCH_GENERATOR_ATTRIBUTE_TYPE);
 1074  0
         if (objDef == null) {
 1075  0
             if (getParentDocType() != null) {
 1076  0
                 return getParentDocType().getDocumentSearchGenerator();
 1077  
             } else {
 1078  0
                 return KEWServiceLocator.getDocumentSearchService().getStandardDocumentSearchGenerator();
 1079  
             }
 1080  
         }
 1081  
 
 1082  
         Object searchGenerator;
 1083  
         try {
 1084  0
             searchGenerator = GlobalResourceLoader.getObject(objDef);
 1085  0
         } catch (RiceRemoteServiceConnectionException e) {
 1086  0
             LOG.warn("Unable to connect to load searchGenerator for " + this.getName() + ".  Using StandardDocumentSearchGenerator as default.");
 1087  0
             LOG.warn(e.getMessage());
 1088  0
             return KEWServiceLocator.getDocumentSearchService().getStandardDocumentSearchGenerator();
 1089  0
         }
 1090  
 
 1091  0
         if (searchGenerator == null) {
 1092  0
             throw new WorkflowRuntimeException("Could not locate DocumentSearchGenerator in this JVM or at application id " + getApplicationId() + ": " + objDef.getClassName());
 1093  
         }
 1094  
 
 1095  0
         return (DocumentSearchGenerator) searchGenerator;
 1096  
     }
 1097  
 
 1098  
     public DocumentSearchCriteriaProcessor getDocumentSearchCriteriaProcessor() {
 1099  0
         ObjectDefinition objDef = getAttributeObjectDefinition(KEWConstants.SEARCH_CRITERIA_PROCESSOR_ATTRIBUTE_TYPE);
 1100  0
         if (objDef == null) {
 1101  0
             if (getParentDocType() != null) {
 1102  0
                 return getParentDocType().getDocumentSearchCriteriaProcessor();
 1103  
             } else {
 1104  0
                 return new StandardDocumentSearchCriteriaProcessor();
 1105  
             }
 1106  
         }
 1107  0
         Object criteriaProcessor = GlobalResourceLoader.getObject(objDef);
 1108  0
         if (criteriaProcessor == null) {
 1109  0
             throw new WorkflowRuntimeException("Could not locate DocumentSearchCriteriaProcessor in this JVM or at application id " + getApplicationId() + ": " + objDef.getClassName());
 1110  
         }
 1111  0
         return (DocumentSearchCriteriaProcessor) criteriaProcessor;
 1112  
     }
 1113  
 
 1114  
     public DocumentSearchResultProcessor getDocumentSearchResultProcessor() {
 1115  0
         if ((documentTypeAttributes == null || documentTypeAttributes.isEmpty())) {
 1116  0
             if (getParentDocType() != null) {
 1117  0
                 return getParentDocType().getDocumentSearchResultProcessor();
 1118  
             } else {
 1119  0
                 return KEWServiceLocator.getDocumentSearchService().getStandardDocumentSearchResultProcessor();
 1120  
 //                     return new StandardDocumentSearchResultProcessor();
 1121  
             }
 1122  
         }
 1123  0
         for (Iterator iterator = documentTypeAttributes.iterator(); iterator.hasNext();) {
 1124  0
             DocumentTypeAttribute attribute = (DocumentTypeAttribute) iterator.next();
 1125  0
             RuleAttribute ruleAttribute = attribute.getRuleAttribute();
 1126  0
             if (KEWConstants.SEARCH_RESULT_PROCESSOR_ATTRIBUTE_TYPE.equals(ruleAttribute.getType())) {
 1127  0
                 ObjectDefinition objDef = getAttributeObjectDefinition(ruleAttribute);
 1128  0
                 return (DocumentSearchResultProcessor) GlobalResourceLoader.getObject(objDef);
 1129  0
             } else if (KEWConstants.SEARCH_RESULT_XML_PROCESSOR_ATTRIBUTE_TYPE.equals(ruleAttribute.getType())) {
 1130  0
                 ObjectDefinition objDef = getAttributeObjectDefinition(ruleAttribute);
 1131  0
                 DocumentSearchResultProcessor resultProcessor = (DocumentSearchResultProcessor) GlobalResourceLoader.getObject(objDef);
 1132  
                 //required to make it work because ruleAttribute XML is required to construct custom columns
 1133  0
                 ((DocumentSearchXMLResultProcessor) resultProcessor).setRuleAttribute(ruleAttribute);
 1134  0
                 return resultProcessor;
 1135  
             }
 1136  0
         }
 1137  0
         return KEWServiceLocator.getDocumentSearchService().getStandardDocumentSearchResultProcessor();
 1138  
 //            return new StandardDocumentSearchResultProcessor();
 1139  
     }
 1140  
 
 1141  
     public CustomActionListAttribute getCustomActionListAttribute() throws ResourceUnavailableException {
 1142  
 
 1143  0
         ObjectDefinition objDef = getAttributeObjectDefinition(KEWConstants.ACTION_LIST_ATTRIBUTE_TYPE);
 1144  0
         if (objDef == null) {
 1145  0
             return null;
 1146  
         }
 1147  
         try {
 1148  0
             return (CustomActionListAttribute) GlobalResourceLoader.getObject(objDef);
 1149  0
         } catch (RuntimeException e) {
 1150  0
             LOG.error("Error obtaining custom action list attribute: " + objDef, e);
 1151  0
             throw e;
 1152  
         }
 1153  
 
 1154  
     }
 1155  
 
 1156  
     public CustomEmailAttribute getCustomEmailAttribute() throws ResourceUnavailableException {
 1157  0
         ObjectDefinition objDef = getAttributeObjectDefinition(KEWConstants.EMAIL_ATTRIBUTE_TYPE);
 1158  0
         if (objDef == null) {
 1159  0
             return null;
 1160  
         }
 1161  0
         return (CustomEmailAttribute) GlobalResourceLoader.getObject(objDef);
 1162  
     }
 1163  
 
 1164  
     public ObjectDefinition getAttributeObjectDefinition(String typeCode) {
 1165  0
         for (Iterator iter = getDocumentTypeAttributes().iterator(); iter.hasNext();) {
 1166  0
             RuleAttribute attribute = ((DocumentTypeAttribute) iter.next()).getRuleAttribute();
 1167  0
             if (attribute.getType().equals(typeCode)) {
 1168  0
                 return getAttributeObjectDefinition(attribute);
 1169  
             }
 1170  0
         }
 1171  0
         if (getParentDocType() != null) {
 1172  0
             return getParentDocType().getAttributeObjectDefinition(typeCode);
 1173  
         }
 1174  0
         return null;
 1175  
     }
 1176  
 
 1177  
     public ObjectDefinition getAttributeObjectDefinition(RuleAttribute ruleAttribute) {
 1178  0
         if (ruleAttribute.getApplicationId() == null) {
 1179  0
             return new ObjectDefinition(ruleAttribute.getClassName(), this.getApplicationId());
 1180  
         } else {
 1181  0
             return new ObjectDefinition(ruleAttribute.getClassName(), ruleAttribute.getApplicationId());
 1182  
         }
 1183  
     }
 1184  
 
 1185  
     public CustomNoteAttribute getCustomNoteAttribute() throws ResourceUnavailableException {
 1186  0
         ObjectDefinition objDef = getAttributeObjectDefinition(KEWConstants.NOTE_ATTRIBUTE_TYPE);
 1187  0
         if (objDef == null) {
 1188  0
             String defaultNoteClass = ConfigContext.getCurrentContextConfig().getDefaultKewNoteClass();
 1189  0
             if (defaultNoteClass == null) {
 1190  
                 // attempt to use deprecated parameter
 1191  0
                 defaultNoteClass = ConfigContext.getCurrentContextConfig().getDefaultKewNoteClass();
 1192  0
                 if (ObjectUtils.isNull(defaultNoteClass)) {
 1193  0
                     return null;
 1194  
                 }
 1195  
             }
 1196  0
             objDef = new ObjectDefinition(defaultNoteClass);
 1197  
         }
 1198  0
         return (CustomNoteAttribute) GlobalResourceLoader.getObject(objDef);
 1199  
     }
 1200  
 
 1201  
     public ObjectDefinition getObjectDefinition(String objectName) {
 1202  0
         return new ObjectDefinition(objectName, getApplicationId());
 1203  
     }
 1204  
 
 1205  
     /**
 1206  
      * Returns true if this document type defines it's own routing, false if it inherits its routing
 1207  
      * from a parent document type.
 1208  
      */
 1209  
     public boolean isRouteInherited() {
 1210  0
         return processes.isEmpty() && getParentDocType() != null;
 1211  
     }
 1212  
 
 1213  
     /**
 1214  
      * Returns the DocumentType which defines the route for this document.  This is the DocumentType
 1215  
      * from which we inherit our Processes which define our routing.
 1216  
      */
 1217  
     public DocumentType getRouteDefiningDocumentType() {
 1218  0
         if (isRouteInherited()) {
 1219  0
             return getParentDocType().getRouteDefiningDocumentType();
 1220  
         }
 1221  0
         return this;
 1222  
     }
 1223  
 
 1224  
     public boolean isDocTypeActive() {
 1225  0
         if (!getActive().booleanValue()) {
 1226  0
             return false;
 1227  
         }
 1228  0
         if (getParentDocType() != null) {
 1229  0
             if (!getParentActiveInd(getParentDocType())) {
 1230  0
                 return false;
 1231  
             }
 1232  
         }
 1233  0
         return true;
 1234  
     }
 1235  
 
 1236  
     private boolean getParentActiveInd(DocumentType parentDocType) {
 1237  0
         if (parentDocType.getActive() == null || parentDocType.getActive().booleanValue()) {
 1238  0
             if (parentDocType.getParentDocType() != null) {
 1239  0
                 return getParentActiveInd(parentDocType.getParentDocType());
 1240  
             }
 1241  0
             return true;
 1242  
         } else {
 1243  0
             return false;
 1244  
         }
 1245  
     }
 1246  
 
 1247  
     /**
 1248  
      * @param documentTypeAttributes The documentTypeAttributes to set.
 1249  
      */
 1250  
     public void setDocumentTypeAttributes(List<DocumentTypeAttribute> documentTypeAttributes) {
 1251  0
         this.documentTypeAttributes = documentTypeAttributes;
 1252  0
     }
 1253  
 
 1254  
     /**
 1255  
      * @return Returns the documentTypeAttributes.
 1256  
      */
 1257  
     public List<DocumentTypeAttribute> getDocumentTypeAttributes() {
 1258  0
         return documentTypeAttributes;
 1259  
     }
 1260  
 
 1261  
 //        public List<DocumentTypeAttribute> getDocumentTypeAttributesWithPotentialInheritance() {
 1262  
 //            if ((documentTypeAttributes == null || documentTypeAttributes.isEmpty())) {
 1263  
 //                    if (getParentDocType() != null) {
 1264  
 //                            return getParentDocType().getDocumentTypeAttributesWithPotentialInheritance();
 1265  
 //                    } else {
 1266  
 //                            return documentTypeAttributes;
 1267  
 //                    }
 1268  
 //            }
 1269  
 //                return new ArrayList<DocumentTypeAttribute>();
 1270  
 //        }
 1271  
 
 1272  
     public void addProcess(Process process) {
 1273  0
         processes.add(process);
 1274  0
     }
 1275  
 
 1276  
     /**
 1277  
      * Gets the processes of this document by checking locally for processes, and if none are
 1278  
      * present, retrieves them from it's parent document type.  The list returned is an immutable
 1279  
      * list.  To add processes to a document type, use the addProcess method.
 1280  
      * <p/>
 1281  
      * NOTE: Since OJB uses direct field access, this will not interfere with the proper
 1282  
      * mapping of the processes field.
 1283  
      *
 1284  
      * @return
 1285  
      */
 1286  
     public List getProcesses() {
 1287  0
         if (processes.isEmpty() && getParentDocType() != null) {
 1288  0
             return getParentProcesses(getParentDocType());
 1289  
         }
 1290  0
         return Collections.unmodifiableList(processes);
 1291  
     }
 1292  
 
 1293  
     public void setProcesses(List routeNodes) {
 1294  0
         this.processes = routeNodes;
 1295  0
     }
 1296  
 
 1297  
     private List getParentProcesses(DocumentType parent) {
 1298  0
         List parentProcesses = parent.getProcesses();
 1299  0
         if (parentProcesses == null) {
 1300  0
             parentProcesses = getParentProcesses(parent.getParentDocType());
 1301  
         }
 1302  0
         return parentProcesses;
 1303  
     }
 1304  
 
 1305  
     public Process getPrimaryProcess() {
 1306  0
         for (Iterator iterator = getProcesses().iterator(); iterator.hasNext();) {
 1307  0
             Process process = (Process) iterator.next();
 1308  0
             if (process.isInitial()) {
 1309  0
                 return process;
 1310  
             }
 1311  0
         }
 1312  0
         return null;
 1313  
     }
 1314  
 
 1315  
     public Process getNamedProcess(String name) {
 1316  0
         for (Iterator iterator = getProcesses().iterator(); iterator.hasNext();) {
 1317  0
             Process process = (Process) iterator.next();
 1318  0
             if (org.apache.commons.lang.ObjectUtils.equals(name, process.getName())) {
 1319  0
                 return process;
 1320  
             }
 1321  0
         }
 1322  0
         return null;
 1323  
     }
 1324  
 
 1325  
     public String getRoutingVersion() {
 1326  0
         return routingVersion;
 1327  
     }
 1328  
 
 1329  
     public void setRoutingVersion(String routingVersion) {
 1330  0
         this.routingVersion = routingVersion;
 1331  0
     }
 1332  
 
 1333  
     /**
 1334  
      * @return the actualNotificationFromAddress
 1335  
      */
 1336  
     public String getActualNotificationFromAddress() {
 1337  0
         return this.actualNotificationFromAddress;
 1338  
     }
 1339  
 
 1340  
     /**
 1341  
      * @param actualNotificationFromAddress the actualNotificationFromAddress to set
 1342  
      */
 1343  
     public void setActualNotificationFromAddress(String actualNotificationFromAddress) {
 1344  0
         this.actualNotificationFromAddress = actualNotificationFromAddress;
 1345  0
     }
 1346  
 
 1347  
     /**
 1348  
      * Returns the same value as the {@link #getNotificationFromAddress()} method but will also have label information if
 1349  
      * the value is inherited from a parent document type
 1350  
      */
 1351  
     public String getDisplayableNotificationFromAddress() {
 1352  0
         return getNotificationFromAddress(true);
 1353  
     }
 1354  
 
 1355  
     /**
 1356  
      * EMPTY METHOD. Use {@link #setActualNotificationFromAddress(String)} instead.
 1357  
      *
 1358  
      * @deprecated
 1359  
      */
 1360  
     public void setDisplayableNotificationFromAddress(String displayableNotificationFromAddress) {
 1361  
         // do nothing
 1362  0
     }
 1363  
 
 1364  
     public String getNotificationFromAddress() {
 1365  0
         return getNotificationFromAddress(false);
 1366  
     }
 1367  
 
 1368  
     /**
 1369  
      * This method gets the notification from address value. If the forDisplayPurposes value is true
 1370  
      * the notification from address value will be invalid for system use
 1371  
      * <p/>
 1372  
      * This method will first call the {@link #getActualNotificationFromAddress()} method to check the value on this object.
 1373  
      * If none is found the system checks for a parent document type.  If a valid parent type exists for this document type
 1374  
      * then the system will use inheritance from that parent document type as long as at least one document type in the
 1375  
      * hierarchy has a value set.  If no value is set on any parent document type or if no parent document type exists the
 1376  
      * system will return null
 1377  
      *
 1378  
      * @param forDisplayPurposes - if true then the string returned will have a label explaining where the value came from
 1379  
      * @return the notification from address value or a displayable value with sourcing information
 1380  
      */
 1381  
     protected String getNotificationFromAddress(boolean forDisplayPurposes) {
 1382  0
         if (StringUtils.isNotBlank(getActualNotificationFromAddress())) {
 1383  
             // this object has an address so return it
 1384  0
             return getActualNotificationFromAddress();
 1385  
         }
 1386  0
         if (ObjectUtils.isNotNull(getParentDocType())) {
 1387  
             // direct parent document type exists
 1388  0
             String parentNotificationFromAddress = getParentDocType().getActualNotificationFromAddress();
 1389  0
             if (StringUtils.isNotBlank(parentNotificationFromAddress)) {
 1390  
                 // found an address set on the immediate parent object so return it
 1391  0
                 if (forDisplayPurposes) {
 1392  0
                     parentNotificationFromAddress += " " + KEWConstants.DOCUMENT_TYPE_INHERITED_VALUE_INDICATOR;
 1393  
                 }
 1394  0
                 return parentNotificationFromAddress;
 1395  
             }
 1396  
             // did not find a valid address on the immediate parent to use hierarchy
 1397  0
             return getParentDocType().getNotificationFromAddress(forDisplayPurposes);
 1398  
         }
 1399  0
         return null;
 1400  
     }
 1401  
 
 1402  
     /**
 1403  
      * Use {@link #setActualNotificationFromAddress(String)} instead
 1404  
      *
 1405  
      * @deprecated
 1406  
      */
 1407  
     public void setNotificationFromAddress(String notificationFromAddress) {
 1408  0
         setActualNotificationFromAddress(notificationFromAddress);
 1409  0
     }
 1410  
 
 1411  
     public boolean isParentOf(DocumentType documentType) {
 1412  
         // this is a depth-first search which works for our needs
 1413  0
         for (Iterator iterator = getChildrenDocTypes().iterator(); iterator.hasNext();) {
 1414  0
             DocumentType child = (DocumentType) iterator.next();
 1415  0
             if (child.getName().equals(documentType.getName()) || child.isParentOf(documentType)) {
 1416  0
                 return true;
 1417  
             }
 1418  0
         }
 1419  0
         return false;
 1420  
     }
 1421  
 
 1422  
     /**
 1423  
      * this exists because the lookup wants to make a call on a bean method when displaying results and those calls are
 1424  
      * entered programatically into the framework by method name
 1425  
      *
 1426  
      * @return
 1427  
      */
 1428  
     public String getLookupParentName() {
 1429  0
         DocumentType parent = getParentDocType();
 1430  0
         if (parent == null) {
 1431  0
             return "Root";
 1432  
         }
 1433  0
         return parent.getName();
 1434  
     }
 1435  
 
 1436  
     public boolean isSuperUser(String principalId) {
 1437  0
         Group workgroup = getSuperUserWorkgroup();
 1438  0
         if (workgroup == null) {
 1439  0
             return false;
 1440  
         }
 1441  0
         return getIdentityManagementService().isMemberOfGroup(principalId, workgroup.getId());
 1442  
     }
 1443  
 
 1444  
     public boolean hasPreviousVersion() {
 1445  0
         if (this.documentTypeId == null) {
 1446  0
             return false;
 1447  
         }
 1448  0
         return !this.documentTypeId.equals(this.previousVersionId);
 1449  
     }
 1450  
 
 1451  
     /**
 1452  
      * @return the actual application id
 1453  
      */
 1454  
     public String getActualApplicationId() {
 1455  0
         return this.actualApplicationId;
 1456  
     }
 1457  
 
 1458  
     /**
 1459  
      * @param actionalApplicationId the actionalApplicationId to set
 1460  
      */
 1461  
     public void setActualApplicationId(String actualApplicationId) {
 1462  0
         this.actualApplicationId = actualApplicationId;
 1463  0
     }
 1464  
 
 1465  
     /**
 1466  
      * Returns the application id for this DocumentType which can be specified on the document type itself,
 1467  
      * inherited from the parent, or defaulted to the configured application id of the application.
 1468  
      */
 1469  
     public String getApplicationId() {
 1470  0
         return getApplicationId(false);
 1471  
     }
 1472  
 
 1473  
     /**
 1474  
      * This method gets the string for the application id value. If the forDisplayPurposes value is true
 1475  
      * the application id value will be invalid for system use.
 1476  
      * <p/>
 1477  
      * This method will first call the {@link #getActualApplicationId()} method to check for a value on this object. If
 1478  
      * none is found a parent document type is used.  If a valid parent type exists for this document type then the system
 1479  
      * will use inheritance from that parent document type as long as at least one document type in the hierarchy has a
 1480  
      * value set.  If no value is set on any parent document type or if no parent document type exists for this object the
 1481  
      * system default is used: {@link CoreConfigHelper#getApplicationId()}
 1482  
      *
 1483  
      * @param forDisplayPurposes - if true then the string returned will have a label explaining where the value came from
 1484  
      * @return the application id value or a displayable value with sourcing information
 1485  
      */
 1486  
     protected String getApplicationId(boolean forDisplayPurposes) {
 1487  0
         if (StringUtils.isNotBlank(getActualApplicationId())) {
 1488  
             // this object has a application id set, so return it
 1489  0
             return getActualApplicationId();
 1490  
         }
 1491  
         // this object has no application id... check for a parent document type
 1492  0
         if (ObjectUtils.isNotNull(getParentDocType())) {
 1493  
             // direct parent document type exists
 1494  0
             String parentValue = getParentDocType().getActualApplicationId();
 1495  0
             if (StringUtils.isNotBlank(parentValue)) {
 1496  
                 // found a parent value set on the immediate parent object so return it
 1497  0
                 if (forDisplayPurposes) {
 1498  0
                     parentValue += " " + KEWConstants.DOCUMENT_TYPE_INHERITED_VALUE_INDICATOR;
 1499  
                 }
 1500  0
                 return parentValue;
 1501  
             }
 1502  
             // no valid application id on direct parent, so use hierarchy to find correct value
 1503  0
             return getParentDocType().getApplicationId(forDisplayPurposes);
 1504  
         }
 1505  0
         String defaultValue = CoreConfigHelper.getApplicationId();
 1506  0
         if (forDisplayPurposes) {
 1507  0
             defaultValue += " " + KEWConstants.DOCUMENT_TYPE_SYSTEM_DEFAULT_INDICATOR;
 1508  
         }
 1509  0
         return defaultValue;
 1510  
     }
 1511  
 
 1512  
     /**
 1513  
      * Returns the same value as the {@link #getApplicationId()} method but will also have label information about
 1514  
      * where the application id came from (ie: inherited from the parent document type)
 1515  
      */
 1516  
     public String getDisplayableApplicationId() {
 1517  0
         return getApplicationId(true);
 1518  
     }
 1519  
 
 1520  
     /**
 1521  
      * Gets the name of the custom email stylesheet to use to render email (if any has been set, null otherwise)
 1522  
      *
 1523  
      * @return name of the custom email stylesheet to use to render email (if any has been set, null otherwise)
 1524  
      */
 1525  
     public String getCustomEmailStylesheet() {
 1526  0
         return customEmailStylesheet;
 1527  
     }
 1528  
 
 1529  
     /**
 1530  
      * Sets the name of the custom email stylesheet to use to render email
 1531  
      *
 1532  
      * @return name of the custom email stylesheet to use to render email
 1533  
      */
 1534  
     public void setCustomEmailStylesheet(String customEmailStylesheet) {
 1535  0
         this.customEmailStylesheet = customEmailStylesheet;
 1536  0
     }
 1537  
 
 1538  
     /**
 1539  
      * @return the blanketApproveWorkgroupId
 1540  
      */
 1541  
     public String getBlanketApproveWorkgroupId() {
 1542  0
         return this.blanketApproveWorkgroupId;
 1543  
     }
 1544  
 
 1545  
 
 1546  
     /**
 1547  
      * @param blanketApproveWorkgroupId the blanketApproveWorkgroupId to set
 1548  
      */
 1549  
     public void setBlanketApproveWorkgroupId(String blanketApproveWorkgroupId) {
 1550  0
         this.blanketApproveWorkgroupId = blanketApproveWorkgroupId;
 1551  0
     }
 1552  
 
 1553  
     /**
 1554  
      * @return the applyRetroactively
 1555  
      */
 1556  
     public Boolean getApplyRetroactively() {
 1557  0
         return this.applyRetroactively;
 1558  
     }
 1559  
 
 1560  
     /**
 1561  
      * @param applyRetroactively the applyRetroactively to set
 1562  
      */
 1563  
     public void setApplyRetroactively(Boolean applyRetroactively) {
 1564  0
         this.applyRetroactively = applyRetroactively;
 1565  0
     }
 1566  
 
 1567  
     private IdentityManagementService getIdentityManagementService() {
 1568  0
         return KimApiServiceLocator.getIdentityManagementService();
 1569  
     }
 1570  
 
 1571  
     /**
 1572  
      * @see org.kuali.rice.kns.bo.Inactivateable#isActive()
 1573  
      */
 1574  
     public boolean isActive() {
 1575  0
         boolean bRet = false;
 1576  
 
 1577  0
         if (active != null) {
 1578  0
             bRet = active.booleanValue();
 1579  
         }
 1580  
 
 1581  0
         return bRet;
 1582  
     }
 1583  
 
 1584  
     /**
 1585  
      * @see org.kuali.rice.kns.bo.Inactivateable#setActive(boolean)
 1586  
      */
 1587  
     public void setActive(boolean active) {
 1588  0
         this.active = Boolean.valueOf(active);
 1589  0
     }
 1590  
 }