001: /*
002: * @(#)PathImpl.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.ITransition;
034: import net.sourceforge.groboutils.mbtf.v1.IPathIterator;
035:
036: import org.apache.log4j.Logger;
037:
038: /**
039: * An immutable implementation of IPath
040: *
041: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
042: * @version $Date: 2003/02/10 22:52:26 $
043: * @since June 12, 2002
044: */
045: public class PathImpl implements IPath {
046: private static final Logger LOG = Logger.getLogger(PathImpl.class);
047:
048: private ITransition[] trans;
049: private IState start;
050:
051: public PathImpl(IState startState, ITransition[] trans) {
052: if (startState == null) {
053: throw new IllegalArgumentException("no null args");
054: }
055:
056: LOG.debug("Path starting at " + startState);
057: if (trans == null) {
058: LOG.debug("-- Path has no transitions");
059: this .trans = new ITransition[0];
060: } else {
061: int len = trans.length;
062: ITransition[] t = new ITransition[len];
063: for (int i = 0; i < len; ++i) {
064: if (trans[i] == null) {
065: throw new IllegalArgumentException(
066: "no nulls allowed in ITransition array");
067: }
068: // else
069: LOG.debug("-- transition " + i + "=" + trans[i]);
070: t[i] = trans[i];
071: }
072: this .trans = t;
073: }
074:
075: this .start = startState;
076: }
077:
078: /**
079: * Generate an iterator for this path. The iterator will only return
080: * transition elements.
081: *
082: * @return a new iterator for the path.
083: */
084: public IPathIterator iterator() {
085: return new PathIteratorImpl(this .trans);
086: }
087:
088: /**
089: * Retrieve the starting state for this path.
090: *
091: * @return the start state for the path, which can never be <tt>null</tt>.
092: */
093: public IState getStartState() {
094: return this .start;
095: }
096:
097: /**
098: * Returns the number of transitions in the path. This is named "size" to
099: * correspond to the <tt>java.util</tt>
100: * container classes terminology.
101: *
102: * @return the path transition count.
103: */
104: public int size() {
105: return this .trans.length;
106: }
107:
108: /**
109: * Returns the number of states visited in the path, which should
110: * always equal <tt>size() + 2</tt>, due to the start and final states,
111: * unless there are no transitions, in which case the depth is 1
112: * (there must always be a start state).
113: *
114: * @return the depth of the path.
115: */
116: public int getDepth() {
117: int size = size();
118: int depth;
119: if (size == 0) {
120: depth = 1;
121: } else {
122: depth = size + 2;
123: }
124: return depth;
125: }
126: }
|