/* This file is part of SableCC ( http://sablecc.org ).
 * 
 * See the NOTICE file distributed with this work for copyright information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.sablecc.sablecc.alphabet;

/**
 * This class represents a pair of symbols.
 * 
 * A symbol pair is defined by two distinct symbols.
 */
final class SymbolPair<T extends Comparable<? super T>> {

    /** The first unmodifiable symbol of the pair */
    private final Symbol<T> symbol1;

    /** The second unmodifiable symbol of the pair */
    private final Symbol<T> symbol2;

    /** Cached hashcode. Is <code>null</code> when not yet computed. */
    private Integer hashCode;

    /**
     * Cached string representation. Is <code>null</code> when not yet
     * computed.
     */
    private String toString;

    /**
     * Constructs a symbol pair with two provided symbols.
     * 
     * @param symbol1
     *            the first symbol of the pair.
     * @param symbol2
     *            the second symbol of the pair.
     */
    SymbolPair(
            Symbol<T> symbol1,
            Symbol<T> symbol2) {

        this.symbol1 = symbol1;
        this.symbol2 = symbol2;
    }

    /**
     * Returns the first symbol of the pair.
     * 
     * @return the first symbol of the pair.
     */
    Symbol<T> getSymbol1() {

        return this.symbol1;
    }

    /**
     * Returns the second symbol of the pair.
     * 
     * @return the second symbol of the pair.
     */
    Symbol<T> getSymbol2() {

        return this.symbol2;
    }

    /**
     * Compares this symbol pair with an object for equality. Returns
     * <code>true</code> if the object is a symbol pair and if it as the same
     * two symbols as those of this instance.
     * 
     * @param obj
     *            the object to compare with.
     * @return <code>true</code> if this symbol pair and the object are equal;
     *         <code>false</code> otherwise.
     */
    @Override
    public boolean equals(
            Object obj) {

        if (obj == null) {
            return false;
        }

        if (!(obj instanceof SymbolPair)) {
            return false;
        }

        SymbolPair symbolPair = (SymbolPair) obj;

        if (this.symbol1 == null && symbolPair.symbol1 != null) {
            return false;
        }

        if (this.symbol2 == null && symbolPair.symbol2 != null) {
            return false;
        }

        return (this.symbol1 == null || this.symbol1.equals(symbolPair.symbol1))
                && (this.symbol2 == null || this.symbol2
                        .equals(symbolPair.symbol2));
    }

    /**
     * Returns a hash code value for this object.
     * 
     * @return a hash code for this object.
     */
    @Override
    public int hashCode() {

        if (this.hashCode == null) {

            int hashCode = 0;

            if (this.symbol1 != null) {
                hashCode += this.symbol1.hashCode();
            }

            if (this.symbol2 != null) {
                hashCode += 17 * this.symbol2.hashCode();
            }

            this.hashCode = hashCode;
        }

        return this.hashCode;
    }

    /**
     * Returns a <code>String</code> representation for this symbol pair. The
     * representation takes the following form: <code>(symbol1,symbol2)</code>
     * 
     * @return a <code>String</code> representing this symbol.
     */
    @Override
    public String toString() {

        if (this.toString == null) {
            this.toString = "(" + this.symbol1 + "," + this.symbol2 + ")";
        }

        return this.toString;
    }
}

@@ -743,104 +743,134 @@
 %0A * 
-This class represents a pair of symbols.%0A * %0A * A symbol pair is defined by two distinct symbols
+A symbol pair is a pair %3Ccode%3E(x,y)%3C/code%3E where each of %3Ccode%3Ex%3C/code%3E%0A * and %3Ccode%3Ey%3C/code%3E is a symbol or %3Ccode%3Enull%3C/code%3E
 .%0A *
@@ -948,29 +948,16 @@
 e first 
-unmodifiable 
 symbol o
@@ -958,32 +958,61 @@
 mbol of the pair
+, possibly %3Ccode%3Enull%3C/code%3E.
  */%0A    private 
@@ -1060,21 +1060,8 @@
 ond 
-unmodifiable 
 symb
@@ -1074,16 +1074,45 @@
 the pair
+, possibly %3Ccode%3Enull%3C/code%3E.
  */%0A    
@@ -2139,193 +2139,126 @@
   * 
-Compares this symbol pair with an object for equality. Returns%0A     * %3Ccode%3Etrue%3C/code%3E if the object is a symbol pair and if it as the same%0A     * two symbols as those of this instance
+Returns whether this instance is equal to the provided object. They are%0A     * equal if they contain identical symbols
 .%0A  
@@ -3151,17 +3151,19 @@
 Returns 
-a
+the
  hash co
@@ -3169,29 +3169,27 @@
 ode 
-value for this object
+of this symbol pair
 .%0A  
@@ -3209,17 +3209,19 @@
 @return 
-a
+the
  hash co
@@ -3226,24 +3226,8 @@
 code
- for this object
 .%0A  
@@ -3674,37 +3674,26 @@
 Returns 
-a %3Ccode%3EString%3C/code%3E
+the string
  represe
@@ -3700,19 +3700,18 @@
 ntation 
+o
 f
-or
  this sy
@@ -3724,161 +3724,57 @@
 air.
- The%0A     * representation takes the following form: %3Ccode%3E(symbol1,symbol2)%3C/code%3E%0A     * %0A     * @return a %3Ccode%3EString%3C/code%3E representing this symbol
+%0A     * %0A     * @return the string representation
 .%0A  

Improve javadoc comments.