package cs437.som.network;

import cs437.som.Dimension;
import cs437.som.SOMError;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Provides for reading in self-organizing maps from files.
*/
class SOMFileReader {
    private static final Pattern dimensionRegEx = Pattern.compile(
            "(?:grid)?\\s*dimensions\\s*:\\s*(\\d+)\\s*,\\s*(\\d+)",
            Pattern.CASE_INSENSITIVE);
    private static final Pattern inputVectorSizeRegEx = Pattern.compile(
            "(?:input)?\\s*length\\s*:\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
    private static final Pattern iterationsRegEx = Pattern.compile(
            "iterations\\s*:\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
    private static final Pattern weightRegEx = Pattern.compile(
            "weights\\s*(?::)", Pattern.CASE_INSENSITIVE);

    private Dimension dimension = null;
    private int inputVectorSize = 0;
    protected int iterations = 0;

    public void parse(BufferedReader input) throws IOException {
        String line = input.readLine();
        Matcher match = weightRegEx.matcher(line);
        while (! match.matches() && input.ready()) {
            if (!matchDimension(line)
                    && !matchInputVectorSize(line)
                    && !matchIterations(line)) {
                unmatchedLine(line);
            }

            line = input.readLine();
            match = weightRegEx.matcher(line);
        }

        if (dimension == null || inputVectorSize < 1) {
            throw new SOMError(String.format(
                    "A valid dimension and input vector size must appear in "
                    + "a map's configuration%nand they must appear before "
                    + "the weight matrix."));
        }
    }

    protected void unmatchedLine(String line) {
    }

    protected boolean matchIterations(String line) {
        Matcher iterationsMatch = iterationsRegEx.matcher(line);
        if (iterationsMatch.matches()) {
            iterations = Integer.parseInt(iterationsMatch.group(1));
            return true;
        }
        return false;
    }

    private boolean matchInputVectorSize(String line) {
        Matcher inputMatch = inputVectorSizeRegEx.matcher(line);
        if (inputMatch.matches()) {
            inputVectorSize = Integer.parseInt(inputMatch.group(1));
            return true;
        }
        return false;
    }

    private boolean matchDimension(String line) {
        Matcher dimMatch = dimensionRegEx.matcher(line);
        if (dimMatch.matches()) {
            dimension = new Dimension(Integer.parseInt(dimMatch.group(1)),
                    Integer.parseInt(dimMatch.group(2)));
            return true;
        }
        return false;
    }

    public Dimension getDimension() {
        return dimension;
    }

    public int getInputVectorSize() {
        return inputVectorSize;
    }

    public int getIterations() {
        return iterations;
    }

    @Override
    public String toString() {
        return "SOMFileReader";
    }
}

@@ -987,16 +987,187 @@
 s = 0;%0A%0A
+    /**%0A     * Parse a self-organizing map from an input stream.%0A     *%0A     * @param input The input stream.%0A     * @throws IOException When an I/O error occurs.%0A     */%0A
     publ
@@ -1979,58 +1979,503 @@
     
-protected void unmatchedLine(String line) %7B%0A    %7D%0A
+/**%0A     * If SOMFileReader does not recognize, it calls this method.  The default%0A     * behavior is doing nothing.  This method is provided for extension in%0A     * subclasses.%0A     *%0A     * @param line The unrecognized line.%0A     */%0A    protected void unmatchedLine(String line) %7B%0A    %7D%0A%0A    /**%0A     * Match an iteration line.%0A     *%0A     * @param line The input's line to attempt to match and extract from.%0A     * @return %7B@code true%7D if the line is matched, %7B@code false%7D otherwise.%0A     */
 %0A   
@@ -2755,32 +2755,246 @@
 n false;%0A    %7D%0A%0A
+    /**%0A     * Match an input vector size line.%0A     *%0A     * @param line The input's line to attempt to match and extract from.%0A     * @return %7B@code true%7D if the line is matched, %7B@code false%7D otherwise.%0A     */%0A
     private bool
@@ -3263,24 +3263,229 @@
 lse;%0A    %7D%0A%0A
+    /**%0A     * Match a dimension line.%0A     *%0A     * @param line The input's line to attempt to match and extract from.%0A     * @return %7B@code true%7D if the line is matched, %7B@code false%7D otherwise.%0A     */%0A
     private 
@@ -3818,151 +3818,517 @@
     
-public Dimension getDimension() %7B%0A        return dimension;%0A    %7D%0A%0A    public int getInputVectorSize() %7B%0A        return inputVectorSize;%0A    %7D%0A
+/**%0A     * Retrieve the parsed dimension.%0A     *%0A     * @return The dimensions from the input stream.%0A     */%0A    public Dimension getDimension() %7B%0A        return dimension;%0A    %7D%0A%0A    /**%0A     * Retrieve the parsed input vector size.%0A     *%0A     * @return The input vector size from the input stream.%0A     */%0A    public int getInputVectorSize() %7B%0A        return inputVectorSize;%0A    %7D%0A%0A    /**%0A     * Return the parsed iteration count.%0A     *%0A     * @return The iteration count from the input stream.%0A     */
 %0A   

Document SOMFileReader.