class IncludeExcludeFilter {

  public static IncludeExcludeFilter fromConfiguration() {
    checkState(Configuration.isInitialized());
    Set<String> filterProperties = Configuration.getConfig()
        .stringPropertyNames()
        .stream()
        .filter(key -> key.startsWith(FILTER_CONFIG_PREFIX))
        .collect(Collectors.toSet());
    if (filterProperties.isEmpty()) {
      return new IncludeExcludeFilter(ImmutableList.of());
    }
    HashMap<String, Rule.Builder> ruleBuilders = new HashMap<>();
    for (String propertyName : filterProperties) {
      String[] propertyNameParts = propertyName.split("\\.");
      if (propertyNameParts.length != 3) {
        throw new InvalidConfigurationException("Unknown property " + propertyName);
      }
      String ruleName = propertyNameParts[1];
      String rulePropertyType = propertyNameParts[2];
      String propertyValue = Configuration.getString(propertyName, null).get();
      Rule.Builder builder = ruleBuilders.get(ruleName);
      if (builder == null) {
        builder = new Rule.Builder(ruleName);
        ruleBuilders.put(ruleName, builder);
      }
      if (rulePropertyType.equals("itemType")) {
        builder.setItemType(propertyValue);
      } else if (rulePropertyType.equals("filterType")) {
        builder.setFilterType(propertyValue);
      } else if (rulePropertyType.equals("filterPattern")) {
        builder.setFilterPattern(propertyValue);
      } else if (rulePropertyType.equals("action")) {
        builder.setAction(propertyValue);
      } else {
        throw new InvalidConfigurationException("Unknown property " + propertyName);
      }
    }
    List<Rule> rules = new ArrayList<>();
    for (Rule.Builder builder : ruleBuilders.values()) {
      try {
        rules.add(builder.build());
      } catch (IllegalStateException | IllegalArgumentException e) {
        throw new InvalidConfigurationException(e.getMessage());
      }
    }
    return new IncludeExcludeFilter(rules);
  }

  @VisibleForTesting  IncludeExcludeFilter(List<Rule> rules);

}