• MyRangeMatcher.java

  • §
    package MusicLandscape.util;
    
    import java.util.Objects;
  • §

    This is a class I put inbetween the MyMatcher abstract base class and the matchers for year and duration, to have less code duplication.

    In the end it turned out to be a little bit of premature optimization, as the TitleMatcherTest required me to duplicate some code in the TitleMatcher anyway.

    /**
     * This class represents the concept of matching an object by some integer within a lower and upper bound.
     * <p>
     * More precisely, a valid pattern is a String that can be interpreted as either a single integer number
     * (leading and trailing whitespace are ignored, if present) which then represents the lower bound
     * or two integer numbers, separated by (any number of) whitespace, which then represent lower and upper bound.
     * <p>
     * The bounds are understood to be inclusive.
     *
     * @author Jonas Altrock (ew20b126@technikum-wien.at)
     * @version 1
     * @since LabWork
     */
    abstract public class MyRangeMatcher<T> extends MyMatcher<T> implements ConsoleScanable {
        /**
         * the lower bound of the accepted range.
         */
        protected int lower;
        /**
         * the upper bound of the accepted range.
         */
        protected int upper;
    
        /**
         * The prompt displayed for changing this matcher's pattern.
         */
        protected String prompt = "enter range";
    
        /**
         * Creates a Matcher object with a specified pattern.
         *
         * @param pat the pattern of this matcher
         */
        public MyRangeMatcher(String pat) {
            super(pat);
        }
    
        /**
         * Sets the pattern of this matcher.
         * <p>
         * Interprets the argument as described in the class documentation. First sets the lower, then the upper bound.
         * The bounds specified are set if and only if at the time of setting they are actually lower (for the lower bound)
         * or higher (for the upper bound) than the other or at least equal to the other.
         *
         * @param pat the pattern to set
         */
        @Override
        public void setPattern(String pat) {
            String[] parts = pat.trim().split("\\s+");
    
            lower = 0;
            upper = Integer.MAX_VALUE;
    
            if (parts.length < 1 || parts[0].isEmpty()) {
                return;
            }
    
            try {
                lower = Integer.max(Integer.parseInt(parts[0]), 0);
            } catch (NumberFormatException ignored) {}
    
            if (parts.length < 2) {
                return;
            }
    
            try {
                int upperBound = Integer.min(Integer.parseInt(parts[1]), upper);
    
                if (upperBound >= lower) {
                    upper = upperBound;
                }
            } catch (NumberFormatException ignored) {}
        }
    
        /**
         * the valid pattern is <kbd>LOWER UPPER</kbd> separated by whitespace.
         *
         * @return the pattern
         */
        @Override
        public String getPattern() {
            return lower + " " + upper;
        }
    
        /**
         * Interactively modify this matcher.
         *
         * @return whether this object was altered or not
         */
        @Override
        public boolean scan() {
            String pattern = ConsoleScanner.nonEmptyString.scan(prompt);
    
            if (pattern != null) {
                String before = getPattern();
                setPattern(pattern);
                return !Objects.equals(before, getPattern());
            }
    
            return false;
        }
    }