package cs437.som.util;

import cs437.som.SOMError;
import cs437.som.TrainableSelfOrganizingMap;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Pattern;

/**
 * Reads a self-organizing map from a file.
 */
public class FileReader {
    private static final Pattern COLON_SPLIT = Pattern.compile(":");
    private TrainableSelfOrganizingMap tsom = null;

    private FileReader(File input) throws IOException {
        BufferedReader isr = new BufferedReader(
                new InputStreamReader(new FileInputStream(input)));
        String[] kv = COLON_SPLIT.split(isr.readLine());
        if (kv.length != 2) {
            throw new SOMError(
                    "Input file is malformed: first line must be a map type statement.");
        }

        String className = "cs437.som.network." + kv[1].trim();
        try {
            Class<?> mapType = Class.forName(className);
            Method readMethod = mapType.getMethod("read", BufferedReader.class);
            tsom = (TrainableSelfOrganizingMap) readMethod.invoke(mapType, isr);
        } catch (ClassNotFoundException e) {
            throw new SOMError("Map type " + className + " cannot be found.");
        } catch (NoSuchMethodException e) {
            throw new SOMError("Map type " + className + " cannot be loaded from a file.");
        } catch (InvocationTargetException e) {
            throw new SOMError(e.getCause().getMessage());
        } catch (IllegalAccessException e) {
            throw new SOMError("Internal error while parsing: " + e.getMessage());
        }
    }

    public static TrainableSelfOrganizingMap read(File file)
            throws IOException {
        FileReader fileReader = new FileReader(file);
        return fileReader.tsom;
    }

    public static TrainableSelfOrganizingMap read(String filename)
            throws IOException {
        File file = new File(filename);
        return read(file);
    }

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

@@ -427,16 +427,426 @@
  null;%0A%0A
+    /**%0A     * Begin reading a SOM from a file.%0A     *%0A     * This method reads the first line, which must be a map type specifier.%0A     * That type specifier is used to create an object of that map type%0A     * through reflection.  The remainder of the input processing is then%0A     * delegated to that SOM.%0A     *%0A     * @param input The input file.%0A     * @throws IOException if an I/O error occurs.%0A     */%0A
     priv
@@ -2047,190 +2047,618 @@
     
-public static TrainableSelfOrganizingMap read(File file)%0A            throws IOException %7B%0A        FileReader fileReader = new FileReader(file);%0A        return fileReader.tsom;%0A    %7D%0A
+/**%0A     * Read a SOM from a %7B@code File%7D.%0A     *%0A     * @param file The input file.%0A     * @return A SOM configured as specified in %7B@code file%7D.%0A     * @throws IOException if an I/O error occurs.%0A     */%0A    public static TrainableSelfOrganizingMap read(File file)%0A            throws IOException %7B%0A        FileReader fileReader = new FileReader(file);%0A        return fileReader.tsom;%0A    %7D%0A%0A    /**%0A     * Read a SOM from a file.%0A     *%0A     * @param filename The path to the input file.%0A     * @return A SOM configured as specified in %7B@code file%7D.%0A     * @throws IOException if an I/O error occurs.%0A     */
 %0A   

Document FileReader.