001: /*
002: * @(#)PathParserImpl.java
003: *
004: * Copyright (C) 2002-2003 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Part of the GroboUtils package at:
009: * http://groboutils.sourceforge.net
010: *
011: * Permission is hereby granted, free of charge, to any person obtaining a
012: * copy of this software and associated documentation files (the "Software"),
013: * to deal in the Software without restriction, including without limitation
014: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
015: * and/or sell copies of the Software, and to permit persons to whom the
016: * Software is furnished to do so, subject to the following conditions:
017: *
018: * The above copyright notice and this permission notice shall be included in
019: * all copies or substantial portions of the Software.
020: *
021: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
022: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
023: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
024: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
025: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
026: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
027: * DEALINGS IN THE SOFTWARE.
028: */
029: package net.sourceforge.groboutils.mbtf.v1.engine;
030:
031: import net.sourceforge.groboutils.mbtf.v1.IPath;
032: import net.sourceforge.groboutils.mbtf.v1.IState;
033: import net.sourceforge.groboutils.mbtf.v1.IAction;
034: import net.sourceforge.groboutils.mbtf.v1.ISystem;
035: import net.sourceforge.groboutils.mbtf.v1.IErrors;
036: import net.sourceforge.groboutils.mbtf.v1.IValidate;
037: import net.sourceforge.groboutils.mbtf.v1.ITransition;
038: import net.sourceforge.groboutils.mbtf.v1.IPathParser;
039: import net.sourceforge.groboutils.mbtf.v1.IPathHistory;
040: import net.sourceforge.groboutils.mbtf.v1.IPathIterator;
041: import net.sourceforge.groboutils.mbtf.v1.TestHaltRuntimeException;
042: import net.sourceforge.groboutils.mbtf.v1.TestFailRuntimeException;
043:
044: import org.apache.log4j.Logger;
045:
046: /**
047: * Knows how to parse an IPath instance, and correctly follow the transitions
048: * and record errors.
049: *
050: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
051: * @version $Date: 2003/02/10 22:52:26 $
052: * @since June 12, 2002
053: */
054: public class PathParserImpl implements IPathParser {
055: private static final Logger LOG = Logger
056: .getLogger(PathParserImpl.class);
057:
058: /**
059: * @exception TestHaltRuntimeException if the path validation reports
060: * a <tt>halt()</tt> to <tt>errors</tt>.
061: */
062: public IErrors parsePath(IPath path, ISystem sys) {
063: ErrorsImpl ei = createErrors();
064: PathHistoryImpl phi = createPathHistory();
065:
066: IState currentState = path.getStartState();
067: IPathIterator pi = path.iterator();
068: while (currentState != null && !ei.isHaltPath()) {
069: ErrorsImpl testErrs = createErrors();
070: try {
071: testErrs.setCurrentPathHistory(phi);
072: LOG.debug("Entering state " + currentState);
073: phi.addState(currentState);
074: LOG.debug("Validating state " + currentState);
075: validate(currentState, testErrs, phi, sys);
076: currentState = null;
077: if (!testErrs.isHaltPath() && pi.hasNext()) {
078: ITransition trans = pi.nextTransition();
079: phi.addTransition(trans);
080: LOG.debug("Vaidatling transition " + trans);
081: validate(trans, testErrs, phi, sys);
082: if (!testErrs.isHaltPath()) {
083: IAction act = trans.getAction();
084: LOG.debug("Start Performing action " + act);
085: act.performAction(sys, testErrs);
086: LOG.debug("End Performing action " + act);
087: currentState = trans.getDestinationState();
088: }
089: }
090: } catch (TestHaltRuntimeException thre) {
091: // should have already been caught
092: throw thre;
093: } catch (ThreadDeath td) {
094: // never catch these. never.
095: throw td;
096: } catch (TestFailRuntimeException tfre) {
097: // The error was already added to the error set.
098: // This exception ends this path, but the exception is
099: // not propigated.
100: } catch (Throwable t) {
101: testErrs.addError("Uncaught exception", t);
102: if (t instanceof RuntimeException) {
103: throw (RuntimeException) t;
104: }
105: t.printStackTrace();
106: throw new IllegalStateException(t.toString());
107: } finally {
108: ei.addErrors(testErrs);
109: }
110: }
111:
112: return ei;
113: }
114:
115: protected void validate(IState state, ErrorsImpl ei,
116: PathHistoryImpl phi, ISystem sys)
117: throws CloneNotSupportedException {
118: IValidate[] v = state.getValidates();
119: if (v.length <= 0) {
120: ei.setCurrentPathHistory(phi);
121: ei.addError("No validations for state '" + state.getName()
122: + "'");
123: return;
124: }
125: for (int i = 0; i < v.length && !ei.isHaltPath(); ++i) {
126: ei.setCurrentPathHistory(phi);
127: v[i].validate(sys, ei);
128: phi.addValidate(v[i], state, ei);
129: ei.setCurrentPathHistory(phi);
130: }
131: }
132:
133: protected void validate(ITransition trans, ErrorsImpl ei,
134: PathHistoryImpl phi, ISystem sys)
135: throws CloneNotSupportedException {
136: IValidate[] v = trans.getValidates();
137: if (v.length <= 0) {
138: ei.setCurrentPathHistory(phi);
139: ei.addError("No validations for transition '"
140: + trans.getName() + "'");
141: return;
142: }
143: for (int i = 0; i < v.length && !ei.isHaltPath(); ++i) {
144: ei.setCurrentPathHistory((IPathHistory) phi.clone());
145: v[i].validate(sys, ei);
146: phi.addValidate(v[i], trans, ei);
147: ei.setCurrentPathHistory((IPathHistory) phi.clone());
148: }
149: }
150:
151: protected ErrorsImpl createErrors() {
152: return new ErrorsImpl();
153: }
154:
155: protected PathHistoryImpl createPathHistory() {
156: return new PathHistoryImpl();
157: }
158: }
|