package org.kohsuke.bali.automaton; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.sun.msv.grammar.Expression; import com.sun.msv.util.StringPair; /** * Binary tree automaton. * * @author Kohsuke Kawaguchi (kk@kohsuke.org) */ public final class TreeAutomaton { public TreeAutomaton( Map _nameCodes ) { this.nameCodes = _nameCodes; } /** All states of this binary automaton. */ private List states = new ArrayList(); /** Obtains all the states in the order of their id. */ public State[] getStates() { return (State[])states.toArray(new State[states.size()]); } private State initialState; /** Gets the initial state of this automaton. */ public State getInitialState() { return initialState; } /** Gets the number of states. */ public int countStates() { return states.size(); } /** Gets the total number of transitions. */ public int countTransitions() { int cnt=0; for (Iterator itr = states.iterator(); itr.hasNext();) { State s = (State) itr.next(); cnt += s.countTransitions(); } return cnt; } /** used to assign numbers to states. */ private int iota = 0; /** * A map from StringPair to Integer that represents * name code. */ private final Map nameCodes; /** Obtains the name code from the given name. */ public int getNameCode( String nsUri, String localName ) { return getNameCode( new StringPair(nsUri,localName) ); } /** Obtains the name code from the given name. */ public int getNameCode( StringPair name ) { Integer r; r = (Integer)nameCodes.get(name); if(r!=null) return r.intValue(); r = (Integer)nameCodes.get(new StringPair(name.namespaceURI,IMPOSSIBLE)); if(r!=null) return r.intValue(); r = (Integer)nameCodes.get(WILDCARD); if(r!=null) return r.intValue(); return -1; // this represents NaN. } /** * Obtains all the (uri,local) pairs with distinct name codes. * uri and local may be IMPOSSIBLE to represent a wildcard. */ public StringPair[] listNameCodes() { return (StringPair[]) nameCodes.keySet().toArray(new StringPair[nameCodes.size()]); } /** Creates a new state in this tree automaton and returns it. */ public State createState( Expression exp, boolean isFinal, State nextState ) { State s = new State(exp,isFinal,iota,nextState); states.add(s); if( iota == 0 ) initialState = s; iota++; return s; } /** Invalid name token value. */ public static final String IMPOSSIBLE = "\u0000"; /** Constant value that represents "*:*". */ public static final StringPair WILDCARD = new StringPair( IMPOSSIBLE, IMPOSSIBLE); }