0001: /*
0002: * Copyright 2005-2006 The Kuali Foundation.
0003: *
0004: *
0005: * Licensed under the Educational Community License, Version 1.0 (the "License");
0006: * you may not use this file except in compliance with the License.
0007: * You may obtain a copy of the License at
0008: *
0009: * http://www.opensource.org/licenses/ecl1.php
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package edu.iu.uis.eden.routeheader;
0018:
0019: import java.sql.Timestamp;
0020: import java.util.ArrayList;
0021: import java.util.Collection;
0022: import java.util.HashMap;
0023: import java.util.Iterator;
0024: import java.util.List;
0025:
0026: import org.apache.commons.lang.StringUtils;
0027: import org.apache.log4j.Logger;
0028:
0029: import edu.iu.uis.eden.EdenConstants;
0030: import edu.iu.uis.eden.KEWServiceLocator;
0031: import edu.iu.uis.eden.WorkflowPersistable;
0032: import edu.iu.uis.eden.actionitem.ActionItem;
0033: import edu.iu.uis.eden.actionlist.DefaultCustomActionListAttribute;
0034: import edu.iu.uis.eden.actionrequests.ActionRequestFactory;
0035: import edu.iu.uis.eden.actionrequests.ActionRequestValue;
0036: import edu.iu.uis.eden.actiontaken.ActionTakenValue;
0037: import edu.iu.uis.eden.clientapp.vo.RouteHeaderVO;
0038: import edu.iu.uis.eden.docsearch.SearchableAttributeValue;
0039: import edu.iu.uis.eden.doctype.DocumentType;
0040: import edu.iu.uis.eden.engine.CompatUtils;
0041: import edu.iu.uis.eden.engine.node.Branch;
0042: import edu.iu.uis.eden.engine.node.BranchState;
0043: import edu.iu.uis.eden.engine.node.KeyValuePair;
0044: import edu.iu.uis.eden.engine.node.RouteNode;
0045: import edu.iu.uis.eden.engine.node.RouteNodeInstance;
0046: import edu.iu.uis.eden.exception.EdenUserNotFoundException;
0047: import edu.iu.uis.eden.exception.InvalidActionTakenException;
0048: import edu.iu.uis.eden.exception.ResourceUnavailableException;
0049: import edu.iu.uis.eden.exception.WorkflowException;
0050: import edu.iu.uis.eden.mail.CustomEmailAttributeImpl;
0051: import edu.iu.uis.eden.notes.CustomNoteAttribute;
0052: import edu.iu.uis.eden.notes.CustomNoteAttributeImpl;
0053: import edu.iu.uis.eden.notes.Note;
0054: import edu.iu.uis.eden.plugin.attributes.CustomActionListAttribute;
0055: import edu.iu.uis.eden.plugin.attributes.CustomEmailAttribute;
0056: import edu.iu.uis.eden.server.BeanConverter;
0057: import edu.iu.uis.eden.user.UserService;
0058: import edu.iu.uis.eden.user.WorkflowUser;
0059: import edu.iu.uis.eden.user.WorkflowUserId;
0060: import edu.iu.uis.eden.util.CodeTranslator;
0061: import edu.iu.uis.eden.util.Utilities;
0062:
0063: /**
0064: * A document within KEW. A document effectively represents a process that moves through
0065: * the workflow engine. It is created from a particular {@link DocumentType} and follows
0066: * the route path defined by that DocumentType.
0067: *
0068: * <p>During a document's lifecycle it progresses through a series of statuses, starting
0069: * with INITIATED and moving to one of the terminal states (such as FINAL, CANCELED, etc).
0070: * The list of status on a document are defined in the {@link EdenConstants} class and
0071: * include the constants starting with "ROUTE_HEADER_" and ending with "_CD".
0072: *
0073: * <p>Associated with the document is the document content. The document content is XML
0074: * which represents the content of that document. This XML content is typically used
0075: * to make routing decisions for the document.
0076: *
0077: * <p>A document has associated with it a set of {@link ActionRequestValue} object and
0078: * {@link ActionTakenValue} objects. Action Requests represent requests for user
0079: * action (such as Approve, Acknowledge, etc). Action Takens represent action that
0080: * users have performed on the document, such as approvals or cancelling of the document.
0081: *
0082: * <p>The instantiated route path of a document is defined by it's graph of
0083: * {@link RouteNodeInstance} objects. The path starts at the initial node of the document
0084: * and progresses from there following the next nodes of each node instance. The current
0085: * active nodes on the document are defined by the "active" flag on the node instance
0086: * where are not marked as "complete".
0087: *
0088: * @see DocumentType
0089: * @see ActionRequestValue
0090: * @see ActionItem
0091: * @see ActionTakenValue
0092: * @see RouteNodeInstance
0093: * @see EdenConstants
0094: *
0095: * @author rkirkend
0096: * @author bmcough
0097: * @author ewestfal
0098: */
0099: public class DocumentRouteHeaderValue implements WorkflowPersistable {
0100: private static final long serialVersionUID = -4700736340527913220L;
0101: private static final Logger LOG = Logger
0102: .getLogger(DocumentRouteHeaderValue.class);
0103:
0104: public static final String CURRENT_ROUTE_NODE_NAME_DELIMITER = ", ";
0105:
0106: private java.lang.Long documentTypeId;
0107: private java.lang.String docRouteStatus;
0108: private java.lang.Integer docRouteLevel;
0109: private java.sql.Timestamp statusModDate;
0110: private java.sql.Timestamp createDate;
0111: private java.sql.Timestamp approvedDate;
0112: private java.sql.Timestamp finalizedDate;
0113: private DocumentRouteHeaderValueContent documentContent;
0114: private java.lang.String docTitle;
0115: private java.lang.String appDocId;
0116: private java.lang.String overrideInd;
0117: private java.lang.Integer docVersion = new Integer(
0118: EdenConstants.DOCUMENT_VERSION_NODAL);
0119: private java.lang.Integer jrfVerNbr;
0120: private java.lang.String initiatorWorkflowId;
0121: private java.lang.String routedByUserWorkflowId;
0122: private java.sql.Timestamp routeStatusDate;
0123: private java.sql.Timestamp routeLevelDate;
0124: private java.lang.Long routeHeaderId;
0125: private String lockCode;
0126:
0127: private List<ActionRequestValue> actionRequests = new ArrayList<ActionRequestValue>();
0128:
0129: // apache lazy list commented out due to not being serializable
0130: // ListUtils.lazyList(new ArrayList(),
0131: // new Factory() {
0132: // public Object create() {
0133: // return new ActionRequestFactory().createBlankActionRequest();
0134: // }
0135: // });
0136: private List<ActionTakenValue> actionsTaken = new ArrayList<ActionTakenValue>();
0137: private List<ActionItem> actionItems = new ArrayList<ActionItem>();
0138: private List<Note> notes = new ArrayList<Note>();
0139: private List<SearchableAttributeValue> searchableAttributeValues = new ArrayList<SearchableAttributeValue>();
0140: private Collection queueItems = new ArrayList();
0141: private boolean routingReport = false;
0142:
0143: private static final boolean FINAL_STATE = true;
0144: protected static final HashMap<String, String> legalActions;
0145: protected static final HashMap<String, String> stateTransitionMap;
0146:
0147: /* New Workflow 2.1 Field */
0148: private List<RouteNodeInstance> initialRouteNodeInstances = new ArrayList<RouteNodeInstance>();
0149:
0150: static {
0151: stateTransitionMap = new HashMap<String, String>();
0152: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_INITIATED_CD,
0153: EdenConstants.ROUTE_HEADER_SAVED_CD
0154: + EdenConstants.ROUTE_HEADER_ENROUTE_CD
0155: + EdenConstants.ROUTE_HEADER_CANCEL_CD);
0156:
0157: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_SAVED_CD,
0158: EdenConstants.ROUTE_HEADER_SAVED_CD
0159: + EdenConstants.ROUTE_HEADER_ENROUTE_CD
0160: + EdenConstants.ROUTE_HEADER_CANCEL_CD
0161: + EdenConstants.ROUTE_HEADER_APPROVED_CD);
0162:
0163: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_ENROUTE_CD,
0164: EdenConstants.ROUTE_HEADER_DISAPPROVED_CD
0165: + EdenConstants.ROUTE_HEADER_CANCEL_CD
0166: + EdenConstants.ROUTE_HEADER_APPROVED_CD
0167: + EdenConstants.ROUTE_HEADER_EXCEPTION_CD
0168: + EdenConstants.ROUTE_HEADER_SAVED_CD);
0169: stateTransitionMap.put(
0170: EdenConstants.ROUTE_HEADER_DISAPPROVED_CD, "");
0171: stateTransitionMap
0172: .put(EdenConstants.ROUTE_HEADER_CANCEL_CD, "");
0173: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_FINAL_CD, "");
0174: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_EXCEPTION_CD,
0175: EdenConstants.ROUTE_HEADER_EXCEPTION_CD
0176: + EdenConstants.ROUTE_HEADER_ENROUTE_CD
0177: + EdenConstants.ROUTE_HEADER_CANCEL_CD
0178: + EdenConstants.ROUTE_HEADER_APPROVED_CD
0179: + EdenConstants.ROUTE_HEADER_DISAPPROVED_CD
0180: + EdenConstants.ROUTE_HEADER_SAVED_CD);
0181: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_APPROVED_CD,
0182: EdenConstants.ROUTE_HEADER_APPROVED_CD
0183: + EdenConstants.ROUTE_HEADER_PROCESSED_CD
0184: + EdenConstants.ROUTE_HEADER_EXCEPTION_CD);
0185: stateTransitionMap.put(EdenConstants.ROUTE_HEADER_PROCESSED_CD,
0186: EdenConstants.ROUTE_HEADER_FINAL_CD
0187: + EdenConstants.ROUTE_HEADER_PROCESSED_CD);
0188:
0189: legalActions = new HashMap<String, String>();
0190: legalActions.put(EdenConstants.ROUTE_HEADER_INITIATED_CD,
0191: EdenConstants.ACTION_TAKEN_FYI_CD
0192: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0193: + EdenConstants.ACTION_TAKEN_SAVED_CD
0194: + EdenConstants.ACTION_TAKEN_COMPLETED_CD
0195: + EdenConstants.ACTION_TAKEN_ROUTED_CD
0196: + EdenConstants.ACTION_TAKEN_CANCELED_CD
0197: + EdenConstants.ACTION_TAKEN_ADHOC_CD
0198: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD
0199: + EdenConstants.ACTION_TAKEN_BLANKET_APPROVE_CD
0200: + EdenConstants.ACTION_TAKEN_MOVE_CD);
0201: legalActions.put(EdenConstants.ROUTE_HEADER_SAVED_CD,
0202: EdenConstants.ACTION_TAKEN_FYI_CD
0203: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0204: + EdenConstants.ACTION_TAKEN_SAVED_CD
0205: + EdenConstants.ACTION_TAKEN_COMPLETED_CD
0206: + EdenConstants.ACTION_TAKEN_ROUTED_CD
0207: + EdenConstants.ACTION_TAKEN_APPROVED_CD
0208: + EdenConstants.ACTION_TAKEN_CANCELED_CD
0209: + EdenConstants.ACTION_TAKEN_ADHOC_CD
0210: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD
0211: + EdenConstants.ACTION_TAKEN_BLANKET_APPROVE_CD
0212: + EdenConstants.ACTION_TAKEN_MOVE_CD);
0213: /* ACTION_TAKEN_ROUTED_CD not included in enroute state
0214: * ACTION_TAKEN_SAVED_CD removed as of version 2.4
0215: */
0216: legalActions
0217: .put(
0218: EdenConstants.ROUTE_HEADER_ENROUTE_CD, /*EdenConstants.ACTION_TAKEN_SAVED_CD + EdenConstants.ACTION_TAKEN_ROUTED_CD + */
0219: EdenConstants.ACTION_TAKEN_APPROVED_CD
0220: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0221: + EdenConstants.ACTION_TAKEN_FYI_CD
0222: + EdenConstants.ACTION_TAKEN_ADHOC_CD
0223: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD
0224: + EdenConstants.ACTION_TAKEN_BLANKET_APPROVE_CD
0225: + EdenConstants.ACTION_TAKEN_CANCELED_CD
0226: + EdenConstants.ACTION_TAKEN_COMPLETED_CD
0227: + EdenConstants.ACTION_TAKEN_DENIED_CD
0228: + EdenConstants.ACTION_TAKEN_SU_APPROVED_CD
0229: + EdenConstants.ACTION_TAKEN_SU_CANCELED_CD
0230: + EdenConstants.ACTION_TAKEN_SU_DISAPPROVED_CD
0231: + EdenConstants.ACTION_TAKEN_SU_ROUTE_LEVEL_APPROVED_CD
0232: + EdenConstants.ACTION_TAKEN_RETURNED_TO_PREVIOUS_CD
0233: + EdenConstants.ACTION_TAKEN_SU_RETURNED_TO_PREVIOUS_CD
0234: + EdenConstants.ACTION_TAKEN_MOVE_CD);
0235: /* ACTION_TAKEN_ROUTED_CD not included in exception state
0236: * ACTION_TAKEN_SAVED_CD removed as of version 2.4.2
0237: */
0238: legalActions
0239: .put(
0240: EdenConstants.ROUTE_HEADER_EXCEPTION_CD, /*EdenConstants.ACTION_TAKEN_SAVED_CD + */
0241: EdenConstants.ACTION_TAKEN_FYI_CD
0242: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0243: + EdenConstants.ACTION_TAKEN_ADHOC_CD
0244: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD
0245: + EdenConstants.ACTION_TAKEN_APPROVED_CD
0246: + EdenConstants.ACTION_TAKEN_BLANKET_APPROVE_CD
0247: + EdenConstants.ACTION_TAKEN_CANCELED_CD
0248: + EdenConstants.ACTION_TAKEN_COMPLETED_CD
0249: + EdenConstants.ACTION_TAKEN_DENIED_CD
0250: + EdenConstants.ACTION_TAKEN_SU_APPROVED_CD
0251: + EdenConstants.ACTION_TAKEN_SU_CANCELED_CD
0252: + EdenConstants.ACTION_TAKEN_SU_DISAPPROVED_CD
0253: + EdenConstants.ACTION_TAKEN_SU_ROUTE_LEVEL_APPROVED_CD
0254: + EdenConstants.ACTION_TAKEN_RETURNED_TO_PREVIOUS_CD
0255: + EdenConstants.ACTION_TAKEN_SU_RETURNED_TO_PREVIOUS_CD
0256: + EdenConstants.ACTION_TAKEN_MOVE_CD);
0257: legalActions.put(EdenConstants.ROUTE_HEADER_FINAL_CD,
0258: EdenConstants.ACTION_TAKEN_FYI_CD
0259: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0260: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
0261: legalActions.put(EdenConstants.ROUTE_HEADER_CANCEL_CD,
0262: EdenConstants.ACTION_TAKEN_FYI_CD
0263: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0264: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
0265: legalActions.put(EdenConstants.ROUTE_HEADER_DISAPPROVED_CD,
0266: EdenConstants.ACTION_TAKEN_FYI_CD
0267: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0268: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
0269: legalActions.put(EdenConstants.ROUTE_HEADER_APPROVED_CD,
0270: EdenConstants.ACTION_TAKEN_FYI_CD
0271: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0272: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
0273: legalActions.put(EdenConstants.ROUTE_HEADER_PROCESSED_CD,
0274: EdenConstants.ACTION_TAKEN_FYI_CD
0275: + EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
0276: + EdenConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
0277: }
0278:
0279: public DocumentRouteHeaderValue() {
0280: }
0281:
0282: public WorkflowUser getInitiatorUser()
0283: throws EdenUserNotFoundException {
0284: // if we are running a simulation, there will be no initiator
0285: if (getInitiatorWorkflowId() == null) {
0286: return null;
0287: }
0288: return getUser(getInitiatorWorkflowId());
0289: }
0290:
0291: public WorkflowUser getRoutedByUser()
0292: throws EdenUserNotFoundException {
0293: // if we are running a simulation, there will be no initiator
0294: if (getRoutedByUserWorkflowId() == null) {
0295: return null;
0296: }
0297: return getUser(getRoutedByUserWorkflowId());
0298: }
0299:
0300: private WorkflowUser getUser(java.lang.String workflowId)
0301: throws EdenUserNotFoundException {
0302: UserService userSrv = (UserService) KEWServiceLocator
0303: .getService(KEWServiceLocator.USER_SERVICE);
0304: WorkflowUser user = null;
0305: user = userSrv.getWorkflowUser(new WorkflowUserId(workflowId));
0306: if (user == null) {
0307: LOG.fatal("we are toasted...user" + workflowId + " rhid "
0308: + this .routeHeaderId);
0309: return null;
0310: } else {
0311: return user;
0312: }
0313: }
0314:
0315: public String getDocRouteStatusLabel() {
0316: return CodeTranslator.getRouteStatusLabel(getDocRouteStatus());
0317: }
0318:
0319: public String getCurrentRouteLevelName() {
0320: String name = "Not Found";
0321: // TODO the isRouteLevelDocument junk can be ripped out
0322: if (routingReport) {
0323: name = "Routing Report";
0324: } else if (CompatUtils.isRouteLevelDocument(this )) {
0325: int routeLevelInt = getDocRouteLevel().intValue();
0326: LOG
0327: .info("Getting current route level name for a Route level document: "
0328: + routeLevelInt
0329: + CURRENT_ROUTE_NODE_NAME_DELIMITER
0330: + routeHeaderId);
0331: List routeLevelNodes = CompatUtils
0332: .getRouteLevelCompatibleNodeList(getDocumentType());
0333: LOG.info("Route level compatible node list has "
0334: + routeLevelNodes.size() + " nodes");
0335: if (routeLevelInt < routeLevelNodes.size()) {
0336: name = ((RouteNode) routeLevelNodes.get(routeLevelInt))
0337: .getRouteNodeName();
0338: }
0339: } else {
0340: Collection nodeInstances = KEWServiceLocator
0341: .getRouteNodeService().getActiveNodeInstances(
0342: getRouteHeaderId());
0343: name = "";
0344: if (nodeInstances.isEmpty()) {
0345: nodeInstances = KEWServiceLocator.getRouteNodeService()
0346: .getTerminalNodeInstances(getRouteHeaderId());
0347: }
0348: for (Iterator iterator = nodeInstances.iterator(); iterator
0349: .hasNext();) {
0350: RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator
0351: .next();
0352: name += nodeInstance.getRouteNode().getRouteNodeName()
0353: + (iterator.hasNext() ? CURRENT_ROUTE_NODE_NAME_DELIMITER
0354: : "");
0355: }
0356: }
0357: return name;
0358: }
0359:
0360: public String getRouteStatusLabel() {
0361: return CodeTranslator.getRouteStatusLabel(getDocRouteStatus());
0362: }
0363:
0364: public Collection getQueueItems() {
0365: return queueItems;
0366: }
0367:
0368: public void setQueueItems(Collection queueItems) {
0369: this .queueItems = queueItems;
0370: }
0371:
0372: public List<ActionItem> getActionItems() {
0373: return actionItems;
0374: }
0375:
0376: public void setActionItems(List<ActionItem> actionItems) {
0377: this .actionItems = actionItems;
0378: }
0379:
0380: public List<ActionTakenValue> getActionsTaken() {
0381: return actionsTaken;
0382: }
0383:
0384: public void setActionsTaken(List<ActionTakenValue> actionsTaken) {
0385: this .actionsTaken = actionsTaken;
0386: }
0387:
0388: public List<ActionRequestValue> getActionRequests() {
0389: return actionRequests;
0390: }
0391:
0392: public void setActionRequests(
0393: List<ActionRequestValue> actionRequests) {
0394: this .actionRequests = actionRequests;
0395: }
0396:
0397: public DocumentType getDocumentType() {
0398: return KEWServiceLocator.getDocumentTypeService().findById(
0399: getDocumentTypeId());
0400: }
0401:
0402: public java.lang.String getAppDocId() {
0403: return appDocId;
0404: }
0405:
0406: public void setAppDocId(java.lang.String appDocId) {
0407: this .appDocId = appDocId;
0408: }
0409:
0410: public java.sql.Timestamp getApprovedDate() {
0411: return approvedDate;
0412: }
0413:
0414: public void setApprovedDate(java.sql.Timestamp approvedDate) {
0415: this .approvedDate = approvedDate;
0416: }
0417:
0418: public java.sql.Timestamp getCreateDate() {
0419: return createDate;
0420: }
0421:
0422: public void setCreateDate(java.sql.Timestamp createDate) {
0423: this .createDate = createDate;
0424: }
0425:
0426: public java.lang.String getDocContent() {
0427: return getDocumentContent().getDocumentContent();
0428: }
0429:
0430: public void setDocContent(java.lang.String docContent) {
0431: DocumentRouteHeaderValueContent content = getDocumentContent();
0432: content.setDocumentContent(docContent);
0433: }
0434:
0435: public java.lang.Integer getDocRouteLevel() {
0436: return docRouteLevel;
0437: }
0438:
0439: public void setDocRouteLevel(java.lang.Integer docRouteLevel) {
0440: this .docRouteLevel = docRouteLevel;
0441: }
0442:
0443: public java.lang.String getDocRouteStatus() {
0444: return docRouteStatus;
0445: }
0446:
0447: public void setDocRouteStatus(java.lang.String docRouteStatus) {
0448: this .docRouteStatus = docRouteStatus;
0449: }
0450:
0451: public java.lang.String getDocTitle() {
0452: return docTitle;
0453: }
0454:
0455: public void setDocTitle(java.lang.String docTitle) {
0456: this .docTitle = docTitle;
0457: }
0458:
0459: public java.lang.Long getDocumentTypeId() {
0460: return documentTypeId;
0461: }
0462:
0463: public void setDocumentTypeId(java.lang.Long docTypeId) {
0464: this .documentTypeId = docTypeId;
0465: }
0466:
0467: public java.lang.Integer getDocVersion() {
0468: return docVersion;
0469: }
0470:
0471: public void setDocVersion(java.lang.Integer docVersion) {
0472: this .docVersion = docVersion;
0473: }
0474:
0475: public java.sql.Timestamp getFinalizedDate() {
0476: return finalizedDate;
0477: }
0478:
0479: public void setFinalizedDate(java.sql.Timestamp finalizedDate) {
0480: this .finalizedDate = finalizedDate;
0481: }
0482:
0483: public java.lang.String getInitiatorWorkflowId() {
0484: return initiatorWorkflowId;
0485: }
0486:
0487: public void setInitiatorWorkflowId(
0488: java.lang.String initiatorWorkflowId) {
0489: this .initiatorWorkflowId = initiatorWorkflowId;
0490: }
0491:
0492: public java.lang.String getRoutedByUserWorkflowId() {
0493: if ((isEnroute())
0494: && (StringUtils.isBlank(routedByUserWorkflowId))) {
0495: return initiatorWorkflowId;
0496: }
0497: return routedByUserWorkflowId;
0498: }
0499:
0500: public void setRoutedByUserWorkflowId(
0501: java.lang.String routedByUserWorkflowId) {
0502: this .routedByUserWorkflowId = routedByUserWorkflowId;
0503: }
0504:
0505: public java.lang.Integer getJrfVerNbr() {
0506: return jrfVerNbr;
0507: }
0508:
0509: public void setJrfVerNbr(java.lang.Integer jrfVerNbr) {
0510: this .jrfVerNbr = jrfVerNbr;
0511: }
0512:
0513: public java.lang.String getOverrideInd() {
0514: return overrideInd;
0515: }
0516:
0517: public void setOverrideInd(java.lang.String overrideInd) {
0518: this .overrideInd = overrideInd;
0519: }
0520:
0521: public java.lang.Long getRouteHeaderId() {
0522: return routeHeaderId;
0523: }
0524:
0525: public void setRouteHeaderId(java.lang.Long routeHeaderId) {
0526: this .routeHeaderId = routeHeaderId;
0527: }
0528:
0529: public java.sql.Timestamp getRouteLevelDate() {
0530: return routeLevelDate;
0531: }
0532:
0533: public void setRouteLevelDate(java.sql.Timestamp routeLevelDate) {
0534: this .routeLevelDate = routeLevelDate;
0535: }
0536:
0537: public java.sql.Timestamp getRouteStatusDate() {
0538: return routeStatusDate;
0539: }
0540:
0541: public void setRouteStatusDate(java.sql.Timestamp routeStatusDate) {
0542: this .routeStatusDate = routeStatusDate;
0543: }
0544:
0545: public java.sql.Timestamp getStatusModDate() {
0546: return statusModDate;
0547: }
0548:
0549: public void setStatusModDate(java.sql.Timestamp statusModDate) {
0550: this .statusModDate = statusModDate;
0551: }
0552:
0553: public Object copy(boolean preserveKeys) {
0554: throw new UnsupportedOperationException(
0555: "The copy method is deprecated and unimplemented!");
0556: }
0557:
0558: /**
0559: * @return True if the document is in the state of Initiated
0560: */
0561: public boolean isStateInitiated() {
0562: return EdenConstants.ROUTE_HEADER_INITIATED_CD
0563: .equals(docRouteStatus);
0564: }
0565:
0566: /**
0567: * @return True if the document is in the state of Saved
0568: */
0569: public boolean isStateSaved() {
0570: return EdenConstants.ROUTE_HEADER_SAVED_CD
0571: .equals(docRouteStatus);
0572: }
0573:
0574: /**
0575: * @return true if the document has ever been inte enroute state
0576: */
0577: public boolean isRouted() {
0578: return !(isStateInitiated() || isStateSaved());
0579: }
0580:
0581: public boolean isInException() {
0582: return EdenConstants.ROUTE_HEADER_EXCEPTION_CD
0583: .equals(docRouteStatus);
0584: }
0585:
0586: public boolean isDisaproved() {
0587: return EdenConstants.ROUTE_HEADER_DISAPPROVED_CD
0588: .equals(docRouteStatus);
0589: }
0590:
0591: public boolean isCanceled() {
0592: return EdenConstants.ROUTE_HEADER_CANCEL_CD
0593: .equals(docRouteStatus);
0594: }
0595:
0596: public boolean isFinal() {
0597: return EdenConstants.ROUTE_HEADER_FINAL_CD
0598: .equals(docRouteStatus);
0599: }
0600:
0601: public boolean isEnroute() {
0602: return EdenConstants.ROUTE_HEADER_ENROUTE_CD
0603: .equals(docRouteStatus);
0604: }
0605:
0606: /**
0607: * @return true if the document is in the processed state
0608: */
0609: public boolean isProcessed() {
0610: return EdenConstants.ROUTE_HEADER_PROCESSED_CD
0611: .equals(docRouteStatus);
0612: }
0613:
0614: /**
0615: * @return true if the document is in the approved state
0616: */
0617: public boolean isApproved() {
0618: return EdenConstants.ROUTE_HEADER_APPROVED_CD
0619: .equals(docRouteStatus);
0620: }
0621:
0622: public boolean isRoutable() {
0623: return EdenConstants.ROUTE_HEADER_ENROUTE_CD
0624: .equals(docRouteStatus)
0625: ||
0626: //EdenConstants.ROUTE_HEADER_EXCEPTION_CD.equals(docRouteStatus) ||
0627: EdenConstants.ROUTE_HEADER_SAVED_CD
0628: .equals(docRouteStatus)
0629: || EdenConstants.ROUTE_HEADER_APPROVED_CD
0630: .equals(docRouteStatus)
0631: || EdenConstants.ROUTE_HEADER_PROCESSED_CD
0632: .equals(docRouteStatus);
0633: }
0634:
0635: /**
0636: * Return true if the given action code is valid for this document's current state.
0637: *
0638: * @param actionCd
0639: * The action code to be tested.
0640: * @return True if the action code is valid for the document's status.
0641: */
0642: public boolean isValidActionToTake(String actionCd) {
0643: String actions = (String) legalActions.get(docRouteStatus);
0644: if (actions.indexOf(actionCd) == -1) {
0645: return false;
0646: } else {
0647: return true;
0648: }
0649: }
0650:
0651: public boolean isValidStatusChange(String newStatus) {
0652: return ((String) stateTransitionMap.get(getDocRouteStatus()))
0653: .indexOf(newStatus) >= 0;
0654: }
0655:
0656: public void setRouteStatus(String newStatus, boolean finalState)
0657: throws InvalidActionTakenException {
0658: if (newStatus != getDocRouteStatus()) {
0659: // only modify the status mod date if the status actually changed
0660: setRouteStatusDate(new Timestamp(System.currentTimeMillis()));
0661: }
0662: if (((String) stateTransitionMap.get(getDocRouteStatus()))
0663: .indexOf(newStatus) >= 0) {
0664: LOG.debug("changing status");
0665: setDocRouteStatus(newStatus);
0666: } else {
0667: LOG.debug("unable to change status");
0668: throw new InvalidActionTakenException("Document status "
0669: + CodeTranslator
0670: .getRouteStatusLabel(getDocRouteStatus())
0671: + " cannot transition to status "
0672: + CodeTranslator.getRouteStatusLabel(newStatus));
0673: }
0674: setStatusModDate(new Timestamp(System.currentTimeMillis()));
0675: if (finalState) {
0676: LOG.debug("setting final timeStamp");
0677: setFinalizedDate(new Timestamp(System.currentTimeMillis()));
0678: }
0679: }
0680:
0681: public boolean isLocked() {
0682: return getLockCode() != EdenConstants.DOC_UNLOCKED;
0683: }
0684:
0685: public void unlock() {
0686: setLockCode(EdenConstants.DOC_UNLOCKED);
0687: }
0688:
0689: public String getLockCode() {
0690: return lockCode;
0691: }
0692:
0693: public void setLockCode(String lockReason) {
0694: this .lockCode = lockReason;
0695: }
0696:
0697: /**
0698: * Mark the document as being processed.
0699: *
0700: * @throws ResourceUnavailableException
0701: * @throws InvalidActionTakenException
0702: */
0703: public void markDocumentProcessed()
0704: throws InvalidActionTakenException {
0705: LOG.debug(this + " marked processed");
0706: setRouteStatus(EdenConstants.ROUTE_HEADER_PROCESSED_CD,
0707: !FINAL_STATE);
0708: }
0709:
0710: /**
0711: * Mark document cancled.
0712: *
0713: * @throws ResourceUnavailableException
0714: * @throws InvalidActionTakenException
0715: */
0716: public void markDocumentCanceled()
0717: throws InvalidActionTakenException {
0718: LOG.debug(this + " marked canceled");
0719: setRouteStatus(EdenConstants.ROUTE_HEADER_CANCEL_CD,
0720: FINAL_STATE);
0721: }
0722:
0723: /**
0724: * Mark document disapproved
0725: *
0726: * @throws ResourceUnavailableException
0727: * @throws InvalidActionTakenException
0728: */
0729: public void markDocumentDisapproved()
0730: throws InvalidActionTakenException {
0731: LOG.debug(this + " marked disapproved");
0732: setRouteStatus(EdenConstants.ROUTE_HEADER_DISAPPROVED_CD,
0733: FINAL_STATE);
0734: }
0735:
0736: /**
0737: * Mark document saved
0738: *
0739: * @throws ResourceUnavailableException
0740: * @throws InvalidActionTakenException
0741: */
0742: public void markDocumentSaved() throws InvalidActionTakenException {
0743: LOG.debug(this + " marked saved");
0744: setRouteStatus(EdenConstants.ROUTE_HEADER_SAVED_CD,
0745: !FINAL_STATE);
0746: }
0747:
0748: /**
0749: * Mark the document as being approved.
0750: *
0751: * @throws ResourceUnavailableException
0752: * @throws InvalidActionTakenException
0753: */
0754: public void markDocumentApproved()
0755: throws InvalidActionTakenException {
0756: LOG.debug(this + " marked approved");
0757: setApprovedDate(new Timestamp(System.currentTimeMillis()));
0758: setRouteStatus(EdenConstants.ROUTE_HEADER_APPROVED_CD,
0759: !FINAL_STATE);
0760: }
0761:
0762: /**
0763: * Mark the document as being in the exception state.
0764: *
0765: * @throws ResourceUnavailableException
0766: * @throws InvalidActionTakenException
0767: */
0768: public void markDocumentInException()
0769: throws InvalidActionTakenException {
0770: LOG.debug(this + " marked in exception");
0771: setRouteStatus(EdenConstants.ROUTE_HEADER_EXCEPTION_CD,
0772: !FINAL_STATE);
0773: }
0774:
0775: /**
0776: * Mark the document as being actively routed.
0777: *
0778: * @throws ResourceUnavailableException
0779: * @throws InvalidActionTakenException
0780: */
0781: public void markDocumentEnroute()
0782: throws InvalidActionTakenException {
0783: LOG.debug(this + " marked enroute");
0784: setRouteStatus(EdenConstants.ROUTE_HEADER_ENROUTE_CD,
0785: !FINAL_STATE);
0786: }
0787:
0788: /**
0789: * Mark document finalized.
0790: *
0791: * @throws ResourceUnavailableException
0792: * @throws InvalidActionTakenException
0793: */
0794: public void markDocumentFinalized()
0795: throws InvalidActionTakenException {
0796: LOG.debug(this + " marked finalized");
0797: setRouteStatus(EdenConstants.ROUTE_HEADER_FINAL_CD, FINAL_STATE);
0798: }
0799:
0800: /**
0801: * This method takes data from a VO and sets it on this route header
0802: * @param routeHeaderVO
0803: * @throws WorkflowException
0804: */
0805: public void setRouteHeaderData(RouteHeaderVO routeHeaderVO)
0806: throws WorkflowException {
0807: // String updatedDocumentContent = BeanConverter.buildUpdatedDocumentContent(routeHeaderVO);
0808: // // updatedDocumentContent will be null if the content has not changed, only update if its changed
0809: // if (updatedDocumentContent != null) {
0810: // setDocContent(updatedDocumentContent);
0811: // }
0812: if (!Utilities.equals(getDocTitle(), routeHeaderVO
0813: .getDocTitle())) {
0814: KEWServiceLocator.getActionListService()
0815: .updateActionItemsForTitleChange(
0816: getRouteHeaderId(),
0817: routeHeaderVO.getDocTitle());
0818: }
0819: setDocTitle(routeHeaderVO.getDocTitle());
0820: setAppDocId(routeHeaderVO.getAppDocId());
0821: setOverrideInd(routeHeaderVO.getOverrideInd());
0822: setStatusModDate(new Timestamp(System.currentTimeMillis()));
0823:
0824: /* set the variables from the routeHeaderVO */
0825: List variables = routeHeaderVO.getVariables();
0826: Iterator it = variables.iterator();
0827: while (it.hasNext()) {
0828: KeyValuePair kvp = (KeyValuePair) it.next();
0829: setVariable(kvp.getKey(), kvp.getValue());
0830: }
0831: }
0832:
0833: /**
0834: * Convenience method that returns the branch of the first (and presumably only?) initial node
0835: * @return the branch of the first (and presumably only?) initial node
0836: */
0837: private Branch getRootBranch() {
0838: // FIXME: assuming there is always a single initial route node instance
0839: return ((RouteNodeInstance) getInitialRouteNodeInstance(0))
0840: .getBranch();
0841: }
0842:
0843: /**
0844: * Looks up a variable (embodied in a "BranchState" key/value pair) in the
0845: * branch state table.
0846: */
0847: private BranchState findVariable(String name) {
0848: Branch rootBranch = getRootBranch();
0849: List branchState = rootBranch.getBranchState();
0850: Iterator it = branchState.iterator();
0851: while (it.hasNext()) {
0852: BranchState state = (BranchState) it.next();
0853: if (Utilities.equals(state.getKey(),
0854: BranchState.VARIABLE_PREFIX + name)) {
0855: return state;
0856: }
0857: }
0858: return null;
0859: }
0860:
0861: /**
0862: * Gets a variable
0863: * @param name variable name
0864: * @return variable value, or null if variable is not defined
0865: */
0866: public String getVariable(String name) {
0867: BranchState state = findVariable(name);
0868: if (state == null) {
0869: LOG.debug("Variable not found: '" + name + "'");
0870: return null;
0871: }
0872: return state.getValue();
0873: }
0874:
0875: /**
0876: * Sets a variable
0877: * @param name variable name
0878: * @param value variable value, or null if variable should be removed
0879: */
0880: public void setVariable(String name, String value) {
0881: BranchState state = findVariable(name);
0882: Branch rootBranch = getRootBranch();
0883: List branchState = rootBranch.getBranchState();
0884: if (state == null) {
0885: if (value == null) {
0886: LOG.debug("set non existent variable '" + name
0887: + "' to null value");
0888: return;
0889: }
0890: LOG.debug("Adding branch state: '" + name + "'='" + value
0891: + "'");
0892: state = new BranchState();
0893: state.setBranch(rootBranch);
0894: state.setKey(BranchState.VARIABLE_PREFIX + name);
0895: state.setValue(value);
0896: rootBranch.addBranchState(state);
0897: } else {
0898: if (value == null) {
0899: LOG.debug("Removing value: " + state.getKey() + "="
0900: + state.getValue());
0901: branchState.remove(state);
0902: } else {
0903: LOG.debug("Setting value of variable '" + name
0904: + "' to '" + value + "'");
0905: state.setValue(value);
0906: }
0907: }
0908: }
0909:
0910: public CustomActionListAttribute getCustomActionListAttribute()
0911: throws WorkflowException, EdenUserNotFoundException {
0912: CustomActionListAttribute customActionListAttribute = null;
0913: if (this .getDocumentType() != null) {
0914: customActionListAttribute = this .getDocumentType()
0915: .getCustomActionListAttribute();
0916: if (customActionListAttribute != null) {
0917: return customActionListAttribute;
0918: }
0919: }
0920: customActionListAttribute = new DefaultCustomActionListAttribute();
0921: return customActionListAttribute;
0922: }
0923:
0924: public CustomEmailAttribute getCustomEmailAttribute()
0925: throws WorkflowException, EdenUserNotFoundException {
0926: CustomEmailAttribute customEmailAttribute = null;
0927: try {
0928: if (this .getDocumentType() != null) {
0929: customEmailAttribute = this .getDocumentType()
0930: .getCustomEmailAttribute();
0931: if (customEmailAttribute != null) {
0932: customEmailAttribute.setRouteHeaderVO(BeanConverter
0933: .convertRouteHeader(this , null));
0934: return customEmailAttribute;
0935: }
0936: }
0937: } catch (Exception e) {
0938: LOG.debug("Error in retrieving custom email attribute", e);
0939: }
0940: customEmailAttribute = new CustomEmailAttributeImpl();
0941: customEmailAttribute.setRouteHeaderVO(BeanConverter
0942: .convertRouteHeader(this , null));
0943: return customEmailAttribute;
0944: }
0945:
0946: public CustomNoteAttribute getCustomNoteAttribute()
0947: throws WorkflowException, EdenUserNotFoundException {
0948: CustomNoteAttribute customNoteAttribute = null;
0949: try {
0950: if (this .getDocumentType() != null) {
0951: customNoteAttribute = this .getDocumentType()
0952: .getCustomNoteAttribute();
0953: if (customNoteAttribute != null) {
0954: customNoteAttribute.setRouteHeaderVO(BeanConverter
0955: .convertRouteHeader(this , null));
0956: return customNoteAttribute;
0957: }
0958: }
0959: } catch (Exception e) {
0960: LOG.debug("Error in retrieving custom note attribute", e);
0961: }
0962: customNoteAttribute = new CustomNoteAttributeImpl();
0963: customNoteAttribute.setRouteHeaderVO(BeanConverter
0964: .convertRouteHeader(this , null));
0965: return customNoteAttribute;
0966: }
0967:
0968: public ActionRequestValue getDocActionRequest(int index) {
0969: while (actionRequests.size() <= index) {
0970: ActionRequestValue actionRequest = new ActionRequestFactory(
0971: this ).createBlankActionRequest();
0972: actionRequest.setNodeInstance(new RouteNodeInstance());
0973: actionRequests.add(actionRequest);
0974: }
0975: return (ActionRequestValue) actionRequests.get(index);
0976: }
0977:
0978: public ActionTakenValue getDocActionTaken(int index) {
0979: while (actionsTaken.size() <= index) {
0980: actionsTaken.add(new ActionTakenValue());
0981: }
0982: return (ActionTakenValue) actionsTaken.get(index);
0983: }
0984:
0985: public ActionItem getDocActionItem(int index) {
0986: while (actionItems.size() <= index) {
0987: actionItems.add(new ActionItem());
0988: }
0989: return (ActionItem) actionItems.get(index);
0990: }
0991:
0992: public RouteNodeInstance getInitialRouteNodeInstance(int index) {
0993: while (initialRouteNodeInstances.size() <= index) {
0994: initialRouteNodeInstances.add(new RouteNodeInstance());
0995: }
0996: return (RouteNodeInstance) initialRouteNodeInstances.get(index);
0997: }
0998:
0999: /**
1000: * @param searchableAttributeValues The searchableAttributeValues to set.
1001: */
1002: public void setSearchableAttributeValues(
1003: List<SearchableAttributeValue> searchableAttributeValues) {
1004: this .searchableAttributeValues = searchableAttributeValues;
1005: }
1006:
1007: /**
1008: * @return Returns the searchableAttributeValues.
1009: */
1010: public List<SearchableAttributeValue> getSearchableAttributeValues() {
1011: return searchableAttributeValues;
1012: }
1013:
1014: public boolean isRoutingReport() {
1015: return routingReport;
1016: }
1017:
1018: public void setRoutingReport(boolean routingReport) {
1019: this .routingReport = routingReport;
1020: }
1021:
1022: public List<RouteNodeInstance> getInitialRouteNodeInstances() {
1023: return initialRouteNodeInstances;
1024: }
1025:
1026: public void setInitialRouteNodeInstances(
1027: List<RouteNodeInstance> initialRouteNodeInstances) {
1028: this .initialRouteNodeInstances = initialRouteNodeInstances;
1029: }
1030:
1031: public List<Note> getNotes() {
1032: return notes;
1033: }
1034:
1035: public void setNotes(List<Note> notes) {
1036: this .notes = notes;
1037: }
1038:
1039: public DocumentRouteHeaderValueContent getDocumentContent() {
1040: if (documentContent == null) {
1041: documentContent = KEWServiceLocator.getRouteHeaderService()
1042: .getContent(getRouteHeaderId());
1043: }
1044: return documentContent;
1045: }
1046:
1047: public void setDocumentContent(
1048: DocumentRouteHeaderValueContent documentContent) {
1049: this.documentContent = documentContent;
1050: }
1051:
1052: }
|