/*
* JFLAP - Formal Languages and Automata Package
*
*
* Susan H. Rodger
* Computer Science Department
* Duke University
* August 27, 2009
* Copyright (c) 2002-2009
* All rights reserved.
* JFLAP is open source software. Please see the LICENSE for terms.
*
*/
package gui.grammar.convert;
import automata.Automaton;
import automata.Transition;
import automata.event.*;
import grammar.*;
import gui.event.*;
import gui.viewer.SelectionDrawer;
import java.awt.Component;
import java.util.*;
/**
* A ConvertController
object is a controller used in the
* conversion of a grammar to some sort of automaton. It monitors both the
* grammar and the automaton being built, as well as their respective views. It
* intervenes as necessary, and as it is a controller object moderates between
* the views, and the automaton and grammar.
*
* @see grammar.Grammar
* @see automaton.Automaton
* @see gui.grammar.GrammarView
* @see gui.viewer.SelectionDrawer
*
* @author Thomas Finley
*/
class ConvertController {
/**
* Instantiates a ConvertController
object.
*
* @param grammarView
* the grammar view
* @param drawer
* the automaton selection drawer
* @param productionsToTransitions
* a map from productions to the corresponding transitions the
* user should come up with... this maping must be one-to-one
* @param parent
* some parent object so that the controller knows where to put
* its message boxes, which may be null
*/
public ConvertController(GrammarViewer grammarView, SelectionDrawer drawer,
Map productionsToTransitions, Component parent) {
this.grammarView = grammarView;
this.drawer = drawer;
this.parent = parent;
grammar = grammarView.getGrammar();
automaton = drawer.getAutomaton();
initListeners();
pToT = productionsToTransitions;
tToP = invert(pToT);
}
/**
* Returns a map containing the inverse of the passed in map.
*
* @param map
* the map, which should be one to one
* @return the inverse of the passed in map, or null
if an
* error occurred
*/
private Map invert(Map map) {
Set entries = map.entrySet();
Iterator it = entries.iterator();
Map inverse = null;
try {
inverse = (Map) map.getClass().newInstance();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
inverse.put(entry.getValue(), entry.getKey());
}
} catch (Throwable e) {
}
return inverse;
}
/**
* This initializes the listeners to the GUI objects, as well as the
* automata.
*/
private void initListeners() {
automaton.addTransitionListener(new AutomataTransitionListener() {
public void automataTransitionChange(AutomataTransitionEvent e) {
if (!e.isAdd()) {
return;
}
Transition transition = e.getTransition();
if (!tToP.containsKey(transition)
|| alreadyDone.contains(tToP.get(transition))) {
javax.swing.JOptionPane.showMessageDialog(parent,
"That transition is not correct!");
automaton.removeTransition(transition);
} else {
Production p = (Production) tToP.get(transition);
alreadyDone.add(p);
grammarView.setChecked(p, true);
}
}
});
grammarView.addSelectionListener(new SelectionListener() {
public void selectionChanged(SelectionEvent event) {
Production[] p = grammarView.getSelected();
drawer.clearSelected();
for (int i = 0; i < p.length; i++) {
drawer.addSelected((Transition) pToT.get(p[i]));
}
parent.repaint();
}
});
}
/**
* Puts all of the remaining uncreated transitions into the automaton.
*/
public void complete() {
Collection productions = new HashSet(pToT.keySet());
Iterator it = productions.iterator();
while (it.hasNext()) {
Production p = (Production) it.next();
if (alreadyDone.contains(p))
continue;
Transition t = (Transition) pToT.get(p);
automaton.addTransition(t);
}
}
/**
* Puts all of the transitions for the selected productions in the
* automaton.
*/
public void createForSelected() {
Production[] p = grammarView.getSelected();
for (int i = 0; i < p.length; i++) {
if (alreadyDone.contains(p[i]))
continue;
Transition t = (Transition) pToT.get(p[i]);
automaton.addTransition(t);
}
}
/**
* Displays and returns if the automaton is done yet.
*
* @return true
if the automaton is done, false
* if it is not
*/
public boolean isDone() {
int toDo = pToT.size() - alreadyDone.size();
String message = toDo == 0 ? "The conversion is finished!" : toDo
+ " more transition" + (toDo == 1 ? "" : "s")
+ " must be added.";
javax.swing.JOptionPane.showMessageDialog(parent, message);
return toDo == 0;
}
/**
* If the conversion is done, this takes the automaton and makes it editable
* in a new window.
*/
public void export() {
boolean done = (pToT.size() - alreadyDone.size()) == 0;
if (!done) {
javax.swing.JOptionPane.showMessageDialog(parent,
"The conversion is not completed yet!");
return;
}
Automaton toExport = (Automaton) automaton.clone();
gui.environment.FrameFactory.createFrame(toExport);
}
/** The grammar view. */
protected GrammarViewer grammarView;
/** The automaton drawer. */
protected SelectionDrawer drawer;
/** The grammar. */
protected Grammar grammar;
/** The automaton. */
protected Automaton automaton;
/** The map of productions to transitions the user should come up with. */
protected Map pToT;
/** The map of transitions to productions. */
protected Map tToP;
/**
* The set of productions whose transitions have already been added.
*/
protected Set alreadyDone = new HashSet();
/** The parent component. */
protected Component parent;
}