Skip to content

Commit

Permalink
Review: Improve documentation
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
  • Loading branch information
codecholeric committed Feb 5, 2023
1 parent 8514897 commit e164340
Showing 1 changed file with 50 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,31 @@
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.io.Files.toByteArray;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
import static com.tngtech.archunit.PublicAPI.Usage.INHERITANCE;
import static com.tngtech.archunit.library.freeze.FreezingArchRule.ensureUnixLineBreaks;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;

/**
* An implementation of {@link ViolationStore} that stores violations instances in a text file, one such file for each rule that is frozen.
*
* <p>
* The files are all stored in a single directory and so their names must be sufficient unique from each other. The out-of-the box implementation (no-arg constructor)
* simply uses a UUID. However, this can be overridden by passing in an instance of {@link TextFileBasedViolationStore.FileNameStrategy} to the appropriate constructor.
* </p>
* A text file based implementation of a {@link ViolationStore}.<br>
* This {@link ViolationStore} will store the violations of every single {@link FreezingArchRule} in a dedicated file.<br>
* It will keep an index of all stored rules as well as a mapping to the individual rule violation files in the same folder.<br>
* By default, the layout within the configured store folder will look like:
* <pre><code>
* storeFolder
* |-- stored.rules (the index file of all stored rules)
* |-- 6fc2fd04-b3ab-44e0-8f78-215c66f2174a (a rule violation file named randomly by UUID and referenced from stored.rules)
* |-- 2186b43a-c24c-417d-bd96-547e2dfdba1c (another rule violation file)
* |-- ... (more rule violation files for every rule that has been stored so far)
* </code></pre>
* To adjust the strategy how the individual rule violation files are named use the constructor
* {@link TextFileBasedViolationStore#TextFileBasedViolationStore(RuleViolationFileNameStrategy) TextFileBasedViolationStore(RuleViolationFileNameStrategy)}.<br>
* This {@link ViolationStore} can be configured through the following properties:
* <pre><code>
* default.path=... # string: the path of the folder where violation files will be stored
* default.allowStoreCreation=... # boolean: whether to allow creating a new index file
* default.allowStoreUpdate=... # boolean: whether to allow updating any store file
* </code></pre>
*/
@PublicAPI(usage = ACCESS)
public final class TextFileBasedViolationStore implements ViolationStore {
Expand All @@ -61,44 +75,29 @@ public final class TextFileBasedViolationStore implements ViolationStore {
private static final String ALLOW_STORE_UPDATE_PROPERTY_NAME = "default.allowStoreUpdate";
private static final String ALLOW_STORE_UPDATE_DEFAULT = "true";

private final FileNameStrategy fileNameStrategy;
private final RuleViolationFileNameStrategy ruleViolationFileNameStrategy;

private boolean storeCreationAllowed;
private boolean storeUpdateAllowed;
private File storeFolder;
private FileSyncedProperties storedRules;

public TextFileBasedViolationStore() {
this(__ -> UUID.randomUUID().toString());
}

/**
* Provides a mechanism to allow the file name that stores the violations of a particular rule to be customised, based on the description of that rule.
* Creates a standard {@link TextFileBasedViolationStore} that names rule violation files by random {@link UUID}s
*
* <p>
* An instance of this interface is passed into the constructor.
* </p>
* @see #TextFileBasedViolationStore(RuleViolationFileNameStrategy)
*/
@FunctionalInterface
public interface FileNameStrategy {
/**
* Based on the description of a rule file, return a name to be used as the file name contianing the frozen violations of that rule.
*
* <p>
* The returned name <i>must</i> be sufficiently unique from any others; since the descriptions themselves are unique, this typically means sanitizing the description into some sort of file name.
* </p>
*
* @param description - of the rule whose frozen violations are to be stored
* @return - the name of a file to store these frozen violations.
*/
String fileName(String description);
public TextFileBasedViolationStore() {
this(__ -> UUID.randomUUID().toString());
}

/**
* @param fileNameStrategy - to override the default strategy for naming the files that contain frozen violation instances for a given rule.
* Creates a {@link TextFileBasedViolationStore} with a custom strategy for rule violation file naming
*
* @param ruleViolationFileNameStrategy controls how the rule violation file name is derived from the rule description
*/
public TextFileBasedViolationStore(FileNameStrategy fileNameStrategy) {
this.fileNameStrategy = fileNameStrategy;
public TextFileBasedViolationStore(RuleViolationFileNameStrategy ruleViolationFileNameStrategy) {
this.ruleViolationFileNameStrategy = ruleViolationFileNameStrategy;
}

@Override
Expand Down Expand Up @@ -180,7 +179,7 @@ private String ensureRuleFileName(ArchRule rule) {
ruleFileName = storedRules.getProperty(ruleDescription);
log.debug("Rule '{}' is already stored in file {}", ruleDescription, ruleFileName);
} else {
ruleFileName = this.fileNameStrategy.fileName(ruleDescription);
ruleFileName = ruleViolationFileNameStrategy.createRuleFileName(ruleDescription);
log.debug("Assigning new file {} to rule '{}'", ruleFileName, ruleDescription);
storedRules.setProperty(ruleDescription, ruleFileName);
}
Expand Down Expand Up @@ -265,4 +264,23 @@ private void syncFileSystem() {
}
}
}

/**
* Allows to adjust the rule violation file names of {@link TextFileBasedViolationStore}
*
* @see #TextFileBasedViolationStore(RuleViolationFileNameStrategy)
*/
@FunctionalInterface
@PublicAPI(usage = INHERITANCE)
public interface RuleViolationFileNameStrategy {
/**
* Returns the file name to store violations of an {@link ArchRule}, possibly based on the rule description.<br>
* The returned names <b>must</b> be sufficiently unique from any others;
* as long as the descriptions themselves are unique, this can be achieved by sanitizing the description into some sort of file name.
*
* @param ruleDescription The description of the {@link ArchRule} to store
* @return The file name the respective rule violation file will have (see {@link TextFileBasedViolationStore})
*/
String createRuleFileName(String ruleDescription);
}
}

0 comments on commit e164340

Please sign in to comment.