BuiltInLintingRulesFactory.java
package org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thewonderlemming.c4plantuml.linter.rules.AbstractLintingRule;
import org.thewonderlemming.c4plantuml.linter.rules.RuleParameters;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.AliasesShouldBeListedInDictionaryRule;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.AliasesShouldBeUniqueRule;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.AliasesShouldFollowStandardConventionRule;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.NoDuplicateRelationshipsRule;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.NoOrphanAliasInBoundariesRule;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.NoOrphanAliasInLayoutsRule;
import org.thewonderlemming.c4plantuml.linter.rules.builtin.NoOrphanAliasInRelationshipsRule;
import org.thewonderlemming.c4plantuml.mojo.linting.BuiltInRules;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.AliasesShouldBeListedInDictionaryRuleParametersFactory;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.AliasesShouldBeUniqueRuleParametersFactory;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.AliasesShouldFollowStandardConventionRuleParametersFactory;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.NoDuplicateRelationshipsRuleParametersFactory;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.NoOrphanAliasInBoundariesRuleParametersFactory;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.NoOrphanAliasInLayoutsRuleParametersFactory;
import org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin.parameters.NoOrphanAliasInRelationshipsRuleParametersFactory;
/**
* Maps {@link AbstractLintingRule} classes to their {@link AbstractRuleParametersFactory} and their name.
*
* @author thewonderlemming
*
*/
public enum BuiltInLintingRulesFactory {
/**
* The {@link AliasesShouldBeListedInDictionaryRule} mapping.
*/
ALIASES_SHOULD_BE_LISTED_IN_DICTIONARY(
"aliasesShouldBeListedInDictionary",
AliasesShouldBeListedInDictionaryRule.class,
AliasesShouldBeListedInDictionaryRuleParametersFactory.class),
/**
* The {@link AliasesShouldBeUniqueRule} mapping.
*/
ALIASES_SHOULD_BE_UNIQUE(
"aliasesShouldBeUnique",
AliasesShouldBeUniqueRule.class,
AliasesShouldBeUniqueRuleParametersFactory.class),
/**
* The {@link AliasesShouldFollowStandardConventionRule} mapping.
*/
ALIASES_SHOULD_FOLLOW_STANDARD_CONVENTION(
"aliasesShouldFollowStandardConvention",
AliasesShouldFollowStandardConventionRule.class,
AliasesShouldFollowStandardConventionRuleParametersFactory.class),
/**
* The {@link NoDuplicateRelationshipsRule} mapping.
*/
NO_DUPLICATES_IN_RELATIONSHIPS(
"noDuplicateRelationships",
NoDuplicateRelationshipsRule.class,
NoDuplicateRelationshipsRuleParametersFactory.class),
/**
* The {@link NoOrphanAliasInBoundariesRule} mapping.
*/
NO_ORPHAN_ALIAS_IN_BOUNDARIES(
"noOrphanAliasInBoundaries",
NoOrphanAliasInBoundariesRule.class,
NoOrphanAliasInBoundariesRuleParametersFactory.class),
/**
* The {@link NoOrphanAliasInLayoutsRule} mapping.
*/
NO_ORPHAN_ALIAS_IN_LAYOUTS(
"noOrphanAliasInLayouts",
NoOrphanAliasInLayoutsRule.class,
NoOrphanAliasInLayoutsRuleParametersFactory.class),
/**
* The {@link NoOrphanAliasInRelationshipsRule} mapping.
*/
NO_ORPHAN_ALIAS_IN_RELATIONSHIPS(
"noOrphanAliasInRelationships",
NoOrphanAliasInRelationshipsRule.class,
NoOrphanAliasInRelationshipsRuleParametersFactory.class);
private static final Logger LOGGER = LoggerFactory.getLogger(BuiltInLintingRulesFactory.class);
private static final Map<String, BuiltInLintingRulesFactory> LOOKUP_BY_NAME = new HashMap<>();
private static final Map<Class<? extends AbstractLintingRule>, BuiltInLintingRulesFactory> LOOKUP_BY_TYPE = new HashMap<>();
private final String ruleName;
private final Class<? extends AbstractRuleParametersFactory> ruleParametersFactoryType;
private final Class<? extends AbstractLintingRule> ruleType;
static {
Stream
.of(BuiltInLintingRulesFactory.values())
.forEach(value -> {
LOOKUP_BY_NAME.put(value.ruleName, value);
LOOKUP_BY_TYPE.put(value.getRuleType(), value);
});
}
/**
* Builds a {@link AbstractLintingRule} instance, given its name and the {@link BuiltInRules} parameters POJO.
*
* @param ruleName the name of the rule to build.
* @param parameters the {@code pom.xml} configuration.
* @return an {@link Optional} of the built rule on success, or empty else.
*/
public static Optional<AbstractLintingRule> createInstanceForName(final String ruleName,
final BuiltInRules parameters) {
final BuiltInLintingRulesFactory rule = LOOKUP_BY_NAME.get(ruleName);
if (null != rule) {
try {
final AbstractRuleParametersFactory config = rule.ruleParametersFactoryType
.getDeclaredConstructor(BuiltInRules.class)
.newInstance(parameters);
LOGGER
.debug("Linting rule {} is activated: {}",
ruleName,
config.isActivated());
return config.isActivated()
? Optional.ofNullable(rule.createInstance(config.getRuleParameters()))
: Optional.empty();
} catch (
InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
LOGGER
.error("Cannot create instance of rule named '{}' because of exception: {}",
ruleName,
e.getMessage(),
e);
}
}
return Optional.empty();
}
/**
* Returns the mapped name of a {@link AbstractLintingRule}, given its type.
*
* @param ruleType the type of the rule to retrieve the name from.
* @return an {@link Optional} of the name of the rule if found, empty else.
*/
public static Optional<String> getRuleNameForType(final Class<? extends AbstractLintingRule> ruleType) {
return LOOKUP_BY_TYPE.containsKey(ruleType)
? Optional.ofNullable(LOOKUP_BY_TYPE.get(ruleType).getRuleName())
: Optional.empty();
}
/**
* Tells whether or not the given {@link AbstractLintingRule} is a built-in rule, or a custom one, which requires
* a different building process.
*
* @param lintingRuleType the type of the rule to check for.
* @return {@code true} if the rule is a built-in one, {@code false} else.
*/
public static boolean isBuiltInLintingRule(final Class<? extends AbstractLintingRule> lintingRuleType) {
return LOOKUP_BY_TYPE.containsKey(lintingRuleType);
}
private BuiltInLintingRulesFactory(final String ruleName, final Class<? extends AbstractLintingRule> ruleType,
final Class<? extends AbstractRuleParametersFactory> ruleParametersFactoryType) {
this.ruleName = ruleName;
this.ruleType = ruleType;
this.ruleParametersFactoryType = ruleParametersFactoryType;
}
/**
* Returns the name of the current mapping.
*
* @return the name of the mapping.
*/
public String getRuleName() {
return this.ruleName;
}
/**
* Returns the {@link AbstractLintingRule} type of the current mapping.
*
* @return the type of the current mapping.
*/
public Class<? extends AbstractLintingRule> getRuleType() {
return this.ruleType;
}
private AbstractLintingRule createInstance(final RuleParameters parameters)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
NoSuchMethodException, SecurityException {
return this.ruleType.getConstructor(RuleParameters.class).newInstance(parameters);
}
}