10
10
11
11
import com .fasterxml .jackson .databind .ObjectMapper ;
12
12
import eu .nebulous .ems .translate .TranslationService ;
13
+ import gr .iccs .imu .ems .brokercep .cep .MathUtil ;
14
+ import lombok .NonNull ;
13
15
import lombok .RequiredArgsConstructor ;
14
16
import lombok .extern .slf4j .Slf4j ;
15
17
import org .apache .commons .lang3 .StringUtils ;
21
23
import java .nio .file .Files ;
22
24
import java .nio .file .Path ;
23
25
import java .nio .file .Paths ;
26
+ import java .util .HashMap ;
24
27
import java .util .List ;
25
28
import java .util .Map ;
29
+ import java .util .Set ;
26
30
import java .util .stream .Collectors ;
27
31
28
32
@ Slf4j
31
35
public class ModelsService implements InitializingBean {
32
36
final static String MODEL_FILE_KEY = "model-file" ;
33
37
final static String BINDINGS_FILE_KEY = "bindings-file" ;
38
+ final static String SOLUTIONS_FILE_KEY = "solutions-file" ;
34
39
final static String OPTIMISER_METRICS_FILE_KEY = "optimiser-metrics-file" ;
35
40
41
+ public final static String SIMPLE_BINDING_KEY = "simple-bindings" ;
42
+ public final static String COMPOSITE_BINDING_KEY = "composite-bindings" ;
43
+
36
44
private final TranslationService translationService ;
37
45
private final EmsBootProperties properties ;
38
46
private final ObjectMapper objectMapper ;
39
47
private final IndexService indexService ;
40
48
49
+ private final Map <String ,Map <String ,Double >> allVariableValues = new HashMap <>();
50
+
41
51
@ Override
42
52
public void afterPropertiesSet () throws Exception {
43
53
if (! properties .isEnabled ()) {
@@ -65,19 +75,62 @@ String extractBindings(Command command, String appId) throws IOException {
65
75
log .debug ("Received a new DSL Generic message from external broker: {}" , command .body ());
66
76
67
77
// Extract EMS constants-to-Optimizer variables bindings
68
- Map <String , String > bindingsMap = null ;
78
+ Map <String ,Map < String , String > > bindingsMap = null ;
69
79
try {
70
80
List <Map <String ,Object >> list = (List ) command .body ().get ("utilityFunctions" );
71
81
if (list ==null || list .isEmpty ()) {
72
82
log .warn ("No utilityFunctions found in DSL generic message: {}" , command .body ());
73
83
} else {
74
- bindingsMap = list .stream ()
75
- .filter (uf -> "constant" .equalsIgnoreCase ( uf .getOrDefault ("type" , "" ).toString () ))
84
+ Map <String , String > simpleBindingsMap = list .stream ()
85
+ .filter (uf -> "constant" .equalsIgnoreCase (uf .getOrDefault ("type" , "" ).toString ()))
86
+ .filter (uf -> ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).size () == 1
87
+ && StringUtils .equals (
88
+ ((Map ) uf .get ("expression" )).getOrDefault ("formula" , "" ).toString ().trim (),
89
+ ((Map ) ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).get (0 )).getOrDefault ("name" , "" ).toString ().trim ()
90
+ )
91
+ )
92
+ .collect (Collectors .toMap (
93
+ uf -> ((Map ) ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).get (0 )).getOrDefault ("value" , "" ).toString ().trim (),
94
+ uf -> uf .getOrDefault ("name" , "" ).toString ().trim ()
95
+ ));
96
+ Map <String , String > compositeBindingsMap = list .stream ()
97
+ .filter (uf -> "constant" .equalsIgnoreCase (uf .getOrDefault ("type" , "" ).toString ()))
98
+ .filter (uf -> ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).size () > 1
99
+ || ! StringUtils .equals (
100
+ ((Map ) uf .get ("expression" )).getOrDefault ("formula" , "" ).toString ().trim (),
101
+ ((Map ) ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).get (0 )).getOrDefault ("name" , "" ).toString ().trim ()
102
+ )
103
+ )
76
104
.collect (Collectors .toMap (
77
- uf -> ((Map ) ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).get (0 )).getOrDefault ("value" , "" ).toString (),
78
- uf -> uf .getOrDefault ("name" , "" ).toString ()
105
+ uf -> {
106
+ log .trace ("Got composite constant entry: {}" , uf );
107
+
108
+ // Get UF variable names-to-vela variables mapping
109
+ final Map <String ,String > varBindings = new HashMap <>();
110
+ ((List ) ((Map ) uf .get ("expression" )).get ("variables" )).forEach (o -> {
111
+ if (o instanceof Map map ) {
112
+ String varName = map .getOrDefault ("name" , "" ).toString ();
113
+ String varValue = map .getOrDefault ("value" , "" ).toString ();
114
+ varBindings .put (varName , varValue );
115
+ }
116
+ });
117
+ log .trace ("Composite constant bindings: {}" , varBindings );
118
+
119
+ // Rename formula variables
120
+ String formula = ((Map ) uf .get ("expression" )).getOrDefault ("formula" , "" ).toString ().trim ();
121
+ log .trace ("Composite constant original formula: {}" , formula );
122
+ @ NonNull String newFormula = MathUtil .renameFormulaArguments (formula , varBindings );
123
+ log .trace ("Composite constant modified formula: {}" , newFormula );
124
+
125
+ return newFormula ;
126
+ },
127
+ uf -> uf .getOrDefault ("name" , "" ).toString ().trim ()
79
128
));
80
- if (bindingsMap .isEmpty ())
129
+ bindingsMap = Map .of (
130
+ SIMPLE_BINDING_KEY , simpleBindingsMap ,
131
+ COMPOSITE_BINDING_KEY , compositeBindingsMap
132
+ );
133
+ if (simpleBindingsMap .isEmpty ())
81
134
log .warn ("No bindings found in DSL generic message: {}" , command .body ());
82
135
}
83
136
} catch (Exception e ) {
@@ -91,7 +144,7 @@ String extractBindings(Command command, String appId) throws IOException {
91
144
storeToFile (bindingsFile , objectMapper .writeValueAsString (bindingsMap ));
92
145
log .info ("Stored bindings in file: app-id={}, file={}" , appId , bindingsFile );
93
146
94
- // Add appId-modelFile entry in the stored Index
147
+ // Add appId-bindingsMap entry in the stored Index
95
148
indexService .storeToIndex (appId , Map .of (BINDINGS_FILE_KEY , bindingsFile ));
96
149
97
150
return "OK" ;
@@ -125,12 +178,65 @@ String extractOptimiserMetrics(Command command, String appId) throws IOException
125
178
storeToFile (metricsFile , objectMapper .writeValueAsString (metricsList ));
126
179
log .info ("Stored metrics in file: app-id={}, file={}" , appId , metricsFile );
127
180
128
- // Add appId-modelFile entry in the stored Index
181
+ // Add appId-metricsList entry in the stored Index
129
182
indexService .storeToIndex (appId , Map .of (OPTIMISER_METRICS_FILE_KEY , metricsFile ));
130
183
131
184
return "OK" ;
132
185
}
133
186
187
+ String extractSolution (Command command , String appId ) throws IOException {
188
+ // Process Optimiser Metrics message
189
+ log .debug ("Received a new Solution message from external broker: {}" , command .body ());
190
+
191
+ // Extract Optimizer metrics
192
+ boolean deployFlag ;
193
+ Map <String ,Double > varValues ;
194
+ try {
195
+ deployFlag = Boolean .parseBoolean (command .body ().getOrDefault ("DeploySolution" , "false" ).toString ());
196
+ Map <String ,Object > map = (Map ) command .body ().get ("VariableValues" );
197
+ if (map ==null || map .isEmpty ()) {
198
+ log .warn ("No VariableValues found in Solution message: {}" , command .body ());
199
+ return "ERROR: No VariableValues found in Solution message: " +command .body ();
200
+ } else {
201
+ Map <String , Object > varValuesObj = map .entrySet ().stream ()
202
+ .filter (e -> StringUtils .isNotBlank (e .getKey ()))
203
+ .collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
204
+ if (varValuesObj .isEmpty ()) {
205
+ log .warn ("Blank VariableValues found in Solution message: {}" , command .body ());
206
+ return "ERROR: Blank VariableValues found in Solution message: " +command .body ();
207
+ }
208
+
209
+ // Update variable values
210
+ varValues = varValuesObj .entrySet ().stream ()
211
+ .filter (e -> StringUtils .isNotBlank (e .getKey ()))
212
+ .filter (e -> e .getValue ()!=null )
213
+ .filter (e -> e .getValue () instanceof Number )
214
+ .collect (Collectors .toMap (
215
+ Map .Entry ::getKey ,
216
+ e ->((Number )e .getValue ()).doubleValue ()
217
+ ));
218
+ }
219
+ } catch (Exception e ) {
220
+ log .warn ("Error while extracting VariableValues from Solution message: " , e );
221
+ return "ERROR: Error while extracting VariableValues from Solution message: " +e .getMessage ();
222
+ }
223
+
224
+ // Get previous application (UF) variable values (solution)
225
+ Map <String , Double > appVariableValues = allVariableValues .computeIfAbsent (appId , app_id -> new HashMap <>());
226
+ if (appVariableValues .isEmpty () || deployFlag )
227
+ appVariableValues .putAll (varValues );
228
+
229
+ // Store app solution in models store
230
+ String solutionFile = getFileName ("sol" , appId , "json" );
231
+ storeToFile (solutionFile , objectMapper .writeValueAsString (appVariableValues ));
232
+ log .info ("Stored solution in file: app-id={}, file={}" , appId , solutionFile );
233
+
234
+ // Add appId-solutionFile entry in the stored Index
235
+ indexService .storeToIndex (appId , Map .of (SOLUTIONS_FILE_KEY , solutionFile ));
236
+
237
+ return "OK" ;
238
+ }
239
+
134
240
String processMetricModelMessage (Command command , String appId ) throws IOException {
135
241
// Process metric model message
136
242
log .debug ("Received a new Metric Model message from external broker: {}" , command .body ());
0 commit comments