All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.javaframe.TraceObject Maven / Gradle / Ivy

/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.javaframe;

import java.util.Calendar;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.coos.actorframe.XmlBuilder;
import org.coos.actorframe.messages.AFConstants;
import org.coos.javaframe.messages.ActorMsg;

/**
 * This class contains information for transition of a state machine. The trace
 * level may be set both on state machine level and what part of the transition
 * to be logged. This trace specification can be set by sending Actor messages
 * to a state machine.
 * 
 * @author Geir Melby, Tellu AS
 */
public class TraceObject implements AFConstants {

	private static int counter = 0;
	private int transitionId = 0;

	protected ActorMsg inputSignal; // The input signal that triggered the
	// transition
	protected String currentState; // The state of the state machine before the
	// transition
	protected String newState; // The state after the transition. May be same
	// as currentState.
	String task; // Text written by the transition.
	protected Vector outputSignals; // Output signals that are sent during the
	// transition
	protected Hashtable timers; // Output signals that are sent during the
	// transition
	Vector errors; // Errors set during the transition
	Vector warnings; // Warnings set during the transition
	Hashtable portOutSignals; // Signals sent out of the Port.
	Hashtable portInSignals; // Signals received by the Port.
	String portTask; // Task executed in the Port
	boolean traceFlag = true;

	/* Defined trace categories that shall be traces for this actor */
	int traceCategories;
	/* Defined trace levels that shall be traced for this actor */
	int traceLevel;
	/* Used to format the timestamp. */
	Calendar timeFormatter;

	private Logger logger;

    private StateMachine curfsm = null;
    
	/**
	 * Used when automatic testing is performed to avoid unnecessary print outs
	 */
	private boolean outputDisabled = false;

    public TraceObject() {
        initTrace("org.coos.actorframe");
    }

    /**
     * @deprecated not used
     */
    public TraceObject(StateMachine curfsm) {
        initTrace(curfsm.getClass().toString());
        this.curfsm = curfsm;
    }

    /**
     * @deprecated not used
     */
    public TraceObject(ActorAddress actor) {
        String ac = actor.getActorID();
        initTrace(ac.replace('/', '.'));
    }

    /**
     * @deprecated not used
     */
    public TraceObject(ActorAddress actor, ActorMsg inputSignal, String currentState) {
        initTrace(actor.getActorID().replace('/', '.'));
    }

	/*
	 * Called from the constructors
	 */
	private void initTrace(String loggerName) {
		outputSignals = new Vector();
		portOutSignals = new Hashtable();
		portInSignals = new Hashtable();
		timeFormatter = Calendar.getInstance();
		logger = LoggerFactory.getLogger(loggerName);
	}

	public void traceInit(int traceCategories, int traceLevel, String loggerName) {
		task = "";
		outputSignals.removeAllElements();
		if (warnings != null) {
			warnings.removeAllElements();
		}
		if (errors != null) {
			errors.removeAllElements();
		}

		transitionId = counter++;
		// These trace option may be overridden later when instance is read from
		// the entity bean
		this.traceCategories = traceCategories;
		this.traceLevel = traceLevel;
		logger = LoggerFactory.getLogger(loggerName);
	}

	public void traceInit(StateMachine curfsm) {
		task = "";
		outputSignals.removeAllElements();
		inputSignal = null;
		portTask = "";
		portOutSignals.clear();
		portInSignals.clear();
		if (warnings != null) {
			warnings.removeAllElements();
		}
		if (errors != null) {
			errors.removeAllElements();
		}
		transitionId = counter++;
		// These trace option may be overridden later when instance is read from
		// the entity bean
        this.curfsm = curfsm;
		traceLevel = curfsm.getTraceLevel();
	}

    /**
     * @return current StateMachine that is holding this traceObject
     */
    public StateMachine getCurrentStateMachine() {
        return curfsm;
    }

    /**
     * @return the transitionId
     */
    public int getTransitionId() {
        return transitionId;
    }

    protected int getTraceFormat() {
        if (curfsm == null) {
            return ApplicationSpec.TRACE_FORMAT_TEXT;
        }
        return curfsm.getApplicationSpec().getTraceFormat();
    }

