package easysm.executors;
import java.io.FileNotFoundException;
import java.util.List;
import java.util.Set;
import easysm.Constants;
import easysm.boundaries.*;
import easysm.calculators.Generator;
import easysm.calculators.Serializator;
import easysm.datatypes.Name;
import easysm.datatypes.information.*;
import easysm.factories.ListFactory;
import easysm.factories.SetFactory;
import easysm.stores.*;
import easysm.stores.Class;
/**
* @author Federica Lupi
* @author Marta Semeria
* @author Alessio Parma
*/
public class Main
{
private Project openProject;
private Invalidator invalidator;
private Checker checker;
private boolean boundariesLoaded;
private String filename;
// Boundaries
private EasySM easySM;
private UpdateProject updateProject;
private UpdateInputCD updateInputCD;
private UpdateStateObservers updateSO;
private UpdateEvents updateEvents;
private UpdateStateTable updateStateTable;
public Main()
{
this(true);
}
public Main(boolean loadBoundaries)
{
invalidator = new Invalidator(this);
checker = new Checker(this);
// Boundaries
boundariesLoaded = loadBoundaries;
if (loadBoundaries) {
updateInputCD = new UpdateInputCD(this);
updateSO = new UpdateStateObservers(this);
updateEvents = new UpdateEvents(this);
updateStateTable = new UpdateStateTable(this);
updateProject = new UpdateProject(this, updateInputCD, updateSO, updateEvents, updateStateTable);
easySM = new EasySM(this, updateProject);
updateProject.setFrame(easySM.getFrame());
updateSO.setPanel(easySM.getFrame().getStateObserversPanel());
updateInputCD.setPanel(easySM.getFrame().getInputClassDiagramPanel());
updateEvents.setPanel(easySM.getFrame().getEventsPanel());
updateStateTable.setPanel(easySM.getFrame().getStateTablePanel());
}
}
/*
*
* Properties
*
*/
public ClassDiagram inputCD()
{
return openProject.inputCD();
}
public StateObservers stateObservers()
{
return openProject.stateObservers();
}
public Events events()
{
return openProject.events();
}
public StateTable stateTable()
{
return openProject.stateTable();
}
public StateMachine stateMachine()
{
return openProject.stateMachine();
}
public ClassDiagram outputCD()
{
return openProject.outputCD();
}
/*
*
* Operations called by BaseBoundary
*
*/
public void doClosePart()
{
// Since we use tabs, we do nothing
}
public void doValidate(Class cl)
{
invalidator.validate(cl);
}
public void doValidate(Enumeration en)
{
invalidator.validate(en);
}
public void doValidate(Attribute attr)
{
invalidator.validate(attr);
}
public void doValidate(Operation op)
{
invalidator.validate(op);
}
public void doValidate(StateObserver so)
{
invalidator.validate(so);
}
public void doValidate(Event event)
{
invalidator.validate(event);
}
/*
*
* Operations called by EasySM
*
*/
public void doNewProject(ProjectInfo projectInfo)
{
openProject = new Project(projectInfo);
filename = openProject.name().toString() + Constants.DEFAULT_EXTENSION;
refreshParts();
}
public void doOpenProject(String filename)
{
if (!filename.endsWith(Constants.DEFAULT_EXTENSION)) {
easySMError(Constants.WRONG_FILE_EXTENSION);
return;
}
try {
openProject = Serializator.deserialize(filename);
} catch (FileNotFoundException e) {
easySMError(Constants.FILE_NOT_FOUND);
return;
} catch (Exception e) {
easySMError(Constants.DESERIALIZATION_ERROR);
return;
}
this.filename = filename;
easySMInfo(Constants.OPENING_PROJECT + filename);
refreshParts();
}
public void doSaveProject()
{
if (openProject == null) {
return;
}
try {
Serializator.serialize(openProject, filename);
} catch (Exception ex) {
easySMError(Constants.SERIALIZATION_ERROR);
return;
}
easySMInfo(Constants.SAVING_PROJECT + filename);
}
public void doCloseProject()
{
if (openProject == null) {
return;
}
try {
Serializator.serialize(openProject, filename);
} catch (Exception ex) {
easySMError(Constants.SERIALIZATION_ERROR);
return;
}
openProject = null;
easySMInfo(Constants.CLOSING_PROJECT + filename);
refreshParts();
}
/*
*
* Operations called by UpdateProject
*
*/
public void doOpenInputCD()
{
refreshUpdateInputCD();
}
public void doOpenSO()
{
refreshUpdateSO();
}
public void doOpenEvents()
{
refreshUpdateEvents();
}
public void doOpenST()
{
refreshUpdateST();
}
// Kept here because used only by doGenerateSM and rowSatisfies
private boolean satisfies;
private State target;
/**
* Preconditions that must be met in order to generate a state machine:
* - GUI must have been loaded
* - A context class must have been defined
* - The state table must have been successfully generated
* - At least a state must have been defined
*/
private boolean generateSMPreconditionsAreMet()
{
// GUI must have been loaded
if (!boundariesLoaded) {
return false;
}
// A context class must have been defined
if (inputCD().context() == null) {
easySMError(Constants.NO_CONTEXT_CLASS);
return false;
}
// The state table must have been successfully generated
if (stateTable().rows().isEmpty()) {
easySMError(Constants.EMPTY_STATE_TABLE);
return false;
}
// At least a state must have been defined
boolean stateDefined = false;
for (Row row : stateTable().rows()) {
if (!row.name().equals(Constants.IMPOSSIBLE_NAME)) {
stateDefined = true;
break;
}
}
if (!stateDefined) {
easySMError(Constants.REQUIRED_STATE);
return false;
}
return true;
}
public void doGenerateSM()
{
if (!generateSMPreconditionsAreMet()) {
return;
}
List<State> states = Generator.generateStates(stateTable());
Set<Transition> transitions = SetFactory.createSet(Transition.class);
// "initial" state
Event createdEvent = null;
for (Event ev : events().eventList()) { // Referencing Event.CREATED does not work,
if (ev.equals(Event.CREATED)) { // this is something really strange.
createdEvent = ev;
break;
}
}
CondReact createdCR = createdEvent.condsReacts().get(0);
updateProject.examine(null, createdCR.usedCond(), createdCR.usedReact());
if (satisfies) {
transitions.add(Generator.generateTransition(states.get(0), target, Event.CREATED, createdCR));
}
// Other states
for (int i = 1; i < states.size(); ++i) {
State st = states.get(i);
// "final" states must not be source of a transition
if (st.isFinal()) {
continue;
}
// Get corresponding row
Row corrRow = null;
for (Row row : stateTable().rows()) {
if (st.equals(row.state())) {
corrRow = row;
break;
}
}
// If st is the initial state, corrRow will be null;
// we skip event 0 because it is the created event
for (int j = 1; j < events().eventList().size(); ++j) {
Event event = events().eventList().get(j);
for (CondReact cr : event.condsReacts()) {
// Send row to examine
updateProject.examine(corrRow, cr.usedCond(), cr.usedReact());
if (satisfies) {
transitions.add(Generator.generateTransition(st, target, event, cr));
}
}
}
}
// State machine
StateMachineInfo smInfo = new StateMachineInfo(states, transitions);
openProject.setStateMachine(new StateMachine(smInfo));
invalidator.validateSM();
// Output class diagram
List<StateObserver> notUsedSO = ListFactory.createList(StateObserver.class);
for (StateObserver so : stateObservers().soList()) {
boolean used = false;
for (StateObserver usedSO : stateTable().usedSO()) {
if (usedSO.equals(so)) {
used = true;
break;
}
}
if (!used) {
notUsedSO.add(so);
}
}
openProject.setOutputCD(Generator.generateOutputCD(inputCD(), notUsedSO, events().eventList()));
invalidator.validateOutputCD();
// Signal operation completion
updateProject.done();
refreshUpdateProject();
}
public void rowSatisfies(boolean satisfies, Row target)
{
this.satisfies = satisfies;
this.target = target.state();
}
/*
*
* Operations called by UpdateInputCD (Class)
*
*/
public void doAddCDElement(ClassInfo newClassInfo)
{
if (checker.canAdd(newClassInfo)) {
Class newClass = new Class(newClassInfo);
inputCD().addCDElement(newClass);
invalidator.invalidateDependentsOf(newClass);
refreshUpdateInputCD();
}
}
public void doDeleteCDElement(Class cl)
{
if (checker.canDelete(cl)) {
invalidator.invalidateDependentsOf(cl);
inputCD().deleteCDElement(cl);
refreshUpdateInputCD();
}
}
public void doUpdateCDElement(Class cl,
ClassInfo newClassInfo)
{
if (checker.canUpdate(cl, newClassInfo)) {
invalidator.invalidateDependentsOf(cl);
inputCD().updateCDElement(cl, newClassInfo);
refreshUpdateInputCD();
}
}
/*
*
* Operations called by UpdateInputCD (Enumeration)
*
*/
public void doAddCDElement(EnumerationInfo newEnumInfo)
{
if (checker.canAdd(newEnumInfo)) {
Enumeration newEnum = new Enumeration(newEnumInfo);
inputCD().addCDElement(newEnum);
invalidator.invalidateDependentsOf(newEnum);
refreshUpdateInputCD();
}
}
public void doDeleteCDElement(Enumeration en)
{
if (checker.canDelete(en)) {
invalidator.invalidateDependentsOf(en);
inputCD().deleteCDElement(en);
refreshUpdateInputCD();
}
}
public void doUpdateCDElement(Enumeration en,
EnumerationInfo newEnumInfo)
{
if (checker.canUpdate(en, newEnumInfo)) {
invalidator.invalidateDependentsOf(en);
inputCD().updateCDElement(en, newEnumInfo);
refreshUpdateInputCD();
}
}
/*
*
* Operations called by UpdateInputCD (Attribute)
*
*/
public void doAddCDElement(AttributeInfo newAttrInfo)
{
if (checker.canAdd(newAttrInfo)) {
Attribute newAttr = new Attribute(newAttrInfo);
inputCD().addCDElement(newAttr);
invalidator.invalidateDependentsOf(newAttr);
refreshUpdateInputCD();
}
}
public void doDeleteCDElement(Attribute attr)
{
if (checker.canDelete(attr)) {
invalidator.invalidateDependentsOf(attr);
inputCD().deleteCDElement(attr);
refreshUpdateInputCD();
}
}
public void doUpdateCDElement(Attribute attr,
AttributeInfo newAttrInfo)
{
if (checker.canUpdate(attr, newAttrInfo)) {
invalidator.invalidateDependentsOf(attr);
inputCD().updateCDElement(attr, newAttrInfo);
refreshUpdateInputCD();
}
}
/*
*
* Operations called by UpdateInputCD (Operation)
*
*/
public void doAddCDElement(OperationInfo newOpInfo)
{
if (checker.canAdd(newOpInfo)) {
Operation newOp = new Operation(newOpInfo);
inputCD().addCDElement(newOp);
invalidator.invalidateDependentsOf(newOp);
refreshUpdateInputCD();
}
}
public void doDeleteCDElement(Operation op)
{
if (checker.canDelete(op)) {
invalidator.invalidateDependentsOf(op);
inputCD().deleteCDElement(op);
refreshUpdateInputCD();
}
}
public void doUpdateCDElement(Operation op,
OperationInfo newOpInfo)
{
if (checker.canUpdate(op, newOpInfo)) {
invalidator.invalidateDependentsOf(op);
inputCD().updateCDElement(op, newOpInfo);
refreshUpdateInputCD();
}
}
/*
*
* Operations called by UpdateInputCD
*
*/
public void doSetContextClass(Class context)
{
inputCD().changeContext(context);
refreshUpdateInputCD();
openProject.clear();
}
public void doValidateInputCD()
{
invalidator.validateInputCD();
refreshUpdateInputCD();
}
/*
*
* Operations called by UpdateStateObservers
*
*/
public void doAddStateObserver(StateObserverInfo newSoInfo)
{
if (checker.canAdd(newSoInfo)) {
StateObserver newSO = new StateObserver(newSoInfo);
stateObservers().addStateObserver(newSO);
invalidator.invalidateDependentsOf(newSO);
refreshUpdateSO();
}
}
public void doDeleteStateObserver(StateObserver so)
{
if (checker.canDelete(so)) {
invalidator.invalidateDependentsOf(so);
stateObservers().deleteStateObserver(so);
refreshUpdateSO();
}
}
public void doUpdateStateObserver(StateObserver so,
StateObserverInfo newSoInfo)
{
if (checker.canUpdate(so, newSoInfo)) {
invalidator.invalidateDependentsOf(so);
stateObservers().updateStateObserver(so, newSoInfo);
refreshUpdateSO();
}
}
public void doGenerateBasicSO()
{
if (inputCD().context() == null) {
soError(Constants.NO_CONTEXT_CLASS);
return;
}
Set<StateObserver> basicSO = Generator.generateBasicSO(inputCD());
// Check if new state observers can be added
StateObserverInfo soInfo;
for (StateObserver so : basicSO) {
soInfo = new StateObserverInfo(so.name(), so.type(), so.invariant());
if (!checker.canAdd(soInfo)) {
return;
}
}
stateObservers().addStateObservers(basicSO);
invalidator.invalidateSOAndDependents();
refreshUpdateSO();
}
public void doValidateSO()
{
invalidator.validateSO();
refreshUpdateSO();
}
/*
*
* Operations called by UpdateEvents
*
*/
public void doAddEvent(EventInfo newEventInfo)
{
if (checker.canAdd(newEventInfo)) {
Event event = new Event(newEventInfo);
events().addEvent(event);
invalidator.invalidateDependentsOf(event);
refreshUpdateEvents();
}
}
public void doDeleteEvent(Event event)
{
if (checker.canDelete(event)) {
invalidator.invalidateDependentsOf(event);
events().deleteEvent(event);
refreshUpdateEvents();
}
}
public void doUpdateEvent(Event event,
EventInfo newEventInfo)
{
if (checker.canUpdate(event, newEventInfo)) {
invalidator.invalidateDependentsOf(event);
events().updateEvent(event, newEventInfo);
refreshUpdateEvents();
}
}
public void doAddCR(Event event,
CondReactInfo newCrInfo)
{
if (checker.canAdd(event, newCrInfo)) {
events().addCR(event, newCrInfo);
for (CondReact cr : event.condsReacts()) {
if (cr.cond().equals(newCrInfo.cond())) {
invalidator.invalidateDependentsOf(cr);
break;
}
}
refreshUpdateEvents();
}
}
public void doDeleteCR(CondReact cr)
{
if (checker.canDelete(cr)) {
invalidator.invalidateDependentsOf(cr);
events().deleteCR(cr);
refreshUpdateEvents();
}
}
public void doUpdateCR(CondReact cr,
CondReactInfo newCrInfo)
{
if (checker.canUpdate(cr, newCrInfo)) {
invalidator.invalidateDependentsOf(cr);
events().updateCR(cr, newCrInfo);
refreshUpdateEvents();
}
}
public void doGenerateBasicEvents()
{
if (inputCD().context() == null) {
eventsError(Constants.NO_CONTEXT_CLASS);
return;
}
Set<Event> basicEvents = Generator.generateBasicEvents(inputCD());
// Check if new events can be added
EventInfo eventInfo;
for (Event basicEvent : basicEvents) {
// We pass null for the parameters set, because we know that they
// they are OK, since they come a correct operation.
eventInfo = new EventInfo(basicEvent.name(), null);
if (!checker.canAdd(eventInfo)) {
return;
}
}
events().addEvents(basicEvents);
invalidator.invalidateEventsAndDependents();
refreshUpdateEvents();
}
public void doValidateEvents()
{
invalidator.validateEvents();
refreshUpdateEvents();
}
/*
*
* Operations called by UpdateStateTable
*
*/
public void doSelectUsedSO(List<StateObserver> usedSO)
{
stateTable().changeUsedSO(usedSO);
invalidator.invalidateDependentsOfST();
refreshUpdateST();
}
public void doSplitCR()
{
if (boundariesLoaded) {
updateStateTable.setEvents(events().vis());
refreshUpdateST();
}
}
public void doSplitCR(List<SplitInfo> splitsInfo)
{
events().split(splitsInfo);
invalidator.invalidateDependentsOfST();
refreshUpdateST();
}
public void doGenerateStateTable()
{
List<Row> rows = Generator.generateStateTable(stateTable().usedSO());
stateTable().changeRows(rows);
invalidator.invalidateDependentsOfST();
refreshUpdateST();
}
public void doDefineState(Row row,
Name name)
{
if (checker.canDefine(name)) {
stateTable().defineState(row, name);
invalidator.invalidateDependentsOfST();
refreshUpdateST();
}
}
public void doValidateST()
{
invalidator.validateST();
refreshUpdateST();
}
/*
*
* Error signalers
*
*/
public void easySMError(String msg)
{
if (boundariesLoaded) {
easySM.error(msg);
}
}
public void easySMInfo(String msg)
{
if (boundariesLoaded) {
easySM.info(msg);
}
}
public void inputCDError(String msg)
{
if (boundariesLoaded) {
updateInputCD.error(msg);
}
}
public void soError(String msg)
{
if (boundariesLoaded) {
updateSO.error(msg);
}
}
public void eventsError(String msg)
{
if (boundariesLoaded) {
updateEvents.error(msg);
}
}
public void stError(String msg)
{
if (boundariesLoaded) {
updateStateTable.error(msg);
}
}
/*
*
* Refreshers
*
*/
private void refreshParts()
{
if (boundariesLoaded) {
if (openProject != null) {
updateInputCD.setInputCD(inputCD().vis(), inputCD().types());
updateSO.setSO(stateObservers().vis(), inputCD().types());
updateEvents.setEvents(events().vis(), inputCD().types());
updateStateTable.setStateTable(stateTable().vis(), stateObservers().vis().stateObserversVis(), events().vis());
} else {
updateInputCD.setInputCD(null, null);
updateSO.setSO(null, null);
updateEvents.setEvents(null, null);
updateStateTable.setStateTable(null, null, null);
}
refreshUpdateProject();
}
}
private void refreshUpdateProject()
{
if (boundariesLoaded) {
if (openProject != null) {
updateProject.setProject(openProject.vis());
if (openProject.stateMachine() != null) {
updateProject.setStateMachine(openProject.stateMachine().vis());
} else {
updateProject.setStateMachine(null);
}
if (openProject.outputCD() != null) {
updateProject.setOutputCD(openProject.outputCD().vis());
} else {
updateProject.setOutputCD(null);
}
} else {
updateProject.setProject(null);
updateProject.setStateMachine(null);
updateProject.setOutputCD(null);
}
}
}
private void refreshUpdateInputCD()
{
if (boundariesLoaded) {
if (openProject != null) {
updateInputCD.setInputCD(inputCD().vis(), inputCD().types());
} else {
updateInputCD.setInputCD(null, null);
}
refreshUpdateProject();
}
}
private void refreshUpdateSO()
{
if (boundariesLoaded) {
if (openProject != null) {
updateSO.setSO(stateObservers().vis(), inputCD().types());
} else {
updateSO.setSO(null, null);
}
refreshUpdateProject();
}
}
private void refreshUpdateEvents()
{
if (boundariesLoaded) {
if (openProject != null) {
updateEvents.setEvents(events().vis(), inputCD().types());
} else {
updateEvents.setEvents(null, null);
}
refreshUpdateProject();
}
}
private void refreshUpdateST()
{
if (boundariesLoaded) {
if (openProject != null) {
updateStateTable.setStateTable(stateTable().vis(), stateObservers().vis().stateObserversVis(), events().vis());
} else {
updateStateTable.setStateTable(null, null, null);
}
refreshUpdateProject();
}
}
}