Skip to content
Snippets Groups Projects
Commit f510b1b3 authored by René Schöne's avatar René Schöne
Browse files

Merge branch 'dev' into 'master'

Updating master with current development state.

Closes #20, #14, #18, and #15

See merge request !4
parents a465e8c8 310ab641
Branches
No related tags found
No related merge requests found
Showing
with 524 additions and 214 deletions
...@@ -30,11 +30,11 @@ import de.tudresden.inf.st.eraser.jastadd.parser.EraserParser.Terminals; ...@@ -30,11 +30,11 @@ import de.tudresden.inf.st.eraser.jastadd.parser.EraserParser.Terminals;
%} %}
WhiteSpace = [ ] | \t | \f | \n | \r | \r\n WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
//Identifier = [:jletter:][:jletterdigit:]* Identifier = [:jletter:][:jletterdigit:]*
Text = \" ([^\"]*) \" Text = \" ([^\"]*) \"
//Integer = [:digit:]+ // | "+" [:digit:]+ | "-" [:digit:]+ Integer = [:digit:]+ // | "+" [:digit:]+ | "-" [:digit:]+
//Real = [:digit:]+ "." [:digit:]* | "." [:digit:]+ Real = [:digit:]+ "." [:digit:]* | "." [:digit:]+
Comment = "//" [^\n\r]+ Comment = "//" [^\n\r]+
...@@ -55,7 +55,10 @@ Comment = "//" [^\n\r]+ ...@@ -55,7 +55,10 @@ Comment = "//" [^\n\r]+
"Channel" { return sym(Terminals.CHANNEL); } "Channel" { return sym(Terminals.CHANNEL); }
"Mqtt" { return sym(Terminals.MQTT); } "Mqtt" { return sym(Terminals.MQTT); }
"Influx" { return sym(Terminals.INFLUX); } "Influx" { return sym(Terminals.INFLUX); }
"ML" { return sym(Terminals.ML); }
"Rule" { return sym(Terminals.RULE); }
// special items (group already has a token definition) // special items (group already has a token definition)
"Activity" { return sym(Terminals.ACTIVITY); }
"Color" { return sym(Terminals.COLOR); } "Color" { return sym(Terminals.COLOR); }
"Contact" { return sym(Terminals.CONTACT); } "Contact" { return sym(Terminals.CONTACT); }
"DateTime" { return sym(Terminals.DATE_TIME); } "DateTime" { return sym(Terminals.DATE_TIME); }
...@@ -68,11 +71,13 @@ Comment = "//" [^\n\r]+ ...@@ -68,11 +71,13 @@ Comment = "//" [^\n\r]+
"String" { return sym(Terminals.STRING); } "String" { return sym(Terminals.STRING); }
"Switch" { return sym(Terminals.SWITCH); } "Switch" { return sym(Terminals.SWITCH); }
// within specification // within specification
"activities" { return sym(Terminals.ACTIVITIES); }
"aggregation" { return sym(Terminals.AGGREGATION); } "aggregation" { return sym(Terminals.AGGREGATION); }
"category" { return sym(Terminals.CATEGORY); } "category" { return sym(Terminals.CATEGORY); }
"channels" { return sym(Terminals.CHANNELS); } "channels" { return sym(Terminals.CHANNELS); }
"channelTypes" { return sym(Terminals.CHANNEL_TYPES); } "channelTypes" { return sym(Terminals.CHANNEL_TYPES); }
"context" { return sym(Terminals.CONTEXT); } "context" { return sym(Terminals.CONTEXT); }
"controls" { return sym(Terminals.CONTROLS); }
"dbName" { return sym(Terminals.DB_NAME); } "dbName" { return sym(Terminals.DB_NAME); }
"default" { return sym(Terminals.DEFAULT); } "default" { return sym(Terminals.DEFAULT); }
"description" { return sym(Terminals.DESCRIPTION); } "description" { return sym(Terminals.DESCRIPTION); }
...@@ -84,6 +89,7 @@ Comment = "//" [^\n\r]+ ...@@ -84,6 +89,7 @@ Comment = "//" [^\n\r]+
"itemType" { return sym(Terminals.ITEM_TYPE); } "itemType" { return sym(Terminals.ITEM_TYPE); }
"label" { return sym(Terminals.LABEL); } "label" { return sym(Terminals.LABEL); }
"links" { return sym(Terminals.LINKS); } "links" { return sym(Terminals.LINKS); }
"metaData" { return sym(Terminals.META_DATA); }
"outgoing" { return sym(Terminals.OUTGOING); } "outgoing" { return sym(Terminals.OUTGOING); }
"parameters" { return sym(Terminals.PARAMETERS); } "parameters" { return sym(Terminals.PARAMETERS); }
"password" { return sym(Terminals.PASSWORD); } "password" { return sym(Terminals.PASSWORD); }
...@@ -96,6 +102,20 @@ Comment = "//" [^\n\r]+ ...@@ -96,6 +102,20 @@ Comment = "//" [^\n\r]+
// special characters // special characters
"=" { return sym(Terminals.EQUALS); } "=" { return sym(Terminals.EQUALS); }
//"\"" { return sym(Terminals.QUOTE); } //"\"" { return sym(Terminals.QUOTE); }
"<" { return sym(Terminals.LT); }
"<=" { return sym(Terminals.LE); }
"==" { return sym(Terminals.EQ); }
"!=" { return sym(Terminals.NE); }
">=" { return sym(Terminals.GE); }
">" { return sym(Terminals.GT); }
"+" { return sym(Terminals.PLUS); }
"*" { return sym(Terminals.MULT); }
"-" { return sym(Terminals.MINUS); }
"/" { return sym(Terminals.DIV); }
"^" { return sym(Terminals.POW); }
"!" { return sym(Terminals.EXCLAMATION); }
"|" { return sym(Terminals.OR); }
"&" { return sym(Terminals.AND); }
":" { return sym(Terminals.COLON); } ":" { return sym(Terminals.COLON); }
"," { return sym(Terminals.COMMA); } "," { return sym(Terminals.COMMA); }
";" { return sym(Terminals.SEMICOLON); } ";" { return sym(Terminals.SEMICOLON); }
...@@ -103,8 +123,12 @@ Comment = "//" [^\n\r]+ ...@@ -103,8 +123,12 @@ Comment = "//" [^\n\r]+
"]" { return sym(Terminals.RB_SQUARE); } "]" { return sym(Terminals.RB_SQUARE); }
"(" { return sym(Terminals.LB_ROUND); } "(" { return sym(Terminals.LB_ROUND); }
")" { return sym(Terminals.RB_ROUND); } ")" { return sym(Terminals.RB_ROUND); }
//{Identifier} { return sym(Terminals.NAME); } "{" { return sym(Terminals.LB_CURLY); }
"}" { return sym(Terminals.RB_CURLY); }
{Identifier} { return sym(Terminals.NAME); }
{Text} { return symText(Terminals.TEXT); } {Text} { return symText(Terminals.TEXT); }
//{Real} { return sym(Terminals.REAL); } {Integer} { return sym(Terminals.INTEGER); }
//{Integer} { return sym(Terminals.INTEGER); } {Real} { return sym(Terminals.REAL); }
<<EOF>> { return sym(Terminals.EOF); } <<EOF>> { return sym(Terminals.EOF); }
/* error fallback */
[^] { throw new Error("Illegal character '"+ yytext() +"' at line " + (yyline+1) + " column " + (yycolumn+1)); }
%header {: %header {:
package de.tudresden.inf.st.eraser.jastadd.parser; package de.tudresden.inf.st.eraser.jastadd.parser;
import de.tudresden.inf.st.eraser.jastadd.model.*; import de.tudresden.inf.st.eraser.jastadd.model.*;
import de.tudresden.inf.st.eraser.jastadd.model.Action;
import de.tudresden.inf.st.eraser.parser.EraserParserHelper; import de.tudresden.inf.st.eraser.parser.EraserParserHelper;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
...@@ -23,31 +24,80 @@ import java.util.HashMap; ...@@ -23,31 +24,80 @@ import java.util.HashMap;
:} ; :} ;
%goal goal; %goal goal;
%goal number_expression;
%goal logical_expression;
Root goal = Root goal =
thing.t goal.r {: insertZero(r.getThingList(), t); return r; :} thing.t goal.r {: insertZero(r.getOpenHAB2Model().getThingList(), t); return r; :}
| item.i goal.r {: return r; :} | item.i goal.r {: return r; :}
| group.g goal.r {: insertZero(r.getGroupList(), g); return r; :} | group.g goal.r {: insertZero(r.getOpenHAB2Model().getGroupList(), g); return r; :}
| thing_type.tt goal.r {: insertZero(r.getThingTypeList(), tt); return r; :} | thing_type.tt goal.r {: insertZero(r.getOpenHAB2Model().getThingTypeList(), tt); return r; :}
| parameter goal.r {: return r; :} | parameter goal.r {: return r; :}
| channel_type.ct goal.r {: insertZero(r.getChannelTypeList(), ct); return r; :} | channel_type.ct goal.r {: insertZero(r.getOpenHAB2Model().getChannelTypeList(), ct); return r; :}
| channel.c goal.r {: return r; :} | channel.c goal.r {: return r; :}
| mqtt_root.mr goal.r {: r.setMqttRoot(mr); return r; :} | mqtt_root.mr goal.r {: r.setMqttRoot(mr); return r; :}
| influx_root.ir goal.r {: r.setInfluxRoot(ir); return r; :}
| machine_learning_root.ml goal.r {: r.setMachineLearningRoot(ml); return r; :}
| rule.rule goal.r {: r.addRule(rule); return r; :}
| thing.t {: return eph.createRoot(t); :} | thing.t {: return eph.createRoot(t); :}
| item.i {: return eph.createRoot(); :} | item.i {: return eph.createRoot(); :}
| group.g {: return eph.createRoot(g); :} | group.g {: return eph.createRoot(g); :}
| thing_type.tt {: return eph.createRoot(tt); :} | thing_type.tt {: return eph.createRoot(tt); :}
| parameter {: return eph.createRoot(); :} | parameter {: return eph.createRoot(); :}
| channel_type.ct {: return eph.createRoot(ct); :} | channel_type.ct {: return eph.createRoot(ct); :}
| channel.c {: return eph.createRoot(); :}
| mqtt_root.mr {: return eph.createRoot(mr); :} | mqtt_root.mr {: return eph.createRoot(mr); :}
| influx_root.ir {: return eph.createRoot(ir); :} | influx_root.ir {: return eph.createRoot(ir); :}
| channel.c {: return eph.createRoot(); :} | machine_learning_root.ml {: return eph.createRoot(ml); :}
| rule.rule {: return eph.createRoot(rule); :}
;
%left RB_ROUND;
%left MULT, DIV;
%left PLUS, MINUS;
%left POW;
%left LT, LE, EQ, GE, GT;
%left OR;
%left AND;
NumberExpression number_expression =
LB_ROUND number_expression.a MULT number_expression.b RB_ROUND {: return new MultExpression(a, b); :}
| LB_ROUND number_expression.a DIV number_expression.b RB_ROUND {: return new DivExpression(a, b); :}
| LB_ROUND number_expression.a PLUS number_expression.b RB_ROUND {: return new AddExpression(a, b); :}
| LB_ROUND number_expression.a MINUS number_expression.b RB_ROUND {: return new SubExpression(a, b); :}
| LB_ROUND number_expression.a POW number_expression.b RB_ROUND {: return new PowerExpression(a, b); :}
| literal_expression.l {: return l; :}
| designator.d {: return d; :}
| LB_ROUND number_expression.e RB_ROUND {: return new ParenthesizedNumberExpression(e); :}
;
LogicalExpression logical_expression =
LB_ROUND logical_expression.a AND logical_expression.b RB_ROUND {: return new AndExpression(a, b); :}
| LB_ROUND logical_expression.a OR logical_expression.b RB_ROUND {: return new OrExpression(a, b); :}
| EXCLAMATION logical_expression.e {: return new NotExpression(e); :}
| LB_ROUND logical_expression.e RB_ROUND {: return new ParenthesizedLogicalExpression(e); :}
| LB_ROUND number_expression.a LT number_expression.b RB_ROUND {: return new ComparingExpression(a, b, ComparatorType.LessThan); :}
| LB_ROUND number_expression.a LE number_expression.b RB_ROUND {: return new ComparingExpression(a, b, ComparatorType.LessOrEqualThan); :}
| LB_ROUND number_expression.a EQ number_expression.b RB_ROUND {: return new ComparingExpression(a, b, ComparatorType.Equals); :}
| LB_ROUND number_expression.a NE number_expression.b RB_ROUND {: return new ComparingExpression(a, b, ComparatorType.NotEquals); :}
| LB_ROUND number_expression.a GE number_expression.b RB_ROUND {: return new ComparingExpression(a, b, ComparatorType.GreaterOrEqualThan); :}
| LB_ROUND number_expression.a GT number_expression.b RB_ROUND {: return new ComparingExpression(a, b, ComparatorType.GreaterThan); :}
;
NumberLiteralExpression literal_expression =
INTEGER.n {: return new NumberLiteralExpression(Integer.parseInt(n)); :}
| REAL.n {: return new NumberLiteralExpression(Double.parseDouble(n)); :}
;
Designator designator =
NAME.n {: return eph.createDesignator(n); :}
; ;
Thing thing = Thing thing =
THING COLON thing_body.tb SEMICOLON {: return tb; :} THING COLON thing_body.tb SEMICOLON {: return tb; :}
; ;
// Thing: id="" label="" type="" channels=["CHANNEL_ID", "CHANNEL_ID"] ;
Thing thing_body = Thing thing_body =
ID EQUALS TEXT.n thing_body.t {: return eph.setID(t, n); :} ID EQUALS TEXT.n thing_body.t {: return eph.setID(t, n); :}
| LABEL EQUALS TEXT.n thing_body.t {: t.setLabel(n); return t; :} | LABEL EQUALS TEXT.n thing_body.t {: t.setLabel(n); return t; :}
...@@ -59,7 +109,6 @@ Thing thing_body = ...@@ -59,7 +109,6 @@ Thing thing_body =
| CHANNELS EQUALS string_list.channels {: return eph.setChannels(new Thing(), channels); :} | CHANNELS EQUALS string_list.channels {: return eph.setChannels(new Thing(), channels); :}
; ;
//old: ITEM COLON item_body.ib SEMICOLON {: return ib; :}
Item item = Item item =
COLOR ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new ColorItem(), ib); :} COLOR ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new ColorItem(), ib); :}
| CONTACT ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new ContactItem(), ib); :} | CONTACT ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new ContactItem(), ib); :}
...@@ -72,16 +121,21 @@ Item item = ...@@ -72,16 +121,21 @@ Item item =
| ROLLER_SHUTTER ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new RollerShutterItem(), ib); :} | ROLLER_SHUTTER ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new RollerShutterItem(), ib); :}
| STRING ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new StringItem(), ib); :} | STRING ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new StringItem(), ib); :}
| SWITCH ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new SwitchItem(), ib); :} | SWITCH ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new SwitchItem(), ib); :}
| ACTIVITY ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new ActivityItem(), ib); :}
| ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new DefaultItem(), ib); :} | ITEM COLON item_body.ib SEMICOLON {: return eph.retype(new DefaultItem(), ib); :}
; ;
// ITEM_TYPE Item: id="" label="" state="" topic=""; // ITEM_TYPE Item: id="" label="" state="" category="" topic="" controls=["ITEM_ID"] metaData={"key":"value"} ;
Item item_body = Item item_body =
ID EQUALS TEXT.n item_body.i {: return eph.setID(i, n); :} ID EQUALS TEXT.n item_body.i {: return eph.setID(i, n); :}
| LABEL EQUALS TEXT.n item_body.i {: i.setLabel(n); return i; :} | LABEL EQUALS TEXT.n item_body.i {: i.setLabel(n); return i; :}
| STATE EQUALS TEXT.n item_body.i {: i.setStateFromString(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); :} | TOPIC EQUALS TEXT.n item_body.i {: return eph.setTopic(i, n); :}
| CATEGORY EQUALS TEXT.n item_body.i {: return eph.setCategory(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(); :} | {: return eph.createItem(); :}
; ;
...@@ -89,7 +143,8 @@ Group group = ...@@ -89,7 +143,8 @@ Group group =
GROUP COLON group_body.gb SEMICOLON {: return gb; :} GROUP COLON group_body.gb SEMICOLON {: return gb; :}
; ;
// Group: id="" groups=[] items=[]; // Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] aggregation="";
// Group: id="" groups=["GROUP_ID", "GROUP_ID"] items=["ITEM_ID", "ITEM_ID"] aggregation="" ("","");
Group group_body = Group group_body =
ID EQUALS TEXT.n group_body.g {: return eph.setID(g, n); :} ID EQUALS TEXT.n group_body.g {: return eph.setID(g, n); :}
| LABEL EQUALS TEXT.n group_body.g {: g.setLabel(n); return g; :} | LABEL EQUALS TEXT.n group_body.g {: g.setLabel(n); return g; :}
...@@ -188,8 +243,35 @@ InfluxRoot influx_root_body = ...@@ -188,8 +243,35 @@ InfluxRoot influx_root_body =
| {: return InfluxRoot.createDefault(); :} | {: return InfluxRoot.createDefault(); :}
; ;
// Machine Learning
MachineLearningRoot machine_learning_root =
ML COLON machine_learning_root_body.b SEMICOLON {: return b; :}
;
// ML: activities={index:"name"} ;
MachineLearningRoot machine_learning_root_body =
ACTIVITIES EQUALS integer_map.map machine_learning_root_body.b {: return eph.setActivities(b, map); :}
| {: return MachineLearningRoot.createDefault(); :}
;
// Rule: condition=condition action=a1 action=a2;
// (only allow one condition and action for now)
Rule rule =
RULE COLON CONDITION EQUALS condition.c action.a SEMICOLON {: return eph.createRule(c, a); :}
;
Condition condition =
logical_expression.be {: return new ExpressionCondition(be); :}
;
// TODO implement action cases
Action action = {: return new NoopAction(); :}
;
// Util: StringList, StringKeyMap, IntegerKeyMap
StringList string_list = StringList string_list =
LB_SQUARE string_list_body.slb RB_SQUARE {: return slb; :} LB_SQUARE string_list_body.slb RB_SQUARE {: return slb; :}
| LB_SQUARE RB_SQUARE {: return new StringList(); :}
; ;
StringList string_list_body = StringList string_list_body =
...@@ -200,11 +282,11 @@ StringList string_list_body = ...@@ -200,11 +282,11 @@ StringList string_list_body =
result.add(n); result.add(n);
return result; return result;
:} :}
| {: return new StringList(); :}
; ;
StringList round_string_list = StringList round_string_list =
LB_ROUND round_string_list_body.slb RB_ROUND {: return slb; :} LB_ROUND round_string_list_body.slb RB_ROUND {: return slb; :}
| LB_ROUND RB_ROUND {: return new StringList(); :}
; ;
StringList round_string_list_body = StringList round_string_list_body =
...@@ -215,5 +297,34 @@ StringList round_string_list_body = ...@@ -215,5 +297,34 @@ StringList round_string_list_body =
result.add(n); result.add(n);
return result; return result;
:} :}
| {: return new StringList(); :} ;
StringKeyMap string_map =
LB_CURLY string_map_body.smb RB_CURLY {: return smb; :}
| LB_CURLY RB_CURLY {: return new StringKeyMap(); :}
;
StringKeyMap string_map_body =
TEXT.key COLON TEXT.value COMMA string_map_body.smb {: smb.put(key, value); return smb; :}
| TEXT.key COLON TEXT.value
{:
StringKeyMap result = new StringKeyMap();
result.put(key, value);
return result;
:}
;
IntegerKeyMap integer_map =
LB_CURLY integer_map_body.imb RB_CURLY {: return imb; :}
| LB_CURLY RB_CURLY {: return new IntegerKeyMap(); :}
;
IntegerKeyMap integer_map_body =
INTEGER.key COLON TEXT.value COMMA integer_map_body.imb {: imb.put(Integer.parseInt(key), value); return imb; :}
| INTEGER.key COLON TEXT.value
{:
IntegerKeyMap result = new IntegerKeyMap();
result.put(Integer.parseInt(key), value);
return result;
:}
; ;
// ---------------- Main ------------------------------ // ---------------- Main ------------------------------
Root ::= Thing* Group* ThingType* ChannelType* ChannelCategory* ItemCategory* User* MqttRoot InfluxRoot Root ::= OpenHAB2Model User* MqttRoot InfluxRoot MachineLearningRoot Rule* Location* ;
MachineLearningRoot Rule* ItemObserver* ;
// ---------------- openHAB ------------------------------
abstract ModelElement ::= <ID:String> ;
abstract LabelledModelElement : ModelElement ::= <Label:String> ;
abstract DescribableModelElement : LabelledModelElement ::= <Description:String> ;
ThingType : DescribableModelElement ::= Parameter* ;
Thing : LabelledModelElement ::= Channel* ;
ChannelType : DescribableModelElement ::= <ItemType:ItemType> <ReadOnly:boolean> ;
abstract ChannelCategory ;
DefaultChannelCategory : ChannelCategory ::= <Value:DefaultChannelCategoryValue> ;
SimpleChannelCategory : ChannelCategory ::= <Value:String> ;
Channel : ModelElement ::= <Type:ChannelType> Link* ;
Link ::= <Item:Item> ;
Parameter : DescribableModelElement ::= <Type:ParameterValueType> [DefaultValue:ParameterDefaultValue] <Context:String> <Required:boolean> ;
ParameterDefaultValue ::= <Value:String> ;
abstract Item : LabelledModelElement ::= <DefaultShouldSendState:boolean> <_fetched_data:boolean> ;
abstract ItemWithBooleanState : Item ::= <_state:boolean> ;
abstract ItemWithStringState : Item ::= <_state:String> ;
abstract ItemWithDoubleState : Item ::= <_state:double> ;
ColorItem : Item ::= <_state:TupleHSB> ;
DateTimeItem : Item ::= <_state:Date> ;
ContactItem : ItemWithBooleanState ;
DimmerItem : ItemWithDoubleState ;
ImageItem : ItemWithStringState ;
LocationItem : ItemWithStringState ;
NumberItem : ItemWithDoubleState ;
PlayerItem : ItemWithStringState ;
RollerShutterItem : ItemWithBooleanState ;
StringItem : ItemWithStringState ;
SwitchItem : ItemWithBooleanState ;
DefaultItem : ItemWithStringState ;
ItemCategory ::= <Name:String> ;
Group : LabelledModelElement ::= Group* Item* [AggregationFunction:GroupAggregationFunction] ;
abstract GroupAggregationFunction ;
SimpleGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:SimpleGroupAggregationFunctionName> ;
ParameterizedGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:ParameterizedGroupAggregationFunctionName>
<Param1:String> <Param2:String> ;
// ---------------- Users ------------------------------ // ---------------- Users ------------------------------
User : LabelledModelElement ; User : LabelledModelElement ;
rel Root.CurrentUser? -> User ;
// ---------------- Util ------------------------------ // ---------------- Util ------------------------------
ExternalHost ::= <HostName:String> <Port:int> ; ExternalHost ::= <HostName:String> <Port:int> ;
// ---------------- MQTT ------------------------------
MqttRoot ::= Topic:MqttTopic* <IncomingPrefix:String> <OutgoingPrefix:String> [Host:ExternalHost] ;
MqttTopic ::= <Part:String> SubTopic:MqttTopic* ;
// ---------------- InfluxDB ------------------------------ // ---------------- InfluxDB ------------------------------
InfluxRoot ::= <User:String> <Password:String> <DbName:String> [Host:ExternalHost] ; InfluxRoot ::= <User:String> <Password:String> <DbName:String> [Host:ExternalHost] ;
// ---------------- Machine Learning Model ------------------------------
MachineLearningRoot ::= [ActivityRecognition:MachineLearningModel] [PreferenceLearning:MachineLearningModel] Activity* ChangeEvent* ;
Activity ::= <Identifier:int> <Label:String> ;
abstract ChangeEvent ::= <Identifier:int> <Timestamp:long> ChangedItem* ;
ChangedItem ::= <NewStateAsString:String> ;
RecognitionEvent : ChangeEvent ;
ManualChangeEvent : ChangeEvent ;
abstract MachineLearningModel ;
ItemPreference ::= <PreferredHSB:TupleHSB> ;
// ---------------- Decision Tree ------------------------------
DecisionTreeRoot : MachineLearningModel ::= RootRule:DecisionTreeRule ;
abstract DecisionTreeElement ::= Preference:ItemPreference*;
abstract DecisionTreeRule : DecisionTreeElement ::= Left:DecisionTreeElement Right:DecisionTreeElement <Label:String> ;
ItemStateCheckRule : DecisionTreeRule ::= ItemStateCheck ;
abstract ItemStateCheck ::= <Comparator:ComparatorType> ;
ItemStateNumberCheck : ItemStateCheck ::= <Value:double> ;
ItemStateStringCheck : ItemStateCheck ::= <Value:String> ;
DecisionTreeLeaf : DecisionTreeElement ::= <ActivityIdentifier:int> <Label:String> ;
// ---------------- Neural Network ------------------------------
NeuralNetworkRoot : MachineLearningModel ::= InputNeuron* HiddenNeuron* OutputLayer ;
OutputLayer ::= OutputNeuron* <Combinator:DoubleArrayDoubleFunction> ;
abstract Neuron ::= Output:NeuronConnection* ;
NeuronConnection ::= <Weight:double> ;
InputNeuron : Neuron ;
HiddenNeuron : Neuron ::= <ActivationFormula:DoubleArrayDoubleFunction> ;
OutputNeuron : HiddenNeuron ::= <Label:String> ;
// ---------------- ECA-Rules ------------------------------
Rule ::= Event* <Condition:ConditionFunction> <Action:ActionEditConsumer> ;
Event ::= <Label:String> ;
ItemObserver ::= ;
// ---------------- Relations ------------------------------
rel ThingType.ChannelType* -> ChannelType ;
rel Thing.Type -> ThingType ;
rel ChannelType.ChannelCategory -> ChannelCategory ;
rel Item.Topic <-> MqttTopic.Item ;
rel Item.Category? -> ItemCategory ;
rel ItemStateCheck.Item -> Item ;
rel NeuronConnection.Neuron <-> Neuron.Input* ;
rel InputNeuron.Item -> Item ;
rel Item.Observer? <-> ItemObserver.ObservedItem ;
rel ItemObserver.TriggeredEvent* <-> Event.Observer ;
rel ItemPreference.Item -> Item ;
rel Item.Controlling* <-> Item.ControlledBy ;
rel Root.CurrentUser? -> User ;
rel ChangedItem.Item -> Item ;
rel RecognitionEvent.Activity -> Activity ;
...@@ -3,64 +3,41 @@ aspect MQTT { ...@@ -3,64 +3,41 @@ aspect MQTT {
// --- default values --- // --- default values ---
private static final int MqttRoot.DEFAULT_PORT = 1883; private static final int MqttRoot.DEFAULT_PORT = 1883;
java.util.Set<String> MqttRoot.ignoredTopics = new java.util.HashSet<>();
//--- resolveTopic --- //--- resolveTopic ---
syn java.util.Optional<MqttTopic> MqttRoot.resolveTopic(String topic) { syn java.util.Optional<MqttTopic> MqttRoot.resolveTopic(String topic) {
ensureCorrectPrefixes(); ensureCorrectPrefixes();
if (!topic.startsWith(getIncomingPrefix())) { if (!topic.startsWith(getIncomingPrefix())) {
logger.debug("Topic '{}' does not start with incoming prefix '{}'", topic, getIncomingPrefix()); logger.warn("Topic '{}' does not start with incoming prefix '{}'", topic, getIncomingPrefix());
return java.util.Optional.empty(); return java.util.Optional.empty();
} }
topic = topic.substring(getIncomingPrefix().length()); String suffix = topic.substring(getIncomingPrefix().length());
String[] tokens = topic.split("/"); return resolveTopicSuffix(suffix);
int tokenIndex = 0;
java.util.Optional<MqttTopic> result = check(tokens, 0, getTopics());
if (!result.isPresent() && !ignoredTopics.contains(topic)) {
logger.error("Could not resolve {}, ignoring it.", topic);
ignoredTopics.add(topic);
}
return result;
} }
java.util.Optional<MqttTopic> MqttRoot.check(String[] tokens, int tokenIndex, JastAddList<MqttTopic> topics) { //--- resolveTopicSuffix ---
for (MqttTopic current : topics) { syn java.util.Optional<MqttTopic> MqttRoot.resolveTopicSuffix(String suffix) {
if (tokens[tokenIndex].equals(current.getPart())) { for (MqttTopic current : getTopics()) {
// topic part matches, move on or return if tokens are empty if (current.getTopicString().equals(suffix)) {
++tokenIndex; return Optional.of(current);
if (tokens.length == tokenIndex) {
return java.util.Optional.of(current);
} else {
return check(tokens, tokenIndex, current.getSubTopics());
} }
} }
} return Optional.empty();
return java.util.Optional.empty();
} }
public void MqttRoot.ensureCorrectPrefixes() { public void MqttRoot.ensureCorrectPrefixes() {
if (!getIncomingPrefix().endsWith("/")) { if (!getIncomingPrefix().isEmpty() && !getIncomingPrefix().endsWith("/")) {
setIncomingPrefix(getIncomingPrefix() + "/"); setIncomingPrefix(getIncomingPrefix() + "/");
} }
if (!getOutgoingPrefix().endsWith("/")) { if (!getOutgoingPrefix().isEmpty() && !getOutgoingPrefix().endsWith("/")) {
setOutgoingPrefix(getOutgoingPrefix() + "/"); setOutgoingPrefix(getOutgoingPrefix() + "/");
} }
} }
//--- getIncomingTopic --- //--- getIncomingTopic ---
syn String MqttTopic.getIncomingTopic() = getMqttRoot().getIncomingPrefix() + allParts(); syn String MqttTopic.getIncomingTopic() = getMqttRoot().getIncomingPrefix() + getTopicString();
//--- getOutgoingTopic --- //--- getOutgoingTopic ---
syn String MqttTopic.getOutgoingTopic() = getMqttRoot().getOutgoingPrefix() + allParts(); syn String MqttTopic.getOutgoingTopic() = getMqttRoot().getOutgoingPrefix() + getTopicString();
//--- allParts ---
inh String MqttTopic.allParts();
eq MqttTopic.getSubTopic(int i).allParts() {
return allParts() + "/" + getSubTopic(i).getPart();
}
eq MqttRoot.getTopic(int i).allParts() {
return getTopic(i).getPart();
}
//--- getMqttSender (should be cached) --- //--- getMqttSender (should be cached) ---
cache MqttRoot.getMqttSender(); cache MqttRoot.getMqttSender();
...@@ -78,12 +55,12 @@ aspect MQTT { ...@@ -78,12 +55,12 @@ aspect MQTT {
inh MqttRoot MqttTopic.getMqttRoot(); inh MqttRoot MqttTopic.getMqttRoot();
eq MqttRoot.getTopic().getMqttRoot() = this; eq MqttRoot.getTopic().getMqttRoot() = this;
eq MqttTopic.getSubTopic().getMqttRoot() = getMqttRoot();
/** /**
* Sends the current state via MQTT. * Sends the current state via MQTT.
*/ */
public void Item.sendState() throws Exception { refine ItemHandling protected void Item.sendState() throws Exception {
refined();
if (getTopic() != null) { if (getTopic() != null) {
getTopic().send(getStateAsString()); getTopic().send(getStateAsString());
} }
...@@ -97,4 +74,14 @@ aspect MQTT { ...@@ -97,4 +74,14 @@ aspect MQTT {
getMqttRoot().getMqttSender().publish(getOutgoingTopic(), message); getMqttRoot().getMqttSender().publish(getOutgoingTopic(), message);
} }
refine OpenHAB2 public void OpenHAB2Model.addNewItem(Item item) {
refined(item);
// update mqtt-topic to new mqtt-root
JavaUtils.ifPresentOrElse(
getRoot().getMqttRoot().resolveTopicSuffix(item.getTopic().getTopicString()),
topic -> item.setTopic(topic),
() -> de.tudresden.inf.st.eraser.util.ParserUtils.createMqttTopic(item, item.getTopic().getTopicString(), getRoot())
);
}
} }
// ---------------- MQTT ------------------------------
MqttRoot ::= Topic:MqttTopic* <IncomingPrefix:String> <OutgoingPrefix:String> [Host:ExternalHost] ;
MqttTopic ::= <TopicString:String> ;
rel Item.Topic? <-> MqttTopic.Item* ;
aspect OpenHAB2 {
syn ActivityItem OpenHAB2Model.getActivityItem() {
return new ActivityItem();
}
public void OpenHAB2Model.addNewItem(Item item) {
JavaUtils.ifPresentOrElse(
resolveGroup(de.tudresden.inf.st.eraser.util.ParserUtils.UNKNOWN_GROUP_NAME),
group -> group.addItem(item),
() -> de.tudresden.inf.st.eraser.util.ParserUtils.createUnknownGroup(this, Collections.singletonList(item)));
}
}
// ---------------- openHAB ------------------------------
OpenHAB2Model ::= Thing* Group* ThingType* ChannelType* ChannelCategory* ItemCategory* /ActivityItem:Item/ ;
abstract ModelElement ::= <ID:String> ;
abstract LabelledModelElement : ModelElement ::= <Label:String> ;
abstract DescribableModelElement : LabelledModelElement ::= <Description:String> ;
ThingType : DescribableModelElement ::= Parameter* ;
rel ThingType.ChannelType* -> ChannelType ;
Thing : LabelledModelElement ::= Channel* ;
rel Thing.Type -> ThingType ;
ChannelType : DescribableModelElement ::= <ItemType:ItemType> <ReadOnly:boolean> ;
rel ChannelType.ChannelCategory -> ChannelCategory ;
abstract ChannelCategory ;
DefaultChannelCategory : ChannelCategory ::= <Value:DefaultChannelCategoryValue> ;
SimpleChannelCategory : ChannelCategory ::= <Value:String> ;
Channel : ModelElement ::= ;
rel Channel.Type -> ChannelType ;
rel Channel.LinkedItem* <-> Item.Channel? ;
Parameter : DescribableModelElement ::= <Type:ParameterValueType> [DefaultValue:ParameterDefaultValue] <Context:String> <Required:boolean> ;
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> ;
abstract ItemWithDoubleState : Item ::= <_state:double> ;
ColorItem : Item ::= <_state:TupleHSB> ;
DateTimeItem : Item ::= <_state:Instant> ;
ContactItem : ItemWithBooleanState ;
DimmerItem : ItemWithDoubleState ;
ImageItem : ItemWithStringState ;
LocationItem : ItemWithStringState ;
NumberItem : ItemWithDoubleState ;
PlayerItem : ItemWithStringState ;
RollerShutterItem : ItemWithDoubleState ;
StringItem : ItemWithStringState ;
SwitchItem : ItemWithBooleanState ;
DefaultItem : ItemWithStringState ;
ActivityItem : ItemWithDoubleState ;
ItemMetaData ::= <Key:String> <Value:String> ;
ItemCategory ::= <Name:String> ;
Group : LabelledModelElement ::= Group* Item* [AggregationFunction:GroupAggregationFunction] ;
abstract GroupAggregationFunction ;
SimpleGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:SimpleGroupAggregationFunctionName> ;
ParameterizedGroupAggregationFunction : GroupAggregationFunction ::= <FunctionName:ParameterizedGroupAggregationFunctionName>
<Param1:String> <Param2:String> ;
...@@ -6,8 +6,6 @@ import de.tudresden.inf.st.eraser.jastadd.model.Root; ...@@ -6,8 +6,6 @@ import de.tudresden.inf.st.eraser.jastadd.model.Root;
import de.tudresden.inf.st.eraser.openhab2.OpenHab2Importer; import de.tudresden.inf.st.eraser.openhab2.OpenHab2Importer;
import de.tudresden.inf.st.eraser.openhab2.mqtt.MQTTUpdater; import de.tudresden.inf.st.eraser.openhab2.mqtt.MQTTUpdater;
import de.tudresden.inf.st.eraser.util.ParserUtils; import de.tudresden.inf.st.eraser.util.ParserUtils;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import java.io.*; import java.io.*;
...@@ -16,7 +14,7 @@ import java.io.*; ...@@ -16,7 +14,7 @@ import java.io.*;
* Main entry point for testing eraser. * Main entry point for testing eraser.
* @author rschoene - Initial contribution * @author rschoene - Initial contribution
*/ */
@SuppressWarnings({"unused", "WeakerAccess", "RedundantThrows"}) @SuppressWarnings({"unused", "RedundantThrows"})
public class Main { public class Main {
public static void main(String[] args) throws IOException, Parser.Exception { public static void main(String[] args) throws IOException, Parser.Exception {
...@@ -25,35 +23,6 @@ public class Main { ...@@ -25,35 +23,6 @@ public class Main {
// Root model = importFromOpenHab(); // Root model = importFromOpenHab();
// testPrinterWith(model); // testPrinterWith(model);
// testUpdaterWith(model); // testUpdaterWith(model);
testXY_to_RGB();
}
private static void testXY_to_RGB() {
/*
XYZ to RGB [M]-1
2.0413690 -0.5649464 -0.3446944
-0.9692660 1.8760108 0.0415560
0.0134474 -0.1183897 1.0154096
*/
double[][] matrixData = { { 2.0413690, -0.5649464, -0.3446944},
{-0.9692660, 1.8760108, 0.0415560},
{ 0.0134474, -0.1183897, 1.0154096}};
RealMatrix mInverted = MatrixUtils.createRealMatrix(matrixData);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (true) {
try {
double x = readFromSystemIn(in, "x:");
double y = readFromSystemIn(in, "y:");
double z = 1;
RealMatrix xyz = MatrixUtils.createColumnRealMatrix(new double[] {x,y,z});
RealMatrix result = mInverted.multiply(xyz);
System.out.println(result);
} catch (IOException | NumberFormatException e) {
e.printStackTrace();
break;
}
}
} }
private static double readFromSystemIn(BufferedReader in, String prompt) throws IOException { private static double readFromSystemIn(BufferedReader in, String prompt) throws IOException {
...@@ -70,7 +39,7 @@ public class Main { ...@@ -70,7 +39,7 @@ public class Main {
private static void testPrinterWith(Root model) { private static void testPrinterWith(Root model) {
model.flushTreeCache(); model.flushTreeCache();
System.out.println("Got model: " + model.description()); System.out.println("Got model: " + model.getOpenHAB2Model().description());
System.out.println("PrettyPrinted:"); System.out.println("PrettyPrinted:");
System.out.println(model.prettyPrint()); System.out.println(model.prettyPrint());
} }
...@@ -79,7 +48,7 @@ public class Main { ...@@ -79,7 +48,7 @@ public class Main {
Root model; Root model;
// model = importFromOpenHab(); // model = importFromOpenHab();
model = importFromFile(); model = importFromFile();
System.out.println("Got model: " + model.description()); System.out.println("Got model: " + model.getOpenHAB2Model().description());
// JsonSerializer.write(model, "openhab2-data.json"); // JsonSerializer.write(model, "openhab2-data.json");
testUpdaterWith(model); testUpdaterWith(model);
} }
...@@ -106,7 +75,7 @@ public class Main { ...@@ -106,7 +75,7 @@ public class Main {
public static Root importFromOpenHab() { public static Root importFromOpenHab() {
OpenHab2Importer importer = new OpenHab2Importer(); OpenHab2Importer importer = new OpenHab2Importer();
return importer.importFrom("192.168.1.250", 8080); return importer.importFrom("192.168.1.250", 8080).getRoot();
} }
public static Root importFromFile() { public static Root importFromFile() {
......
...@@ -48,12 +48,17 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> { ...@@ -48,12 +48,17 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> {
r.put(c.getName(), ((node, model) -> f.apply(model, termValue(node, terminalName)))); r.put(c.getName(), ((node, model) -> f.apply(model, termValue(node, terminalName))));
} }
private void addResolverForOpenHAB2Model(Map<String, ResolveAstNodeForOpenHAB2Model> r, Class<?> c, BiFunction<OpenHAB2Model, String, Optional<? extends ASTNode>> f, String terminalName) {
r.put(c.getName(), ((node, model) -> f.apply(model, termValue(node, terminalName))));
}
private Map<String, ResolveAstNode> resolvers = new HashMap<>(); private Map<String, ResolveAstNode> resolvers = new HashMap<>();
private Map<String, ResolveAstNodeForOpenHAB2Model> resolversForOpenHAB2Model = new HashMap<>();
private void initResolvers() { private void initResolvers() {
addResolver(resolvers, ThingType.class, Root::resolveThingType, "ID"); addResolverForOpenHAB2Model(resolversForOpenHAB2Model, ThingType.class, OpenHAB2Model::resolveThingType, "ID");
addResolver(resolvers, ChannelType.class, Root::resolveChannelType, "ID"); addResolverForOpenHAB2Model(resolversForOpenHAB2Model, ChannelType.class, OpenHAB2Model::resolveChannelType, "ID");
addResolver(resolvers, Item.class, Root::resolveItem, "ID"); addResolverForOpenHAB2Model(resolversForOpenHAB2Model, Item.class, OpenHAB2Model::resolveItem, "ID");
addResolver(resolvers, MqttTopic.class, Root::resolveMqttTopic, "IncomingTopic"); addResolver(resolvers, MqttTopic.class, Root::resolveMqttTopic, "IncomingTopic");
} }
...@@ -363,11 +368,15 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> { ...@@ -363,11 +368,15 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> {
} }
} }
interface ResolveAstNode { interface ResolveAstNode {
Optional<? extends ASTNode> resolve(JsonNode node, Root model) throws IOException; Optional<? extends ASTNode> resolve(JsonNode node, Root model) throws IOException;
} }
interface ResolveAstNodeForOpenHAB2Model {
Optional<? extends ASTNode> resolve(JsonNode node, OpenHAB2Model model) throws IOException;
}
class ResolveLater { class ResolveLater {
JsonNode node; JsonNode node;
......
package de.tudresden.inf.st.eraser.jastadd.model;
import java.util.function.Consumer;
/**
* Consumer used to make edits in the action part of ECA rules.
*
* @author rschoene - Initial contribution
*/
public interface Action2EditConsumer extends Consumer<Item> {
}
package de.tudresden.inf.st.eraser.jastadd.model;
import java.util.function.Function;
/**
* Function, that takes a double as input and outputs a double.
*
* @author rschoene - Initial contribution
*/
public interface DoubleDoubleFunction extends Function<Double, Double> {
}
...@@ -46,7 +46,7 @@ public abstract class InfluxAdapter implements AutoCloseable { ...@@ -46,7 +46,7 @@ public abstract class InfluxAdapter implements AutoCloseable {
/** /**
* Forces this adapter to compute {@link #asyncQuery(String, String, Class, QueryResultCallback)} synchronously. * Forces this adapter to compute {@link #asyncQuery(String, String, Class, QueryResultCallback)} synchronously.
*/ */
public void diableAsyncQuery() { public void disableAsyncQuery() {
this.reallyAsync = false; this.reallyAsync = false;
} }
......
package de.tudresden.inf.st.eraser.jastadd.model;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.time.Instant;
import java.util.List;
/**
* Adapter for internally held machine learning models.
*
* @author rschoene - Initial contribution
*/
public class InternalMachineLearningHandler implements MachineLearningEncoder, MachineLearningDecoder {
private static final Logger logger = LogManager.getLogger(InternalMachineLearningHandler.class);
private InternalMachineLearningModel model;
public InternalMachineLearningHandler setModel(InternalMachineLearningModel model) {
this.model = model;
return this;
}
@Override
public void setKnowledgeBaseRoot(Root root) {
// ignored
}
@Override
public void newData(List<Item> changedItems) {
logger.debug("Ignored new data of {}", changedItems);
}
@Override
public List<Item> getTargets() {
return model.getTargetItems();
}
@Override
public List<Item> getRelevantItems() {
return model.getRelevantItems();
}
@Override
public void triggerTraining() {
logger.debug("Ignored training trigger.");
}
@Override
public MachineLearningResult classify() {
List<ItemPreference> preferences = model.classify().computePreferences();
return new InternalMachineLearningResult(preferences);
}
@Override
public Instant lastModelUpdate() {
return null;
}
}
package de.tudresden.inf.st.eraser.jastadd.model;
import java.util.List;
/**
* Result of a classification returned by an internally held machine learning model.
*
* @author rschoene - Initial contribution
*/
public class InternalMachineLearningResult implements MachineLearningResult {
private final List<ItemPreference> preferences;
InternalMachineLearningResult(List<ItemPreference> preferences) {
this.preferences = preferences;
}
@Override
public List<ItemPreference> getPreferences() {
return this.preferences;
}
}
package de.tudresden.inf.st.eraser.jastadd.model;
import java.util.function.Function;
/**
* Merge states from given items into one (generic) state represented as a string.
*
* @author rschoene - Initial contribution
*/
public interface ItemsToStringFunction extends Function<Iterable<Item>, String> {
}
package de.tudresden.inf.st.eraser.jastadd.model;
import java.time.Instant;
/**
* This interface represents the connection from a machine learning model back to the knowledge base.
* It decodes the output of the machine learning model and outputs the result of the classification.
*
* @author rschoene - Initial contribution
*/
@SuppressWarnings("unused")
public interface MachineLearningDecoder extends MachineLearningSetRoot {
/**
* Execute the machine learning model and returns the classification result.
* @return the result of the classification
*/
MachineLearningResult classify();
// less important
/**
* Returns the time when the model was last updated, i.e., when the last training was completed.
* @return the time when the model was last updated, or <code>null</code> if the model was not trained yet
*/
Instant lastModelUpdate();
}
package de.tudresden.inf.st.eraser.jastadd.model;
import java.util.List;
/**
* This interface represents the connection from knowledge base to one machine learning model.
* It takes information from the knowledge base, and encodes them to a representation that is readable both for
* the used technique and the purpose of the machine learning model.
*
* @author rschoene - Initial contribution
*/
@SuppressWarnings("unused")
public interface MachineLearningEncoder extends MachineLearningSetRoot {
/**
* Update when new data is available.
* @param changedItems A list of items whose state has changed
*/
void newData(List<Item> changedItems);
// to be discussed, in which form this is specified
/**
* Get the items that this model is supposed to change.
* @return the list of targeted items
*/
List<Item> getTargets();
// to be discussed, in which form this is specified
/**
* Get the items which are relevant for the decision making of this model.
* @return the list of items relevant for decision making
*/
List<Item> getRelevantItems();
// to be discussed, if this is necessary
/**
* Explicit hint for this model to start/trigger training. The model might ignore this hint.
*/
void triggerTraining();
}
package de.tudresden.inf.st.eraser.jastadd.model;
import de.tudresden.inf.st.eraser.jastadd.model.ItemPreference;
import java.util.List;
/**
* Representation of a classification result using a MachineLearningModel.
*
* @author rschoene - Initial contribution
*/
@SuppressWarnings("unused")
public interface MachineLearningResult {
// Object rawClass();
// double rawConfidence();
// can be used for both activity and preferences
/**
* Get the result as a list of item preferences, i.e., new states to be set for those items.
* @return the classification result as item preferences
*/
List<ItemPreference> getPreferences();
}
package de.tudresden.inf.st.eraser.jastadd.model;
/**
* Common interface for both {@link MachineLearningDecoder} and {@link MachineLearningEncoder}.
*
* @author rschoene - Initial contribution
*/
public interface MachineLearningSetRoot {
/**
* Informs this handler of the knowledge base.
* This method is called before any other of the interface methods.
* @param root The root node of the knowledge base
*/
void setKnowledgeBaseRoot(Root root);
}
package de.tudresden.inf.st.eraser.jastadd.model;
import java.util.function.Supplier;
/**
* Provide a new state in form of a string which is set to the item.
*
* @author rschoene - Initial contribution
*/
public interface NewStateProvider extends Supplier<String> {
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment