diff --git a/eraser-base/src/main/jastadd/Item.jrag b/eraser-base/src/main/jastadd/Item.jrag index 87d45fa2e45bd59de85bbdf8a04dac716b5ae1b0..e6378febc6811e38d19984d70e7e28c24fe27efa 100644 --- a/eraser-base/src/main/jastadd/Item.jrag +++ b/eraser-base/src/main/jastadd/Item.jrag @@ -290,7 +290,6 @@ aspect ItemHandling { * <li>Send the new state via MQTT</li> * <li>Send the new state to Influx DB</li> * <li>Notify the attached {@link ItemObserver}, if any</li> - * <li>Update state of controlled items</li> * </ul> * @param shouldSendState whether to send the new state (currently affects MQTT and Influx) */ @@ -306,9 +305,6 @@ aspect ItemHandling { if (hasItemObserver()) { getItemObserver().apply(); } - for (Item controlled : getControllingList()) { - doUpdateFor(controlled); - } } //--- sendState --- @@ -388,22 +384,49 @@ aspect ItemHandling { syn DateTimeItem Item.asDateTimeItem() = (DateTimeItem) this; syn DateTimeItem DateTimeItem.asDateTimeItem() = this; - //--- doUpdateFor --- - protected abstract void Item.doUpdateFor(Item controlling); - protected void ItemWithBooleanState.doUpdateFor(Item controlling) { - controlling.setStateFromBoolean(this.getState()); + + //--- State Copy --- + public void Item.addControlling(Item controlledItem) { + getRoot().addRule(createControllerRule(this,controlledItem)); + } + + public void Item.addControlledBy(Item controllerItem) { + getRoot().addRule(createControllerRule(controllerItem,this)); + } + + + private Rule Item.createControllerRule(Item controllerItem, Item controlledItem) { + Rule rule = new Rule(); + + ItemStateChangeCondition condition = new ItemStateChangeCondition(); + condition.setItem(controllerItem); + rule.addCondition(condition); + + SetStateFromTriggeringItemAction action = new SetStateFromTriggeringItemAction(); + action.setAffectedItem(controlledItem); + rule.addAction(action); + + return rule; + + } + + + //--- copyStateTo --- + protected abstract void Item.copyStateTo(Item stateReceiver); + protected void ItemWithBooleanState.copyStateTo(Item stateReceiver) { + stateReceiver.setStateFromBoolean(this.getState()); } - protected void ItemWithStringState.doUpdateFor(Item controlling) { - controlling.setStateFromString(this.getState()); + protected void ItemWithStringState.copyStateTo(Item stateReceiver) { + stateReceiver.setStateFromString(this.getState()); } - protected void ItemWithDoubleState.doUpdateFor(Item controlling) { - controlling.setStateFromDouble(this.getState()); + protected void ItemWithDoubleState.copyStateTo(Item stateReceiver) { + stateReceiver.setStateFromDouble(this.getState()); } - protected void ColorItem.doUpdateFor(Item controlling) { - controlling.setStateFromColor(this.getState()); + protected void ColorItem.copyStateTo(Item stateReceiver) { + stateReceiver.setStateFromColor(this.getState()); } - protected void DateTimeItem.doUpdateFor(Item controlling) { - controlling.setStateFromInstant(this.getState()); + protected void DateTimeItem.copyStateTo(Item stateReceiver) { + stateReceiver.setStateFromInstant(this.getState()); } private void ColorItem.setBrightness(int value) { @@ -415,18 +438,12 @@ aspect ItemHandling { public void ItemUpdateColor.apply() { getItem().setStateFromColor(getNewHSB()); getItem().freeze(); - for (Item controller : getItem().getControlledByList()) { - controller.setStateFromColor(getNewHSB()); - } getItem().unfreeze(); } //--- ItemUpdate.apply --- public void ItemUpdateDouble.apply() { getItem().setStateFromDouble(getNewValue()); getItem().freeze(); - for (Item controller : getItem().getControlledByList()) { - controller.setStateFromDouble(getNewValue()); - } getItem().unfreeze(); } diff --git a/eraser-base/src/main/jastadd/Printing.jrag b/eraser-base/src/main/jastadd/Printing.jrag index fec6c4abfb0a9761e4970d3881adeead29a9464a..0b454039a9b84c02c68f2cef4593c0a334b99b37 100644 --- a/eraser-base/src/main/jastadd/Printing.jrag +++ b/eraser-base/src/main/jastadd/Printing.jrag @@ -49,7 +49,7 @@ aspect Printing { .build(); } -//ITEM_TYPE Item: id="" label="" state="" category="" topic="" controls=["ITEM_ID", "ITEM_ID"]; +//ITEM_TYPE Item: id="" label="" state="" category="" topic=""; syn String Item.prettyPrint() { return new MemberPrinter(prettyPrintType()) .addRequired("id", getID()) @@ -57,7 +57,6 @@ aspect Printing { .addRequired("state", getStateAsString()) .addOptional("category", hasCategory(), () -> getCategory().getName()) .addOptional("topic", hasTopic(), () -> getTopic().getTopicString()) - .addIds("controls", getControllingList()) .addNodes("metaData", getNumMetaData(), getMetaDataList(), md -> "\"" + md.getKey() + "\":\"" + md.getValue() + "\"", MemberPrinter.ListBracketType.CURLY) @@ -86,7 +85,6 @@ aspect Printing { .addNonDefault("label", getLabel()) .addOptional("category", hasCategory(), () -> getCategory().getName()) .addOptional("topic", hasTopic(), () -> getTopic().getTopicString()) - .addIds("controls", getControllingList()) .addNodes("metaData", getNumMetaData(), getMetaDataList(), md -> "\"" + md.getKey() + "\":\"" + md.getValue() + "\"", MemberPrinter.ListBracketType.CURLY) diff --git a/eraser-base/src/main/jastadd/Rules.jrag b/eraser-base/src/main/jastadd/Rules.jrag index e1e0db7c7248016dd6db7bea0d6579994548cee9..464b3d3d2f132797e712573805158a507c694c6a 100644 --- a/eraser-base/src/main/jastadd/Rules.jrag +++ b/eraser-base/src/main/jastadd/Rules.jrag @@ -79,6 +79,7 @@ aspect Rules { syn boolean Condition.holdsFor(Item item); eq ItemStateCheckCondition.holdsFor(Item item) = getItemStateCheck().holdsFor(item); eq ExpressionCondition.holdsFor(Item item) = getLogicalExpression().eval(); + eq ItemStateChangeCondition.holdsFor(Item item) = getItem() == item; // --- Action.applyFor --- public abstract void Action.applyFor(Item item); @@ -101,7 +102,7 @@ aspect Rules { getAffectedItem().setStateFromString(getNewStateProvider().get()); } public void SetStateFromTriggeringItemAction.applyFor(Item item) { - item.doUpdateFor(getAffectedItem()); + item.copyStateTo(getAffectedItem()); } public void SetStateFromItemsAction.applyFor(Item item) { getAffectedItem().setStateFromString(getCombinator().apply(getSourceItems())); diff --git a/eraser-base/src/main/jastadd/Rules.relast b/eraser-base/src/main/jastadd/Rules.relast index 3385858454a006cda3c052dbc41028684cb17d23..25a0fd2b41f3f1051e03d06ace4f41b6907030e6 100644 --- a/eraser-base/src/main/jastadd/Rules.relast +++ b/eraser-base/src/main/jastadd/Rules.relast @@ -2,6 +2,7 @@ Rule ::= Condition* Action* ; abstract Condition ; ItemStateCheckCondition : Condition ::= ItemStateCheck ; +ItemStateChangeCondition : Condition ::= Item; ExpressionCondition : Condition ::= LogicalExpression ; abstract Action ; NoopAction : Action ; diff --git a/eraser-base/src/main/jastadd/eraser.flex b/eraser-base/src/main/jastadd/eraser.flex index bc9b3e8d9a41c9bd4cc51d1879f081b32538f103..5f70414fa4005ad1baf1b0623459ce7c5f2f69f2 100644 --- a/eraser-base/src/main/jastadd/eraser.flex +++ b/eraser-base/src/main/jastadd/eraser.flex @@ -77,7 +77,6 @@ Comment = "//" [^\n\r]+ "channels" { return sym(Terminals.CHANNELS); } "channelTypes" { return sym(Terminals.CHANNEL_TYPES); } "context" { return sym(Terminals.CONTEXT); } -"controls" { return sym(Terminals.CONTROLS); } "dbName" { return sym(Terminals.DB_NAME); } "default" { return sym(Terminals.DEFAULT); } "description" { return sym(Terminals.DESCRIPTION); } diff --git a/eraser-base/src/main/jastadd/eraser.parser b/eraser-base/src/main/jastadd/eraser.parser index 5c275fa8c16d8a694608581b08640ae8a9db5451..68967a5655bf12cab2e2127db29e1f0ac5ebd808 100644 --- a/eraser-base/src/main/jastadd/eraser.parser +++ b/eraser-base/src/main/jastadd/eraser.parser @@ -125,15 +125,13 @@ Item item = | ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new DefaultItem(), ib); :} ; -// ITEM_TYPE Item: id="" label="" state="" category="" topic="" controls=["ITEM_ID"] metaData={"key":"value"} ; +// ITEM_TYPE Item: id="" label="" state="" category="" topic="" metaData={"key":"value"} ; Item item_body = ID EQUALS TEXT.n item_body.i {: return eph.setID(i, n); :} | LABEL EQUALS TEXT.n item_body.i {: i.setLabel(n); return i; :} | STATE EQUALS TEXT.n item_body.i {: i.setStateFromString(n); return i; :} | TOPIC EQUALS TEXT.n item_body.i {: return eph.setTopic(i, n); :} | CATEGORY EQUALS TEXT.n item_body.i {: return eph.setCategory(i, n); :} - | CONTROLS EQUALS string_list.controlling item_body.i - {: return eph.setControlling(i, controlling); :} | META_DATA EQUALS string_map.md item_body.i {: return eph.setMetaData(i, md); :} | {: return eph.createItem(); :} diff --git a/eraser-base/src/main/jastadd/shem.relast b/eraser-base/src/main/jastadd/shem.relast index 34ad05feba959e8f1b39449ec56ba96e3dc7a14f..ca1878ac6d2722a3e2a1671e066b19c5175c7be6 100644 --- a/eraser-base/src/main/jastadd/shem.relast +++ b/eraser-base/src/main/jastadd/shem.relast @@ -27,7 +27,6 @@ ParameterDefaultValue ::= <Value:String> ; abstract Item : LabelledModelElement ::= <_fetched_data:boolean> MetaData:ItemMetaData* [ItemObserver] ; rel Item.Category? -> ItemCategory ; -rel Item.Controlling* <-> Item.ControlledBy* ; abstract ItemWithBooleanState : Item ::= <_state:boolean> ; abstract ItemWithStringState : Item ::= <_state:String> ; diff --git a/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/Application.java b/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/Application.java index c646b0e5fe74e09998894767e12f249158f6fbd4..d8a76db65406f94d78f1197ab2fbf8fde10e61f1 100644 --- a/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/Application.java +++ b/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/Application.java @@ -243,7 +243,6 @@ public class Application { item.getTopic() != null ? item.getTopic().getTopicString() : null, item.isFrozen(), item.isSendState(), - item.getControllingList().stream().map(Item::getID).collect(Collectors.toList()), wrapMetaData(item.getMetaDataList())); } diff --git a/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/SimpleItem.java b/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/SimpleItem.java index 2eac624367215c547ef4cfe0058fdcce337062fa..cd18057f917fedb077a237c2618b2e6e9d0c26d0 100644 --- a/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/SimpleItem.java +++ b/eraser.spark/src/main/java/de/tudresden/inf/st/eraser/spark/SimpleItem.java @@ -17,6 +17,5 @@ public class SimpleItem { public final String topic; public final boolean frozen; public final boolean sendState; - public final List<String> controlling; public final Map<String, String> metaData; }