    /**
     * @return the logger
     */
    public Logger getLogger() {
        return logger;
    }

    public void setOutputDisabled(boolean outputDisabled) {
		this.outputDisabled = outputDisabled;
	}

	public ActorAddress getActor() {
	    if (inputSignal == null) {
	        return null;
	    }
		return inputSignal.getReceiverRole();
	}

	public ActorMsg getInputSignal() {
		return inputSignal;
	}

	public String getCurrentState() {
		return currentState;
	}

	public String getNewState() {
		return newState;
	}

	public Vector getOutputSignals() {
		return outputSignals;
	}

	public Vector getWarnings() {
		return warnings != null ? warnings : new Vector();
	}

	public Vector getErrors() {
		return errors;
	}

	public Hashtable getPortOutSignals() {
		return portOutSignals;
	}

	public Hashtable getPortInSignals() {
		return portInSignals;
	}

	/* Set current trace level */
	public void traceSetLevel(int level) {
		traceLevel = level;
	}

	public void traceTask(String str) {
		if (/* ((traceCategories & TraceConstants.tcTask) == 0) & */(traceLevel > TraceConstants.tlDebug))
			return; // Ignore trace
		if (task.equals(""))
			task = str;
		else
			task = task + "; " + str;
	}
	
	/**
	 * 
	 * @return String created by calls to traceTask(String)
	 */
	public String getTraceTask() {
	    return task;
	}

	public void traceSystem(String str) {
		if (!outputDisabled)
			traceOut(TraceConstants.tlInfo, TraceConstants.tcSystem, getTraceHeader() + str);
	}

	public String getTraceHeader() {
		try {
            if (inputSignal != null) {
            	StringBuffer str = new StringBuffer();
            	str.append("ACTOR: " + inputSignal.getReceiverRole());
            	str.append(" TRIGGER: " + inputSignal.getMsgId());
            	str.append(" STATE: " + currentState);
            	str.append(" MESSAGE: ");
            	return str.toString();
            }
        } catch (Exception e) {
        } 
		return "method getTraceHeader failed, actor is null ";
	}

	/**
	 * Probably should be removed
	 * 
	 * @param trace
	 */
	public void setTrace(boolean trace) {
		this.traceFlag = trace;
	}

	public void traceOutput(ActorMsg am) {
		outputSignals.addElement(am);
		/*
		 * if (!am.getSenderRole().hasActorPort() && ) {
		 * outputSignals.addElement(am); } else {
		 * addPortOutputSignal(am.getSenderRole().getActorPort(), am); }
		 */
	}

	public void traceWarning(String s) {
		if (logger.isWarnEnabled()) {
			logger.log(TraceConstants.tlWarn, getTraceHeader() + s);
		}
		if (traceLevel > TraceConstants.tlWarn)
			return; // Ignore trace
		if (warnings == null) {
			warnings = new Vector();
		}
		warnings.addElement(s);

	}

	public void traceError(String s) {
		if (logger.isErrorEnabled()) {
			logger.log(TraceConstants.tlError, getTraceHeader() + s);
		}
		if (traceLevel > TraceConstants.tlError)
			return; // Ignore trace
		if (errors == null) {
			errors = new Vector();
		}
		errors.addElement(s);

	}

	public void traceOut(int level, String value) {
		traceOut(level, 1, value);
	}

	/**
	 * Generate trace, either to "stdout" or "stderr" depending on level and
	 * categories, and if trace level specified implies tracing. If
	 * "outputDisabled" is false, no print out is done.
	 */
	public void traceOut(int level, int categories, String value) {
		if (!outputDisabled && level >= traceLevel) {
			logger.setTraceLevel(traceLevel);
			logger.log(level, categories, value);
		}
	}

	public String getPortString(ActorMsg inp) {
		String s = "";
		if (portOutSignals.isEmpty() && portInSignals.isEmpty())
			return s;

		Enumeration portNames = portInSignals.keys();
		while (portNames.hasMoreElements()) {
			String name = (String) portNames.nextElement();
			if (inp != null)
				s += "  PORT NAME: " + name + "\n";
			Vector in = ((Vector) portInSignals.get(name));
			if (in != null) {
				Enumeration ein = in.elements();
				while (ein.hasMoreElements()) {
					if (inp != null)
						s += "  ";
					s += "  INPUT:  " + (String) ein.nextElement() + "\n";
				}
			}

			Vector out = ((Vector) portOutSignals.get(name));
			if (out != null) {
				Enumeration eout = out.elements();
				while (eout.hasMoreElements()) {
					if (inp != null)
						s += "  ";
					s += "  OUTPUT: " + (String) eout.nextElement() + "\n";
				}
			}
		}

		return s;
	}

