Configuration.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package cz.senslog.watchdog.config;
  2. import org.apache.logging.log4j.LogManager;
  3. import org.apache.logging.log4j.Logger;
  4. import org.yaml.snakeyaml.Yaml;
  5. import java.io.FileNotFoundException;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.nio.file.Files;
  9. import java.nio.file.Path;
  10. import java.nio.file.Paths;
  11. import java.util.*;
  12. import static java.util.Collections.emptyList;
  13. import static java.util.Collections.singletonList;
  14. public class Configuration {
  15. private static final Logger logger = LogManager.getLogger(Configuration.class);
  16. private final GeneralConfig generalConfig;
  17. private final Collection<ExecutableGroup> execGroups;
  18. private final Collection<ExecutableSuperGroup> execSuperGroups;
  19. private final Collection<MessageBrokerConfig> messageBrokerConfigs;
  20. private final Collection<EmailServerConfig> emailServerConfigs;
  21. private final Collection<SensLogServerConfig> sensLogServerConfigs;
  22. private final Collection<DataProviderConfig> dataProviderConfigs;
  23. private Configuration(
  24. GeneralConfig generalConfig,
  25. Collection<ExecutableGroup> executableGroups,
  26. Collection<ExecutableSuperGroup> execSGroups,
  27. Collection<EmailServerConfig> emailServerConfigs,
  28. Collection<MessageBrokerConfig> messageBrokerConfigs,
  29. Collection<SensLogServerConfig> sensLogServerConfigs,
  30. Collection<DataProviderConfig> dataProviderConfigs
  31. ){
  32. this.generalConfig = generalConfig;
  33. this.execGroups = executableGroups;
  34. this.execSuperGroups = execSGroups;
  35. this.messageBrokerConfigs = messageBrokerConfigs;
  36. this.emailServerConfigs = emailServerConfigs;
  37. this.sensLogServerConfigs = sensLogServerConfigs;
  38. this.dataProviderConfigs = dataProviderConfigs;
  39. }
  40. private static Configuration make(
  41. GeneralConfig generalConfig,
  42. List<TempUnitConfig> monitoredObjects,
  43. Map<String, EmailServerConfig> emailServers,
  44. Map<String, MessageBrokerConfig> messageBrokers,
  45. Map<String, SensLogServerConfig> sensLogServers,
  46. Map<String, DataProviderConfig> dataProviders,
  47. Map<String, GroupConfig> groups,
  48. Map<String, SuperGroupConfig> superGroups
  49. ) {
  50. Map<String, ExecutableGroup> executableGroupsMap = new HashMap<>();
  51. for (TempUnitConfig mObject : monitoredObjects) {
  52. Set<String> unitGroups = mObject.groups;
  53. List<TempSensorConfig> sensors = mObject.sensors;
  54. if (unitGroups.isEmpty() && sensors.isEmpty()) {
  55. throw new IllegalStateException("The monitored object '"+mObject.id+"' is not assigned to any groups.");
  56. }
  57. sensors = !sensors.isEmpty() ? sensors : singletonList(new TempAllSensorsConfig(mObject.period));
  58. for (TempSensorConfig sensor : sensors) {
  59. String sensorId = sensor.id != null ? sensor.id : mObject.id;
  60. Set<String> sensorGroups = sensor.groups;
  61. if (unitGroups.isEmpty() && sensorGroups.isEmpty()) {
  62. throw new IllegalStateException("The monitored object '"+sensorId+"' is not assigned to any groups.");
  63. }
  64. sensorGroups.addAll(unitGroups);
  65. for (String groupId : sensorGroups) {
  66. GroupConfig groupConfig = groups.get(groupId);
  67. if (groupConfig == null) {
  68. throw new IllegalStateException(
  69. "Assigned group '"+groupId+"' to the monitored object '"+sensorId+"' does not exist."
  70. );
  71. }
  72. Integer period = groupConfig.getPeriod() != null ? groupConfig.getPeriod() : mObject.period;
  73. period = period != null ? period : sensor.period;
  74. if (period == null) {
  75. throw new IllegalStateException(
  76. "The monitored object '"+sensor.id+"' does not contain a valid 'period' value."
  77. );
  78. }
  79. if (!dataProviders.containsKey(groupConfig.getDataProviderId())) {
  80. throw new IllegalStateException(
  81. "Assigned data provider '"+groupConfig.getDataProviderId()+"' does not exist."
  82. );
  83. }
  84. if (!messageBrokers.containsKey(groupConfig.getMessageBrokerId())) {
  85. throw new IllegalStateException(
  86. "Assigned message broker '"+groupConfig.getMessageBrokerId()+"' does not exist."
  87. );
  88. }
  89. ExecutableGroup executableGroup = executableGroupsMap.computeIfAbsent(
  90. groupId, k -> new ExecutableGroup(groupConfig)
  91. );
  92. MonitoredObject sensorMObj = sensor.id != null ? new MonitoredObject(sensor.id, period) : new AllMonitoredObjects(period);
  93. executableGroup.swapPeriod(sensorMObj.getPeriod());
  94. executableGroup.computeIfAbsent(mObject.id, MonitoredObject::new)
  95. .addNode(sensorMObj.getId(), sensorMObj);
  96. }
  97. }
  98. }
  99. for (Map.Entry<String, GroupConfig> groupEntry : groups.entrySet()) {
  100. String groupId = groupEntry.getKey();
  101. GroupConfig groupConfig = groupEntry.getValue();
  102. if (!executableGroupsMap.containsKey(groupId)) {
  103. MonitoredObject allSensors = new AllMonitoredObjects(groupConfig.getPeriod());
  104. executableGroupsMap.computeIfAbsent(groupId, k -> new ExecutableGroup(groupConfig))
  105. .computeIfAbsent(groupId, k -> new AllMonitoredObjects(groupConfig.getPeriod()))
  106. .addNode(allSensors.getId(), allSensors);
  107. }
  108. }
  109. Map<String, ExecutableSuperGroup> executableSGroupsMap = new HashMap<>();
  110. for (SuperGroupConfig sGConfig : superGroups.values()) {
  111. if (sGConfig.getPeriod() == null) {
  112. throw new IllegalStateException(
  113. "The monitored object '"+sGConfig.getId()+"' does not contain a valid 'period' value."
  114. );
  115. }
  116. ExecutableSuperGroup executableSuperGroup = new ExecutableSuperGroup(sGConfig);
  117. for (String groupId : sGConfig.getGroups()) {
  118. ExecutableGroup group = executableGroupsMap.get(groupId);
  119. if (group == null) {
  120. throw new IllegalStateException("Assigned group '"+groupId+"' does not exist.");
  121. }
  122. GroupConfig gConfig = group.getConfig();
  123. GroupConfig newGConfig = new GroupConfig(gConfig.getId(), gConfig.getName(), true,
  124. gConfig.getDataProviderId(), gConfig.getMessageBrokerId(), sGConfig.getPeriod()
  125. );
  126. executableSuperGroup.addNode(groupId, ExecutableGroup.copy(group, newGConfig));
  127. }
  128. executableSGroupsMap.put(sGConfig.getId(), executableSuperGroup);
  129. }
  130. Collection<ExecutableGroup> execGroups = executableGroupsMap.values();
  131. Collection<ExecutableSuperGroup> execSGroups = executableSGroupsMap.values();
  132. Collection<EmailServerConfig> emailServerConfigs = emailServers.values();
  133. Collection<SensLogServerConfig> sensLogServerConfigs = sensLogServers.values();
  134. Collection<DataProviderConfig> dataProviderConfigs = dataProviders.values();
  135. Collection<MessageBrokerConfig> messageBrokerConfigs = messageBrokers.values();
  136. return new Configuration(generalConfig, execGroups, execSGroups,
  137. emailServerConfigs, messageBrokerConfigs,
  138. sensLogServerConfigs, dataProviderConfigs
  139. );
  140. }
  141. public static Configuration load(String fileName) throws IOException {
  142. logger.info("Loading '{}' configuration file.", fileName);
  143. if (!fileName.toLowerCase().endsWith(".yaml")) {
  144. throw new IllegalArgumentException(fileName + "does not contain .yaml extension.");
  145. }
  146. Path filePath = Paths.get(fileName);
  147. if (Files.notExists(filePath)) {
  148. throw new FileNotFoundException(fileName + " does not exist");
  149. }
  150. Map<Object, Object> properties;
  151. logger.debug("Opening the file '{}'.", fileName);
  152. try (InputStream fileStream = Files.newInputStream(filePath)) {
  153. logger.debug("Parsing the yaml file '{}'.", fileName);
  154. properties = new Yaml().load(fileStream);
  155. logger.debug("The configuration yaml file '{}' was parsed successfully.", fileName);
  156. }
  157. if (properties == null || properties.isEmpty()) {
  158. throw new IOException(String.format(
  159. "The configuration yaml file %s is empty or was not loaded successfully. ", fileName
  160. ));
  161. }
  162. try {
  163. return make(
  164. parseGeneralConfig(createPropertyConfig(properties, "general")),
  165. parseMonitoredObjects(createPropertyConfig(properties, "monitoredObjects")),
  166. parseEmailServers(createPropertyConfig(properties, "emailServers")),
  167. parseMessageBrokers(createPropertyConfig(properties, "messageBrokers")),
  168. parseSensLogServers(createPropertyConfig(properties, "senslogServers")),
  169. parseDataProviders(createPropertyConfig(properties, "dataProviders")),
  170. parseGroups(createPropertyConfig(properties, "groups")),
  171. parseSuperGroups(createPropertyConfig(properties, "superGroups"))
  172. );
  173. } catch (IOException e) {
  174. throw new IOException(String.format(
  175. "Configuration file '%s' contains an error at '%s' attribute.", fileName, e.getMessage()
  176. ));
  177. }
  178. }
  179. private static GeneralConfig parseGeneralConfig(PropertyConfig config) {
  180. return new GeneralConfig(config);
  181. }
  182. private static Map<String, EmailServerConfig> parseEmailServers(PropertyConfig config) {
  183. Set<String> serverIds = config.getAttributes();
  184. Map<String, EmailServerConfig> emailServers = new HashMap<>();
  185. for (String id : serverIds) {
  186. PropertyConfig serverConfig = config.getPropertyConfig(id);
  187. emailServers.put(id, EmailServerConfig.create(serverConfig));
  188. }
  189. return emailServers;
  190. }
  191. private static Map<String, MessageBrokerConfig> parseMessageBrokers(PropertyConfig config) {
  192. Set<String> brokerIds = config.getAttributes();
  193. Map<String, MessageBrokerConfig> messageBrokers = new HashMap<>(brokerIds.size());
  194. for (String id : brokerIds) {
  195. PropertyConfig brokerConfig = config.getPropertyConfig(id);
  196. MessageBrokerType type = MessageBrokerType.of(brokerConfig.getStringProperty("type"));
  197. messageBrokers.put(id, type.createConfig(id, brokerConfig.getPropertyConfig("config"))
  198. );
  199. }
  200. return messageBrokers;
  201. }
  202. private static Map<String, SensLogServerConfig> parseSensLogServers(PropertyConfig config) {
  203. Set<String> serverIds = config.getAttributes();
  204. Map<String, SensLogServerConfig> serverConfigs = new HashMap<>(serverIds.size());
  205. for (String id : serverIds) {
  206. PropertyConfig serverConfig = config.getPropertyConfig(id);
  207. serverConfigs.put(id, SensLogServerConfig.create(serverConfig));
  208. }
  209. return serverConfigs;
  210. }
  211. private static Map<String, DataProviderConfig> parseDataProviders(PropertyConfig config) {
  212. Set<String> providerIds = config.getAttributes();
  213. Map<String, DataProviderConfig> dataProviders = new HashMap<>(providerIds.size());
  214. for (String id : providerIds) {
  215. PropertyConfig providerConfig = config.getPropertyConfig(id);
  216. DataProviderType type = DataProviderType.of(providerConfig.getStringProperty("type"));
  217. dataProviders.put(id, type.createConfig(id, providerConfig.getPropertyConfig("config")));
  218. }
  219. return dataProviders;
  220. }
  221. private static Map<String, GroupConfig> parseGroups(PropertyConfig config) {
  222. Set<String> groupIds = config.getAttributes();
  223. Map<String, GroupConfig> groups = new HashMap<>(groupIds.size());
  224. for (String id : groupIds) {
  225. PropertyConfig groupConfig = config.getPropertyConfig(id);
  226. groups.put(id, GroupConfig.create(groupConfig));
  227. }
  228. return groups;
  229. }
  230. private static Map<String, SuperGroupConfig> parseSuperGroups(PropertyConfig config) {
  231. Set<String> groupIds = config.getAttributes();
  232. Map<String, SuperGroupConfig> groups = new HashMap<>(groupIds.size());
  233. for (String id : groupIds) {
  234. PropertyConfig groupConfig = config.getPropertyConfig(id);
  235. List<String> subGroupList = groupConfig.getArrayPropertyOf("groups", String.class);
  236. Set<String> subGroupNames = new HashSet<>(subGroupList);
  237. groups.put(id, new SuperGroupConfig(id,
  238. groupConfig.getStringProperty("name"),
  239. groupConfig.getStringProperty("messageBroker"),
  240. groupConfig.getOptionalProperty("period", Integer.class).orElse(null),
  241. subGroupNames
  242. ));
  243. }
  244. return groups;
  245. }
  246. private static List<TempUnitConfig> parseMonitoredObjects(PropertyConfig config) {
  247. Set<String> unitIds = config.getAttributes();
  248. List<TempUnitConfig> unitConfigs = new ArrayList<>(unitIds.size());
  249. for (String unitId : unitIds) {
  250. PropertyConfig unitConfig = config.getPropertyConfig(unitId);
  251. Integer unitPeriod = unitConfig.getOptionalProperty("period", Integer.class).orElse(null);
  252. List<String> unitGroupList = unitConfig.containsProperty("groups") ? unitConfig.getArrayPropertyOf("groups", String.class) : null;
  253. Set<String> unitGroups = unitGroupList != null ? new HashSet<>(unitGroupList) : new HashSet<>();
  254. List<TempSensorConfig> sensorConfigList = new ArrayList<>();
  255. if (unitConfig.containsProperty("sensors")) {
  256. Object sensorsObj = unitConfig.getProperty("sensors");
  257. if (sensorsObj instanceof List) {
  258. List<Integer> sensors = unitConfig.getArrayPropertyOf("sensors", Integer.class);
  259. for (Integer sensorId : sensors) {
  260. sensorConfigList.add(new TempSensorConfig(Integer.toString(sensorId), unitPeriod, new HashSet<>()));
  261. }
  262. } else if (sensorsObj instanceof Map) {
  263. PropertyConfig sensorsConfig = unitConfig.getPropertyConfig("sensors");
  264. Set<String> sensorIds = sensorsConfig.getAttributes();
  265. for (String sensorId : sensorIds) {
  266. PropertyConfig sensorConfig = sensorsConfig.getPropertyConfig(sensorId);
  267. Integer sensorPeriod = sensorConfig.getOptionalProperty("period", Integer.class).orElse(unitPeriod);
  268. List<String> sensorGroupList = sensorConfig.containsProperty("groups") ? sensorConfig.getArrayPropertyOf("groups", String.class) : emptyList();
  269. sensorConfigList.add(new TempSensorConfig(sensorId, sensorPeriod, new HashSet<>(sensorGroupList)));
  270. }
  271. }
  272. }
  273. unitConfigs.add(new TempUnitConfig(unitId, unitPeriod, sensorConfigList, unitGroups));
  274. }
  275. return unitConfigs;
  276. }
  277. private static PropertyConfig createPropertyConfig(Map<Object, Object> properties, String propertyName) throws IOException {
  278. Object generalConfig = properties.get(propertyName);
  279. if (generalConfig == null) {
  280. return new PropertyConfig(propertyName, propertyName);
  281. }
  282. if (!(generalConfig instanceof Map)) {
  283. throw new IOException(propertyName);
  284. }
  285. Map<?, ?> generalConfigMap = (Map<?, ?>) generalConfig;
  286. PropertyConfig propertyConfig = new PropertyConfig(propertyName, propertyName);
  287. for (Map.Entry<?, ?> entry : generalConfigMap.entrySet()) {
  288. String keyName = entry.getKey().toString();
  289. propertyConfig.setProperty(keyName, entry.getValue());
  290. }
  291. return propertyConfig;
  292. }
  293. public Collection<MessageBrokerConfig> getMessageBrokerConfigs() {
  294. return messageBrokerConfigs;
  295. }
  296. public Collection<EmailServerConfig> getEmailServerConfigs() {
  297. return emailServerConfigs;
  298. }
  299. public Collection<SensLogServerConfig> getSensLogServerConfigs() {
  300. return sensLogServerConfigs;
  301. }
  302. public Collection<DataProviderConfig> getDataProviderConfigs() {
  303. return dataProviderConfigs;
  304. }
  305. public Collection<ExecutableGroup> getExecGroups() {
  306. return execGroups;
  307. }
  308. public GeneralConfig getGeneralConfig() {
  309. return generalConfig;
  310. }
  311. public Collection<ExecutableSuperGroup> getSuperGroupsConfig() {
  312. return execSuperGroups;
  313. }
  314. private static class TempUnitConfig {
  315. private final String id;
  316. private final Integer period;
  317. private final List<TempSensorConfig> sensors;
  318. private final Set<String> groups;
  319. private TempUnitConfig(String id, Integer period, List<TempSensorConfig> sensors, Set<String> groups) {
  320. this.id = id;
  321. this.period = period;
  322. this.sensors = sensors;
  323. this.groups = groups;
  324. }
  325. }
  326. private static class TempSensorConfig {
  327. private final String id;
  328. private final Integer period;
  329. private final Set<String> groups;
  330. private TempSensorConfig(String id, Integer period, Set<String> groups) {
  331. this.id = id;
  332. this.period = period;
  333. this.groups = groups;
  334. }
  335. }
  336. private static class TempAllSensorsConfig extends TempSensorConfig {
  337. private TempAllSensorsConfig(Integer period) {
  338. super(null, period, new HashSet<>());
  339. }
  340. }
  341. }