Edge.java

package edu.hawaii.ics.yucheng;

import java.util.Scanner;

/**
 * A undirected, non-cyclical edge. This class is immutable.
 */
final class Edge implements Comparable<Edge> {

    private final int myFirst;
    private final int mySecond;


    /**
     * Initializes a new instance of the class.
     * 
     * @param first The first vertex.
     * 
     * @param second The second vertex.
     */
    public Edge(final int first, final int second) {
        if (first < 0 || second < 0 || first == second)
            throw new GraphException("Invalid arguments.");

        if (first < second) {
            myFirst = first;
            mySecond = second;
        } else {
            myFirst = second;
            mySecond = first;
        }
    }


    /**
     * Initializes a new instance of the class.
     * 
     * @param scanner The scanner.
     * 
     * @throws GraphException Thrown if there is an error reading from the
     *           scanner.
     */
    public Edge(final Scanner scanner) throws GraphException {
        if (scanner == null)
            throw new NullPointerException("scanner");

        // Catch and rethrow an exceptions in this constructor.
        try {
            // Read the next line.
            final String from = scanner.nextLine();

            // Split the line into a left and right side of the comma.
            final String[] fields = from.split(",");
            if (fields.length != 2)
                throw new GraphException("Invalid edge (No comma present)");

            // Parse the first and second values as integers. The values are stored
            // in the file as 1-based values, but this class stores them as 0-based
            // values.
            final int first = Integer.parseInt(fields[0].trim()) - 1;
            final int second = Integer.parseInt(fields[1].trim()) - 1;

            // Check for bad indices.
            if (first < 0)
                throw new GraphException("Invalid edge (First index too small)");

            if (second < 0)
                throw new GraphException("Invalid edge (Second index too small)");

            if (first == second)
                throw new GraphException("Invalid edge (self-loop detected at vertex "
                    + (first + 1) + ")");

            if (first < second) {
                myFirst = first;
                mySecond = second;
            } else {
                myFirst = second;
                mySecond = first;
            }

        } catch (final GraphException e) {
            throw e;

        } catch (final Exception e) {
            final String name = e.getClass().getName();
            throw new GraphException("Invalid edge (" + name + ")", e);
        }
    }


    /**
     * Compares this edge to another edge.
     * 
     * @param o The other edge.
     * 
     * @return Negative if less than, positive if greater than, and zero if equal.
     */
    public int compareTo(final Edge o) {
        // This is always greater than null edges.
        if (o == null)
            return 1;

        // Return zero if both are found.
        if (o.contains(myFirst) && o.contains(mySecond))
            return 0;

        // Sort by first, then by second.
        int result;
        if (0 != (result = myFirst - o.myFirst))
            return result;
        return mySecond - o.mySecond;
    }


    /**
     * Returns true if the edge contains a specified index.
     * 
     * @param index The index.
     * 
     * @return True if the edge contains the index or false if it does not.
     */
    public boolean contains(final int index) {
        return myFirst == index || mySecond == index;
    }


    /**
     * Returns true if the object equals this instance.
     * 
     * @param obj The object to compare.
     * 
     * @return True indicates the object equals this instance.
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == null)
            return false;
        if (obj == this)
            return true;
        if (!obj.getClass().equals(getClass()))
            return false;
        return 0 == compareTo((Edge) obj);
    }


    /**
     * Returns the first index.
     * 
     * @return The first index.
     */
    public int first() {
        return myFirst;
    }


    /**
     * Returns the opposite index of the one specified. For example, passing the
     * value of first() will return seconds(), and passing the value of second()
     * will return first().
     * 
     * @param index The index.
     * 
     * @return The opposite index.
     */
    public int getOpposite(final int index) {
        if (myFirst == index)
            return mySecond;

        if (mySecond != index)
            throw new GraphException("Invalid index");

        return myFirst;
    }


    /**
     * Returns a hash code value for the object.
     * 
     * @return A hash code value for this object.
     */
    @Override
    public int hashCode() {
        return myFirst | mySecond << 16;
    }


    /**
     * Returns the second index.
     * 
     * @return The second index.
     */
    public int second() {
        return mySecond;
    }


    /**
     * Returns the string representation of the class data.
     * 
     * @return The string representation of the class data.
     */
    @Override
    public String toString() {
        return myFirst + 1 + ".." + (mySecond + 1);
    }
}
Valid HTML 4.01 Valid CSS