/** * Copyright (C) 2001-3, Anthony Harrison anh23@pitt.edu 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 2.1 of the License, or (at your option) any later version. * This library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.jactr.core.production.action; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.chunk.IChunk; import org.jactr.core.logging.Logger; import org.jactr.core.model.IModel; import org.jactr.core.production.IInstantiation; import org.jactr.core.queue.ITimedEvent; import org.jactr.core.queue.timedevents.AbstractTimedEvent; /** * OutputAction is a general purpose output function. It takes a string that can * contain variable names that will, at firing, be resolved to their bound * values. This is useful for tracing and producing pseudo-verbal protocols in * the model. The output is directed to the ModelLogEvent.OUTPUT log. a general * output action, equivalent to !output! in ACT-R proper Output is of the form * "This is test, and this is a =variable" */ /** * Description of the Class * * @author harrison * @created February 11, 2003 */ public class OutputAction extends DefaultAction { private static transient Log LOGGER = LogFactory.getLog(OutputAction.class .getName()); /** * Description of the Field */ public String _outputTemplate; /** * Constructor for the OutputAction object */ public OutputAction() { this(""); } /** * Constructor for the OutputAction object * * @param output * Description of the Parameter */ public OutputAction(String output) { _outputTemplate = output; } /** * Sets the text attribute of the OutputAction object * * @param text * The new text value */ public void setText(String text) { _outputTemplate = text; } /** * Gets the text attribute of the OutputAction object * * @return The text value */ public String getText() { return _outputTemplate; } public IAction bind(Map<String, Object> bindings) { OutputAction oa = new OutputAction(_outputTemplate); oa.replaceVariables(bindings); return oa; } protected void replaceVariables(Map<String, Object> bindings) { if (_outputTemplate != null) _outputTemplate = replaceVariables(_outputTemplate, bindings); } /** * Description of the Method * * @param instantiation * Description of the Parameter * @return Description of the Return Value */ @Override public double fire(IInstantiation instantiation, double firingTime) { final IModel model = instantiation.getModel(); ITimedEvent event = new AbstractTimedEvent(firingTime, firingTime) { @Override public void fire(double currentTime) { super.fire(currentTime); if (LOGGER.isDebugEnabled()) LOGGER.debug("Outputting " + _outputTemplate); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.OUTPUT, _outputTemplate); } @Override public String toString() { return String.format("Output('%s' @ %.2f)", _outputTemplate, getEndTime()); } }; /* * queue the event */ model.getTimedEventQueue().enqueue(event); return 0; } /** * Description of the Method * * @param var * Description of the Parameter * @param start * Description of the Parameter * @return Description of the Return Value */ static private int findEndOfVariableName(String var, int start) { int end = ++start; char[] charArray = var.toCharArray(); while (end < charArray.length) if (Character.isWhitespace(charArray[end])) return end; else end++; return end; } /** * Description of the Method * * @param variableBindings * Description of the Parameter * @return Description of the Return Value */ static public String replaceVariables(String template, Map<String,Object> variableBindings) { StringBuffer sb = new StringBuffer(); int start = 0; int end = 0; while (end != -1) { // find a =variable end = template.indexOf("=", start); if (end != -1) { // there is a variable like name int endOfVariableName = findEndOfVariableName(template, end); String variableName = template.substring(end, endOfVariableName); sb.append(template.substring(start, end)); if (!variableName.equals("=")) { // it's not an equal sign alone variableName = variableName.toLowerCase(); if (LOGGER.isDebugEnabled()) LOGGER.debug("Variable Name " + variableName + " found"); Object val = resolve(variableName, variableBindings); if (val instanceof IChunk) val = ((IChunk) val).getSymbolicChunk().getName(); if (LOGGER.isDebugEnabled()) LOGGER.debug(variableName + " = " + val); if (variableBindings.containsKey(variableName)) sb.append(val); else { sb.append(variableName); LOGGER.error(variableBindings.get("=production") + ".outputAction : " + variableName + " was not found. Available : " + variableBindings); } } else { if (LOGGER.isDebugEnabled()) LOGGER.debug(variableName + " is not a variable name, appending"); sb.append(variableName); } end = endOfVariableName; } else if (start < template.length()) sb.append(template.substring(start)); start = end; } return sb.toString(); } }