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