package de.unisiegen.gtitool.ui.logic;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import org.jgraph.graph.DefaultGraphModel;
import de.unisiegen.gtitool.core.entities.DefaultRegexAlphabet;
import de.unisiegen.gtitool.core.entities.DefaultState;
import de.unisiegen.gtitool.core.entities.DefaultSymbol;
import de.unisiegen.gtitool.core.entities.DefaultTransition;
import de.unisiegen.gtitool.core.entities.DefaultWord;
import de.unisiegen.gtitool.core.entities.State;
import de.unisiegen.gtitool.core.entities.Symbol;
import de.unisiegen.gtitool.core.entities.Transition;
import de.unisiegen.gtitool.core.entities.InputEntity.EntityType;
import de.unisiegen.gtitool.core.entities.regex.ConcatenationNode;
import de.unisiegen.gtitool.core.entities.regex.DisjunctionNode;
import de.unisiegen.gtitool.core.entities.regex.EpsilonNode;
import de.unisiegen.gtitool.core.entities.regex.KleeneNode;
import de.unisiegen.gtitool.core.entities.regex.OneChildNode;
import de.unisiegen.gtitool.core.entities.regex.Regex;
import de.unisiegen.gtitool.core.entities.regex.RegexNode;
import de.unisiegen.gtitool.core.entities.regex.TokenNode;
import de.unisiegen.gtitool.core.entities.regex.TwoChildNode;
import de.unisiegen.gtitool.core.entities.regex.UnfinishedNode;
import de.unisiegen.gtitool.core.exceptions.alphabet.AlphabetException;
import de.unisiegen.gtitool.core.exceptions.state.StateException;
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.machines.Machine;
import de.unisiegen.gtitool.core.machines.Machine.MachineType;
import de.unisiegen.gtitool.core.machines.dfa.DFA;
import de.unisiegen.gtitool.core.machines.dfa.DefaultDFA;
import de.unisiegen.gtitool.core.machines.enfa.ENFA;
import de.unisiegen.gtitool.core.machines.nfa.DefaultNFA;
import de.unisiegen.gtitool.core.machines.nfa.NFA;
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.regex.DefaultRegex;
import de.unisiegen.gtitool.core.regex.DefaultRegex.RegexType;
import de.unisiegen.gtitool.core.storage.exceptions.StoreException;
import de.unisiegen.gtitool.core.util.ObjectPair;
import de.unisiegen.gtitool.core.util.Util;
import de.unisiegen.gtitool.logger.Logger;
import de.unisiegen.gtitool.ui.convert.Converter;
import de.unisiegen.gtitool.ui.i18n.Messages;
import de.unisiegen.gtitool.ui.jgraph.DefaultStateView;
import de.unisiegen.gtitool.ui.jgraph.DefaultTransitionView;
import de.unisiegen.gtitool.ui.jgraph.JGTIGraph;
import de.unisiegen.gtitool.ui.jgraph.StateView;
import de.unisiegen.gtitool.ui.logic.interfaces.LogicClass;
import de.unisiegen.gtitool.ui.model.ConvertMachineTableColumnModel;
import de.unisiegen.gtitool.ui.model.ConvertMachineTableModel;
import de.unisiegen.gtitool.ui.model.DefaultMachineModel;
import de.unisiegen.gtitool.ui.model.DefaultRegexModel;
import de.unisiegen.gtitool.ui.netbeans.ConvertMachineDialogForm;
import de.unisiegen.gtitool.ui.preferences.PreferenceManager;
import de.unisiegen.gtitool.ui.utils.LayoutManager;
import de.unisiegen.gtitool.ui.utils.PowerSet;
import de.unisiegen.gtitool.ui.utils.TextLoader;
/**
* The {@link ConvertMachineDialog}.
*
* @author Christian Fehler
* @version $Id$
*/
public final class ConvertMachineDialog implements
LogicClass < ConvertMachineDialogForm >, Converter
{
/**
* Does the next step after a delay.
*
* @author Christian Fehler
*/
protected final class AutoStepTimerTask extends TimerTask
{
/**
* {@inheritDoc}
*
* @see TimerTask#run()
*/
@Override
public final void run ()
{
SwingUtilities.invokeLater ( new Runnable ()
{
public void run ()
{
if ( ConvertMachineDialog.this.endReached )
{
handleStop ();
}
else
{
performNextStep ( true );
}
}
} );
}
}
/**
* The convert {@link Machine} type enum.
*
* @author Christian Fehler
*/
public enum ConvertMachineType
{
/**
* The {@link DFA} to {@link Regex} conversion type.
*/
DFA_TO_REGEX,
/**
* The {@link ENFA} to {@link DFA} conversion type.
*/
ENFA_TO_DFA,
/**
* The {@link ENFA} to {@link DFA} complete conversion type.
*/
ENFA_TO_DFA_COMPLETE,
/**
* The {@link ENFA} to {@link NFA} conversion type.
*/
ENFA_TO_NFA,
/**
* The {@link ENFA} to {@link NFA} complete conversion type.
*/
ENFA_TO_NFA_COMPLETE,
/**
* The {@link ENFA} to {@link NFA} cb-version conversion type.
*/
ENFA_TO_NFA_CB,
/**
* The {@link ENFA} to {@link NFA} cb-version complete conversion type.
*/
ENFA_TO_NFA_COMPLETE_CB,
/**
* The {@link NFA} to {@link DFA} conversion type.
*/
NFA_TO_DFA,
/**
* The {@link NFA} to {@link DFA} complete conversion type.
*/
NFA_TO_DFA_COMPLETE;
}
/**
* The {@link Position}.
*
* @author Christian Fehler
*/
private class Position
{
/**
* The x position.
*/
private double x;
/**
* The y position.
*/
private double y;
/**
* Allocates a new {@link Position}.
*
* @param x The x position.
* @param y The y position.
*/
public Position ( double x, double y )
{
this.x = x;
this.y = y;
}
/**
* Returns the x position.
*
* @return The x position.
* @see #x
*/
public final double getX ()
{
return this.x;
}
/**
* Returns the y position.
*
* @return The y position.
* @see #y
*/
public final double getY ()
{
return this.y;
}
/**
* {@inheritDoc}
*
* @see Object#toString()
*/
@Override
public final String toString ()
{
return "x: " + this.x + ", y: " + this.y; //$NON-NLS-1$//$NON-NLS-2$
}
}
/**
* The {@link Step} enum.
*
* @author Christian Fehler
*/
private enum Step
{
/**
* The activate new closure {@link State}s step.
*/
ACTIVATE_NEW_CLOSURE_STATES,
/**
* The activate new {@link State}s step.
*/
ACTIVATE_NEW_STATES,
/**
* The activate old closure {@link State} step.
*/
ACTIVATE_OLD_CLOSURE_STATE,
/**
* The activate old {@link State} step.
*/
ACTIVATE_OLD_STATE,
/**
* The activate start closure {@link State} step.
*/
ACTIVATE_START_CLOSURE_STATE,
/**
* The activate start {@link State} step.
*/
ACTIVATE_START_STATE,
/**
* The activate {@link Symbol}s step.
*/
ACTIVATE_SYMBOLS,
/**
* The add start {@link State} step.
*/
ADD_START_STATE,
/**
* The add {@link State} and {@link Transition} step.
*/
ADD_STATE_AND_TRANSITION,
/**
* The calculate new language step
*/
CALCULATE_NEW_LANGUAGE,
/**
* The finish step.
*/
FINISH;
/**
* {@inheritDoc}
*
* @see Enum#toString()
*/
@Override
public final String toString ()
{
switch ( this )
{
case ACTIVATE_START_STATE :
{
return "activate start state"; //$NON-NLS-1$
}
case ACTIVATE_START_CLOSURE_STATE :
{
return "activate start closure state"; //$NON-NLS-1$
}
case ADD_START_STATE :
{
return "add start state"; //$NON-NLS-1$
}
case ACTIVATE_OLD_STATE :
{
return "activate old state"; //$NON-NLS-1$
}
case ACTIVATE_OLD_CLOSURE_STATE :
{
return "activate old closure state"; //$NON-NLS-1$
}
case ACTIVATE_SYMBOLS :
{
return "activate symbols"; //$NON-NLS-1$
}
case ACTIVATE_NEW_STATES :
{
return "activate new states"; //$NON-NLS-1$
}
case ACTIVATE_NEW_CLOSURE_STATES :
{
return "activate new closure states"; //$NON-NLS-1$
}
case ADD_STATE_AND_TRANSITION :
{
return "add state and transition"; //$NON-NLS-1$
}
case FINISH :
{
return "finish"; //$NON-NLS-1$
}
case CALCULATE_NEW_LANGUAGE :
{
return "calculate new language"; //$NON-NLS-1$
}
}
throw new RuntimeException ( "unsupported step" );//$NON-NLS-1$
}
}
/**
* The {@link StepItem}.
*
* @author Christian Fehler
*/
private class StepItem
{
/**
* The current active {@link State}.
*/
private State activeState;
/**
* The active {@link State}s of the converted {@link JGTIGraph}.
*/
private ArrayList < State > activeStatesConverted;
/**
* The active {@link State}s of the original {@link JGTIGraph}.
*/
private ArrayList < State > activeStatesOriginal;
/**
* The active {@link Step}.
*/
private Step activeStep;
/**
* The current active {@link Symbol}.
*/
private Symbol activeSymbol;
/**
* The active {@link Symbol}s of the converted {@link JGTIGraph}.
*/
private ArrayList < Symbol > activeSymbolsConverted;
/**
* The active {@link Symbol}s of the original {@link JGTIGraph}.
*/
private ArrayList < Symbol > activeSymbolsOriginal;
/**
* The active {@link Transition}s of the converted {@link JGTIGraph}.
*/
private ArrayList < Transition > activeTransitionsConverted;
/**
* The active {@link Transition}s of the original {@link JGTIGraph}.
*/
private ArrayList < Transition > activeTransitionsOriginal;
/**
* The actual {@link RegexNode}
*/
private RegexNode actualRegex = null;
/**
* The added {@link DefaultStateView}.
*/
private DefaultStateView addedDefaultStateView = null;
/**
* The added {@link DefaultTransitionView}.
*/
private DefaultTransitionView addedDefaultTransitionView = null;
/**
* The added {@link Symbol}.
*/
private ObjectPair < Transition, Symbol > addedSymbol = null;
/**
* The last finals index
*/
private int lastFinalsIndex = 0;
/**
* Allocates a new {@link StepItem}.
*
* @param activeStep The active {@link Step}.
* @param currentActiveSymbol The current active {@link Symbol}.
* @param currentActiveState The current active {@link State}.
* @param activeStatesOriginal The active {@link State}s of the original
* {@link JGTIGraph}.
* @param activeStatesConverted The active {@link State}s of the converted
* {@link JGTIGraph}.
* @param activeTransitionsOriginal The active {@link Transition}s of the
* original {@link JGTIGraph}.
* @param activeTransitionsConverted The active {@link Transition}s of the
* converted {@link JGTIGraph}.
* @param activeSymbolsOriginal The active {@link Symbol}s of the original
* {@link JGTIGraph}.
* @param activeSymbolsConverted The active {@link Symbol}s of the converted
* {@link JGTIGraph}.
* @param actualRegex The actual {@link RegexNode}
* @param finalsIndex The last finals index
*/
public StepItem ( Step activeStep, Symbol currentActiveSymbol,
State currentActiveState, ArrayList < State > activeStatesOriginal,
ArrayList < State > activeStatesConverted,
ArrayList < Transition > activeTransitionsOriginal,
ArrayList < Transition > activeTransitionsConverted,
ArrayList < Symbol > activeSymbolsOriginal,
ArrayList < Symbol > activeSymbolsConverted, RegexNode actualRegex,
int finalsIndex )
{
/**
* if ( activeStep == null ) { throw new IllegalArgumentException (
* "active step is null" ); //$NON-NLS-1$ } if ( currentActiveSymbol ==
* null ) { throw new IllegalArgumentException ( "active symbol is null"
* ); //$NON-NLS-1$ }
**/
this.activeStep = activeStep;
this.activeSymbol = currentActiveSymbol;
this.activeState = currentActiveState;
this.activeStatesOriginal = activeStatesOriginal;
this.activeStatesConverted = activeStatesConverted;
this.activeTransitionsOriginal = activeTransitionsOriginal;
this.activeTransitionsConverted = activeTransitionsConverted;
this.activeSymbolsOriginal = activeSymbolsOriginal;
this.activeSymbolsConverted = activeSymbolsConverted;
this.actualRegex = actualRegex;
this.lastFinalsIndex = finalsIndex;
}
/**
* Returns the activeState.
*
* @return The activeState.
* @see #activeState
*/
public final State getActiveState ()
{
return this.activeState;
}
/**
* Returns the activeStatesConverted.
*
* @return The activeStatesConverted.
* @see #activeStatesConverted
*/
public final ArrayList < State > getActiveStatesConverted ()
{
return this.activeStatesConverted;
}
/**
* Returns the activeStatesOriginal.
*
* @return The activeStatesOriginal.
* @see #activeStatesOriginal
*/
public final ArrayList < State > getActiveStatesOriginal ()
{
return this.activeStatesOriginal;
}
/**
* Returns the activeStep.
*
* @return The activeStep.
* @see #activeStep
*/
public final Step getActiveStep ()
{
return this.activeStep;
}
/**
* Returns the activeSymbol.
*
* @return The activeSymbol.
* @see #activeSymbol
*/
public final Symbol getActiveSymbol ()
{
return this.activeSymbol;
}
/**
* Returns the activeSymbolsConverted.
*
* @return The activeSymbolsConverted.
* @see #activeSymbolsConverted
*/
public final ArrayList < Symbol > getActiveSymbolsConverted ()
{
return this.activeSymbolsConverted;
}
/**
* Returns the activeSymbolsOriginal.
*
* @return The activeSymbolsOriginal.
* @see #activeSymbolsOriginal
*/
public final ArrayList < Symbol > getActiveSymbolsOriginal ()
{
return this.activeSymbolsOriginal;
}
/**
* Returns the activeTransitionsConverted.
*
* @return The activeTransitionsConverted.
* @see #activeTransitionsConverted
*/
public final ArrayList < Transition > getActiveTransitionsConverted ()
{
return this.activeTransitionsConverted;
}
/**
* Returns the activeTransitionsOriginal.
*
* @return The activeTransitionsOriginal.
* @see #activeTransitionsOriginal
*/
public final ArrayList < Transition > getActiveTransitionsOriginal ()
{
return this.activeTransitionsOriginal;
}
/**
* Returns the actualRegex.
*
* @return The actualRegex.
* @see #actualRegex
*/
public RegexNode getActualRegex ()
{
return this.actualRegex;
}
/**
* Returns the addedDefaultStateView.
*
* @return The addedDefaultStateView.
* @see #addedDefaultStateView
*/
public final DefaultStateView getAddedDefaultStateView ()
{
return this.addedDefaultStateView;
}
/**
* Returns the addedDefaultTransitionView.
*
* @return The addedDefaultTransitionView.
* @see #addedDefaultTransitionView
*/
public final DefaultTransitionView getAddedDefaultTransitionView ()
{
return this.addedDefaultTransitionView;
}
/**
* Returns the addedSymbol.
*
* @return The addedSymbol.
* @see #addedSymbol
*/
public final ObjectPair < Transition, Symbol > getAddedSymbol ()
{
return this.addedSymbol;
}
/**
* Returns the lastFinalsIndex.
*
* @return The lastFinalsIndex.
* @see #lastFinalsIndex
*/
public int getFinalsIndex ()
{
return this.lastFinalsIndex;
}
/**
* Sets the addedDefaultStateView.
*
* @param addedDefaultStateView The addedDefaultStateView to set.
* @see #addedDefaultStateView
*/
public final void setAddedDefaultStateView (
DefaultStateView addedDefaultStateView )
{
this.addedDefaultStateView = addedDefaultStateView;
}
/**
* Sets the addedDefaultTransitionView.
*
* @param addedDefaultTransitionView The addedDefaultTransitionView to set.
* @see #addedDefaultTransitionView
*/
public final void setAddedDefaultTransitionView (
DefaultTransitionView addedDefaultTransitionView )
{
this.addedDefaultTransitionView = addedDefaultTransitionView;
}
/**
* Sets the addedSymbol.
*
* @param addedSymbol The addedSymbol to set.
* @see #addedSymbol
*/
public final void setAddedSymbol (
ObjectPair < Transition, Symbol > addedSymbol )
{
this.addedSymbol = addedSymbol;
}
}
/**
* The initial position.
*/
private static final int INITIAL_POSITION = 200;
/**
* The {@link Logger} for this class.
*/
private static final Logger logger = Logger
.getLogger ( ConvertMachineDialog.class );
/**
* The algorithm
*/
private String algorithm;
/**
* The algorithm window
*/
private TextWindow algorithmWindow;
/**
* The auto step {@link Timer}.
*/
private Timer autoStepTimer = null;
/**
* The {@link ConvertMachineTableModel}.
*/
private ConvertMachineTableModel convertMachineTableModel;
/**
* The {@link ConvertMachineType}.
*/
private ConvertMachineType convertMachineType;
/**
* The current {@link State}.
*/
private State currentActiveState;
/**
* The current {@link Symbol}.
*/
private Symbol currentActiveSymbol;
/**
* The empty set {@link State}.
*/
private State emptySetState = null;
/**
* Flag that indicates if the end is reached.
*/
protected boolean endReached = false;
/**
* The final states
*/
private ArrayList < State > finals = new ArrayList < State > ();
/**
* The index for the {@link ArrayList} of final states
*/
private int finalsIndex = 0;
/**
* The {@link ConvertMachineDialogForm}.
*/
private ConvertMachineDialogForm gui;
/**
* The converted {@link JGTIGraph} containing the diagramm.
*/
private JGTIGraph jGTIGraphConverted;
/**
* The original {@link JGTIGraph} containing the diagramm.
*/
private JGTIGraph jGTIGraphOriginal;
/**
* Varialbe used for {@link DFA} -> {@link Regex}
*/
private int k;
/**
* The converted {@link Machine}.
*/
private Machine machineConverted;
/**
* The original {@link Machine}.
*/
private Machine machineOriginal;
/**
* The {@link MachinePanel}.
*/
private MachinePanel machinePanel;
/**
* The converted {@link DefaultMachineModel}.
*/
private DefaultMachineModel modelConverted;
/**
* The original {@link DefaultMachineModel}.
*/
private DefaultMachineModel modelOriginal;
/**
* The converted {@link DefaultRegexModel}.
*/
private DefaultRegexModel modelRegexConverted;
/**
* The parent {@link JFrame}.
*/
private JFrame parent;
/**
* The {@link Position} map.
*/
private HashMap < String, Position > positionMap;
/**
* The start {@link State} of the original machine
*/
private State start = null;
/**
* The current {@link Step}.
*/
private Step step = null;
/**
* The {@link StepItem} list.
*/
private ArrayList < StepItem > stepItemList = new ArrayList < StepItem > ();
/**
* The {@link ConvertMachineTableColumnModel}.
*/
private ConvertMachineTableColumnModel tableColumnModel = new ConvertMachineTableColumnModel ();
/**
* Allocates a new {@link ConvertMachineDialog}.
*
* @param parent The parent {@link JFrame}.
* @param machinePanel The {@link MachinePanel}.
*/
public ConvertMachineDialog ( JFrame parent, MachinePanel machinePanel )
{
logger.debug ( "ConvertMachineDialog", //$NON-NLS-1$
"allocate a new convert machine dialog" ); //$NON-NLS-1$
if ( parent == null )
{
throw new IllegalArgumentException ( "parent is null" );//$NON-NLS-1$
}
if ( machinePanel == null )
{
throw new IllegalArgumentException ( "machine panel is null" );//$NON-NLS-1$
}
this.parent = parent;
this.machinePanel = machinePanel;
}
/**
* Adds a outline comment.
*
* @param prettyString The {@link PrettyString} to add.
*/
private final void addOutlineComment ( PrettyString prettyString )
{
this.convertMachineTableModel.addRow ( prettyString );
this.gui.jGTITableOutline.changeSelection ( this.convertMachineTableModel
.getRowCount () - 1, ConvertMachineTableModel.OUTLINE_COLUMN, false,
false );
}
/**
* Adds the power set {@link State}s.
*/
private final void addPowerSetStates ()
{
ArrayList < State > nameList = new ArrayList < State > ();
for ( State current : this.machineOriginal.getState () )
{
nameList.add ( current );
}
PowerSet < State > powerSet = new PowerSet < State > ( nameList );
for ( Set < State > currentSet : powerSet )
{
// the empty set state is added at last
if ( currentSet.size () > 0 )
{
boolean startState = false;
if ( currentSet.size () == 1 )
{
State foundState = null;
for ( State current : this.machineOriginal.getState () )
{
if ( current.isStartState () )
{
foundState = current;
break;
}
}
if ( foundState == null )
{
throw new RuntimeException ( "no start state found" ); //$NON-NLS-1$
}
if ( currentSet.iterator ().next ().getName ().equals (
foundState.getName () ) )
{
startState = true;
}
}
StringBuilder name = new StringBuilder ( "{" ); //$NON-NLS-1$
boolean first = true;
boolean finalState = false;
for ( State currentState : currentSet )
{
if ( !first )
{
name.append ( ", " ); //$NON-NLS-1$
}
first = false;
finalState = finalState || currentState.isFinalState ();
name.append ( currentState.getName () );
}
name.append ( "}" ); //$NON-NLS-1$
try
{
State newState = new DefaultState ( this.machineConverted
.getAlphabet (), this.machineConverted.getPushDownAlphabet (),
name.toString (), startState, finalState );
if ( startState )
{
setCurrentActiveState ( newState, true );
}
this.modelConverted.createStateView ( INITIAL_POSITION,
INITIAL_POSITION, newState, false );
}
catch ( StateException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
}
}
// empty set state
try
{
this.emptySetState = new DefaultState ( this.machineConverted
.getAlphabet (), this.machineConverted.getPushDownAlphabet (),
"\u2205", false, false ); //$NON-NLS-1$
this.modelConverted.createStateView ( INITIAL_POSITION, INITIAL_POSITION,
this.emptySetState, false );
}
catch ( StateException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
}
/**
* Adds a {@link StepItem}.
*/
private final void addStepItem ()
{
ArrayList < State > activeStatesOriginal = new ArrayList < State > ();
ArrayList < State > activeStatesConverted = new ArrayList < State > ();
ArrayList < Transition > activeTransitionsOriginal = new ArrayList < Transition > ();
ArrayList < Transition > activeTransitionsConverted = new ArrayList < Transition > ();
ArrayList < Symbol > activeSymbolsOriginal = new ArrayList < Symbol > ();
ArrayList < Symbol > activeSymbolsConverted = new ArrayList < Symbol > ();
for ( State current : this.machineOriginal.getState () )
{
if ( current.isActive () )
{
activeStatesOriginal.add ( current );
}
}
for ( Transition current : this.machineOriginal.getTransition () )
{
if ( current.isActive () )
{
activeTransitionsOriginal.add ( current );
}
}
for ( Transition currentTransition : this.machineOriginal.getTransition () )
{
for ( Symbol currentSymbol : currentTransition )
{
if ( currentSymbol.isActive () )
{
activeSymbolsOriginal.add ( currentSymbol );
}
}
}
if ( !this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
for ( State current : this.machineConverted.getState () )
{
if ( current.isActive () )
{
activeStatesConverted.add ( current );
}
}
for ( Transition current : this.machineConverted.getTransition () )
{
if ( current.isActive () )
{
activeTransitionsConverted.add ( current );
}
}
for ( Transition currentTransition : this.machineConverted
.getTransition () )
{
for ( Symbol currentSymbol : currentTransition )
{
if ( currentSymbol.isActive () )
{
activeSymbolsConverted.add ( currentSymbol );
}
}
}
}
RegexNode node = null;
if ( this.modelRegexConverted != null )
{
if ( this.modelRegexConverted.getRegex ().getRegexNode () != null )
{
node = this.modelRegexConverted.getRegex ().getRegexNode ().clone ();
}
}
this.stepItemList
.add ( new StepItem ( this.step, this.currentActiveSymbol,
this.currentActiveState, activeStatesOriginal,
activeStatesConverted, activeTransitionsOriginal,
activeTransitionsConverted, activeSymbolsOriginal,
activeSymbolsConverted, node, this.finalsIndex ) );
}
/**
* Cancels the auto step timer.
*/
private final void cancelAutoStepTimer ()
{
if ( this.autoStepTimer != null )
{
this.autoStepTimer.cancel ();
this.autoStepTimer = null;
}
}
/**
* Clears the {@link State} highlighting of the converted {@link JGTIGraph}.
*/
private final void clearStateHighlightConverted ()
{
for ( State currentState : this.machineConverted.getState () )
{
currentState.setActive ( false );
}
}
/**
* Clears the {@link State} highlighting of the original {@link JGTIGraph}.
*/
private final void clearStateHighlightOriginal ()
{
for ( State currentState : this.machineOriginal.getState () )
{
currentState.setActive ( false );
}
}
/**
* Clears the {@link Symbol} highlighting of the converted {@link JGTIGraph}.
*/
private final void clearSymbolHighlightConverted ()
{
for ( Transition currentTransition : this.machineConverted.getTransition () )
{
for ( Symbol currentSymbol : currentTransition.getSymbol () )
{
currentSymbol.setActive ( false );
}
}
}
/**
* Clears the {@link Symbol} highlighting of the original {@link JGTIGraph}.
*/
private final void clearSymbolHighlightOriginal ()
{
for ( Transition currentTransition : this.machineOriginal.getTransition () )
{
for ( Symbol currentSymbol : currentTransition.getSymbol () )
{
currentSymbol.setActive ( false );
}
}
}
/**
* Clears the {@link Transition} highlighting of the converted
* {@link JGTIGraph}.
*/
private final void clearTransitionHighlightConverted ()
{
for ( Transition currentTransition : this.machineConverted.getTransition () )
{
currentTransition.setActive ( false );
}
}
/**
* Clears the {@link Transition} highlighting of the original
* {@link JGTIGraph}.
*/
private final void clearTransitionHighlightOriginal ()
{
for ( Transition currentTransition : this.machineOriginal.getTransition () )
{
currentTransition.setActive ( false );
}
}
/**
* {@inheritDoc}
*
* @see Converter#convert(EntityType,EntityType,boolean,boolean)
*/
public final void convert ( EntityType fromEntityType,
EntityType toEntityType, boolean complete, boolean cb )
{
if ( fromEntityType == null )
{
throw new IllegalArgumentException ( "from entity type is null" );//$NON-NLS-1$
}
if ( toEntityType == null )
{
throw new IllegalArgumentException ( "to entity type is null" );//$NON-NLS-1$
}
if ( fromEntityType.equals ( MachineType.NFA )
&& toEntityType.equals ( MachineType.DFA ) )
{
if ( complete )
{
this.convertMachineType = ConvertMachineType.NFA_TO_DFA_COMPLETE;
}
else
{
this.convertMachineType = ConvertMachineType.NFA_TO_DFA;
}
}
else if ( fromEntityType.equals ( MachineType.ENFA )
&& toEntityType.equals ( MachineType.NFA ) )
{
if ( cb )
{
if ( complete )
{
this.convertMachineType = ConvertMachineType.ENFA_TO_NFA_COMPLETE_CB;
}
else
{
this.convertMachineType = ConvertMachineType.ENFA_TO_NFA_CB;
}
}
else
{
if ( complete )
{
this.convertMachineType = ConvertMachineType.ENFA_TO_NFA_COMPLETE;
}
else
{
this.convertMachineType = ConvertMachineType.ENFA_TO_NFA;
}
}
}
else if ( fromEntityType.equals ( MachineType.ENFA )
&& toEntityType.equals ( MachineType.DFA ) )
{
if ( complete )
{
this.convertMachineType = ConvertMachineType.ENFA_TO_DFA_COMPLETE;
}
else
{
this.convertMachineType = ConvertMachineType.ENFA_TO_DFA;
}
}
else if ( fromEntityType.equals ( MachineType.DFA )
&& toEntityType.equals ( RegexType.REGEX ) )
{
this.convertMachineType = ConvertMachineType.DFA_TO_REGEX;
}
else
{
throw new IllegalArgumentException ( "unsupported conversion from : " //$NON-NLS-1$
+ fromEntityType + " to " + toEntityType ); //$NON-NLS-1$
}
this.gui = new ConvertMachineDialogForm ( this, this.parent );
// outline
this.convertMachineTableModel = new ConvertMachineTableModel ();
this.gui.jGTITableOutline.setModel ( this.convertMachineTableModel );
this.gui.jGTITableOutline.setColumnModel ( this.tableColumnModel );
this.gui.jGTITableOutline.getTableHeader ().setReorderingAllowed ( false );
this.gui.jGTITableOutline.getSelectionModel ().setSelectionMode (
ListSelectionModel.SINGLE_SELECTION );
Rectangle rect = PreferenceManager.getInstance ()
.getConvertMachineDialogBounds ();
this.gui.jGTISplitPaneGraph.setDividerLocation ( ( rect.height - 100 ) / 2 );
this.gui.jGTISplitPaneOutline.setDividerLocation ( rect.width - 250 );
try
{
this.modelOriginal = new DefaultMachineModel ( this.machinePanel
.getModel ().getElement (), null );
}
catch ( TransitionSymbolOnlyOneTimeException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( StateException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( AlphabetException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( TransitionException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( StoreException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
this.jGTIGraphOriginal = this.modelOriginal.getJGTIGraph ();
this.jGTIGraphOriginal.setEnabled ( false );
this.gui.jGTIScrollPaneOriginal.setViewportView ( this.jGTIGraphOriginal );
this.machineOriginal = this.modelOriginal.getMachine ();
switch ( this.convertMachineType )
{
case NFA_TO_DFA :
{
this.modelConverted = new DefaultMachineModel ( new DefaultDFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString ( "ConvertMachineDialog.Title", //$NON-NLS-1$
Messages.getString ( "ConvertMachineDialog.NFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.DFA" ) ) );//$NON-NLS-1$
break;
}
case NFA_TO_DFA_COMPLETE :
{
this.modelConverted = new DefaultMachineModel ( new DefaultDFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString (
"ConvertMachineDialog.CompleteTitle", Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.NFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.DFA" ) ) );//$NON-NLS-1$
break;
}
case ENFA_TO_NFA :
{
this.modelConverted = new DefaultMachineModel ( new DefaultNFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString ( "ConvertMachineDialog.Title", //$NON-NLS-1$
Messages.getString ( "ConvertMachineDialog.ENFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.NFA" ) ) );//$NON-NLS-1$
break;
}
case ENFA_TO_NFA_COMPLETE :
{
this.modelConverted = new DefaultMachineModel ( new DefaultNFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString (
"ConvertMachineDialog.CompleteTitle", Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.ENFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.NFA" ) ) );//$NON-NLS-1$
break;
}
case ENFA_TO_NFA_CB :
{
this.modelConverted = new DefaultMachineModel ( new DefaultNFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString (
"ConvertMachineDialog.TitleCB", //$NON-NLS-1$
Messages.getString ( "ConvertMachineDialog.ENFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.NFA" ) ) );//$NON-NLS-1$
break;
}
case ENFA_TO_NFA_COMPLETE_CB :
{
this.modelConverted = new DefaultMachineModel ( new DefaultNFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString (
"ConvertMachineDialog.CompleteTitleCB", Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.ENFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.NFA" ) ) );//$NON-NLS-1$
break;
}
case ENFA_TO_DFA :
{
this.modelConverted = new DefaultMachineModel ( new DefaultDFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString ( "ConvertMachineDialog.Title", //$NON-NLS-1$
Messages.getString ( "ConvertMachineDialog.ENFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.DFA" ) ) );//$NON-NLS-1$
break;
}
case ENFA_TO_DFA_COMPLETE :
{
this.modelConverted = new DefaultMachineModel ( new DefaultDFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.gui.setTitle ( Messages.getString (
"ConvertMachineDialog.CompleteTitle", Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.ENFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.DFA" ) ) );//$NON-NLS-1$
break;
}
case DFA_TO_REGEX :
{
this.modelConverted = new DefaultMachineModel ( new DefaultDFA (
this.machineOriginal.getAlphabet (), this.machineOriginal
.getPushDownAlphabet (), this.machineOriginal
.isUsePushDownAlphabet () ) );
this.k = this.modelOriginal.getMachine ().getState ().size () + 1;
try
{
this.modelRegexConverted = new DefaultRegexModel ( new DefaultRegex (
new DefaultRegexAlphabet ( this.machineOriginal.getAlphabet ()
.get () ) ) );
this.modelRegexConverted.initializeGraph ();
this.jGTIGraphConverted = this.modelRegexConverted.getJGTIGraph ();
}
catch ( AlphabetException exc )
{
exc.printStackTrace ();
}
this.gui.jGTIButtonOk.setToolTipText ( Messages
.getString ( "ConvertMachineDialog.OkToolTipRegex" ) ); //$NON-NLS-1$
this.gui.jGTIButtonCancel.setToolTipText ( Messages
.getString ( "ConvertMachineDialog.CancelToolTipRegex" ) ); //$NON-NLS-1$
this.gui.setTitle ( Messages.getString (
"ConvertMachineDialog.Title", Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.DFA" ), Messages//$NON-NLS-1$
.getString ( "ConvertMachineDialog.REGEX" ) ) );//$NON-NLS-1$
break;
}
}
if ( !this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
this.gui.styledRegexParserPanel.setVisible ( false );
this.gui.jGTISplitPaneConverted.setDividerSize ( 0 );
this.jGTIGraphConverted = this.modelConverted.getJGTIGraph ();
this.machineConverted = this.modelConverted.getMachine ();
this.jGTIGraphConverted.setEnabled ( false );
this.positionMap = new HashMap < String, Position > ();
this.step = Step.ACTIVATE_START_STATE;
this.currentActiveSymbol = this.machineConverted.getAlphabet ().get ( 0 );
}
else
{
this.step = Step.CALCULATE_NEW_LANGUAGE;
}
this.gui.jGTIScrollPaneConverted.setViewportView ( this.jGTIGraphConverted );
if ( isComplete () )
{
addPowerSetStates ();
}
if ( !this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
// auto layout
while ( !this.endReached )
{
performNextStep ( false );
}
new LayoutManager ( this.modelConverted, null ).doLayout ();
for ( DefaultStateView current : this.modelConverted.getStateViewList () )
{
int yOffset = current.getState ().isLoopTransition () ? StateView.LOOP_TRANSITION_OFFSET
: 0;
this.positionMap.put ( current.getState ().getName (), new Position (
current.getPositionX (), current.getPositionY () + yOffset ) );
}
while ( !this.stepItemList.isEmpty () )
{
performPreviousStep ( false );
}
}
setStatus ();
show ();
}
/**
* Creates a {@link DisjunctionNode} of the symbols
*
* @param symbols The symbols for the {@link DisjunctionNode}
* @return {@link DisjunctionNode} of the symbols
*/
private RegexNode createDisjunction ( ArrayList < Symbol > symbols )
{
if ( symbols.size () < 1 )
{
return null;
}
Symbol s = symbols.remove ( 0 );
RegexNode r;
if ( s.equals ( new DefaultSymbol () ) )
{
r = new EpsilonNode ();
}
else
{
r = new TokenNode ( s.getName () );
}
if ( symbols.size () == 0 )
{
return r;
}
return new DisjunctionNode ( createDisjunction ( symbols ), r );
}
/**
* Eliminates a {@link RegexNode} from a {@link RegexNode}
*
* @param node The {@link RegexNode} to delete
* @param regex The {@link RegexNode}
*/
private void eliminateNodeFromRegex ( RegexNode node, RegexNode regex )
{
RegexNode parentRegex = regex.getParentNodeForNode ( node );
if ( parentRegex instanceof OneChildNode )
{
eliminateNodeFromRegex ( parentRegex, regex );
}
if ( parentRegex instanceof ConcatenationNode )
{
eliminateNodeFromRegex ( parentRegex, regex );
}
if ( parentRegex instanceof DisjunctionNode )
{
RegexNode r;
if ( ( ( TwoChildNode ) parentRegex ).getRegex1 ().equals ( node ) )
{
r = ( ( TwoChildNode ) parentRegex ).getRegex2 ();
}
else
{
r = ( ( TwoChildNode ) parentRegex ).getRegex1 ();
}
RegexNode parentParent = regex.getParentNodeForNode ( parentRegex );
if ( parentParent instanceof TwoChildNode )
{
TwoChildNode p = ( TwoChildNode ) parentParent;
if ( p.getRegex1 ().equals ( parentRegex ) )
{
p.setRegex1 ( r );
}
else
{
p.setRegex2 ( r );
}
}
else
{
OneChildNode one = ( OneChildNode ) parentParent;
one.setRegex ( r );
}
}
}
/**
* Returns the RegexNode for the Languages
*
* @param LKK The {@link RegexNode} for LKK
* @param LKJ The {@link RegexNode} for LKJ
* @return The RegexNode for the Languages
*/
private RegexNode generateRegex ( RegexNode LKK, RegexNode LKJ )
{
RegexNode regex = LKJ;
if ( LKK == null )
{
return null;
}
if ( regex == null )
{
return null;
}
return new ConcatenationNode ( new KleeneNode ( LKK ), LKJ );
}
/**
* Returns the RegexNode for the Languages
*
* @param LIK The {@link RegexNode} for LIK
* @param LKK The {@link RegexNode} for LKK
* @param LKJ The {@link RegexNode} for LKJ
* @return The RegexNode for the Languages
*/
private RegexNode generateRegex ( RegexNode LIK, RegexNode LKK, RegexNode LKJ )
{
RegexNode regex = generateRegex ( LKK, LKJ );
if ( LIK == null )
{
return null;
}
if ( regex == null )
{
return null;
}
return new ConcatenationNode ( LIK, regex );
}
/**
* Returns the RegexNode for the Languages
*
* @param LIJ The {@link RegexNode} for LIJ
* @param LIK The {@link RegexNode} for LIK
* @param LKK The {@link RegexNode} for LKK
* @param LKJ The {@link RegexNode} for LKJ
* @return The RegexNode for the Languages
*/
private RegexNode generateRegex ( RegexNode LIJ, RegexNode LIK,
RegexNode LKK, RegexNode LKJ )
{
RegexNode regex = generateRegex ( LIK, LKK, LKJ );
if ( LIJ == null )
{
return regex;
}
if ( regex == null )
{
return LIJ;
}
return new DisjunctionNode ( LIJ, regex );
}
/**
* Returns the convertMachineTableModel.
*
* @return The convertMachineTableModel.
* @see #convertMachineTableModel
*/
public ConvertMachineTableModel getConvertMachineTableModel ()
{
return this.convertMachineTableModel;
}
/**
* Returns the convertMachineType.
*
* @return The convertMachineType.
* @see #convertMachineType
*/
public ConvertMachineType getConvertMachineType ()
{
return this.convertMachineType;
}
/**
* {@inheritDoc}
*
* @see LogicClass#getGUI()
*/
public final ConvertMachineDialogForm getGUI ()
{
return this.gui;
}
/**
* Returns the L1 for s0 to s1
*
* @param s0 {@link State} s0
* @param s1 {@link State} s1
* @return The L1 for s0 to s1
*/
private RegexNode getL1 ( State s0, State s1 )
{
ArrayList < Symbol > l1 = new ArrayList < Symbol > ();
if ( s0.equals ( s1 ) )
{
l1.add ( new DefaultSymbol () );
}
for ( Transition t : this.machineOriginal.getTransition () )
{
if ( t.getStateBegin ().equals ( s0 ) && t.getStateEnd ().equals ( s1 ) )
{
l1.addAll ( t.getSymbol () );
for ( Symbol s : t.getSymbol () )
{
s.setActive ( true );
}
}
}
return createDisjunction ( l1 );
}
/**
* Returns Lk for s0 to s1
*
* @param s0 {@link State} s0
* @param s1 {@link State} s1
* @param tmpK The k
* @return Lk for s0 to s1
*/
private RegexNode getLK ( State s0, State s1, int tmpK )
{
int i = tmpK;
if ( i-- != 1 )
{
State s = this.machineOriginal.getState ( i - 1 );
RegexNode LIJ = new UnfinishedNode ( s0, s1, i );
RegexNode LIK = new UnfinishedNode ( s0, s, i );
RegexNode LKK = new UnfinishedNode ( s, s, i );
RegexNode LKJ = new UnfinishedNode ( s, s1, i );
RegexNode result = generateRegex ( LIJ, LIK, LKK, LKJ );
return result;
}
RegexNode result = getL1 ( s0, s1 );
return result;
}
/**
* Returns the machinePanel.
*
* @return The machinePanel.
* @see #machinePanel
*/
public MachinePanel getMachinePanel ()
{
return this.machinePanel;
}
/**
* Returns the modelConverted.
*
* @return The modelConverted.
* @see #modelConverted
*/
public DefaultMachineModel getModelConverted ()
{
return this.modelConverted;
}
/**
* Returns the modelOriginal.
*
* @return The modelOriginal.
* @see #modelOriginal
*/
public DefaultMachineModel getModelOriginal ()
{
return this.modelOriginal;
}
/**
* Returns the modelRegexConverted.
*
* @return The modelRegexConverted.
* @see #modelRegexConverted
*/
public DefaultRegexModel getModelRegexConverted ()
{
return this.modelRegexConverted;
}
/**
* Returns the position of the {@link State} or null if the position is not
* defined.
*
* @param state The {@link State}.
* @return The position of the {@link State} or null if the position is not
* defined.
*/
private final Position getPosition ( State state )
{
return this.positionMap.get ( state.getName () );
}
/**
* Returns the tableColumnModel.
*
* @return The tableColumnModel.
* @see #tableColumnModel
*/
public ConvertMachineTableColumnModel getTableColumnModel ()
{
return this.tableColumnModel;
}
/**
* Shows or dispose the Algorithm window
*
* @param show Show or dispose
*/
public final void handleAlgorithmWindowChanged ( boolean show )
{
if ( ( this.algorithm == null ) || ( this.algorithm.length () == 0 ) )
{
TextLoader loader = new TextLoader ();
this.algorithm = loader.loadAlgorithm ( this.convertMachineType );
}
if ( this.algorithmWindow == null )
{
this.algorithmWindow = new TextWindow ( this.gui, this.algorithm, true,
this.gui.jGTIToggleButtonAlgorithm, this.convertMachineType
.toString () );
}
if ( show )
{
this.algorithmWindow.show ();
}
else
{
this.algorithmWindow.dispose ();
}
}
/**
* Handles the action on the auto step button.
*/
public final void handleAutoStep ()
{
logger.debug ( "handleAutoStep", "handle auto step" ); //$NON-NLS-1$ //$NON-NLS-2$
setStatus ();
startAutoStepTimer ();
}
/**
* Handles the action on the begin step button.
*/
public final void handleBeginStep ()
{
performBeginStep ();
}
/**
* Handles the action on the cancel button.
*/
public final void handleCancel ()
{
logger.debug ( "handleCancel", "handle cancel" ); //$NON-NLS-1$ //$NON-NLS-2$
cancelAutoStepTimer ();
PreferenceManager.getInstance ().setConvertMachineDialogPreferences (
this.gui );
if ( this.algorithmWindow != null )
{
this.algorithmWindow.dispose ();
}
this.gui.dispose ();
}
/**
* Handles the action on the end step button.
*/
public final void handleEndStep ()
{
performEndStep ();
}
/**
* Handles the action on the next step button.
*/
public final void handleNextStep ()
{
performNextStep ( true );
}
/**
* Handles the action on the ok button.
*/
public final void handleOk ()
{
logger.debug ( "handleOk", "handle ok" ); //$NON-NLS-1$ //$NON-NLS-2$
cancelAutoStepTimer ();
this.gui.setVisible ( false );
while ( !this.endReached )
{
performNextStep ( false );
}
if ( !this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
this.machinePanel.getMainWindow ().handleNew (
this.modelConverted.getElement (), true );
}
else
{
this.machinePanel.getMainWindow ().handleNew (
new DefaultRegexModel ( this.modelRegexConverted.getRegex () ) );
}
PreferenceManager.getInstance ().setConvertMachineDialogPreferences (
this.gui );
if ( this.algorithmWindow != null )
{
this.algorithmWindow.dispose ();
}
this.gui.dispose ();
}
/**
* Handles the action on the previous step button.
*/
public final void handlePreviousStep ()
{
performPreviousStep ( true );
}
/**
* Handle print action.
*/
public void handlePrint ()
{
PrintDialog dialog = new PrintDialog ( this.parent, this );
dialog.show ();
}
/**
* Handles the action on the stop button.
*/
public final void handleStop ()
{
logger.debug ( "handleStop", "handle stop" ); //$NON-NLS-1$ //$NON-NLS-2$
cancelAutoStepTimer ();
this.gui.jGTIToolBarToggleButtonAutoStep.setSelected ( false );
setStatus ();
}
/**
* Returns true if the complete version is used, otherwise false.
*
* @return True if the complete version is used, otherwise false.
*/
private final boolean isComplete ()
{
switch ( this.convertMachineType )
{
case NFA_TO_DFA :
{
return false;
}
case NFA_TO_DFA_COMPLETE :
{
return true;
}
case ENFA_TO_NFA :
{
return false;
}
case ENFA_TO_NFA_COMPLETE :
{
return true;
}
case ENFA_TO_NFA_CB :
{
return false;
}
case ENFA_TO_NFA_COMPLETE_CB :
{
return true;
}
case ENFA_TO_DFA :
{
return false;
}
case ENFA_TO_DFA_COMPLETE :
{
return true;
}
case DFA_TO_REGEX :
{
return false;
}
}
throw new RuntimeException ( "unsupported convert machine type" ); //$NON-NLS-1$
}
/**
* Returns true if the normal {@link State} is a member of the {@link State}
* set,otherwise false.
*
* @param stateSet The {@link State} set.
* @param normalState The normal {@link State}.
* @return True if the normal {@link State} is a member of the {@link State}
* set,otherwise false.
*/
private final boolean isStateMemberOfStateSet ( State stateSet,
State normalState )
{
String name = stateSet.getName ();
if ( this.convertMachineType.equals ( ConvertMachineType.ENFA_TO_NFA_CB ) )
{
return name.equals ( normalState.getName () );
}
if ( name.charAt ( 0 ) != '{' )
{
throw new RuntimeException ( "not a state set name: " + name ); //$NON-NLS-1$
}
if ( name.charAt ( name.length () - 1 ) != '}' )
{
throw new RuntimeException ( "not a state set name: " + name ); //$NON-NLS-1$
}
String [] splitStateSet = name.substring ( 1, name.length () - 1 ).split (
"," ); //$NON-NLS-1$
for ( String current : splitStateSet )
{
String newName = current;
if ( newName.length () == 0 )
{
throw new RuntimeException ( "name is empty" ); //$NON-NLS-1$
}
// remove spaces
while ( newName.charAt ( 0 ) == ' ' )
{
newName = newName.substring ( 1 );
if ( newName.length () == 0 )
{
throw new RuntimeException ( "name is empty" ); //$NON-NLS-1$
}
}
while ( newName.charAt ( newName.length () - 1 ) == ' ' )
{
newName = newName.substring ( 0, newName.length () - 1 );
if ( newName.length () == 0 )
{
throw new RuntimeException ( "name is empty" ); //$NON-NLS-1$
}
}
if ( normalState.getName ().equals ( newName ) )
{
return true;
}
}
return false;
}
/**
* Performs the begin step.
*/
private final void performBeginStep ()
{
logger.debug ( "performBeginStep", "handle begin step" ); //$NON-NLS-1$ //$NON-NLS-2$
while ( !this.stepItemList.isEmpty () )
{
performPreviousStep ( false );
}
setStatus ();
updateGraph ();
}
/**
* Performs the end step.
*/
private final void performEndStep ()
{
logger.debug ( "performEndStep", "handle nfa to dfa end step" ); //$NON-NLS-1$ //$NON-NLS-2$
while ( !this.endReached )
{
performNextStep ( false );
}
setStatus ();
updateGraph ();
}
/**
* Performs the next step.
*
* @param manualStep Flag that indicates if the {@link Step} is a manual
* {@link Step}.
*/
protected final void performNextStep ( boolean manualStep )
{
addStepItem ();
if ( this.step.equals ( Step.ACTIVATE_START_STATE ) )
{
State startState = null;
for ( State current : this.machineOriginal.getState () )
{
if ( current.isStartState () )
{
startState = current;
break;
}
}
if ( startState == null )
{
throw new NullPointerException ( "no start state" ); //$NON-NLS-1$
}
if ( manualStep )
{
logger.debug ( "performNextStep", "perform next step: " + this.step //$NON-NLS-1$ //$NON-NLS-2$
+ ": " + startState.getName () ); //$NON-NLS-1$
}
startState.setActive ( true );
// outline
PrettyString prettyString = new PrettyString ();
prettyString
.add ( Messages
.getPrettyString (
"ConvertMachineDialog.ActivateStartState", startState.toPrettyString () ) ); //$NON-NLS-1$
addOutlineComment ( prettyString );
switch ( this.convertMachineType )
{
case NFA_TO_DFA :
{
this.step = Step.ADD_START_STATE;
break;
}
case NFA_TO_DFA_COMPLETE :
{
this.step = Step.ACTIVATE_SYMBOLS;
break;
}
case ENFA_TO_NFA :
case ENFA_TO_NFA_COMPLETE :
case ENFA_TO_NFA_CB :
case ENFA_TO_NFA_COMPLETE_CB :
case ENFA_TO_DFA :
case ENFA_TO_DFA_COMPLETE :
{
if ( this.machineConverted.getState ().isEmpty () )
{
this.step = Step.ACTIVATE_START_CLOSURE_STATE;
break;
}
this.step = Step.ACTIVATE_SYMBOLS;
break;
}
case DFA_TO_REGEX :
{
throw new IllegalStateException ( "should not be" ); //$NON-NLS-1$
}
}
}
else if ( this.step.equals ( Step.ACTIVATE_START_CLOSURE_STATE ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
ArrayList < State > activeStateList = new ArrayList < State > ();
for ( State current : this.machineOriginal.getState () )
{
if ( current.isActive () )
{
activeStateList.add ( current );
}
}
Collections.sort ( activeStateList );
ArrayList < State > activeClosureStateList = new ArrayList < State > ();
for ( State current : Util.getClosure ( activeStateList ) )
{
current.setActive ( true );
activeClosureStateList.add ( current );
}
Collections.sort ( activeClosureStateList );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ConvertMachineDialog.ActivateStartClosureState" ) //$NON-NLS-1$
+ " (", Style.NONE ) ); //$NON-NLS-1$
if ( activeStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
prettyString.add ( new PrettyToken ( ") = ", Style.NONE ) ); //$NON-NLS-1$
if ( activeClosureStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeClosureStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
if ( isComplete () )
{
this.step = Step.ACTIVATE_SYMBOLS;
}
else
{
this.step = Step.ADD_START_STATE;
}
}
else if ( this.step.equals ( Step.ADD_START_STATE ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
StringBuilder name = new StringBuilder ();
boolean finalState = false;
boolean notImportant = false;
if ( this.convertMachineType.equals ( ConvertMachineType.ENFA_TO_NFA_CB ) )
{
for ( State currentState : this.machineOriginal.getState () )
{
if ( currentState.isActive () )
{
notImportant = !currentState.isImportant ();
if ( currentState.isFinalState () )
{
finalState = true;
}
name.append ( currentState.getName () );
currentState.setActive ( false );
break;
}
}
}
else
{
name.append ( "{" ); //$NON-NLS-1$
boolean first = true;
for ( State currentState : this.machineOriginal.getState () )
{
if ( currentState.isActive () )
{
if ( currentState.isFinalState () )
{
finalState = true;
}
if ( !first )
{
name.append ( ", " );//$NON-NLS-1$
}
first = false;
name.append ( currentState.getName () );
}
}
name.append ( "}" );//$NON-NLS-1$
}
if ( notImportant )
{
try
{
State stateFound = new DefaultState ( name.toString () );
PrettyString prettyString = new PrettyString ();
prettyString
.add ( Messages
.getPrettyString (
"ConvertMachineDialog.StartStateNotImportant", stateFound.toPrettyString () ) ); //$NON-NLS-1$
addOutlineComment ( prettyString );
boolean found = false;
for ( State s : this.machineOriginal.getState () )
{
if ( s.isActive () )
{
found = true;
break;
}
}
if ( found )
{
this.step = Step.ADD_START_STATE;
}
else
{
setCurrentActiveState ( this.machineConverted.getState ( 0 ),
manualStep );
this.step = Step.ACTIVATE_OLD_STATE;
}
}
catch ( StateException exc )
{
exc.printStackTrace ();
}
}
else
{
State stateFound = null;
for ( State current : this.machineConverted.getState () )
{
if ( current.getName ().equals ( name.toString () ) )
{
stateFound = current;
break;
}
}
if ( stateFound == null )
{
State newState;
DefaultStateView newStateView;
try
{
newState = new DefaultState ( this.machineConverted.getAlphabet (),
this.machineConverted.getPushDownAlphabet (), name.toString (),
true, finalState );
newState.setActive ( true );
}
catch ( StateException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
newStateView = this.modelConverted.createStateView (
INITIAL_POSITION, INITIAL_POSITION, newState, false );
Position position = getPosition ( newState );
if ( position != null )
{
newStateView.move ( position.getX (), position.getY () );
}
// add to step item
this.stepItemList.get ( this.stepItemList.size () - 1 )
.setAddedDefaultStateView ( newStateView );
stateFound = newState;
}
setCurrentActiveState ( stateFound, manualStep );
// outline
PrettyString prettyString = new PrettyString ();
prettyString
.add ( Messages
.getPrettyString (
"ConvertMachineDialog.AddStartState", stateFound.toPrettyString () ) ); //$NON-NLS-1$
addOutlineComment ( prettyString );
if ( this.convertMachineType
.equals ( ConvertMachineType.ENFA_TO_NFA_CB ) )
{
boolean found = false;
for ( State s : this.machineOriginal.getState () )
{
if ( s.isActive () )
{
found = true;
break;
}
}
if ( found )
{
this.step = Step.ADD_START_STATE;
}
else
{
setCurrentActiveState ( this.machineConverted.getState ( 0 ),
manualStep );
this.step = Step.ACTIVATE_OLD_STATE;
}
}
else
{
this.step = Step.ACTIVATE_SYMBOLS;
}
}
}
else if ( this.step.equals ( Step.ACTIVATE_OLD_STATE ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
ArrayList < State > activeStateList = new ArrayList < State > ();
for ( State current : this.machineOriginal.getState () )
{
if ( isStateMemberOfStateSet ( this.currentActiveState, current ) )
{
current.setActive ( true );
activeStateList.add ( current );
}
}
Collections.sort ( activeStateList );
this.currentActiveState.setActive ( true );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ConvertMachineDialog.ActivateOldState" ) //$NON-NLS-1$
+ " ", Style.NONE ) ); //$NON-NLS-1$
if ( activeStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
switch ( this.convertMachineType )
{
case NFA_TO_DFA :
{
this.step = Step.ACTIVATE_SYMBOLS;
break;
}
case NFA_TO_DFA_COMPLETE :
{
this.step = Step.ACTIVATE_SYMBOLS;
break;
}
case ENFA_TO_NFA_CB :
{
this.step = Step.ACTIVATE_SYMBOLS;
break;
}
case ENFA_TO_NFA_COMPLETE_CB :
{
this.step = Step.ACTIVATE_SYMBOLS;
break;
}
case ENFA_TO_NFA :
{
this.step = Step.ACTIVATE_OLD_CLOSURE_STATE;
break;
}
case ENFA_TO_NFA_COMPLETE :
{
this.step = Step.ACTIVATE_OLD_CLOSURE_STATE;
break;
}
case ENFA_TO_DFA :
{
this.step = Step.ACTIVATE_OLD_CLOSURE_STATE;
break;
}
case ENFA_TO_DFA_COMPLETE :
{
this.step = Step.ACTIVATE_OLD_CLOSURE_STATE;
break;
}
case DFA_TO_REGEX :
{
throw new IllegalStateException ( "should not be" ); //$NON-NLS-1$
}
}
}
else if ( this.step.equals ( Step.ACTIVATE_OLD_CLOSURE_STATE ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
ArrayList < State > activeStateList = new ArrayList < State > ();
for ( State current : this.machineOriginal.getState () )
{
if ( current.isActive () )
{
activeStateList.add ( current );
}
}
Collections.sort ( activeStateList );
ArrayList < State > activeClosureStateList = new ArrayList < State > ();
for ( State current : Util.getClosure ( activeStateList ) )
{
current.setActive ( true );
activeClosureStateList.add ( current );
}
Collections.sort ( activeClosureStateList );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ConvertMachineDialog.ActivateOldClosureState" ) //$NON-NLS-1$
+ " (", Style.NONE ) ); //$NON-NLS-1$
if ( activeStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
prettyString.add ( new PrettyToken ( ") = ", Style.NONE ) ); //$NON-NLS-1$
if ( activeClosureStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeClosureStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
this.step = Step.ACTIVATE_SYMBOLS;
}
else if ( this.step.equals ( Step.ACTIVATE_SYMBOLS ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
clearSymbolHighlightOriginal ();
ArrayList < State > activeStateList = new ArrayList < State > ();
for ( State currentState : this.machineOriginal.getState () )
{
if ( currentState.isActive () )
{
activeStateList.add ( currentState );
for ( Transition currentTransition : currentState
.getTransitionBegin () )
{
loopSymbol : for ( Symbol currentSymbol : currentTransition
.getSymbol () )
{
if ( currentSymbol.equals ( this.currentActiveSymbol ) )
{
currentSymbol.setActive ( true );
break loopSymbol;
}
}
}
}
}
Collections.sort ( activeStateList );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ConvertMachineDialog.ActivateSymbols" ) //$NON-NLS-1$
+ " (", Style.NONE ) ); //$NON-NLS-1$
if ( activeStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
prettyString.add ( this.currentActiveSymbol );
prettyString.add ( new PrettyToken ( ")", Style.NONE ) ); //$NON-NLS-1$
addOutlineComment ( prettyString );
this.step = Step.ACTIVATE_NEW_STATES;
}
else if ( this.step.equals ( Step.ACTIVATE_NEW_STATES ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
ArrayList < Transition > transitionList = new ArrayList < Transition > ();
for ( Transition currentTransition : this.machineOriginal
.getTransition () )
{
loopSymbol : for ( Symbol currentSymbol : currentTransition
.getSymbol () )
{
if ( currentSymbol.isActive () )
{
transitionList.add ( currentTransition );
break loopSymbol;
}
}
}
ArrayList < State > oldActiveStateList = new ArrayList < State > ();
for ( State current : this.machineOriginal.getState () )
{
if ( current.isActive () )
{
oldActiveStateList.add ( current );
}
}
Collections.sort ( oldActiveStateList );
clearStateHighlightOriginal ();
clearSymbolHighlightOriginal ();
ArrayList < State > newActiveStateList = new ArrayList < State > ();
if ( this.convertMachineType.equals ( ConvertMachineType.ENFA_TO_NFA_CB ) )
{
for ( Transition currentTransition : transitionList )
{
for ( State s : Util.getClosure ( currentTransition.getStateEnd () ) )
{
if ( s.isImportant () )
{
s.setActive ( true );
newActiveStateList.add ( s );
}
}
}
}
else
{
for ( Transition currentTransition : transitionList )
{
currentTransition.getStateEnd ().setActive ( true );
newActiveStateList.add ( currentTransition.getStateEnd () );
}
}
Collections.sort ( newActiveStateList );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ConvertMachineDialog.ActivateNewStates" )//$NON-NLS-1$
+ " (", Style.NONE ) );//$NON-NLS-1$
if ( oldActiveStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : oldActiveStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
prettyString.add ( this.currentActiveSymbol );
prettyString.add ( new PrettyToken ( ") = ", Style.NONE ) ); //$NON-NLS-1$
if ( newActiveStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : newActiveStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
switch ( this.convertMachineType )
{
case NFA_TO_DFA :
{
this.step = Step.ADD_STATE_AND_TRANSITION;
break;
}
case NFA_TO_DFA_COMPLETE :
{
this.step = Step.ADD_STATE_AND_TRANSITION;
break;
}
case ENFA_TO_NFA :
{
this.step = Step.ACTIVATE_NEW_CLOSURE_STATES;
break;
}
case ENFA_TO_NFA_COMPLETE :
{
this.step = Step.ACTIVATE_NEW_CLOSURE_STATES;
break;
}
case ENFA_TO_NFA_CB :
{
this.step = Step.ADD_STATE_AND_TRANSITION;
break;
}
case ENFA_TO_NFA_COMPLETE_CB :
{
this.step = Step.ADD_STATE_AND_TRANSITION;
break;
}
case ENFA_TO_DFA :
{
this.step = Step.ACTIVATE_NEW_CLOSURE_STATES;
break;
}
case ENFA_TO_DFA_COMPLETE :
{
this.step = Step.ACTIVATE_NEW_CLOSURE_STATES;
break;
}
case DFA_TO_REGEX :
{
throw new IllegalStateException ( "should not be" ); //$NON-NLS-1$
}
}
}
else if ( this.step.equals ( Step.ACTIVATE_NEW_CLOSURE_STATES ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
ArrayList < State > activeStateList = new ArrayList < State > ();
for ( State current : this.machineOriginal.getState () )
{
if ( current.isActive () )
{
activeStateList.add ( current );
}
}
ArrayList < State > activeClosureStateList = new ArrayList < State > ();
for ( State current : Util.getClosure ( activeStateList ) )
{
current.setActive ( true );
activeClosureStateList.add ( current );
}
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ConvertMachineDialog.ActivateNewClosureStates" ) //$NON-NLS-1$
+ " (", Style.NONE ) ); //$NON-NLS-1$
if ( activeStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
prettyString.add ( new PrettyToken ( ") = ", Style.NONE ) ); //$NON-NLS-1$
if ( activeClosureStateList.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : activeClosureStateList )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
this.step = Step.ADD_STATE_AND_TRANSITION;
}
else if ( this.step.equals ( Step.ADD_STATE_AND_TRANSITION ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
StringBuilder name = new StringBuilder ();
boolean finalState = false;
boolean emptySetStateFound = true;
boolean moreAhead = false;
if ( this.convertMachineType.equals ( ConvertMachineType.ENFA_TO_NFA_CB ) )
{
for ( State currentState : this.machineOriginal.getState () )
{
if ( currentState.isActive () )
{
if ( name.length () > 0 )
{
moreAhead = true;
break;
}
currentState.setActive ( false );
emptySetStateFound = false;
finalState = finalState || currentState.isFinalState ();
name.append ( currentState.getName () );
}
}
}
else
{
name.append ( "{" ); //$NON-NLS-1$
boolean first = true;
for ( State currentState : this.machineOriginal.getState () )
{
if ( currentState.isActive () )
{
emptySetStateFound = false;
finalState = finalState || currentState.isFinalState ();
if ( !first )
{
name.append ( ", " );//$NON-NLS-1$
}
first = false;
name.append ( currentState.getName () );
}
}
name.append ( "}" );//$NON-NLS-1$
}
if ( emptySetStateFound )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"empty set state found" );//$NON-NLS-1$
}
switch ( this.convertMachineType )
{
case NFA_TO_DFA :
case NFA_TO_DFA_COMPLETE :
{
name.delete ( 0, name.length () );
name.append ( "\u2205" );//$NON-NLS-1$
break;
}
case ENFA_TO_NFA :
case ENFA_TO_NFA_COMPLETE :
case ENFA_TO_NFA_CB :
case ENFA_TO_NFA_COMPLETE_CB :
{
this.step = Step.FINISH;
// outline
PrettyString prettyString = new PrettyString ();
prettyString
.add ( new PrettyToken (
Messages
.getString ( "ConvertMachineDialog.AddStateAndTransitionEmptySet" ), //$NON-NLS-1$
Style.NONE ) );
addOutlineComment ( prettyString );
if ( manualStep )
{
setStatus ();
updateGraph ();
}
return;
}
case ENFA_TO_DFA :
case ENFA_TO_DFA_COMPLETE :
{
name.delete ( 0, name.length () );
name.append ( "\u2205" );//$NON-NLS-1$
break;
}
case DFA_TO_REGEX :
{
throw new IllegalStateException ( "should not be" ); //$NON-NLS-1$
}
}
}
State stateFound = null;
for ( State current : this.machineConverted.getState () )
{
if ( current.getName ().equals ( name.toString () ) )
{
stateFound = current;
break;
}
}
State newState;
DefaultStateView newStateView;
if ( stateFound == null )
{
try
{
newState = new DefaultState ( this.machineConverted.getAlphabet (),
this.machineConverted.getPushDownAlphabet (), name.toString (),
false, finalState );
newState.setActive ( true );
}
catch ( StateException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
newStateView = this.modelConverted.createStateView ( INITIAL_POSITION,
INITIAL_POSITION, newState, false );
Position position = getPosition ( newState );
if ( position != null )
{
newStateView.move ( position.getX (), position.getY () );
}
// add to step item
this.stepItemList.get ( this.stepItemList.size () - 1 )
.setAddedDefaultStateView ( newStateView );
}
else
{
newState = stateFound;
newState.setActive ( true );
newStateView = this.modelConverted.getStateViewForState ( newState );
}
// set the empty set state
if ( emptySetStateFound )
{
this.emptySetState = newState;
// check if the empty set state transition is already added
if ( this.emptySetState.getTransitionBegin ().size () == 0 )
{
// add transition
Transition transition;
try
{
ArrayList < Symbol > symbolList = new ArrayList < Symbol > ();
for ( Symbol current : this.machineConverted.getAlphabet () )
{
symbolList.add ( new DefaultSymbol ( current.getName () ) );
}
transition = new DefaultTransition ( this.machineConverted
.getAlphabet (), this.machineConverted.getPushDownAlphabet (),
new DefaultWord (), new DefaultWord (), this.emptySetState,
this.emptySetState, symbolList );
}
catch ( TransitionSymbolNotInAlphabetException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( TransitionSymbolOnlyOneTimeException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
this.modelConverted.createTransitionView ( transition, newStateView,
newStateView, false, false, true );
}
}
Transition foundTransition = null;
for ( Transition current : this.currentActiveState.getTransitionBegin () )
{
if ( current.getStateEnd () == newState )
{
foundTransition = current;
break;
}
}
if ( foundTransition == null )
{
Transition transition;
try
{
transition = new DefaultTransition ( this.machineConverted
.getAlphabet (), this.machineConverted.getPushDownAlphabet (),
new DefaultWord (), new DefaultWord (), this.currentActiveState,
newState,
new DefaultSymbol ( this.currentActiveSymbol.getName () ) );
transition.setActive ( true );
}
catch ( TransitionSymbolNotInAlphabetException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( TransitionSymbolOnlyOneTimeException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
DefaultTransitionView newTransitionView = this.modelConverted
.createTransitionView ( transition, this.modelConverted
.getStateViewForState ( this.currentActiveState ),
newStateView, false, false, true );
// add to step item
this.stepItemList.get ( this.stepItemList.size () - 1 )
.setAddedDefaultTransitionView ( newTransitionView );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( Messages.getPrettyString (
"ConvertMachineDialog.AddStateAndTransitionAdd", //$NON-NLS-1$
transition.getStateBegin ().toPrettyString (), transition
.getStateEnd ().toPrettyString (), transition.getSymbol ( 0 )
.toPrettyString () ) );
addOutlineComment ( prettyString );
}
else
{
Symbol symbol;
try
{
symbol = new DefaultSymbol ( this.currentActiveSymbol.getName () );
foundTransition.add ( symbol );
}
catch ( TransitionSymbolNotInAlphabetException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( TransitionSymbolOnlyOneTimeException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
// add to step item
this.stepItemList.get ( this.stepItemList.size () - 1 ).setAddedSymbol (
new ObjectPair < Transition, Symbol > ( foundTransition, symbol ) );
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( Messages.getPrettyString (
"ConvertMachineDialog.AddStateAndTransitionModify", //$NON-NLS-1$
symbol.toPrettyString (), foundTransition.getStateBegin ()
.toPrettyString (), foundTransition.getStateEnd ()
.toPrettyString () ) );
addOutlineComment ( prettyString );
}
if ( moreAhead )
{
this.step = Step.ADD_STATE_AND_TRANSITION;
}
else
{
this.step = Step.FINISH;
}
}
else if ( this.step.equals ( Step.FINISH ) )
{
if ( manualStep )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"perform next step: " + this.step );//$NON-NLS-1$
}
clearStateHighlightOriginal ();
clearStateHighlightConverted ();
clearTransitionHighlightOriginal ();
clearTransitionHighlightConverted ();
clearTransitionHighlightOriginal ();
clearSymbolHighlightConverted ();
// calculate next symbol
boolean useNextState = false;
int index = -1;
for ( int i = 0 ; i < this.machineConverted.getAlphabet ().size () ; i++ )
{
if ( this.currentActiveSymbol == this.machineConverted.getAlphabet ()
.get ( i ) )
{
index = i;
if ( i == this.machineConverted.getAlphabet ().size () - 1 )
{
useNextState = true;
}
break;
}
}
if ( useNextState )
{
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( Messages.getPrettyString (
"ConvertMachineDialog.FinishNextState", //$NON-NLS-1$
this.currentActiveSymbol.toPrettyString (), this.currentActiveState
.toPrettyString () ) );
addOutlineComment ( prettyString );
for ( int i = 0 ; i < this.machineConverted.getState ().size () ; i++ )
{
if ( this.currentActiveState == this.machineConverted.getState ( i ) )
{
// the active state was the last state
if ( i == this.machineConverted.getState ().size () - 1 )
{
this.endReached = true;
}
// the next state is the empty set state, but this empty set state
// is the last
else if ( ( this.emptySetState == this.machineConverted
.getState ( i + 1 ) )
&& ( i == this.machineConverted.getState ().size () - 2 ) )
{
this.endReached = true;
}
// the next state is the empty set state
else if ( this.emptySetState == this.machineConverted
.getState ( i + 1 ) )
{
if ( i < this.machineConverted.getState ().size () - 1 )
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"skip empty set state" );//$NON-NLS-1$
setCurrentActiveState (
this.machineConverted.getState ( i + 2 ), manualStep );
}
else
{
logger.debug ( "performNextStep",//$NON-NLS-1$
"skip empty set state -> end reached" );//$NON-NLS-1$
this.endReached = true;
}
}
// the normal next state
else
{
setCurrentActiveState ( this.machineConverted.getState ( i + 1 ),
manualStep );
}
break;
}
}
this.currentActiveSymbol = this.machineConverted.getAlphabet ()
.get ( 0 );
}
else
{
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( Messages.getPrettyString (
"ConvertMachineDialog.FinishNextSymbol", //$NON-NLS-1$
this.currentActiveSymbol.toPrettyString () ) );
addOutlineComment ( prettyString );
this.currentActiveSymbol = this.machineConverted.getAlphabet ().get (
index + 1 );
}
this.step = Step.ACTIVATE_OLD_STATE;
}
else if ( this.step.equals ( Step.CALCULATE_NEW_LANGUAGE ) )
{
clearStateHighlightOriginal ();
clearTransitionHighlightOriginal ();
clearSymbolHighlightOriginal ();
RegexNode node = this.modelRegexConverted.getRegex ().getRegexNode ();
if ( node == null )
{
this.finals.clear ();
for ( State s : this.modelOriginal.getMachine ().getState () )
{
if ( s.isStartState () )
{
this.start = s;
}
if ( s.isFinalState () )
{
this.finals.add ( s );
}
}
State finState = this.finals.get ( this.finalsIndex );
RegexNode newNode = getLK ( this.start, finState, this.k );
this.start.setActive ( true );
finState.setActive ( true );
this.modelRegexConverted.getRegex ().setRegexNode ( newNode,
newNode.toString () );
PrettyString string = new PrettyString ();
PrettyString kString = new PrettyString ( new PrettyToken ( String
.valueOf ( this.k ), Style.REGEX_SYMBOL ) );
string.add ( Messages.getPrettyString (
"ConvertMachineDialog.CreateLanguage", this.start.toPrettyString () //$NON-NLS-1$
, finState.toPrettyString (), kString, newNode.toPrettyString () ) );
addOutlineComment ( string );
}
else
{
UnfinishedNode uNode = node.getNextUnfinishedNode ();
if ( uNode != null )
{
RegexNode newNode = null;
RegexNode parentNode = node.getParentNodeForNode ( uNode );
if ( parentNode instanceof OneChildNode )
{
RegexNode tmp = getLK ( uNode.getS0 (), uNode.getS1 (), uNode
.getK () );
newNode = tmp;
if ( tmp != null )
{
( ( OneChildNode ) parentNode ).setRegex ( tmp );
}
else
{
eliminateNodeFromRegex ( uNode, node );
}
}
if ( parentNode instanceof TwoChildNode )
{
TwoChildNode two = ( TwoChildNode ) parentNode;
RegexNode r = getLK ( uNode.getS0 (), uNode.getS1 (), uNode.getK () );
newNode = r;
if ( r != null )
{
if ( two.getRegex1 ().equals ( uNode ) )
{
two.setRegex1 ( r );
}
else
{
two.setRegex2 ( r );
}
}
else
{
eliminateNodeFromRegex ( uNode, node );
}
}
this.modelRegexConverted.getRegex ().setRegexNode ( node,
node.toString () );
uNode.getS0 ().setActive ( true );
uNode.getS1 ().setActive ( true );
for ( Transition t : this.machineOriginal.getTransition () )
{
if ( t.getStateBegin ().equals ( uNode.getS0 () )
&& t.getStateEnd ().equals ( uNode.getS1 () ) )
{
t.setActive ( true );
}
}
PrettyString string = new PrettyString ();
PrettyString kString = new PrettyString ( new PrettyToken ( String
.valueOf ( uNode.getK () ), Style.REGEX_SYMBOL ) );
if ( newNode != null )
{
string
.add ( Messages
.getPrettyString (
"ConvertMachineDialog.CreateLanguage", uNode.getS0 ().toPrettyString () //$NON-NLS-1$
, uNode.getS1 ().toPrettyString (), kString, newNode
.toPrettyString () ) );
}
else
{
string
.add ( Messages
.getPrettyString (
"ConvertMachineDialog.CreateLanguage", uNode.getS0 ().toPrettyString () //$NON-NLS-1$
, uNode.getS1 ().toPrettyString (), kString,
new PrettyString ( new PrettyToken (
"\u2205", Style.KEYWORD ) ) ) ); //$NON-NLS-1$
}
addOutlineComment ( string );
}
else
{
this.finalsIndex++ ;
RegexNode n = getLK ( this.start,
this.finals.get ( this.finalsIndex ), this.k );
RegexNode newNode;
if ( n == null )
{
newNode = node;
}
else
{
newNode = new DisjunctionNode ( node, n );
}
this.modelRegexConverted.getRegex ().setRegexNode ( newNode,
newNode.toString () );
PrettyString string = new PrettyString ();
if ( n != null )
{
this.start.setActive ( true );
this.finals.get ( this.finalsIndex ).setActive ( true );
string.add ( Messages.getPrettyString (
"ConvertMachineDialog.CreateDisjunction", this.finals.get ( //$NON-NLS-1$
this.finalsIndex ).toPrettyString (), node
.toPrettyString (), n.toPrettyString () ) );
}
addOutlineComment ( string );
}
}
if ( this.modelRegexConverted.getRegex ().getRegexNode () != null )
{
RegexNode nextUnfishedNode = this.modelRegexConverted.getRegex ()
.getRegexNode ().getNextUnfinishedNode ();
if ( ( this.finalsIndex + 1 >= this.finals.size () )
&& ( nextUnfishedNode == null ) )
{
this.endReached = true;
}
}
}
else
{
throw new RuntimeException ( "unsupported step" ); //$NON-NLS-1$
}
if ( manualStep )
{
setStatus ();
updateGraph ();
}
}
/**
* Performs the previous step.
*
* @param manualStep Flag that indicates if the {@link Step} is a manual
* {@link Step}.
*/
private final void performPreviousStep ( boolean manualStep )
{
if ( manualStep )
{
logger.debug ( "performPreviousStep",//$NON-NLS-1$
"perform previous step" ); //$NON-NLS-1$
}
StepItem stepItem = this.stepItemList
.remove ( this.stepItemList.size () - 1 );
clearStateHighlightOriginal ();
if ( !this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
clearStateHighlightConverted ();
clearTransitionHighlightConverted ();
clearSymbolHighlightConverted ();
}
clearTransitionHighlightOriginal ();
clearSymbolHighlightOriginal ();
for ( State current : stepItem.getActiveStatesOriginal () )
{
current.setActive ( true );
}
for ( State current : stepItem.getActiveStatesConverted () )
{
current.setActive ( true );
}
for ( Transition current : stepItem.getActiveTransitionsOriginal () )
{
current.setActive ( true );
}
for ( Transition current : stepItem.getActiveTransitionsConverted () )
{
current.setActive ( true );
}
for ( Symbol current : stepItem.getActiveSymbolsOriginal () )
{
current.setActive ( true );
}
for ( Symbol current : stepItem.getActiveSymbolsConverted () )
{
current.setActive ( true );
}
this.step = stepItem.getActiveStep ();
setCurrentActiveState ( stepItem.getActiveState (), manualStep );
this.currentActiveSymbol = stepItem.getActiveSymbol ();
if ( stepItem.getAddedDefaultStateView () != null )
{
this.modelConverted.removeState ( stepItem.getAddedDefaultStateView (),
false );
}
if ( stepItem.getAddedDefaultTransitionView () != null )
{
this.modelConverted.removeTransition ( stepItem
.getAddedDefaultTransitionView (), false );
}
if ( stepItem.getAddedSymbol () != null )
{
Transition transition = stepItem.getAddedSymbol ().getFirst ();
Symbol symbol = stepItem.getAddedSymbol ().getSecond ();
transition.remove ( symbol );
}
if ( this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
this.finalsIndex = stepItem.getFinalsIndex ();
if ( stepItem.getActualRegex () != null )
{
RegexNode node = stepItem.getActualRegex ();
this.modelRegexConverted.changeRegexNode ( node, node.toString () );
}
else
{
this.k = this.modelOriginal.getMachine ().getState ().size () + 1;
try
{
this.modelRegexConverted = new DefaultRegexModel ( new DefaultRegex (
new DefaultRegexAlphabet ( this.machineOriginal.getAlphabet ()
.get () ) ) );
this.modelRegexConverted.initializeGraph ();
this.jGTIGraphConverted = this.modelRegexConverted.getJGTIGraph ();
}
catch ( Exception e )
{
e.printStackTrace ();
System.exit ( 1 );
}
}
}
// outline
this.convertMachineTableModel.removeLastRow ();
this.gui.jGTITableOutline.changeSelection ( this.convertMachineTableModel
.getRowCount () - 1, ConvertMachineTableModel.OUTLINE_COLUMN, false,
false );
this.endReached = false;
if ( manualStep )
{
setStatus ();
updateGraph ();
}
}
/**
* Sets the current active {@link State}.
*
* @param state The next active {@link State}.
* @param manualStep Flag that indicates if the {@link Step} is a manual
* {@link Step}.
*/
private final void setCurrentActiveState ( State state, boolean manualStep )
{
if ( manualStep )
{
logger.debug ( "setCurrentActiveState", //$NON-NLS-1$
"set the current active state to: " + Messages.QUOTE + state //$NON-NLS-1$
+ Messages.QUOTE );
}
if ( ( state != null ) && ( state == this.emptySetState ) )
{
throw new IllegalArgumentException (
"active state is the empty set state: " //$NON-NLS-1$
+ state.getName () );
}
this.currentActiveState = state;
}
/**
* Sets the button status.
*/
private final void setStatus ()
{
if ( this.gui.jGTIToolBarToggleButtonAutoStep.isSelected () )
{
this.gui.jGTIToolBarButtonBeginStep.setEnabled ( false );
this.gui.jGTIToolBarButtonPreviousStep.setEnabled ( false );
this.gui.jGTIToolBarButtonNextStep.setEnabled ( false );
this.gui.jGTIToolBarToggleButtonAutoStep.setEnabled ( false );
this.gui.jGTIToolBarButtonStop.setEnabled ( true );
this.gui.jGTIToolBarButtonEndStep.setEnabled ( false );
}
else
{
boolean beginReached = this.stepItemList.isEmpty ();
this.gui.jGTIToolBarButtonBeginStep.setEnabled ( !beginReached );
this.gui.jGTIToolBarButtonPreviousStep.setEnabled ( !beginReached );
this.gui.jGTIToolBarButtonNextStep.setEnabled ( !this.endReached );
this.gui.jGTIToolBarToggleButtonAutoStep.setEnabled ( !this.endReached );
this.gui.jGTIToolBarButtonStop.setEnabled ( false );
this.gui.jGTIToolBarButtonEndStep.setEnabled ( !this.endReached );
}
}
/**
* Shows the {@link ConvertMachineDialogForm}.
*/
public final void show ()
{
logger.debug ( "show", "show the convert machine dialog" ); //$NON-NLS-1$ //$NON-NLS-2$
Rectangle rect = PreferenceManager.getInstance ()
.getConvertMachineDialogBounds ();
if ( ( rect.x == PreferenceManager.DEFAULT_CONVERT_MACHINE_DIALOG_POSITION_X )
|| ( rect.y == PreferenceManager.DEFAULT_CONVERT_MACHINE_DIALOG_POSITION_Y ) )
{
rect.x = this.parent.getBounds ().x + ( this.parent.getWidth () / 2 )
- ( this.gui.getWidth () / 2 );
rect.y = this.parent.getBounds ().y + ( this.parent.getHeight () / 2 )
- ( this.gui.getHeight () / 2 );
}
this.gui.setBounds ( rect );
this.gui.setVisible ( true );
}
/**
* Starts the auto step timer.
*/
private final void startAutoStepTimer ()
{
cancelAutoStepTimer ();
this.autoStepTimer = new Timer ();
int time = PreferenceManager.getInstance ().getAutoStepItem ()
.getAutoStepInterval ();
this.autoStepTimer.schedule ( new AutoStepTimerTask (), time, time );
}
/**
* Updates the {@link JGTIGraph}s.
*/
private final void updateGraph ()
{
this.modelConverted.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelConverted.getGraphModel () ) );
if ( this.convertMachineType.equals ( ConvertMachineType.DFA_TO_REGEX ) )
{
this.modelRegexConverted.initializeGraph ();
this.jGTIGraphConverted = this.modelRegexConverted.getJGTIGraph ();
this.gui.jGTIScrollPaneConverted
.setViewportView ( this.jGTIGraphConverted );
if ( this.modelRegexConverted.getRegex ().getRegexNode () != null )
{
this.modelRegexConverted.createTree ();
this.gui.styledRegexParserPanel.setText ( this.modelRegexConverted
.getRegex ().getRegexNode ().toPrettyString ().toString () );
}
else
{
this.gui.styledRegexParserPanel.setText ( "" ); //$NON-NLS-1$
}
}
this.modelOriginal.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelOriginal.getGraphModel () ) );
}
}