diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 22:39:59 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 22:39:59 -0300 |
| commit | c82e3b3b2de0633317ec8fc85925e91422820597 (patch) | |
| tree | 96567416ce23c5ce85601f9cedc3a94bb1c55cba /BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java | |
| parent | b3ac1c8690c3e14c879913e5dcc03a5f5e14876e (diff) | |
Start splitting into maven modules
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java')
| -rw-r--r-- | BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java deleted file mode 100644 index 7c5205b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java +++ /dev/null @@ -1,265 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.InputStream; -import java.util.InputMismatchException; -import java.util.Scanner; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.Pair; -import bjc.utils.exceptions.UnknownPragmaException; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IMap; - -/** - * This class parses a rules based config file, and uses it to drive a provided - * set of actions - * - * @author ben - * - * @param <E> - * The type of the state object to use - * - */ -public class RuleBasedConfigReader<E> { - /* Function to execute when starting a rule. - * Takes the tokenizer, and a pair of the read token and application state - */ - private BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start; - - /* - * Function to use when continuing a rule - * Takes a tokenizer and application state - */ - private BiConsumer<FunctionalStringTokenizer, E> continueRule; - - /* - * Function to use when ending a rule - * Takes an application state - */ - private Consumer<E> end; - - /* - * Map of pragma names to pragma actions - * Pragma actions are functions taking a tokenizer and application state - */ - private final IMap<String, BiConsumer<FunctionalStringTokenizer, E>> pragmas; - - /** - * Create a new rule-based config reader - * - * @param start - * The action to fire when starting a rule - * @param continueRule - * The action to fire when continuing a rule - * @param end - * The action to fire when ending a rule - */ - public RuleBasedConfigReader(final BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start, - final BiConsumer<FunctionalStringTokenizer, E> continueRule, final Consumer<E> end) { - this.start = start; - this.continueRule = continueRule; - this.end = end; - - this.pragmas = new FunctionalMap<>(); - } - - /** - * Add a pragma to this reader - * - * @param name - * The name of the pragma to add - * @param action - * The function to execute when this pragma is read - */ - public void addPragma(final String name, final BiConsumer<FunctionalStringTokenizer, E> action) { - if (name == null) throw new NullPointerException("Pragma name must not be null"); - else if (action == null) throw new NullPointerException("Pragma action must not be null"); - - pragmas.put(name, action); - } - - private void continueRule(final E state, final boolean isRuleOpen, final String line) { - // Make sure our input is correct - if (isRuleOpen == false) - throw new InputMismatchException("Cannot continue rule with no rule open"); - else if (continueRule == null) - throw new InputMismatchException("Rule continuation not supported for current grammar"); - - /* - * Accept the rule - */ - continueRule.accept(new FunctionalStringTokenizer(line.substring(1), " "), state); - } - - private boolean endRule(final E state, final boolean isRuleOpen) { - /* - * Ignore blank line without an open rule - */ - if (isRuleOpen == false) - /* - * Do nothing - */ - return false; - else { - /* - * Nothing happens on rule end - */ - if (end != null) { - /* - * Process the rule ending - */ - end.accept(state); - } - - /* - * Return a closed rule - */ - return false; - } - } - - /** - * Run a stream through this reader - * - * @param input - * The stream to get input - * @param initialState - * The initial state of the reader - * @return The final state of the reader - */ - public E fromStream(final InputStream input, final E initialState) { - if (input == null) throw new NullPointerException("Input stream must not be null"); - - /* - * Application state: We're giving this back later - */ - final E state = initialState; - - /* - * Prepare our input source - */ - try (Scanner source = new Scanner(input)) { - source.useDelimiter("\n"); - /* - * This is true when a rule's open - */ - final IHolder<Boolean> isRuleOpen = new Identity<>(false); - - /* - * Do something for every line of the file - */ - source.forEachRemaining((line) -> { - /* - * Skip comment lines - */ - if (line.startsWith("#") || line.startsWith("//")) - /* - * It's a comment - */ - return; - else if (line.equals("")) { - /* - * End the rule - */ - isRuleOpen.replace(endRule(state, isRuleOpen.getValue())); - } else if (line.startsWith("\t")) { - /* - * Continue the rule - */ - continueRule(state, isRuleOpen.getValue(), line); - } else { - /* - * Open a rule - */ - isRuleOpen.replace(startRule(state, isRuleOpen.getValue(), line)); - } - }); - } - - /* - * Return the state that the user has created - */ - return state; - } - - /** - * Set the action to execute when continuing a rule - * - * @param continueRule - * The action to execute on continuation of a rule - */ - public void setContinueRule(final BiConsumer<FunctionalStringTokenizer, E> continueRule) { - this.continueRule = continueRule; - } - - /** - * Set the action to execute when ending a rule - * - * @param end - * The action to execute on ending of a rule - */ - public void setEndRule(final Consumer<E> end) { - this.end = end; - } - - /** - * Set the action to execute when starting a rule - * - * @param start - * The action to execute on starting of a rule - */ - public void setStartRule(final BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start) { - if (start == null) throw new NullPointerException("Action on rule start must be non-null"); - - this.start = start; - } - - private boolean startRule(final E state, boolean isRuleOpen, final String line) { - /* - * Create the line tokenizer - */ - final FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(line, " "); - - /* - * Get the initial token - */ - final String nextToken = tokenizer.nextToken(); - - /* - * Handle pragmas - */ - if (nextToken.equals("pragma")) { - /* - * Get the pragma name - */ - final String token = tokenizer.nextToken(); - - /* - * Handle pragmas - */ - pragmas.getOrDefault(token, (tokenzer, stat) -> { - throw new UnknownPragmaException("Unknown pragma " + token); - }).accept(tokenizer, state); - } else { - /* - * Make sure input is correct - */ - if (isRuleOpen == true) - throw new InputMismatchException("Nested rules are currently not supported"); - - /* - * Start a rule - */ - start.accept(tokenizer, new Pair<>(nextToken, state)); - - isRuleOpen = true; - } - - return isRuleOpen; - } -} |
