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