Skip to content

Commit 4c20d07

Browse files
rbuddebjost2s
authored andcommitted
Issue #1651: add extensions for robot plugins
- adjust bookmarks for extensions - add d.ts file and change Map to JSONObject - names changed to camelCase - effect of changed names in restEntities.json - rm useless resources - corrections for program defaults - add frontend extensions - set robot.nn property - add extensions to restEntities and adapt tests - toolboxes edited - prototype for conditional toolboxes, programs, ... - properties get #ifdef preprocessing
1 parent 9501fe5 commit 4c20d07

File tree

142 files changed

+1329
-1938
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+1329
-1938
lines changed

OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/factory/RobotFactory.java

+34-31
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,26 @@
2323
public class RobotFactory {
2424
private static final Logger LOG = LoggerFactory.getLogger(RobotFactory.class);
2525

26+
private static final List<String> NO_DEFINITIONS = Collections.emptyList();
27+
2628
private final PluginProperties pluginProperties;
2729
private final BlocklyDropdownFactory blocklyDropdown2EnumFactory;
28-
private final String beginnerToolbox;
29-
private final String expertToolbox;
30-
private final String programDefault;
31-
private final String configurationToolbox;
30+
private final List<String> beginnerToolbox;
31+
private final List<String> expertToolbox;
32+
private final List<String> programDefault;
33+
private final List<String> configurationToolbox;
3234
private final String configurationDefault;
3335
private Map<String, IWorker> workers = new HashMap<>(); //worker type to implementing class(es) collect->de.fhg.iais.roberta.visitor.collect.Ev3UsedHardwareCollectorWorker
3436
private Map<String, List<String>> workflows = new HashMap<>(); //workflow name to a list of types of applicable workers: showsource->collect,generate
3537

3638
public RobotFactory(PluginProperties pluginProperties) {
3739
this.pluginProperties = pluginProperties;
3840
this.blocklyDropdown2EnumFactory = new BlocklyDropdownFactory();
39-
this.beginnerToolbox = Util.readResourceContent(this.pluginProperties.getStringProperty("robot.program.toolbox.beginner"));
40-
this.expertToolbox = Util.readResourceContent(this.pluginProperties.getStringProperty("robot.program.toolbox.expert"));
41-
if ( hasNN() ) {
42-
this.programDefault = Util.readResourceContent(this.pluginProperties.getStringProperty("robot.program.default.nn"));
43-
} else {
44-
this.programDefault = Util.readResourceContent(this.pluginProperties.getStringProperty("robot.program.default"));
45-
}
46-
this.configurationToolbox = Util.readResourceContent(this.pluginProperties.getStringProperty("robot.configuration.toolbox"));
41+
this.beginnerToolbox = Util.readResourceContentAsTemplate(this.pluginProperties.getStringProperty("robot.program.toolbox.beginner"));
42+
this.expertToolbox = Util.readResourceContentAsTemplate(this.pluginProperties.getStringProperty("robot.program.toolbox.expert"));
43+
this.programDefault = Util.readResourceContentAsTemplate(this.pluginProperties.getStringProperty("robot.program.default"));
44+
this.configurationToolbox = Util.readResourceContentAsTemplate(this.pluginProperties.getStringProperty("robot.configuration.toolbox"));
45+
// A configuration must NOT contain #ifdefs
4746
this.configurationDefault = Util.readResourceContent(this.pluginProperties.getStringProperty("robot.configuration.default"));
4847
loadWorkers();
4948
}
@@ -69,20 +68,20 @@ public final String getGroup() {
6968
return group != null && !group.equals("") ? group : this.pluginProperties.getRobotName();
7069
}
7170

72-
public final String getProgramToolboxBeginner() {
73-
return this.beginnerToolbox;
71+
public final String getProgramToolboxBeginner(List<String> extensions) {
72+
return Util.applyTemplate(this.beginnerToolbox, extensions);
7473
}
7574

76-
public final String getProgramToolboxExpert() {
77-
return this.expertToolbox;
75+
public final String getProgramToolboxExpert(List<String> extensions) {
76+
return Util.applyTemplate(this.expertToolbox, extensions);
7877
}
7978

80-
public final String getProgramDefault() {
81-
return this.programDefault;
79+
public final String getProgramDefault(List<String> extensions) {
80+
return Util.applyTemplate(this.programDefault, extensions);
8281
}
8382

84-
public final String getConfigurationToolbox() {
85-
return this.configurationToolbox;
83+
public final String getConfigurationToolbox(List<String> extensions) {
84+
return Util.applyTemplate(this.configurationToolbox, extensions);
8685
}
8786

8887
public final String getConfigurationDefault() {
@@ -93,32 +92,36 @@ public final String getRealName() {
9392
return this.pluginProperties.getStringProperty("robot.real.name");
9493
}
9594

96-
public final Boolean hasSim() {
95+
public final boolean hasSim() {
9796
return !this.pluginProperties.getStringProperty("robot.plugin.workflow.getsimulationcode").equals("do.nothing");
9897
}
9998

100-
public final Boolean hasMultipleSim() {
101-
return this.pluginProperties.getStringProperty("robot.multisim") != null && this.pluginProperties.getStringProperty("robot.multisim").equals("true");
99+
public final boolean hasMultipleSim() {
100+
String p = this.pluginProperties.getStringProperty("robot.multisim");
101+
return p != null && p.equals("true");
102102
}
103103

104104
public boolean hasMarkerSim() {
105-
return this.pluginProperties.getStringProperty("robot.markersim") != null && this.pluginProperties.getStringProperty("robot.markersim").equals("true");
105+
String p = this.pluginProperties.getStringProperty("robot.markersim");
106+
return p != null && p.equals("true");
106107
}
107108

108-
public final Boolean hasNN() {
109-
return this.pluginProperties.getStringProperty("robot.nn") != null && this.pluginProperties.getStringProperty("robot.nn").equals("true");
109+
public final String nnProperty() {
110+
String p = this.pluginProperties.getStringProperty("robot.nn");
111+
return p == null ? "never" : p;
110112
}
111113

112114
public final JSONArray getNNActivations() {
113-
if ( hasNN() ) {
114-
String values = this.pluginProperties.getStringProperty("robot.nn.activations");
115+
String values = this.pluginProperties.getStringProperty("robot.nn.activations");
116+
if ( values == null ) {
117+
return new JSONArray();
118+
} else {
115119
List<String> activations = Stream.of(values.trim().split("\\s*,\\s*")).collect(Collectors.toList());
116120
return new JSONArray(activations);
117121
}
118-
return new JSONArray();
119122
}
120123

121-
public Boolean hasWebotsSim() {
124+
public boolean hasWebotsSim() {
122125
return this.pluginProperties.getStringProperty("robot.webots.sim") != null && this.pluginProperties.getStringProperty("robot.webots.sim").equals("true");
123126
}
124127

@@ -161,7 +164,7 @@ public final String getVendorId() {
161164
return this.pluginProperties.getStringProperty("robot.vendor");
162165
}
163166

164-
public final Boolean hasConfiguration() {
167+
public final boolean hasConfiguration() {
165168
return Boolean.parseBoolean(this.pluginProperties.getStringProperty("robot.configuration"));
166169
}
167170

OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/Util.java

+61
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.sql.Timestamp;
1515
import java.text.CharacterIterator;
1616
import java.text.StringCharacterIterator;
17+
import java.util.ArrayList;
1718
import java.util.Arrays;
1819
import java.util.Base64;
1920
import java.util.Date;
@@ -23,6 +24,7 @@
2324
import java.util.Properties;
2425
import java.util.StringJoiner;
2526
import java.util.concurrent.atomic.AtomicInteger;
27+
import java.util.regex.Matcher;
2628
import java.util.regex.Pattern;
2729
import java.util.stream.Collectors;
2830
import java.util.stream.Stream;
@@ -49,6 +51,8 @@ public class Util {
4951
private static final Pattern NUMBER_PATTERN = Pattern.compile("^(-?\\d+((.|e-|e\\+)?\\d*|_?\\d*[a-zA-Z]{0,3})?|(0x|0X)[0-9a-fA-F]*)$");
5052
private static final Pattern FILENAME_PATTERN = Pattern.compile("^[\\w-]+.[A-Za-z]{1,6}$");
5153
private static final Pattern PORT_NAME_PATTERN = Pattern.compile("^\\w+$");
54+
private static final Pattern IFDEF_PATTERN = Pattern.compile("^\\s*#ifdef (.*)$");
55+
private static final Pattern END_PATTERN = Pattern.compile("^\\s*#end$");
5256
private static final String INVALID = "invalid";
5357
/**
5458
* YAML parser. NOT thread-safe!
@@ -318,6 +322,8 @@ public static String getErrorTicketId() {
318322
return "E-" + Util.errorTicketNumber.incrementAndGet();
319323
}
320324

325+
private static List<String> EMPTY_STRING_LIST = new ArrayList<>();
326+
321327
/**
322328
* read all lines from a resource, concatenate them to a string separated by a newline
323329
*
@@ -338,6 +344,61 @@ public static String readResourceContent(String resourceName) {
338344
} catch ( Exception e ) {
339345
throw new DbcException("reading resource failed for: " + resourceName, e);
340346
}
347+
348+
}
349+
350+
/**
351+
* read all lines from a resource, concatenate them to a string separated by a newline.
352+
* Allow #ifdef <extension> ... #end for conditional adding/removing resource lines
353+
*
354+
* @param resourceName
355+
* @return the content of the resource as a String list
356+
* @throws DbcException if the read fails
357+
*/
358+
public static List<String> readResourceContentAsTemplate(String resourceName) {
359+
final Class<?> clazz = Util.class;
360+
final List<String> resourceAsList = new ArrayList<>();
361+
try (BufferedReader in = new BufferedReader(new InputStreamReader(clazz.getResourceAsStream(resourceName), StandardCharsets.UTF_8))) {
362+
String line;
363+
while ( (line = in.readLine()) != null ) {
364+
resourceAsList.add(line);
365+
}
366+
return resourceAsList;
367+
} catch ( Exception e ) {
368+
throw new DbcException("reading resource as template failed for: " + resourceName, e);
369+
}
370+
}
371+
372+
/**
373+
* read all lines from a resource, concatenate them to a string separated by a newline.
374+
* Allow #ifdef <extension> ... #end for conditional adding/removing resource lines
375+
*
376+
* @param resourceName
377+
* @return the content of the resource as a String list
378+
* @throws DbcException if the read fails
379+
*/
380+
public static String applyTemplate(List<String> resourceAsList, List<String> extensions) {
381+
final String lineSeparator = System.lineSeparator();
382+
final StringBuilder sb = new StringBuilder();
383+
boolean ignoreLinesTriggeredByIfdef = false;
384+
for ( String line : resourceAsList ) {
385+
Matcher m = IFDEF_PATTERN.matcher(line);
386+
if ( m.matches() ) {
387+
if ( ignoreLinesTriggeredByIfdef ) {
388+
throw new DbcException("resource has nested #ifdefs");
389+
} else {
390+
String extension = m.group(1);
391+
if ( !extensions.contains(extension) ) {
392+
ignoreLinesTriggeredByIfdef = true;
393+
}
394+
}
395+
} else if ( END_PATTERN.matcher(line).matches() ) {
396+
ignoreLinesTriggeredByIfdef = false;
397+
} else if ( !ignoreLinesTriggeredByIfdef ) {
398+
sb.append(line).append(lineSeparator);
399+
}
400+
}
401+
return sb.toString();
341402
}
342403

343404
/**

OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/XsltAndJavaTransformer.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public Pair<String, String> transform(RobotFactory factory, String programText,
8484
BlockSet jaxbProgram = JaxbHelper.xml2Element(programText, BlockSet.class);
8585
xmlVersion = jaxbProgram.getXmlversion();
8686
Assert.notNull(jaxbProgram, "jaxb returns null for the program");
87-
checkAndAddNnDataForPlugin(factory.hasNN(), jaxbProgram);
87+
checkAndAddNnDataForPlugin(factory.nnProperty(), jaxbProgram);
8888
// jaxbProgram.setXmlversion("4.0"); // this is a bit too early, may cause problems, but later it is much more expensive
8989
programText = JaxbHelper.blockSet2xml(jaxbProgram);
9090
} catch ( Exception e ) {
@@ -127,8 +127,8 @@ public String transformXslt(String xml) {
127127
return output;
128128
}
129129

130-
private void checkAndAddNnDataForPlugin(boolean hasNN, BlockSet jaxbImportExport) {
131-
if ( hasNN ) {
130+
private void checkAndAddNnDataForPlugin(String nnProperty, BlockSet jaxbImportExport) {
131+
if ( !nnProperty.equals("never") ) {
132132
for ( Instance instance : jaxbImportExport.getInstance() ) {
133133
if ( instance.getBlock().get(0).getType().contains("robControls_start") ) {
134134
Block startBlock = instance.getBlock().get(0);

OpenRobertaServer/src/main/java/de/fhg/iais/roberta/generated/restEntities/BaseResponse.java

+22-22
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,27 @@ public BaseResponse merge(JSONObject jsonO) {
127127
setParameters(jsonO.optJSONObject(key));
128128
} else if ( "initToken".equals(key) ) {
129129
setInitToken(jsonO.getString(key));
130-
} else if ( "server.time".equals(key) ) {
130+
} else if ( "serverTime".equals(key) ) {
131131
setServerTime(jsonO.getLong(key));
132-
} else if ( "server.version".equals(key) ) {
132+
} else if ( "serverVersion".equals(key) ) {
133133
setServerVersion(jsonO.getString(key));
134-
} else if ( "robot.wait".equals(key) ) {
134+
} else if ( "robotWait".equals(key) ) {
135135
setRobotWait(jsonO.optLong(key));
136-
} else if ( "robot.battery".equals(key) ) {
136+
} else if ( "robotBattery".equals(key) ) {
137137
setRobotBattery(jsonO.optString(key));
138-
} else if ( "robot.name".equals(key) ) {
138+
} else if ( "robotName".equals(key) ) {
139139
setRobotName(jsonO.optString(key));
140-
} else if ( "robot.version".equals(key) ) {
140+
} else if ( "robotVersion".equals(key) ) {
141141
setRobotVersion(jsonO.optString(key));
142-
} else if ( "robot.firmwareName".equals(key) ) {
142+
} else if ( "robotFirmwareName".equals(key) ) {
143143
setRobotFirmwareName(jsonO.optString(key));
144-
} else if ( "robot.sensorvalues".equals(key) ) {
144+
} else if ( "robotSensorvalues".equals(key) ) {
145145
setRobotSensorvalues(jsonO.optJSONObject(key));
146-
} else if ( "robot.nepoexitvalue".equals(key) ) {
146+
} else if ( "robotNepoexitvalue".equals(key) ) {
147147
setRobotNepoexitvalue(jsonO.optInt(key));
148-
} else if ( "robot.state".equals(key) ) {
148+
} else if ( "robotState".equals(key) ) {
149149
setRobotState(jsonO.optString(key));
150-
} else if ( "notifications.available".equals(key) ) {
150+
} else if ( "notificationsAvailable".equals(key) ) {
151151
setNotificationsAvailable(jsonO.optBoolean(key));
152152
} else {
153153
throw new RuntimeException("JSON parse error. Found invalid key: " + key + " in " + jsonO);
@@ -703,34 +703,34 @@ public JSONObject toJson() {
703703
jsonO.put("parameters", this.parameters);
704704
}
705705
jsonO.put("initToken", this.initToken);
706-
jsonO.put("server.time", this.serverTime);
707-
jsonO.put("server.version", this.serverVersion);
706+
jsonO.put("serverTime", this.serverTime);
707+
jsonO.put("serverVersion", this.serverVersion);
708708
if ( this.robotWaitDefined ) {
709-
jsonO.put("robot.wait", this.robotWait);
709+
jsonO.put("robotWait", this.robotWait);
710710
}
711711
if ( this.robotBattery != null ) {
712-
jsonO.put("robot.battery", this.robotBattery);
712+
jsonO.put("robotBattery", this.robotBattery);
713713
}
714714
if ( this.robotName != null ) {
715-
jsonO.put("robot.name", this.robotName);
715+
jsonO.put("robotName", this.robotName);
716716
}
717717
if ( this.robotVersion != null ) {
718-
jsonO.put("robot.version", this.robotVersion);
718+
jsonO.put("robotVersion", this.robotVersion);
719719
}
720720
if ( this.robotFirmwareName != null ) {
721-
jsonO.put("robot.firmwareName", this.robotFirmwareName);
721+
jsonO.put("robotFirmwareName", this.robotFirmwareName);
722722
}
723723
if ( this.robotSensorvalues != null ) {
724-
jsonO.put("robot.sensorvalues", this.robotSensorvalues);
724+
jsonO.put("robotSensorvalues", this.robotSensorvalues);
725725
}
726726
if ( this.robotNepoexitvalueDefined ) {
727-
jsonO.put("robot.nepoexitvalue", this.robotNepoexitvalue);
727+
jsonO.put("robotNepoexitvalue", this.robotNepoexitvalue);
728728
}
729729
if ( this.robotState != null ) {
730-
jsonO.put("robot.state", this.robotState);
730+
jsonO.put("robotState", this.robotState);
731731
}
732732
if ( this.notificationsAvailableDefined ) {
733-
jsonO.put("notifications.available", this.notificationsAvailable);
733+
jsonO.put("notificationsAvailable", this.notificationsAvailable);
734734
}
735735
} catch ( JSONException e ) {
736736
throw new RuntimeException("JSON unparse error when unparsing: " + this, e);

0 commit comments

Comments
 (0)