001package de.monochromata.anaphors.ast;
002
003import de.monochromata.anaphors.ast.relatedexp.RelatedExpression;
004
005/**
006 * An abstract implementation of the anaphora interface.
007 *
008 * @param <N>  The node type in the AST
009 * @param <E>  The expression type
010 * @param <T>  The type type
011 * @param <B>  The binding type
012 * @param <TB> The type binding type
013 * @param <S>  The scope type (optional)
014 * @param <I>  The type used to represent identifiers
015 * @param <QI> The type used to represent qualified identifiers
016 * @param <R>  The sub-type of related expression to use
017 * @param <A>  The sub-type of AST-based anaphora to use
018 */
019public abstract class AbstractASTBasedAnaphora<N, E, T, B, TB extends B, S, I, QI, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>>
020        implements ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A> {
021
022    private final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart;
023    private final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphorPart;
024
025    private final boolean isUnderspecified;
026
027    /**
028     * Used in contract testing.
029     */
030    @SuppressWarnings("unused")
031    protected AbstractASTBasedAnaphora() {
032        this(null, null, false);
033    }
034
035    public AbstractASTBasedAnaphora(final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart,
036            final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphorPart, final boolean isUnderspecified) {
037        this.relatedExpressionPart = relatedExpressionPart;
038        this.anaphorPart = anaphorPart;
039        this.isUnderspecified = isUnderspecified;
040    }
041
042    @Override
043    public RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> getRelatedExpressionPart() {
044        return relatedExpressionPart;
045    }
046
047    @Override
048    public AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> getAnaphorPart() {
049        return anaphorPart;
050    }
051
052    @Override
053    public boolean isUnderspecified() {
054        return isUnderspecified;
055    }
056
057    @Override
058    public boolean isExplicated() {
059        return !isUnderspecified();
060    }
061
062    @Override
063    public int hashCode() {
064        final int prime = 31;
065        int result = 1;
066        result = prime * result + ((anaphorPart == null) ? 0 : anaphorPart.hashCode());
067        result = prime * result + (isUnderspecified ? 1231 : 1237);
068        result = prime * result + ((relatedExpressionPart == null) ? 0 : relatedExpressionPart.hashCode());
069        return result;
070    }
071
072    @Override
073    public boolean equals(final Object obj) {
074        if (this == obj) {
075            return true;
076        }
077        if (obj == null) {
078            return false;
079        }
080        if (getClass() != obj.getClass()) {
081            return false;
082        }
083        final AbstractASTBasedAnaphora other = (AbstractASTBasedAnaphora) obj;
084        if (anaphorPart == null) {
085            if (other.anaphorPart != null) {
086                return false;
087            }
088        } else if (!anaphorPart.equals(other.anaphorPart)) {
089            return false;
090        }
091        if (isUnderspecified != other.isUnderspecified) {
092            return false;
093        }
094        if (relatedExpressionPart == null) {
095            if (other.relatedExpressionPart != null) {
096                return false;
097            }
098        } else if (!relatedExpressionPart.equals(other.relatedExpressionPart)) {
099            return false;
100        }
101        return true;
102    }
103
104    @Override
105    public String toString() {
106        return "AbstractASTBasedAnaphora [relatedExpressionPart=" + relatedExpressionPart + ", anaphorPart="
107                + anaphorPart + ", isUnderspecified=" + isUnderspecified + "]";
108    }
109
110}