package de.unisiegen.gtitool.core.entities;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeSet;
import javax.swing.event.EventListenerList;
import de.unisiegen.gtitool.core.entities.listener.ModifyStatusChangedListener;
import de.unisiegen.gtitool.core.entities.listener.PrettyStringChangedListener;
import de.unisiegen.gtitool.core.entities.listener.TransitionChangedListener;
import de.unisiegen.gtitool.core.exceptions.transition.TransitionException;
import de.unisiegen.gtitool.core.exceptions.transition.TransitionSymbolNotInAlphabetException;
import de.unisiegen.gtitool.core.exceptions.transition.TransitionSymbolOnlyOneTimeException;
import de.unisiegen.gtitool.core.i18n.Messages;
import de.unisiegen.gtitool.core.parser.ParserOffset;
import de.unisiegen.gtitool.core.parser.style.PrettyPrintable;
import de.unisiegen.gtitool.core.parser.style.PrettyString;
import de.unisiegen.gtitool.core.parser.style.PrettyToken;
import de.unisiegen.gtitool.core.parser.style.Style;
import de.unisiegen.gtitool.core.parser.style.PrettyString.PrettyStringMode;
import de.unisiegen.gtitool.core.storage.Attribute;
import de.unisiegen.gtitool.core.storage.Element;
import de.unisiegen.gtitool.core.storage.Modifyable;
import de.unisiegen.gtitool.core.storage.Storable;
import de.unisiegen.gtitool.core.storage.exceptions.StoreException;
/**
* The {@link DefaultTransition} entity.
*
* @author Christian Fehler
* @version $Id$
*/
public final class DefaultTransition implements Transition
{
/**
* The serial version uid.
*/
private static final long serialVersionUID = 7649068993385065572L;
/**
* This {@link DefaultTransition} is a selected {@link DefaultTransition}.
*/
private boolean selected = false;
/**
* This {@link Transition} is a active {@link Transition}.
*/
private boolean active = false;
/**
* The {@link Alphabet} of this {@link DefaultTransition}.
*/
private Alphabet alphabet = null;
/**
* This {@link Transition} is a error {@link Transition}.
*/
private boolean error = false;
/**
* The id of this {@link DefaultTransition}.
*/
private int id = ID_NOT_DEFINED;
/**
* The initial {@link Word} which is read from the {@link Stack}.
*/
private Word initialPushDownWordRead = new DefaultWord ();
/**
* The {@link Word} which should be written on the {@link Stack}.
*/
private Word initialPushDownWordWrite = new DefaultWord ();
/**
* The initial set of {@link Symbol}s.
*/
private TreeSet < Symbol > initialSymbolSet;
/**
* The {@link EventListenerList}.
*/
private EventListenerList listenerList = new EventListenerList ();
/**
* The offset of this {@link DefaultTransition} in the source code.
*
* @see #getParserOffset()
* @see #setParserOffset(ParserOffset)
*/
private ParserOffset parserOffset = NO_PARSER_OFFSET;
/**
* The push down {@link Alphabet} of this {@link DefaultTransition}.
*/
private Alphabet pushDownAlphabet;
/**
* The {@link Word} which is read from the {@link Stack}.
*/
private Word pushDownWordRead = new DefaultWord ();
/**
* The {@link Word} which should be written on the {@link Stack}.
*/
private Word pushDownWordWrite = new DefaultWord ();
/**
* The {@link State} where the {@link DefaultTransition} begins.
*/
private State stateBegin;
/**
* The {@link State} id where the {@link DefaultTransition} begins.
*/
private int stateBeginId;
/**
* The {@link State} where the {@link DefaultTransition} ends.
*/
private State stateEnd;
/**
* The {@link State} id where the {@link DefaultTransition} ends.
*/
private int stateEndId;
/**
* The set of {@link Symbol}s.
*/
private TreeSet < Symbol > symbolSet;
/**
* The cached stack {@link PrettyString}.
*/
private PrettyString cachedStackPrettyString = null;
/**
* The cached {@link PrettyString}.
*/
private PrettyString cachedPrettyString = null;
/**
* The {@link PrettyStringChangedListener}.
*/
private PrettyStringChangedListener prettyStringChangedListener;
/**
* The label rectangle.
*/
public Rectangle labelBounds = new Rectangle ();
/**
* Allocates a new {@link DefaultTransition}.
*/
public DefaultTransition ()
{
this.prettyStringChangedListener = new PrettyStringChangedListener ()
{
public void prettyStringChanged ()
{
firePrettyStringChanged ();
}
};
this.symbolSet = new TreeSet < Symbol > ();
try
{
add ( new DefaultSymbol () );
}
catch ( TransitionException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
this.initialSymbolSet = new TreeSet < Symbol > ();
this.initialSymbolSet.add ( new DefaultSymbol () );
resetModify ();
}
/**
* Allocates a new {@link DefaultTransition}.
*
* @param alphabet The {@link Alphabet} of this {@link DefaultTransition}.
* @param pushDownAlphabet The push down {@link Alphabet} of this
* {@link DefaultTransition}.
* @param pushDownWordRead The {@link Word} which is read from the
* {@link Stack}.
* @param pushDownWordWrite The {@link Word} which should be written on the
* {@link Stack}.
* @param stateBegin The {@link State} where the {@link DefaultTransition}
* begins.
* @param stateEnd The {@link State} where the {@link DefaultTransition} ends.
* @param symbols The array of {@link Symbol}s.
* @throws TransitionSymbolNotInAlphabetException If something with the
* {@link DefaultTransition} is not correct.
* @throws TransitionSymbolOnlyOneTimeException If something with the
* {@link DefaultTransition} is not correct.
*/
public DefaultTransition ( Alphabet alphabet, Alphabet pushDownAlphabet,
Word pushDownWordRead, Word pushDownWordWrite, State stateBegin,
State stateEnd, Iterable < Symbol > symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
this.prettyStringChangedListener = new PrettyStringChangedListener ()
{
public void prettyStringChanged ()
{
firePrettyStringChanged ();
}
};
this.symbolSet = new TreeSet < Symbol > ();
this.initialSymbolSet = new TreeSet < Symbol > ();
// Alphabet
setAlphabet ( alphabet );
// PushDownAlphabet
setPushDownAlphabet ( pushDownAlphabet );
// PushDownWordRead
setPushDownWordRead ( pushDownWordRead );
// PushDownWordWrite
setPushDownWordWrite ( pushDownWordWrite );
// StateBegin
setStateBegin ( stateBegin );
// StateEnd
setStateEnd ( stateEnd );
// Symbols
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
add ( symbols );
resetModify ();
}
/**
* Allocates a new {@link DefaultTransition}.
*
* @param alphabet The {@link Alphabet} of this {@link DefaultTransition}.
* @param pushDownAlphabet The push down {@link Alphabet} of this
* {@link DefaultTransition}. *
* @param pushDownWordRead The {@link Word} which is read from the
* {@link Stack}.
* @param pushDownWordWrite The {@link Word} which should be written on the
* {@link Stack}.
* @param stateBegin The {@link State} where the {@link DefaultTransition}
* begins.
* @param stateEnd The {@link State} where the {@link DefaultTransition} ends.
* @param symbols The array of {@link Symbol}s.
* @throws TransitionSymbolNotInAlphabetException If something with the
* {@link DefaultTransition} is not correct.
* @throws TransitionSymbolOnlyOneTimeException If something with the
* {@link DefaultTransition} is not correct.
*/
public DefaultTransition ( Alphabet alphabet, Alphabet pushDownAlphabet,
Word pushDownWordRead, Word pushDownWordWrite, State stateBegin,
State stateEnd, Symbol ... symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
this.prettyStringChangedListener = new PrettyStringChangedListener ()
{
public void prettyStringChanged ()
{
firePrettyStringChanged ();
}
};
this.symbolSet = new TreeSet < Symbol > ();
this.initialSymbolSet = new TreeSet < Symbol > ();
setAlphabet ( alphabet );
setPushDownAlphabet ( pushDownAlphabet );
setPushDownWordRead ( pushDownWordRead );
setPushDownWordWrite ( pushDownWordWrite );
setStateBegin ( stateBegin );
setStateEnd ( stateEnd );
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
add ( symbols );
resetModify ();
}
/**
* Allocates a new {@link DefaultTransition}.
*
* @param element The {@link Element}. *
* @throws TransitionSymbolNotInAlphabetException If something with the
* {@link DefaultTransition} is not correct.
* @throws TransitionSymbolOnlyOneTimeException If something with the
* {@link DefaultTransition} is not correct.
* @throws StoreException If the {@link Element} can not be parsed.
*/
public DefaultTransition ( Element element )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException, StoreException
{
this.prettyStringChangedListener = new PrettyStringChangedListener ()
{
public void prettyStringChanged ()
{
firePrettyStringChanged ();
}
};
// Check if the element is correct
if ( !element.getName ().equals ( "Transition" ) ) //$NON-NLS-1$
{
throw new IllegalArgumentException (
"element " + Messages.QUOTE + element.getName () //$NON-NLS-1$
+ Messages.QUOTE + " is not a transition" ); //$NON-NLS-1$
}
// Symbols
this.symbolSet = new TreeSet < Symbol > ();
this.initialSymbolSet = new TreeSet < Symbol > ();
// Attribute
boolean foundId = false;
boolean foundStateBeginId = false;
boolean foundStateEndId = false;
for ( Attribute current : element.getAttribute () )
{
if ( current.getName ().equals ( "id" ) ) //$NON-NLS-1$
{
setId ( current.getValueInt () );
foundId = true;
}
else if ( current.getName ().equals ( "stateBeginId" ) ) //$NON-NLS-1$
{
setStateBeginId ( current.getValueInt () );
foundStateBeginId = true;
}
else if ( current.getName ().equals ( "stateEndId" ) ) //$NON-NLS-1$
{
setStateEndId ( current.getValueInt () );
foundStateEndId = true;
}
else
{
throw new StoreException ( Messages
.getString ( "StoreException.AdditionalAttribute" ) ); //$NON-NLS-1$
}
}
// Not all attribute values found
if ( ( !foundId ) || ( !foundStateBeginId ) || ( !foundStateEndId ) )
{
throw new StoreException ( Messages
.getString ( "StoreException.MissingAttribute" ) ); //$NON-NLS-1$
}
// Element
boolean foundPushDownWordRead = false;
boolean foundPushDownWordWrite = false;
for ( Element current : element.getElement () )
{
if ( current.getName ().equals ( "Symbol" ) ) //$NON-NLS-1$
{
add ( new DefaultSymbol ( current ) );
}
else if ( current.getName ().equals ( "PushDownWordRead" ) ) //$NON-NLS-1$
{
current.setName ( "Word" ); //$NON-NLS-1$
setPushDownWordRead ( new DefaultWord ( current ) );
foundPushDownWordRead = true;
}
else if ( current.getName ().equals ( "PushDownWordWrite" ) ) //$NON-NLS-1$
{
current.setName ( "Word" ); //$NON-NLS-1$
setPushDownWordWrite ( new DefaultWord ( current ) );
foundPushDownWordWrite = true;
}
else
{
throw new StoreException ( Messages
.getString ( "StoreException.AdditionalElement" ) ); //$NON-NLS-1$
}
}
// Not all element values found
if ( ( !foundPushDownWordRead ) || ( !foundPushDownWordWrite ) )
{
throw new StoreException ( Messages
.getString ( "StoreException.MissingElement" ) ); //$NON-NLS-1$
}
resetModify ();
}
/**
* Allocates a new {@link DefaultTransition}.
*
* @param pushDownWordRead The {@link Word} which is read from the
* {@link Stack}.
* @param pushDownWordWrite The {@link Word} which should be written on the
* {@link Stack}.
* @param symbols The array of {@link Symbol}s.
* @throws TransitionSymbolNotInAlphabetException If something with the
* {@link DefaultTransition} is not correct.
* @throws TransitionSymbolOnlyOneTimeException If something with the
* {@link DefaultTransition} is not correct.
*/
public DefaultTransition ( Word pushDownWordRead, Word pushDownWordWrite,
Iterable < Symbol > symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
this.prettyStringChangedListener = new PrettyStringChangedListener ()
{
public void prettyStringChanged ()
{
firePrettyStringChanged ();
}
};
this.symbolSet = new TreeSet < Symbol > ();
this.initialSymbolSet = new TreeSet < Symbol > ();
setPushDownWordRead ( pushDownWordRead );
setPushDownWordWrite ( pushDownWordWrite );
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
add ( symbols );
resetModify ();
}
/**
* Allocates a new {@link DefaultTransition}.
*
* @param pushDownWordRead The {@link Word} which is read from the
* {@link Stack}.
* @param pushDownWordWrite The {@link Word} which should be written on the
* {@link Stack}.
* @param symbols The array of {@link Symbol}s.
* @throws TransitionSymbolNotInAlphabetException If something with the
* {@link DefaultTransition} is not correct.
* @throws TransitionSymbolOnlyOneTimeException If something with the
* {@link DefaultTransition} is not correct.
*/
public DefaultTransition ( Word pushDownWordRead, Word pushDownWordWrite,
Symbol ... symbols ) throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
this.prettyStringChangedListener = new PrettyStringChangedListener ()
{
public void prettyStringChanged ()
{
firePrettyStringChanged ();
}
};
this.symbolSet = new TreeSet < Symbol > ();
this.initialSymbolSet = new TreeSet < Symbol > ();
setPushDownWordRead ( pushDownWordRead );
setPushDownWordWrite ( pushDownWordWrite );
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
add ( symbols );
resetModify ();
}
/**
* {@inheritDoc}
*
* @see Transition#add(Iterable)
*/
public final void add ( Iterable < Symbol > symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
for ( Symbol current : symbols )
{
add ( current );
}
}
/**
* {@inheritDoc}
*
* @see Transition#add(Symbol)
*/
public final void add ( Symbol symbol )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
if ( ( this.alphabet != null ) && ( !symbol.isEpsilon () )
&& ( !this.alphabet.contains ( symbol ) ) )
{
ArrayList < Symbol > tmpList = new ArrayList < Symbol > ();
tmpList.add ( symbol );
throw new TransitionSymbolNotInAlphabetException ( this, this.alphabet,
tmpList );
}
if ( this.symbolSet.contains ( symbol ) )
{
ArrayList < Symbol > tmpList = new ArrayList < Symbol > ();
for ( Symbol current : this.symbolSet )
{
if ( symbol.equals ( current ) )
{
tmpList.add ( current );
break;
}
}
tmpList.add ( symbol );
throw new TransitionSymbolOnlyOneTimeException ( this, tmpList );
}
// the symbol must be cloned because of the different possible styles
if ( symbol.isEpsilon () )
{
Symbol newSymbol = new DefaultSymbol ();
newSymbol
.addPrettyStringChangedListener ( this.prettyStringChangedListener );
this.symbolSet.add ( newSymbol );
}
else
{
Symbol newSymbol = new DefaultSymbol ( symbol.getName () );
newSymbol
.addPrettyStringChangedListener ( this.prettyStringChangedListener );
this.symbolSet.add ( newSymbol );
}
fireTransitionChanged ();
fireModifyStatusChanged ();
firePrettyStringChanged ();
}
/**
* {@inheritDoc}
*
* @see Transition#add(Symbol[])
*/
public final void add ( Symbol ... symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
for ( Symbol current : symbols )
{
add ( current );
}
}
/**
* {@inheritDoc}
*
* @see Modifyable#addModifyStatusChangedListener(ModifyStatusChangedListener)
*/
public final void addModifyStatusChangedListener (
ModifyStatusChangedListener listener )
{
this.listenerList.add ( ModifyStatusChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see PrettyPrintable#addPrettyStringChangedListener(PrettyStringChangedListener)
*/
public final void addPrettyStringChangedListener (
PrettyStringChangedListener listener )
{
this.listenerList.add ( PrettyStringChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see Transition#addTransitionChangedListener(TransitionChangedListener)
*/
public final void addTransitionChangedListener (
TransitionChangedListener listener )
{
this.listenerList.add ( TransitionChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see Comparable#compareTo(Object)
*/
public final int compareTo ( Transition other )
{
return this.id < other.getId () ? -1 : ( this.id > other.getId () ? 1 : 0 );
}
/**
* {@inheritDoc}
*
* @see Transition#contains(Symbol)
*/
public final boolean contains ( Symbol symbol )
{
return this.symbolSet.contains ( symbol );
}
/**
* {@inheritDoc}
*
* @see Object#equals(Object)
*/
@Override
public final boolean equals ( Object other )
{
if ( other instanceof DefaultTransition )
{
DefaultTransition defaultTransition = ( DefaultTransition ) other;
if ( ( this.id == ID_NOT_DEFINED )
|| ( defaultTransition.id == ID_NOT_DEFINED ) )
{
throw new IllegalArgumentException ( "id is not defined" ); //$NON-NLS-1$
}
return this.id == defaultTransition.id;
}
return false;
}
/**
* Let the listeners know that the modify status has changed.
*/
private final void fireModifyStatusChanged ()
{
ModifyStatusChangedListener [] listeners = this.listenerList
.getListeners ( ModifyStatusChangedListener.class );
boolean newModifyStatus = isModified ();
for ( ModifyStatusChangedListener current : listeners )
{
current.modifyStatusChanged ( newModifyStatus );
}
}
/**
* Let the listeners know that the {@link PrettyString} has changed.
*/
protected final void firePrettyStringChanged ()
{
this.cachedPrettyString = null;
this.cachedStackPrettyString = null;
PrettyStringChangedListener [] listeners = this.listenerList
.getListeners ( PrettyStringChangedListener.class );
for ( PrettyStringChangedListener current : listeners )
{
current.prettyStringChanged ();
}
}
/**
* Let the listeners know that the {@link Transition} has changed.
*/
private final void fireTransitionChanged ()
{
TransitionChangedListener [] listeners = this.listenerList
.getListeners ( TransitionChangedListener.class );
for ( TransitionChangedListener current : listeners )
{
current.transitionChanged ( this );
}
}
/**
* {@inheritDoc}
*
* @see Transition#getAlphabet()
*/
public final Alphabet getAlphabet ()
{
return this.alphabet;
}
/**
* {@inheritDoc}
*
* @see Storable#getElement()
*/
public final Element getElement ()
{
Element newElement = new Element ( "Transition" ); //$NON-NLS-1$
newElement.addAttribute ( new Attribute ( "id", this.id ) ); //$NON-NLS-1$
newElement.addAttribute ( new Attribute ( "stateBeginId", //$NON-NLS-1$
getStateBeginId () ) );
newElement.addAttribute ( new Attribute ( "stateEndId", getStateEndId () ) ); //$NON-NLS-1$
Element pushDownWordReadElement = this.pushDownWordRead.getElement ();
pushDownWordReadElement.setName ( "PushDownWordRead" ); //$NON-NLS-1$
newElement.addElement ( pushDownWordReadElement );
Element pushDownWordWriteElement = this.pushDownWordWrite.getElement ();
pushDownWordWriteElement.setName ( "PushDownWordWrite" ); //$NON-NLS-1$
newElement.addElement ( pushDownWordWriteElement );
for ( Symbol current : this.symbolSet )
{
newElement.addElement ( current );
}
return newElement;
}
/**
* {@inheritDoc}
*
* @see Transition#getId()
*/
public final int getId ()
{
return this.id;
}
/**
* {@inheritDoc}
*
* @see Transition#getLabelBounds()
*/
public final Rectangle getLabelBounds ()
{
return this.labelBounds;
}
/**
* {@inheritDoc}
*
* @see Entity#getParserOffset()
*/
public final ParserOffset getParserOffset ()
{
return this.parserOffset;
}
/**
* {@inheritDoc}
*
* @see Transition#getPushDownAlphabet()
*/
public final Alphabet getPushDownAlphabet ()
{
return this.pushDownAlphabet;
}
/**
* {@inheritDoc}
*
* @see Transition#getPushDownWordRead()
*/
public final Word getPushDownWordRead ()
{
return this.pushDownWordRead;
}
/**
* {@inheritDoc}
*
* @see Transition#getPushDownWordWrite()
*/
public final Word getPushDownWordWrite ()
{
return this.pushDownWordWrite;
}
/**
* {@inheritDoc}
*
* @see Transition#getStateBegin()
*/
public final State getStateBegin ()
{
return this.stateBegin;
}
/**
* {@inheritDoc}
*
* @see Transition#getStateBeginId()
*/
public final int getStateBeginId ()
{
return this.stateBegin == null ? this.stateBeginId : this.stateBegin
.getId ();
}
/**
* {@inheritDoc}
*
* @see Transition#getStateEnd()
*/
public final State getStateEnd ()
{
return this.stateEnd;
}
/**
* {@inheritDoc}
*
* @see Transition#getStateEndId()
*/
public final int getStateEndId ()
{
return this.stateEnd == null ? this.stateEndId : this.stateEnd.getId ();
}
/**
* {@inheritDoc}
*
* @see Transition#getSymbol()
*/
public final TreeSet < Symbol > getSymbol ()
{
return this.symbolSet;
}
/**
* {@inheritDoc}
*
* @see Transition#getSymbol(int)
*/
public final Symbol getSymbol ( int index )
{
Iterator < Symbol > iterator = this.symbolSet.iterator ();
for ( int i = 0 ; i < index ; i++ )
{
iterator.next ();
}
return iterator.next ();
}
/**
* {@inheritDoc}
*
* @see Transition#getTransitionType()
*/
public final TransitionType getTransitionType ()
{
if ( ( this.symbolSet.size () == 1 )
&& this.symbolSet.first ().isEpsilon () )
{
return TransitionType.EPSILON_ONLY;
}
if ( this.symbolSet.size () >= 1 )
{
boolean epsilonFound = false;
for ( Symbol current : this.symbolSet )
{
if ( current.isEpsilon () )
{
epsilonFound = true;
break;
}
}
if ( epsilonFound )
{
return TransitionType.EPSILON_SYMBOL;
}
return TransitionType.SYMBOL;
}
throw new IllegalArgumentException ( "unknown transition type: " //$NON-NLS-1$
+ this.symbolSet );
}
/**
* {@inheritDoc}
*
* @see Object#hashCode()
*/
@Override
public final int hashCode ()
{
if ( this.id == ID_NOT_DEFINED )
{
throw new IllegalArgumentException ( "id is not defined" ); //$NON-NLS-1$
}
return this.id;
}
/**
* {@inheritDoc}
*
* @see Transition#isActive()
*/
public final boolean isActive ()
{
return this.active;
}
/**
* {@inheritDoc}
*
* @see Transition#isError()
*/
public final boolean isError ()
{
return this.error;
}
/**
* {@inheritDoc}
*
* @see Transition#isIdDefined()
*/
public final boolean isIdDefined ()
{
return this.id != ID_NOT_DEFINED;
}
/**
* {@inheritDoc}
*
* @see Modifyable#isModified()
*/
public final boolean isModified ()
{
return ( ( !this.symbolSet.equals ( this.initialSymbolSet ) )
|| ( !this.pushDownWordRead.equals ( this.initialPushDownWordRead ) ) || ( !this.pushDownWordWrite
.equals ( this.initialPushDownWordWrite ) ) );
}
/**
* {@inheritDoc}
*
* @see Transition#isSelected()
*/
public final boolean isSelected ()
{
return this.selected;
}
/**
* {@inheritDoc}
*
* @see Iterable#iterator()
*/
public final Iterator < Symbol > iterator ()
{
return this.symbolSet.iterator ();
}
/**
* {@inheritDoc}
*
* @see Transition#remove(Iterable)
*/
public final void remove ( Iterable < Symbol > symbols )
{
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
for ( Symbol current : symbols )
{
remove ( current );
}
}
/**
* {@inheritDoc}
*
* @see Transition#remove(Symbol)
*/
public final void remove ( Symbol symbol )
{
if ( !this.symbolSet.contains ( symbol ) )
{
throw new IllegalArgumentException ( "symbol is not in this transition" ); //$NON-NLS-1$
}
symbol
.removePrettyStringChangedListener ( this.prettyStringChangedListener );
this.symbolSet.remove ( symbol );
fireTransitionChanged ();
fireModifyStatusChanged ();
firePrettyStringChanged ();
}
/**
* {@inheritDoc}
*
* @see Transition#remove(Symbol[])
*/
public final void remove ( Symbol ... symbols )
{
if ( symbols == null )
{
throw new NullPointerException ( "symbols is null" ); //$NON-NLS-1$
}
for ( Symbol current : symbols )
{
remove ( current );
}
}
/**
* {@inheritDoc}
*
* @see Modifyable#removeModifyStatusChangedListener(ModifyStatusChangedListener)
*/
public final void removeModifyStatusChangedListener (
ModifyStatusChangedListener listener )
{
this.listenerList.remove ( ModifyStatusChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see PrettyPrintable#removePrettyStringChangedListener(PrettyStringChangedListener)
*/
public final void removePrettyStringChangedListener (
PrettyStringChangedListener listener )
{
this.listenerList.remove ( PrettyStringChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see Transition#removeTransitionChangedListener(TransitionChangedListener)
*/
public final void removeTransitionChangedListener (
TransitionChangedListener listener )
{
this.listenerList.remove ( TransitionChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see Transition#replace(Iterable)
*/
public void replace ( Iterable < Symbol > symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
for ( Symbol current : this.symbolSet )
{
current
.removePrettyStringChangedListener ( this.prettyStringChangedListener );
}
this.symbolSet.clear ();
add ( symbols );
}
/**
* {@inheritDoc}
*
* @see Transition#replace(Symbol)
*/
public void replace ( Symbol symbol )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
for ( Symbol current : this.symbolSet )
{
current
.removePrettyStringChangedListener ( this.prettyStringChangedListener );
}
this.symbolSet.clear ();
add ( symbol );
}
/**
* {@inheritDoc}
*
* @see Transition#replace(Symbol[])
*/
public void replace ( Symbol ... symbols )
throws TransitionSymbolNotInAlphabetException,
TransitionSymbolOnlyOneTimeException
{
for ( Symbol current : this.symbolSet )
{
current
.removePrettyStringChangedListener ( this.prettyStringChangedListener );
}
this.symbolSet.clear ();
add ( symbols );
}
/**
* {@inheritDoc}
*
* @see Modifyable#resetModify()
*/
public final void resetModify ()
{
this.initialSymbolSet.clear ();
this.initialSymbolSet.addAll ( this.symbolSet );
this.initialPushDownWordRead = new DefaultWord ();
this.initialPushDownWordRead.add ( this.pushDownWordRead );
this.initialPushDownWordWrite = new DefaultWord ();
this.initialPushDownWordWrite.add ( this.pushDownWordWrite );
}
/**
* {@inheritDoc}
*
* @see Transition#setActive(boolean)
*/
public final void setActive ( boolean active )
{
if ( this.active != active )
{
this.active = active;
firePrettyStringChanged ();
}
}
/**
* {@inheritDoc}
*
* @see Transition#setAlphabet(Alphabet)
*/
public final void setAlphabet ( Alphabet alphabet )
{
if ( alphabet == null )
{
throw new NullPointerException ( "alphabet is null" ); //$NON-NLS-1$
}
if ( this.alphabet != null )
{
throw new IllegalArgumentException ( "alphabet is already set" ); //$NON-NLS-1$
}
this.alphabet = alphabet;
}
/**
* {@inheritDoc}
*
* @see Transition#setError(boolean)
*/
public final void setError ( boolean error )
{
if ( this.error != error )
{
this.error = error;
firePrettyStringChanged ();
}
}
/**
* {@inheritDoc}
*
* @see Transition#setId(int)
*/
public final void setId ( int id )
{
if ( this.id != ID_NOT_DEFINED )
{
throw new IllegalArgumentException ( "id is already setted" ); //$NON-NLS-1$
}
this.id = id;
}
/**
* {@inheritDoc}
*
* @see Transition#setLabelBounds(Rectangle)
*/
public final void setLabelBounds ( Rectangle labelBounds )
{
this.labelBounds = labelBounds;
}
/**
* {@inheritDoc}
*
* @see Entity#setParserOffset(de.unisiegen.gtitool.core.parser.ParserOffset)
*/
public final void setParserOffset ( ParserOffset parserOffset )
{
this.parserOffset = parserOffset;
}
/**
* {@inheritDoc}
*
* @see Transition#setPushDownAlphabet(Alphabet)
*/
public final void setPushDownAlphabet ( Alphabet pushDownAlphabet )
{
if ( pushDownAlphabet == null )
{
throw new NullPointerException ( "push down alphabet is null" ); //$NON-NLS-1$
}
this.pushDownAlphabet = pushDownAlphabet;
}
/**
* {@inheritDoc}
*
* @see Transition#setPushDownWordRead(Word)
*/
public final void setPushDownWordRead ( Word pushDownWordRead )
{
if ( pushDownWordRead == null )
{
throw new NullPointerException ( "push down word read is null" ); //$NON-NLS-1$
}
if ( this.pushDownWordRead == null )
{
pushDownWordRead
.addPrettyStringChangedListener ( this.prettyStringChangedListener );
this.pushDownWordRead = pushDownWordRead;
fireModifyStatusChanged ();
firePrettyStringChanged ();
return;
}
if ( !this.pushDownWordRead.equals ( pushDownWordRead ) )
{
this.pushDownWordRead
.removePrettyStringChangedListener ( this.prettyStringChangedListener );
pushDownWordRead
.addPrettyStringChangedListener ( this.prettyStringChangedListener );
this.pushDownWordRead = pushDownWordRead;
fireModifyStatusChanged ();
firePrettyStringChanged ();
}
}
/**
* {@inheritDoc}
*
* @see Transition#setPushDownWordWrite(Word)
*/
public final void setPushDownWordWrite ( Word pushDownWordWrite )
{
if ( pushDownWordWrite == null )
{
throw new NullPointerException ( "push down word write is null" ); //$NON-NLS-1$
}
if ( this.pushDownWordWrite == null )
{
pushDownWordWrite
.addPrettyStringChangedListener ( this.prettyStringChangedListener );
this.pushDownWordWrite = pushDownWordWrite;
fireModifyStatusChanged ();
firePrettyStringChanged ();
return;
}
if ( !this.pushDownWordWrite.equals ( pushDownWordWrite ) )
{
this.pushDownWordWrite
.removePrettyStringChangedListener ( this.prettyStringChangedListener );
pushDownWordWrite
.addPrettyStringChangedListener ( this.prettyStringChangedListener );
this.pushDownWordWrite = pushDownWordWrite;
fireModifyStatusChanged ();
firePrettyStringChanged ();
}
}
/**
* {@inheritDoc}
*
* @see Transition#setSelected(boolean)
*/
public final void setSelected ( boolean selected )
{
if ( this.selected != selected )
{
this.selected = selected;
firePrettyStringChanged ();
}
}
/**
* {@inheritDoc}
*
* @see Transition#setStateBegin(State)
*/
public final void setStateBegin ( State stateBegin )
{
if ( stateBegin == null )
{
throw new NullPointerException ( "state begin is null" ); //$NON-NLS-1$
}
this.stateBegin = stateBegin;
}
/**
* Sets the {@link State} id where the {@link DefaultTransition} begins.
*
* @param stateBeginId The {@link State} id to set.
*/
private final void setStateBeginId ( int stateBeginId )
{
if ( this.stateBegin != null )
{
throw new IllegalArgumentException (
"can not set the id if there is a state" ); //$NON-NLS-1$
}
this.stateBeginId = stateBeginId;
}
/**
* {@inheritDoc}
*
* @see Transition#setStateEnd(State)
*/
public final void setStateEnd ( State stateEnd )
{
if ( stateEnd == null )
{
throw new NullPointerException ( "state end is null" ); //$NON-NLS-1$
}
this.stateEnd = stateEnd;
}
/**
* Sets the {@link State} id where the {@link DefaultTransition} ends.
*
* @param stateEndId The {@link State} id to set.
*/
private final void setStateEndId ( int stateEndId )
{
if ( this.stateEnd != null )
{
throw new IllegalArgumentException (
"can not set the id if there is a state" ); //$NON-NLS-1$
}
this.stateEndId = stateEndId;
}
/**
* {@inheritDoc}
*
* @see Transition#size()
*/
public final int size ()
{
return this.symbolSet.size ();
}
/**
* {@inheritDoc}
*
* @see PrettyPrintable#toPrettyString()
*/
public final PrettyString toPrettyString ()
{
if ( this.symbolSet.size () == 0 )
{
throw new RuntimeException ( "symbol set is empty" ); //$NON-NLS-1$
}
if ( ( this.cachedPrettyString == null )
|| PrettyString.MODE.equals ( PrettyStringMode.CACHING_OFF ) )
{
this.cachedPrettyString = new PrettyString ();
this.cachedPrettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
ArrayList < Symbol > t = new ArrayList < Symbol > ();
t.addAll ( getSymbol () );
while ( !t.isEmpty () )
{
ArrayList < Symbol > a = DefaultRegexAlphabet.checkForClass ( t );
if ( !first )
{
this.cachedPrettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
if ( a.size () == 1 )
{
this.cachedPrettyString.add ( a.get ( 0 ) );
}
else if ( a.size () == 2 )
{
this.cachedPrettyString.add ( a.get ( 0 ) );
this.cachedPrettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
this.cachedPrettyString.add ( a.get ( 1 ) );
}
else
{
ArrayList < Symbol > activeSymbols = new ArrayList < Symbol > ();
for ( Symbol s : a )
{
if ( s.isActive () )
{
if ( !s.equals ( a.get ( 0 ) )
|| !s.equals ( a.get ( a.size () - 1 ) ) )
{
activeSymbols.add ( s );
}
}
}
this.cachedPrettyString.add ( a.get ( 0 ) );
if ( activeSymbols.isEmpty () )
{
this.cachedPrettyString.add ( new PrettyToken ( "..", Style.NONE ) ); //$NON-NLS-1$
}
else
{
int lastIndex = 0;
for ( Symbol s : activeSymbols )
{
int index = a.indexOf ( s );
int diff = index - lastIndex;
if ( diff == 1 )
{
this.cachedPrettyString.add ( new PrettyToken (
", ", Style.NONE ) ); //$NON-NLS-1$
this.cachedPrettyString.add ( s );
}
else if ( diff > 1 )
{
this.cachedPrettyString.add ( new PrettyToken (
"..", Style.NONE ) ); //$NON-NLS-1$
this.cachedPrettyString.add ( s );
}
lastIndex = index;
if ( activeSymbols.indexOf ( s ) == activeSymbols.size () - 1 )
{
if ( index == a.size () - 2 )
{
this.cachedPrettyString.add ( new PrettyToken (
", ", Style.NONE ) ); //$NON-NLS-1$
}
else
{
this.cachedPrettyString.add ( new PrettyToken (
"..", Style.NONE ) ); //$NON-NLS-1$
}
}
}
}
this.cachedPrettyString.add ( a.get ( a.size () - 1 ) );
}
t.removeAll ( a );
}
this.cachedPrettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
if ( ( this.pushDownWordRead.size () > 0 )
|| ( this.pushDownWordWrite.size () > 0 ) )
{
this.cachedPrettyString.add ( new PrettyToken ( " ", Style.NONE ) ); //$NON-NLS-1$
if ( this.pushDownWordRead.size () == 0 )
{
this.cachedPrettyString.add ( new PrettyToken (
"\u03B5", Style.SYMBOL ) ); //$NON-NLS-1$
}
else
{
this.cachedPrettyString.add ( this.pushDownWordRead );
}
this.cachedPrettyString
.add ( new PrettyToken ( "\u2191", Style.KEYWORD ) ); //$NON-NLS-1$
this.cachedPrettyString.add ( new PrettyToken ( " ", Style.NONE ) ); //$NON-NLS-1$
if ( this.pushDownWordWrite.size () == 0 )
{
this.cachedPrettyString.add ( new PrettyToken (
"\u03B5", Style.SYMBOL ) ); //$NON-NLS-1$
}
else
{
this.cachedPrettyString.add ( this.pushDownWordWrite );
}
this.cachedPrettyString
.add ( new PrettyToken ( "\u2193", Style.KEYWORD ) ); //$NON-NLS-1$
}
}
return this.cachedPrettyString;
}
/**
* {@inheritDoc}
*
* @see Transition#toStackOperationPrettyString()
*/
public final PrettyString toStackOperationPrettyString ()
{
if ( this.symbolSet.size () == 0 )
{
throw new RuntimeException ( "symbol set is empty" ); //$NON-NLS-1$
}
if ( ( this.cachedStackPrettyString == null )
|| PrettyString.MODE.equals ( PrettyStringMode.CACHING_OFF ) )
{
// does not use the active style of symbols
this.cachedStackPrettyString = new PrettyString ();
this.cachedStackPrettyString.add ( new PrettyToken ( "(", Style.NONE ) ); //$NON-NLS-1$
this.cachedStackPrettyString.add ( this.stateBegin );
this.cachedStackPrettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
this.cachedStackPrettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( Symbol current : this.symbolSet )
{
if ( !first )
{
this.cachedStackPrettyString
.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
if ( current.isEpsilon () )
{
this.cachedStackPrettyString.add ( new PrettyToken ( "\u03B5", //$NON-NLS-1$
Style.SYMBOL ) );
}
else
{
this.cachedStackPrettyString.add ( new PrettyToken ( current
.getName (), Style.SYMBOL ) );
}
}
this.cachedStackPrettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
this.cachedStackPrettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
if ( getPushDownWordRead ().size () == 0 )
{
this.cachedStackPrettyString.add ( new PrettyToken (
"\u03B5", Style.SYMBOL ) ); //$NON-NLS-1$
}
else
{
this.cachedStackPrettyString.add ( this.pushDownWordRead );
}
this.cachedStackPrettyString
.add ( new PrettyToken ( "), (", Style.NONE ) ); //$NON-NLS-1$
this.cachedStackPrettyString.add ( this.stateEnd );
this.cachedStackPrettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
if ( getPushDownWordWrite ().size () == 0 )
{
this.cachedStackPrettyString.add ( new PrettyToken (
"\u03B5", Style.SYMBOL ) ); //$NON-NLS-1$
}
else
{
this.cachedStackPrettyString.add ( this.pushDownWordWrite );
}
this.cachedStackPrettyString.add ( new PrettyToken ( ")", Style.NONE ) ); //$NON-NLS-1$
if ( this.selected )
{
this.cachedStackPrettyString
.setOverwrittenColor ( Style.TRANSITION_SELECTED );
}
else
{
this.cachedStackPrettyString.setOverwrittenColor ( null );
}
}
return this.cachedStackPrettyString;
}
/**
* {@inheritDoc}
*
* @see Entity#toString()
*/
@Override
public final String toString ()
{
if ( this.symbolSet.size () == 0 )
{
// used from the parser
return "";//$NON-NLS-1$
}
StringBuilder result = new StringBuilder ();
result.append ( "{" ); //$NON-NLS-1$
boolean first = true;
ArrayList < Symbol > t = new ArrayList < Symbol > ();
t.addAll ( getSymbol () );
while ( !t.isEmpty () )
{
ArrayList < Symbol > a = DefaultRegexAlphabet.checkForClass ( t );
if ( !first )
{
result.append ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
if ( a.size () == 1 )
{
result.append ( a.get ( 0 ) );
}
else if ( a.size () == 2 )
{
result.append ( a.get ( 0 ) );
result.append ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
result.append ( a.get ( 1 ) );
}
else
{
result.append ( new PrettyToken ( "[", Style.SYMBOL ) ); //$NON-NLS-1$
result.append ( a.get ( 0 ) );
result.append ( new PrettyToken ( "-", Style.NONE ) ); //$NON-NLS-1$
result.append ( a.get ( a.size () - 1 ) );
result.append ( new PrettyToken ( "]", Style.SYMBOL ) ); //$NON-NLS-1$
}
t.removeAll ( a );
}
result.append ( "}" ); //$NON-NLS-1$
if ( ( this.pushDownWordRead.size () > 0 )
|| ( this.pushDownWordWrite.size () > 0 ) )
{
result.append ( " " ); //$NON-NLS-1$
if ( this.pushDownWordRead.size () == 0 )
{
result.append ( "\u03B5" ); //$NON-NLS-1$
}
else
{
result.append ( this.pushDownWordRead );
}
result.append ( "\u2191 " ); //$NON-NLS-1$
if ( this.pushDownWordWrite.size () == 0 )
{
result.append ( "\u03B5" ); //$NON-NLS-1$
}
else
{
result.append ( this.pushDownWordWrite );
}
result.append ( "\u2193" ); //$NON-NLS-1$
}
return result.toString ();
}
}