001: /*
002: * @(#)PathHistoryImpl.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.IState;
032: import net.sourceforge.groboutils.mbtf.v1.IValidate;
033: import net.sourceforge.groboutils.mbtf.v1.ITransition;
034: import net.sourceforge.groboutils.mbtf.v1.IPathHistory;
035: import net.sourceforge.groboutils.mbtf.v1.IErrors;
036:
037: import java.util.Vector;
038:
039: import org.apache.log4j.Logger;
040:
041: /**
042: * Records the states and transition history during a path traversal.
043: * The instance can be cloned for the cases of errors and warnings needing to
044: * store the path history when they occured. The instance should also support
045: * a toString() method for easy debugging and logging.
046: *
047: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
048: * @version $Date: 2003/02/10 22:52:26 $
049: * @since June 12, 2002
050: */
051: public class PathHistoryImpl implements IPathHistory, Cloneable {
052: private static final Logger LOG = Logger
053: .getLogger(PathHistoryImpl.class);
054:
055: private static interface IHistoryPart {
056: public String toString();
057: }
058:
059: private static class StateHistoryPart implements IHistoryPart {
060: private IState state;
061:
062: public StateHistoryPart(IState s) {
063: this .state = s;
064: }
065:
066: public String toString() {
067: if (this .state == null) {
068: return " finished terminal state.\n";
069: }
070: return " entered state '" + this .state.getName() + "'\n";
071: }
072: }
073:
074: private static class TransHistoryPart implements IHistoryPart {
075: private ITransition trans;
076:
077: public TransHistoryPart(ITransition t) {
078: this .trans = t;
079: }
080:
081: public String toString() {
082: return " followed transition '" + this .trans.getName()
083: + "'\n";
084: }
085: }
086:
087: private static abstract class ValidHistoryPart implements
088: IHistoryPart {
089: protected String err;
090:
091: public ValidHistoryPart(IValidate v, IErrors e) {
092: if (e != null && e.getErrors().length > 0) {
093: this .err = e.toString();
094: } else {
095: this .err = "No errors.";
096: }
097: }
098: }
099:
100: private static class StateValidHistoryPart extends ValidHistoryPart {
101: private IState state;
102:
103: public StateValidHistoryPart(IValidate v, IState s, IErrors e) {
104: super (v, e);
105: this .state = s;
106: }
107:
108: public String toString() {
109: return " validated state '" + this .state.getName()
110: + "': " + this .err + "\n";
111: }
112: }
113:
114: private static class TransValidHistoryPart extends ValidHistoryPart {
115: private ITransition trans;
116:
117: public TransValidHistoryPart(IValidate v, ITransition t,
118: IErrors e) {
119: super (v, e);
120: this .trans = t;
121: }
122:
123: public String toString() {
124: return " validated transition '" + this .trans.getName()
125: + "': " + this .err + "\n";
126: }
127: }
128:
129: private int errorCount = 0;
130: private Vector history = new Vector();
131:
132: /**
133: * When the current state changes, add the new state here. This should
134: * be called for the start state, and once at the end of every successful
135: * transition.
136: */
137: public void addState(IState s) {
138: LOG.debug("addState( " + s + " )");
139: this .history.addElement(new StateHistoryPart(s));
140: LOG.debug(" - History is now: " + toString());
141: }
142:
143: /**
144: * When a transition is about to occur, it should be added here.
145: */
146: public void addTransition(ITransition t) {
147: LOG.debug("addTransition( " + t + " )");
148: this .history.addElement(new TransHistoryPart(t));
149: }
150:
151: /**
152: * After a validation call, the error results should be added here.
153: */
154: public void addValidate(IValidate val, IState owningState,
155: IErrors errors) {
156: LOG.debug("addValidate( " + val + ", " + owningState + ", "
157: + errors + " )");
158: if (errors != null) {
159: this .errorCount += errors.getErrors().length;
160: }
161: this .history.addElement(new StateValidHistoryPart(val,
162: owningState, errors));
163: }
164:
165: /**
166: * After a validation call, the error results should be added here.
167: */
168: public void addValidate(IValidate val,
169: ITransition owningTransition, IErrors errors) {
170: LOG.debug("addValidate( " + val + ", " + owningTransition
171: + ", " + errors + " )");
172: if (errors != null) {
173: this .errorCount += errors.getErrors().length;
174: }
175: this .history.addElement(new TransValidHistoryPart(val,
176: owningTransition, errors));
177: }
178:
179: /**
180: * Returns the total number of errors (halts, failures, and errors)
181: * registered during validation and transitions.
182: */
183: public int getErrorCount() {
184: return this .errorCount;
185: }
186:
187: public String toString() {
188: IHistoryPart hp[] = new IHistoryPart[this .history.size()];
189: this .history.copyInto(hp);
190: if (hp.length <= 0) {
191: return "[no history]";
192: }
193: StringBuffer sb = new StringBuffer("[Path History:\n");
194: for (int i = 0; i < hp.length; ++i) {
195: sb.append(hp[i]);
196: }
197: sb.append("\n]");
198: return sb.toString();
199: }
200:
201: protected Object clone() throws CloneNotSupportedException {
202: PathHistoryImpl phi = (PathHistoryImpl) super .clone();
203: phi.errorCount = this .errorCount;
204: phi.history = (Vector) this .history.clone();
205:
206: return phi;
207: }
208:
209: public IPathHistory copy() {
210: try {
211: return (IPathHistory) clone();
212: } catch (CloneNotSupportedException e) {
213: throw new IllegalStateException(e.toString());
214: }
215: }
216: }
|