Skip to content

Commit dcf0933

Browse files
author
Tony Brar
committed
Add support for config profiles
Active profile is specified in profile.yml Separate folders are created for each profile Closes #40
1 parent b4ee95f commit dcf0933

File tree

5 files changed

+70
-8
lines changed

5 files changed

+70
-8
lines changed

config/default/commands.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# example custom commands config file
2+
TurretShoot:
3+
kingRollerPower: 1.0
4+
timeout: 2.1
5+
6+
NewTree:
7+
key1: value1
8+
key2: value2

config/profile.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
default

core/src/main/java/org/teamtators/rotator/config/ConfigLoader.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.databind.JsonNode;
44
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.fasterxml.jackson.databind.node.ObjectNode;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78

@@ -11,6 +12,7 @@
1112
import java.io.FileInputStream;
1213
import java.io.IOException;
1314
import java.io.InputStream;
15+
import java.util.Iterator;
1416

1517
public class ConfigLoader {
1618
private static final Logger logger = LoggerFactory.getLogger(ConfigLoader.class);
@@ -33,4 +35,51 @@ public JsonNode load(String fileName) {
3335
throw new ConfigException(String.format("Error loading config %s", fileName), e);
3436
}
3537
}
38+
39+
/**
40+
* Get a config, modified for the specified profile
41+
*
42+
* @param configName Config to get
43+
* @param profileName Profile to apply
44+
* @return Combined config for profile
45+
*/
46+
public JsonNode getProfileConfig(String configName, String profileName) {
47+
// TODO: check if that profile even exists
48+
JsonNode mainConfig = load(configName);
49+
File f = new File(configDir + File.separator + profileName + File.separator + configName);
50+
// check if we should just use default config
51+
if (profileName.equals("empty") || !f.exists()) {
52+
return mainConfig;
53+
} else {
54+
JsonNode profileConfig = load(profileName + File.separator + configName);
55+
return mergeNodes(mainConfig, profileConfig);
56+
}
57+
}
58+
59+
/**
60+
* Combine two JsonNodes
61+
*
62+
* @param mainNode Node to merge into
63+
* @param updateNode Node to merge with
64+
* @return Combined node
65+
*/
66+
public static JsonNode mergeNodes(JsonNode mainNode, JsonNode updateNode) {
67+
Iterator<String> fieldNames = updateNode.fieldNames();
68+
while (fieldNames.hasNext()) {
69+
String fieldName = fieldNames.next();
70+
JsonNode jsonNode = mainNode.get(fieldName);
71+
// if field exists and is an embedded object
72+
if (jsonNode != null && jsonNode.isObject()) {
73+
// recurse into embedded object
74+
mergeNodes(jsonNode, updateNode.get(fieldName));
75+
} else {
76+
if (mainNode instanceof ObjectNode) {
77+
// overwrite field
78+
JsonNode value = updateNode.get(fieldName);
79+
((ObjectNode) mainNode).replace(fieldName, value);
80+
}
81+
}
82+
}
83+
return mainNode;
84+
}
3685
}

desktop/src/main/java/org/teamtators/rotator/Main.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ public void start() {
4545

4646
commandStore.setRobot(robot);
4747

48-
logger.debug("Loading configs");
49-
ObjectNode commandsConfig = (ObjectNode) configLoader.load("commands.yml");
50-
ObjectNode simulationConfig = (ObjectNode) configLoader.load("simulation.yml");
51-
ObjectNode triggersConfig = (ObjectNode) configLoader.load("triggers.yml");
48+
String profileName = configLoader.load("profile.yml").textValue();
49+
logger.debug("Loading configs with profile {}");
50+
ObjectNode commandsConfig = (ObjectNode) configLoader.getProfileConfig("commands.yml", profileName);
51+
ObjectNode simulationConfig = (ObjectNode) configLoader.getProfileConfig("subsystems.yml", profileName);
52+
ObjectNode triggersConfig = (ObjectNode) configLoader.getProfileConfig("triggers.yml", profileName);
53+
logger.debug("Finished loading configs");
5254

5355
logger.debug("Configuring subsystems");
5456
for (Subsystem subsystem : robot.subsystems()) {

rio/src/main/java/org/teamtators/rotator/Robot.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ private void initialize() {
6565
commandStore.setRobot(robot);
6666

6767
logger.debug("Created injector. Loading configs");
68-
ObjectNode commandsConfig = (ObjectNode) configLoader.load("commands.yml");
69-
ObjectNode subsystemsConfig = (ObjectNode) configLoader.load("subsystems.yml");
70-
ObjectNode triggersConfig = (ObjectNode) configLoader.load("triggers.yml");
71-
68+
String profileName = configLoader.load("profile.yml").textValue();
69+
logger.debug("Currently active config profile: {}", profileName);
70+
ObjectNode commandsConfig = (ObjectNode) configLoader.getProfileConfig("commands.yml", profileName);
71+
ObjectNode subsystemsConfig = (ObjectNode) configLoader.getProfileConfig("subsystems.yml", profileName);
72+
ObjectNode triggersConfig = (ObjectNode) configLoader.getProfileConfig("triggers.yml", profileName);
73+
logger.debug("Completed loading configs");
7274

7375
logger.debug("Configuring subsystems");
7476
for (Subsystem subsystem : subsystems) {

0 commit comments

Comments
 (0)