Location.java

package org.sterling.source;

import java.util.Objects;

public class Location implements Comparable<Location> {

    public static final String DEFAULT_SOURCE = "NULL";
    public static final Location NULL = at(DEFAULT_SOURCE, -1, -1);

    public static Location at(int line, int column) {
        return at(DEFAULT_SOURCE, line, column);
    }

    public static Location at(String source, int line, int column) {
        return new Location(source, line, column);
    }

    private final String source;
    private final int line;
    private final int column;

    public Location(String source, int line, int column) {
        this.source = source;
        this.line = line;
        this.column = column;
    }

    @Override
    public int compareTo(Location other) {
        if (line == other.line) {
            return column - other.column;
        } else {
            return line - other.line;
        }
    }

    @Override
    public boolean equals(Object o) {
        boolean matches = false;
        if (o == this) {
            matches = true;
        } else if (o instanceof Location) {
            Location other = (Location) o;
            matches = Objects.equals(source, other.source)
                && Objects.equals(line, other.line)
                && Objects.equals(column, other.column);
        }
        return matches;
    }

    public int getColumn() {
        return column;
    }

    public int getLine() {
        return line;
    }

    public String getSource() {
        return source;
    }

    @Override
    public int hashCode() {
        return Objects.hash(source, line, column);
    }

    public boolean isNull() {
        return equals(NULL);
    }

    @Override
    public String toString() {
        return "'" + source + "' (" + (line + 1) + ", " + (column + 1) + ")";
    }
}