001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kew.engine.node;
017
018 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
019
020 import java.util.Iterator;
021 import java.util.List;
022
023
024 /**
025 * Logs {@link RouteNodeInstance} graphs in a format which is indented and easy to read.
026 *
027 * @author Kuali Rice Team (rice.collab@kuali.org)
028 */
029 public class NodeJotter {
030
031 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(NodeJotter.class);
032 private static final String INDENT = " ";
033
034 public static void jotNodeInstance(DocumentRouteHeaderValue document, RouteNodeInstance nodeInstance) {
035 try {
036 if (LOG.isDebugEnabled()) {
037 List initialNodeInstances = document.getInitialRouteNodeInstances();
038 for (Iterator iterator = initialNodeInstances.iterator(); iterator.hasNext();) {
039 RouteNodeInstance initialNodeInstance = (RouteNodeInstance) iterator.next();
040 NodeType nodeType = NodeType.fromNodeInstance(initialNodeInstance);
041 LOG.debug(orchestrateOutput(initialNodeInstance, nodeType, null, 0));
042 }
043 } else if (LOG.isInfoEnabled()) {
044 NodeType nodeType = NodeType.fromNodeInstance(nodeInstance);
045 LOG.info(outputNodeInstanceToLog(nodeInstance, nodeType, 0));
046 }
047 } catch (Throwable t) {
048 LOG.warn("Caught error attempting to jot node instance" + nodeInstance);
049 }
050 }
051
052 private static String orchestrateOutput(RouteNodeInstance nodeInstance, NodeType nodeType, SplitJoinContext sjCtx, int indentDepth) throws Exception {
053 String output = "";
054 boolean isSplit = NodeType.SPLIT.equals(nodeType);
055 boolean isJoin = NodeType.JOIN.equals(nodeType);
056 if (isJoin && sjCtx != null) {
057 sjCtx.joinNodeInstance = nodeInstance;
058 return output;
059 }
060 SplitJoinContext newSplitJoinContext = null;
061 if (isSplit) {
062 newSplitJoinContext = new SplitJoinContext(nodeInstance);
063 }
064 output += outputNodeInstanceToLog(nodeInstance, nodeType, indentDepth);
065 for (Iterator iterator = nodeInstance.getNextNodeInstances().iterator(); iterator.hasNext();) {
066 RouteNodeInstance nextNodeInstance = (RouteNodeInstance) iterator.next();
067 nodeType = NodeType.fromNodeInstance(nextNodeInstance);
068 if (newSplitJoinContext != null) {
069 output += orchestrateOutput(nextNodeInstance, nodeType, newSplitJoinContext, indentDepth + 1);
070 } else {
071 output += orchestrateOutput(nextNodeInstance, nodeType, sjCtx, indentDepth + 1);
072 }
073 }
074 if (isSplit) {
075 if (newSplitJoinContext != null && newSplitJoinContext.joinNodeInstance != null) {
076 nodeType = NodeType.fromNodeInstance(newSplitJoinContext.joinNodeInstance);
077 output += orchestrateOutput(newSplitJoinContext.joinNodeInstance, nodeType, sjCtx, indentDepth);
078 }
079 }
080 return output;
081 }
082
083 private static String outputNodeInstanceToLog(RouteNodeInstance nodeInstance, NodeType nodeType, int indentDepth) throws Exception {
084 String memAddress = nodeInstance.toString().split("@")[1];
085 String dataIndent = getIndent(indentDepth + 1);
086 String output = getIndent(indentDepth) + "[NODE type=" + nodeType.getName() + "]\n" + dataIndent + "Name: " + nodeInstance.getName() + "(" + memAddress + ")\n";
087 output += dataIndent + "State: ";
088 for (Iterator iterator = nodeInstance.getState().iterator(); iterator.hasNext();) {
089 NodeState nodeState = (NodeState) iterator.next();
090 output += nodeState.getKey() + "=" + nodeState.getValue();
091 if (iterator.hasNext()) {
092 output += ",";
093 }
094 }
095 output += "\n" + dataIndent + "Status Flags: initial=" + nodeInstance.isInitial() + ", active=" + nodeInstance.isActive() + ", complete=" + nodeInstance.isComplete();
096 output += (nodeInstance.getProcess() == null ? "" : "\n" + dataIndent + "ProcessDefinition Name: " + nodeInstance.getProcess().getName());
097 output += "\n";
098 return output;
099 }
100
101 private static String getIndent(int indentDepth) {
102 StringBuffer buffer = new StringBuffer();
103 for (int depth = 0; depth < indentDepth; depth++) {
104 buffer.append(INDENT);
105 }
106 return buffer.toString();
107 }
108
109 private static class SplitJoinContext {
110 public RouteNodeInstance splitNodeInstance;
111 public RouteNodeInstance joinNodeInstance;
112
113 public SplitJoinContext(RouteNodeInstance splitNodeInstance) {
114 this.splitNodeInstance = splitNodeInstance;
115 }
116 }
117
118 }