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