package easysm.executors;
import java.util.Set;
import easysm.Constants;
import easysm.datatypes.Expr;
import easysm.datatypes.Name;
import easysm.datatypes.information.*;
import easysm.factories.SetFactory;
import easysm.stores.*;
import easysm.stores.Class;
/**
* @author Alessio Parma
*/
public class Checker
{
private Set<Name> predefinedTypesNames = SetFactory.createSet(Name.class);
private Main main;
public Checker(Main main)
{
this.main = main;
// Predefined types names
predefinedTypesNames.add(Constants.BOOLEAN_NAME);
predefinedTypesNames.add(Constants.INTEGER_NAME);
predefinedTypesNames.add(Constants.REAL_NAME);
predefinedTypesNames.add(Constants.STRING_NAME);
}
/*
*
* Class checkers
*
*/
public boolean canAdd(ClassInfo newClassInfo)
{
return !typeExists(newClassInfo.name());
}
public boolean canDelete(Class cl)
{
if (main.inputCD().context() != null && main.inputCD().context().equals(cl)) {
main.inputCDError(Constants.CLASS_IS_CONTEXT);
return false;
}
return !typeIsUsed(cl.name());
}
public boolean canUpdate(Class oldClass, ClassInfo newClassInfo)
{
Name newClassName = newClassInfo.name();
if (oldClass.name().equals(newClassName)) {
return true;
}
return !typeExists(newClassName);
}
private boolean classExists(Name className)
{
for (Class c : main.inputCD().classes()) {
if (c.name().equals(className))
return true;
}
return false;
}
/*
*
* Enumeration checkers
*
*/
public boolean canAdd(EnumerationInfo newEnumInfo)
{
if (typeExists(newEnumInfo.name())) {
return false;
}
if (literalsAreRepeated(newEnumInfo.literalsInfo())) {
main.inputCDError(Constants.REPEATED_LITERALS);
return false;
}
return true;
}
public boolean canDelete(Enumeration en)
{
if (typeIsUsed(en.name())) {
return false;
}
// return literalsAreUsed(en.literals());
return true;
}
public boolean canUpdate(Enumeration oldEnum, EnumerationInfo newEnumInfo)
{
if (literalsAreRepeated(newEnumInfo.literalsInfo())) {
main.inputCDError(Constants.REPEATED_LITERALS);
return false;
}
Name newEnumName = newEnumInfo.name();
if (oldEnum.name().equals(newEnumName)) {
return true;
}
return !typeExists(newEnumName);
}
private boolean enumExists(Name enumName)
{
for (Enumeration e : main.inputCD().enums()) {
if (e.name().equals(enumName))
return true;
}
return false;
}
private boolean literalsAreRepeated(Set<LiteralInfo> literalsInfo)
{
if (literalsInfo == null) {
return false;
}
Set<Name> literalsNames = SetFactory.createSet(Name.class);
// We add the name of each literal to the set;
// since it is a set, it will not add a name if
// it is already in the set.
for (LiteralInfo li : literalsInfo) {
if (!literalsNames.add(li.name())) {
return true;
}
}
return false;
}
/**
* A literal may be used in:
* - Invariants
* - Conditions and reactions
private boolean literalsAreUsed(Set<Literal> literals)
{
StringBuilder invOccurences = new StringBuilder();
StringBuilder crOccurences = new StringBuilder();
for (Literal lit : literals) {
invOccurences.append(occurencesInInvariants(lit));
crOccurences.append(occurencesInCondsReacts(lit));
}
String invErrors = invOccurences.toString();
String crErrors = crOccurences.toString();
if (!(invErrors.isEmpty() && crErrors.isEmpty())) {
invErrors = "* State observers:\n" + invErrors;
crErrors = "* Events:\n" + crErrors;
main.inputCDError(invErrors + crErrors);
return true;
}
return false;
}
private String occurencesInInvariants(Literal lit)
{
Set<StateObserver> blockingSO = SetFactory.createSet(StateObserver.class);
for (StateObserver currSO : main.stateObservers().stateObserverSet()) {
if (currSO.invariant().contains(lit)) {
blockingSO.add(currSO);
}
}
return processOccurencesInInvariants(blockingSO);
}
private String occurencesInCondsReacts(Literal lit)
{
Set<Event> blockingEvents = SetFactory.createSet(Event.class);
for (Event ev : main.events().eventSet()) {
for (CondReact cr : ev.conditionsReactions()) {
if (cr.cond().contains(lit)) {
blockingEvents.add(ev);
break;
}
if (cr.react().contains(lit)) {
blockingEvents.add(ev);
break;
}
}
}
return processOccurrencesInCondsReacts(blockingEvents);
}*/
/*
*
* Attribute checkers
*
*/
public boolean canAdd(AttributeInfo newAttrInfo)
{
Name newAttrName = newAttrInfo.name();
Class container = (Class) newAttrInfo.ofClass();
if (attrExists(newAttrName, container)) {
main.inputCDError(Constants.EXISTING_ATTRIBUTE);
return false;
}
return true;
}
public boolean canDelete(Attribute attr)
{
// return !attrIsUsed(attr);
return true;
}
public boolean canUpdate(Attribute oldAttr, AttributeInfo newAttrInfo)
{
Name newAttrName = newAttrInfo.name();
Class container = (Class) newAttrInfo.ofClass();
if (!oldAttr.name().equals(newAttrName) && attrExists(newAttrName, container)) {
main.inputCDError(Constants.EXISTING_ATTRIBUTE);
return false;
}
return true;
}
private boolean attrExists(Name attrName, Class container)
{
for (Attribute a : container.attributes()) {
if (a.name().equals(attrName))
return true;
}
return false;
}
/**
* An attribute may be used in:
* - Invariants
* - Conditions and reactions
private boolean attrIsUsed(Attribute attr)
{
String invOccur = occurencesInInvariants(attr);
String crOccur = occurencesInCondsReacts(attr);
String errorString = invOccur + crOccur;
if (!errorString.isEmpty()) {
main.soError("* Attributes:\n" + errorString);
return true;
}
return false;
}
private String occurencesInInvariants(Attribute attr)
{
Set<StateObserver> blockingSO = SetFactory.createSet(StateObserver.class);
for (StateObserver currSO : main.stateObservers().stateObserverSet()) {
if (currSO.invariant().contains(attr)) {
blockingSO.add(currSO);
}
}
return processOccurencesInInvariants(blockingSO);
}
private String occurencesInCondsReacts(Attribute attr)
{
Set<Event> blockingEvents = SetFactory.createSet(Event.class);
for (Event ev : main.events().eventSet()) {
for (CondReact cr : ev.conditionsReactions()) {
if (cr.cond().contains(attr)) {
blockingEvents.add(ev);
break;
}
if (cr.react().contains(attr)) {
blockingEvents.add(ev);
break;
}
}
}
return processOccurrencesInCondsReacts(blockingEvents);
}*/
/*
*
* Operation checkers
*
*/
public boolean canAdd(OperationInfo newOpInfo)
{
Name newOpName = newOpInfo.name();
Class container = (Class) newOpInfo.ofClass();
if (opExists(newOpName, container)) {
main.inputCDError(Constants.EXISTING_OPERATION);
return false;
}
if (paramsAreRepeated(newOpInfo.parametersInfo())) {
main.inputCDError(Constants.REPEATED_PARAMETERS);
return false;
}
return true;
}
public boolean canDelete(Operation op)
{
// return !opIsUsed(op);
return true;
}
public boolean canUpdate(Operation oldOp, OperationInfo newOpInfo)
{
Name newOpName = newOpInfo.name();
Class container = (Class) newOpInfo.ofClass();
if (!oldOp.name().equals(newOpName) && opExists(newOpName, container)) {
main.inputCDError(Constants.EXISTING_OPERATION);
return false;
}
if (paramsAreRepeated(newOpInfo.parametersInfo())) {
main.inputCDError(Constants.REPEATED_PARAMETERS);
return false;
}
return true;
}
private boolean opExists(Name opName, Class container)
{
for (Operation o : container.operations()) {
if (o.name().equals(opName))
return true;
}
return false;
}
/**
* An operation may be used in:
* - Invariants
* - Conditions and reactions
private boolean opIsUsed(Operation op)
{
String invOccur = occurencesInInvariants(op);
String crOccur = occurencesInCondsReacts(op);
String errorString = invOccur + crOccur;
if (!errorString.isEmpty()) {
main.soError("* Operations:\n" + errorString);
return true;
}
return false;
}
private String occurencesInInvariants(Operation op)
{
Set<StateObserver> blockingSO = SetFactory.createSet(StateObserver.class);
for (StateObserver currSO : main.stateObservers().stateObserverSet()) {
if (currSO.invariant().contains(op)) {
blockingSO.add(currSO);
}
}
return processOccurencesInInvariants(blockingSO);
}
private String occurencesInCondsReacts(Operation op)
{
Set<Event> blockingEvents = SetFactory.createSet(Event.class);
for (Event ev : main.events().eventSet()) {
for (CondReact cr : ev.conditionsReactions()) {
if (cr.cond().contains(op)) {
blockingEvents.add(ev);
break;
}
if (cr.react().contains(op)) {
blockingEvents.add(ev);
break;
}
}
}
return processOccurrencesInCondsReacts(blockingEvents);
}*/
/*
*
* State observer checkers
*
*/
public boolean canAdd(StateObserverInfo newSoInfo)
{
Name newSoName = newSoInfo.name();
if (soExists(newSoName)) {
main.soError(Constants.EXISTING_STATE_OBSERVER);
return false;
}
if (eventExists(newSoName)) {
main.soError(Constants.EXISTING_EVENT);
return false;
}
return true;
}
public boolean canDelete(StateObserver so)
{
// return !soIsUsed(so);
if (main.stateTable().usedSO() != null) {
for (StateObserver currSO : main.stateTable().usedSO()) {
if (so.equals(currSO)) {
main.soError(Constants.USED_STATE_OBSERVER);
return false;
}
}
}
return true;
}
public boolean canUpdate(StateObserver oldSo, StateObserverInfo newSoInfo)
{
Name newSoName = newSoInfo.name();
if (oldSo.name().equals(newSoName)) {
return true;
}
if (soExists(newSoName)) {
main.soError(Constants.EXISTING_STATE_OBSERVER);
return false;
}
if (eventExists(newSoName)) {
main.soError(Constants.EXISTING_EVENT);
return false;
}
return true;
}
private boolean soExists(Name soName)
{
for (StateObserver so : main.stateObservers().soList()) {
if (so.name().equals(soName))
return true;
}
return false;
}
/**
* A state observer may be used in:
* - Invariants
* - Conditions and reactions
private boolean soIsUsed(StateObserver so)
{
String invOccur = occurencesInInvariants(so);
String crOccur = occurencesInCondsReacts(so);
String errorString = invOccur + crOccur;
if (!errorString.isEmpty()) {
main.soError("* State observers:\n" + errorString);
return true;
}
return false;
}
private String occurencesInInvariants(StateObserver so)
{
Set<StateObserver> blockingSO = SetFactory.createSet(StateObserver.class);
for (StateObserver currSO : main.stateObservers().stateObserverSet()) {
if (currSO.invariant().contains(so)) {
blockingSO.add(currSO);
}
}
return processOccurencesInInvariants(blockingSO);
}
private String occurencesInCondsReacts(StateObserver so)
{
Set<Event> blockingEvents = SetFactory.createSet(Event.class);
for (Event ev : main.events().eventSet()) {
for (CondReact cr : ev.conditionsReactions()) {
if (cr.cond().contains(so)) {
blockingEvents.add(ev);
break;
}
if (cr.react().contains(so)) {
blockingEvents.add(ev);
break;
}
}
}
return processOccurrencesInCondsReacts(blockingEvents);
}*/
/*
*
* Event checkers
*
*/
public boolean canAdd(EventInfo newEventInfo)
{
Name newEventName = newEventInfo.name();
if (eventExists(newEventName)) {
main.eventsError(Constants.EXISTING_EVENT);
return false;
}
if (soExists(newEventName)) {
main.eventsError(Constants.EXISTING_STATE_OBSERVER);
return false;
}
if (paramsAreRepeated(newEventInfo.paramsInfo())) {
main.eventsError(Constants.REPEATED_PARAMETERS);
return false;
}
return true;
}
public boolean canDelete(Event event)
{
// return !eventIsUsed(event);
return true;
}
public boolean canUpdate(Event oldEvent, EventInfo newEventInfo)
{
Name newEventName = newEventInfo.name();
if (!oldEvent.name().equals(newEventName)) {
if (eventExists(newEventName)) {
main.eventsError(Constants.EXISTING_EVENT);
return false;
}
if (soExists(newEventName)) {
main.eventsError(Constants.EXISTING_STATE_OBSERVER);
return false;
}
}
if (paramsAreRepeated(newEventInfo.paramsInfo())) {
main.eventsError(Constants.REPEATED_PARAMETERS);
return false;
}
return true;
}
private boolean eventExists(Name eventName)
{
for (Event ev : main.events().eventList()) {
if (ev.name().equals(eventName))
return true;
}
return false;
}
/**
* An event may be used in:
* - Invariants
* - Conditions and reactions
private boolean eventIsUsed(Event event)
{
String invOccur = occurencesInInvariants(event);
String crOccur = occurencesInCondsReacts(event);
String errorString = invOccur + crOccur;
if (!errorString.isEmpty()) {
main.eventsError("* Events:\n" + errorString);
return true;
}
return false;
}
private String occurencesInInvariants(Event event)
{
Set<StateObserver> blockingSO = SetFactory.createSet(StateObserver.class);
for (StateObserver currSO : main.stateObservers().stateObserverSet()) {
if (currSO.invariant().contains(event)) {
blockingSO.add(currSO);
}
}
return processOccurencesInInvariants(blockingSO);
}
private String occurencesInCondsReacts(Event event)
{
Set<Event> blockingEvents = SetFactory.createSet(Event.class);
for (Event ev : main.events().eventSet()) {
for (CondReact cr : ev.conditionsReactions()) {
if (cr.cond().contains(event)) {
blockingEvents.add(ev);
break;
}
if (cr.react().contains(event)) {
blockingEvents.add(ev);
break;
}
}
}
return processOccurrencesInCondsReacts(blockingEvents);
}*/
/*
*
* Condition reaction checkers
*
*/
public boolean canAdd(Event event, CondReactInfo newCrInfo)
{
if (crExists(event, newCrInfo)) {
main.eventsError(Constants.EXISTING_COND_REACT);
return false;
}
return true;
}
public boolean canDelete(CondReact cr)
{
return true;
}
public boolean canUpdate(CondReact cr,
CondReactInfo newCrInfo)
{
Event event = null;
for (Event currEvent : main.events().eventList()) {
if (currEvent.condsReacts().contains(cr)) {
event = currEvent;
break;
}
}
if (!cr.cond().equals(newCrInfo.cond()) && crExists(event, newCrInfo)) {
main.eventsError(Constants.EXISTING_COND_REACT);
return false;
}
return true;
}
private boolean crExists(Event event, CondReactInfo crInfo)
{
Expr cond = crInfo.cond();
for (CondReact cr : event.condsReacts()) {
if (cr.cond().equals(cond)) {
return true;
}
}
return false;
}
/*
*
* State checkers
*
*/
public boolean canDefine(Name newStateName)
{
for (Row row : main.stateTable().rows()) {
if (row.name().equals(newStateName)) {
main.stError(Constants.EXISTING_STATE);
return false;
}
}
return true;
}
/*
*
* Private methods
*
*/
/*private String processOccurencesInInvariants(Set<StateObserver> blockingSO)
{
StringBuilder builder = new StringBuilder();
if (!blockingSO.isEmpty()) {
for (StateObserver currSO : blockingSO) {
builder.append(currSO + "\n");
}
}
return builder.toString();
}
private String processOccurrencesInCondsReacts(Set<Event> blockingEvents)
{
StringBuilder builder = new StringBuilder();
if (!blockingEvents.isEmpty()) {
for (Event ev : blockingEvents) {
builder.append(ev + "\n");
}
}
return builder.toString();
}*/
private boolean paramsAreRepeated(Set<ParameterInfo> paramsInfo)
{
if (paramsInfo == null) {
return false;
}
Set<Name> paramsNames = SetFactory.createSet(Name.class);
// We add the name of each parameter to the set;
// since it is a set, it will not add a name if
// it is already in the set.
for (ParameterInfo pi : paramsInfo) {
if (!paramsNames.add(pi.name())) {
return true;
}
}
return false;
}
private boolean typeExists(Name typeName)
{
if (classExists(typeName)) {
main.inputCDError(Constants.EXISTING_CLASS);
return true;
}
if (enumExists(typeName)) {
main.inputCDError(Constants.EXISTING_ENUM);
return true;
}
if (predefinedTypesNames.contains(typeName)) {
main.inputCDError(Constants.EXISTING_TYPE);
return true;
}
return false;
}
/**
* A type may be used by:
* - Attributes
* - Operations and their parameters
* - State observers
* - Events parameters
*/
private boolean typeIsUsed(Name typeName)
{
// Classes
Set<Attribute> blockingAttributes = SetFactory.createSet(Attribute.class);
Set<Operation> blockingOperations = SetFactory.createSet(Operation.class);
for (Class currCl : main.inputCD().classes()) {
// We ignore the attributes and operations
// of the class we are going to delete.
if (currCl.name().equals(typeName)) {
continue;
}
// Attributes
for (Attribute attr : currCl.attributes()) {
// Attribute type
if (attr.type().name().equals(typeName)) {
blockingAttributes.add(attr);
}
}
// Operations
for (Operation op : currCl.operations()) {
// Operation return type
if (op.returnType().name().equals(typeName)) {
blockingOperations.add(op);
}
// Parameters types
for (Parameter param : op.parameters()) {
if (param.type().name().equals(typeName)) {
blockingOperations.add(op);
break;
}
}
}
}
// State observers
Set<StateObserver> blockingSO = SetFactory.createSet(StateObserver.class);
for (StateObserver so : main.stateObservers().soList()) {
if (so.type().name().equals(typeName)) {
blockingSO.add(so);
}
}
// Events
Set<Event> blockingEvents = SetFactory.createSet(Event.class);
for (Event ev : main.events().eventList()) {
// Parameters types
for (Parameter param : ev.parameters()) {
if (param.type().name().equals(typeName)) {
blockingEvents.add(ev);
break;
}
}
}
// Error string builder
StringBuilder builder = new StringBuilder();
// Process blocking attributes
if (!blockingAttributes.isEmpty()) {
builder.append("* Attributes:\n");
for (Attribute attr : blockingAttributes) {
builder.append(attr + " (class " + ((Class) attr.containedIn()).name() + ")\n");
}
}
// Process blocking operations
if (!blockingOperations.isEmpty()) {
builder.append("* Operations:\n");
for (Operation op : blockingOperations) {
builder.append(op + " (class " + ((Class) op.containedIn()).name() + ")\n");
}
}
// Process blocking state observers
if (!blockingSO.isEmpty()) {
builder.append("* State observers:\n");
for (StateObserver so : blockingSO) {
builder.append(so + "\n");
}
}
// Process blocking events
if (!blockingEvents.isEmpty()) {
builder.append("* Events:\n");
for (Event ev : blockingEvents) {
builder.append(ev + "\n");
}
}
// Error string
String errorString = builder.toString();
if (!errorString.isEmpty()) {
String intro = "Cannot delete given class/enum, corresponding type is used in following elements:\n";
main.inputCDError(intro + errorString);
return true;
}
return false;
}
}