/**
 * Copyright (C) 2015 The Authors.
 */
package dk.itu.kelvin.parser;

// I/O utilities
import java.io.File;

// File type utilities
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;

// Functional utilities
import dk.itu.kelvin.util.function.Callback;

// Threading
import dk.itu.kelvin.thread.TaskQueue;

/**
 * Parser class.
 */
public abstract class Parser {
  /**
   * Map of file MIME types.
   *
   * @see <a href="http://en.wikipedia.org/wiki/MIME">
   *      http://en.wikipedia.org/wiki/MIME</a>
   */
  private static final FileTypeMap TYPES = new MimetypesFileTypeMap();

  /**
   * Read and parse an input file.
   *
   * <p>
   * All I/O and parsing takes place on a separate thread and the specified
   * callback is invoked once the parsing has finished.
   *
   * @param file      The file to read.
   * @param callback  The callback to invoke once the parsing has finished.
   */
  public void read(final File file, final Callback callback) {
    TaskQueue.run(() -> {
      try {
        this.parse(file);
      }
      catch (Exception ex) {
        ex.printStackTrace();
      }
      finally {
        callback.done();
      }
    });
  }

  /**
   * Parse the contents of the specified file.
   *
   * <p>
   * This method must be implemented by superclasses and is where the actual
   * file parsing happens.
   *
   * @param file The file whose contents to parse.
   *
   * @throws Exception In case of an error during parsing.
   */
  protected abstract void parse(final File file) throws Exception;

  /**
   * Return a parser instance that can parse the specified file.
   *
   * @param file  The file to find a matching parser for.
   * @return      A parser instance that can parse the specified file or
   *              {@code null} if no matching parser was found.
   */
  public static final Parser probe(final File file) {
    if (file == null || !file.isFile()) {
      return null;
    }

    // Get the MIME type of the file.
    String type = TYPES.getContentType(file);

    switch (type.toLowerCase()) {
      case "application/xml":
      case "application/x-bzip2":
        return null;

      case "application/octet-stream":
        return null;

      default:
        return null;
    }
  }
}

@@ -213,16 +213,68 @@
 peMap;%0A%0A
+// Utilities%0Aimport dk.itu.kelvin.util.Collection;%0A%0A
 // Funct
@@ -388,16 +388,238 @@
 Queue;%0A%0A
+// Models%0Aimport dk.itu.kelvin.model.Address;%0Aimport dk.itu.kelvin.model.BoundingBox;%0Aimport dk.itu.kelvin.model.Land;%0Aimport dk.itu.kelvin.model.Node;%0Aimport dk.itu.kelvin.model.Relation;%0Aimport dk.itu.kelvin.model.Way;%0A%0A
 /**%0A * P
@@ -1830,16 +1830,823 @@
 ption;%0A%0A
+  /**%0A   * Get the parsed bounds.%0A   *%0A   * @return The parsed bounds.%0A   */%0A  public abstract BoundingBox bounds();%0A%0A  /**%0A   * Get the parsed node elements.%0A   *%0A   * @return The parsed node elements.%0A   */%0A  public abstract Collection%3CNode%3E nodes();%0A%0A  /**%0A   * Get the parsed way elements.%0A   *%0A   * @return The parsed way elements.%0A   */%0A  public abstract Collection%3CWay%3E ways();%0A%0A  /**%0A   * Get the parsed relation elements.%0A   *%0A   * @return The parsed relation elements.%0A   */%0A  public abstract Collection%3CRelation%3E relations();%0A%0A  /**%0A   * Get the parsed land polygons.%0A   *%0A   * @return The parsed land polygons.%0A   */%0A  public abstract Collection%3CWay%3E land();%0A%0A  /**%0A   * Get the parsed addresses.%0A   *%0A   * @return The parsed addresses.%0A   */%0A  public abstract Collection%3CAddress%3E addresses();%0A%0A
   /**%0A  

Add additional methods.