/** * Create a configuration graph from a collection of Configuration, resource name pairs and a name validation * function. * * @param configurationNamePairs A map whose keys are configurations and values are the resource names use to * report errors while processing configurations. * @param nameValidator A function which throws exceptions on module names which are not valid. */ public ConfigurationGraph(Map<Configuration, String> configurationNamePairs, Consumer<String> nameValidator) { moduleConfigurations = new HashMap<>(); moduleDependencies = new LinkedHashMap<>(); for (Map.Entry<Configuration, String> configEntry : configurationNamePairs.entrySet()) { addVertex(configEntry.getKey(), configEntry.getValue(), nameValidator); } }
/** * Find the prioritized stream of configurations for a given module (inclusive of the module itself). * * @param nodeName The name of the initial module whose dependency should be resolved * * @return A list of modules returned in the order of increasing precedence * * @throws SystemConfigException if the graph can't be resolved */ public Stream<String> preOrderRightToLeftTraversal(String nodeName) throws SystemConfigException { if (!moduleConfigurations.containsKey(nodeName)) { LOG.error(NO_SUCH_MODULE.logFormat(nodeName)); throw new SystemConfigException(NO_SUCH_MODULE.format(nodeName)); } return preOrderRightToLeftTraversal(nodeName, new ArrayList<>()); }
/** * Build the graph of configurations and dependencies. * * @return A graph whose vertices are Configurations and whose edges are dependencies between them. * * @throws SystemConfigException If any errors occur while parsing the configurations into a graph. */ private ConfigurationGraph loadConfigurationGraph() throws SystemConfigException { try { Map<Configuration, String> configurationFileNameMap = configResourceLoader .loadResourcesWithName(MODULE_CONFIG_FILE_NAME) .collect(Collectors.toMap(configResourceLoader::loadConfigFromResource, Resource::getDescription) ); return new ConfigurationGraph(configurationFileNameMap, ModuleLoader::validateModuleName); } catch (IOException e) { LOG.error(MODULE_IO_EXCEPTION.logFormat(e.getMessage())); throw new SystemConfigException(MODULE_IO_EXCEPTION.format(e.getMessage()), e); } }
/** * Find the prioritized stream of configurations for a given module (inclusive of the module itself). * * @param nodeName The name of the initial module whose dependency should be resolved * * @return A list of modules returned in the order of increasing precedence * * @throws SystemConfigException if the graph can't be resolved */ public Stream<String> preOrderRightToLeftTraversal(String nodeName) throws SystemConfigException { if (!moduleConfigurations.containsKey(nodeName)) { LOG.error(NO_SUCH_MODULE.logFormat(nodeName)); throw new SystemConfigException(NO_SUCH_MODULE.format(nodeName)); } return preOrderRightToLeftTraversal(nodeName, new ArrayList<>()); }
/** * Build the graph of configurations and dependencies. * * @return A graph whose vertices are Configurations and whose edges are dependencies between them. * * @throws SystemConfigException If any errors occur while parsing the configurations into a graph. */ private ConfigurationGraph loadConfigurationGraph() throws SystemConfigException { try { Map<Configuration, String> configurationFileNameMap = configResourceLoader .loadResourcesWithName(MODULE_CONFIG_FILE_NAME) .collect(Collectors.toMap(configResourceLoader::loadConfigFromResource, Resource::getDescription) ); return new ConfigurationGraph(configurationFileNameMap, ModuleLoader::validateModuleName); } catch (IOException e) { LOG.error(MODULE_IO_EXCEPTION.logFormat(e.getMessage())); throw new SystemConfigException(MODULE_IO_EXCEPTION.format(e.getMessage()), e); } }
/** * Find the prioritized stream of configurations for a given module (inclusive of the module itself). * * @param nodeName The name of the initial module whose dependencies to load (inclusively) * @param path The list of nodes back to the root of the tree parse * * @return A list of modules returned in the order of increasing precedence * * @throws SystemConfigException if there is a broken or circular dependency link */ protected Stream<String> preOrderRightToLeftTraversal(String nodeName, List<String> path) throws SystemConfigException { if (!moduleConfigurations.containsKey(nodeName)) { LOG.error(MISSING_DEPENDENCY.logFormat(nodeName, path)); throw new SystemConfigException(MISSING_DEPENDENCY.format(nodeName, path)); } if (path.contains(nodeName)) { LOG.error(CIRCULAR_DEPENDENCY.logFormat(nodeName, path)); throw new SystemConfigException(CIRCULAR_DEPENDENCY.format(nodeName, path)); } List<String> pathLocal = new ArrayList<>(path); pathLocal.add(nodeName); Stream<String> childrenStream = moduleDependencies.get(nodeName).stream() .flatMap(childNode -> preOrderRightToLeftTraversal(childNode, pathLocal)); return Stream.concat(Stream.of(nodeName), childrenStream); }
/** * Create a configuration graph from a collection of Configuration, resource name pairs and a name validation * function. * * @param configurationNamePairs A map whose keys are configurations and values are the resource names use to * report errors while processing configurations. * @param nameValidator A function which throws exceptions on module names which are not valid. */ public ConfigurationGraph(Map<Configuration, String> configurationNamePairs, Consumer<String> nameValidator) { moduleConfigurations = new HashMap<>(); moduleDependencies = new LinkedHashMap<>(); for (Map.Entry<Configuration, String> configEntry : configurationNamePairs.entrySet()) { addVertex(configEntry.getKey(), configEntry.getValue(), nameValidator); } }
/** * Find the prioritized stream of configurations for a given module (inclusive of the module itself). * * @param nodeName The name of the initial module whose dependencies to load (inclusively) * @param path The list of nodes back to the root of the tree parse * * @return A list of modules returned in the order of increasing precedence * * @throws SystemConfigException if there is a broken or circular dependency link */ protected Stream<String> preOrderRightToLeftTraversal(String nodeName, List<String> path) throws SystemConfigException { if (!moduleConfigurations.containsKey(nodeName)) { LOG.error(MISSING_DEPENDENCY.logFormat(nodeName, path)); throw new SystemConfigException(MISSING_DEPENDENCY.format(nodeName, path)); } if (path.contains(nodeName)) { LOG.error(CIRCULAR_DEPENDENCY.logFormat(nodeName, path)); throw new SystemConfigException(CIRCULAR_DEPENDENCY.format(nodeName, path)); } List<String> pathLocal = new ArrayList<>(path); pathLocal.add(nodeName); Stream<String> childrenStream = moduleDependencies.get(nodeName).stream() .flatMap(childNode -> preOrderRightToLeftTraversal(childNode, pathLocal)); return Stream.concat(Stream.of(nodeName), childrenStream); }