	public String toString() {

	    // Skip router timer message
        if (inputSignal.messageName() != null && inputSignal.messageName().equals(ROUTER_UPDATE_TIMER_MSG)) {
            return "";
        }
        
        // XML format

        if (getTraceFormat() == ApplicationSpec.TRACE_FORMAT_XML) {
            return XmlBuilder.toXML(this);
        }
        
		StringBuffer sb = new StringBuffer("\n");
		sb.append("START TRANSITION NO: " + transitionId);

		if (inputSignal != null) {
	        sb.append(" ACTOR: " + inputSignal.getReceiverRole());
	        if (inputSignal.getReceiverRole().hasActorPort()) {
	            // port execution, get the first
	            sb.append(" PORT: " + inputSignal.getReceiverRole().getActorPort() + "\n");
	        }

			sb.append(" TRIGGER: " + inputSignal.messageName());
			sb.append(" CURRENT STATE: " + filterStateName(currentState));
			sb.append(" NEXT STATE: " + filterStateName(newState) + "\n");
			sb.append("  INPUT:  " + inputSignal.messageContent() + "\n");
		}
		if (warnings != null) {
			for (int i = 0; i < warnings.size(); i++) {
				String str = (String) warnings.elementAt(i);
				sb.append("  WARNING: " + str + "\n");
			}
		}

		if (errors != null) {
			for (int i = 0; i < errors.size(); i++) {
				String str = (String) errors.elementAt(i);
				sb.append("  ERROR:   " + str + "\n");
			}
		}

		for (int i = 0; i < outputSignals.size(); i++) {
			ActorMsg msg = (ActorMsg) outputSignals.elementAt(i);
			sb.append("  OUTPUT: " + msg.messageContent() + "\n");
		}
		if (!task.equals("")) {
			sb.append("  TASK:    " + task + "\n");
		}
		sb.append(getPortString(inputSignal));

		if (!inputSignal.getReceiverRole().hasActorPort()) {
			sb.append("END TRANSITION ACTOR: \n");
		} else {
			sb.append("END TRANSITION PORT: \n");
		}
		sb.append("-------------------------------------------------------------------->");
		return sb.toString();
	}

	/**
	 * @deprecated found from input signal
	 * @param actor actorAddress of actor
	 */
	public void setActor(ActorAddress actor) {
	}

	public void addPortOutputSignal(String portname, ActorMsg outsig) {
		if (portOutSignals.containsKey(portname)) {
			Vector out = (Vector) portOutSignals.get(portname);
			out.addElement(outsig.messageContent());
		} else {
			Vector tmp = new Vector();
			tmp.addElement(outsig.messageContent());
			portOutSignals.put(portname, tmp);
		}
	}

	public void addPortInputSignal(String portname, ActorMsg insig) {
		if (portInSignals.containsKey(portname)) {
			Vector out = (Vector) portInSignals.get(portname);
			out.addElement(insig.messageContent());
		} else {
			Vector tmp = new Vector();
			tmp.addElement(insig.messageContent());
			portInSignals.put(portname, tmp);
		}
	}

	public void setInputSignal(ActorMsg inputSignal) {
		this.inputSignal = inputSignal;
	}

	public void setCurrentState(String currentState) {
		this.currentState = currentState;
	}

	public void setNewState(String newState) {
		this.newState = newState;
	}

	public String filterStateName(String name) {
		if (name == null) {
			return null;
		}
		int first;
		int last;
		StringBuffer buf;
		while (name.indexOf(':') != -1) {
			buf = new StringBuffer();
			first = name.indexOf(':');
			last = name.indexOf(':', first + 1);
			buf.append(name.substring(0, first));
			buf.append(name.substring(last + 1, name.length()));
			name = buf.toString();
		}
		return name;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy