001package de.monochromata.anaphors.ast.chain;
002
003import static java.util.Collections.emptyList;
004import static java.util.Collections.singletonList;
005
006import java.util.List;
007
008import de.monochromata.anaphors.ast.ASTBasedAnaphora;
009import de.monochromata.anaphors.ast.AnaphorPart;
010import de.monochromata.anaphors.ast.RelatedExpressionPart;
011import de.monochromata.anaphors.ast.relatedexp.RelatedExpression;
012
013/**
014 * Used to form chains of anaphors. A chain element can have a single
015 * predecessor and multiple successors. I.e. an anaphor can have a single
016 * related expression and a related expression can have multiple related
017 * expressions.
018 * <p>
019 * E.g.
020 *
021 * <pre>
022 * {@code new String("hello"); println(helloString); println(helloString);}
023 * </pre>
024 *
025 * would be realized as three {@link ChainElement}s:
026 *
027 * <pre>
028 * {@code ChainElement(RelatedExpressionPart)
029 * ├ ChainElement(AnaphorPart #1)
030 * └ ChainElement(AnaphorPart #2)}
031 * </pre>
032 * <p>
033 * This 1:N relationship between related expressions and anaphors reflects their
034 * realization via local variables. From a theoretical, linguistic point it
035 * might also suitable to consider the second anaphor to be related to the first
036 * anaphor instead of being related to the (initial) related expression. From a
037 * cognitive point in three-level semantics, the related expression and the two
038 * anaphors would refer to a single node in memory and order would occur
039 * temporally only in the order of reading.
040 * <p>
041 * While an {@link ASTBasedAnaphora} combines both a
042 * {@link RelatedExpressionPart} and a {@link AnaphorPart}, an anaphoric chain
043 * represents them as two {@link ChainElement}s. That way, a two
044 * {@link AnaphorPart}s that are related to the same
045 * {@link RelatedExpressionPart} can be represented as three
046 * {@link ChainElement}s.
047 *
048 * @param <N>  The node type in the AST
049 * @param <E>  The expression type
050 * @param <T>  The type type
051 * @param <B>  The binding type
052 * @param <TB> The type binding type
053 * @param <S>  The scope type (optional)
054 * @param <I>  The type used to represent identifiers
055 * @param <QI> The type used to represent qualified identifiers
056 * @param <AT> The type used for attachments to chain elements that have an
057 *             anaphor part. The attachment may be used to stored e.g. an old
058 *             anaphora relation.
059 * @param <R>  The sub-type of related expression to use
060 * @param <A>  The sub-type of AST-based anaphora to use
061 * @param <C>  The sub-type of chain element to use
062 */
063public class ChainElement<N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> {
064
065    public final C previous;
066    public final List<C> next;
067
068    public final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpression;
069    public final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphor;
070
071    public final AT anaphorAttachment;
072
073    /**
074     * Used in contract testing.
075     */
076    @SuppressWarnings("unused")
077    protected ChainElement() {
078        this(null, null, null, null, null);
079    }
080
081    public ChainElement(final C previous, final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphor,
082            final AT anaphorAttachment) {
083        this(previous, emptyList(), null, anaphor, anaphorAttachment);
084    }
085
086    public ChainElement(final C next, final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpression) {
087        this(null, singletonList(next), relatedExpression, null, null);
088    }
089
090    public ChainElement(final List<C> next,
091            final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpression) {
092        this(null, next, relatedExpression, null, null);
093    }
094
095    public ChainElement(final C previous, final List<C> next,
096            final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpression,
097            final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphor, final AT anaphorAttachment) {
098        this.previous = previous;
099        this.next = next;
100        this.relatedExpression = relatedExpression;
101        this.anaphor = anaphor;
102        this.anaphorAttachment = anaphorAttachment;
103    }
104
105    @Override
106    public int hashCode() {
107        final int prime = 31;
108        int result = 1;
109        result = prime * result + ((anaphor == null) ? 0 : anaphor.hashCode());
110        result = prime * result + ((anaphorAttachment == null) ? 0 : anaphorAttachment.hashCode());
111        result = prime * result + ((relatedExpression == null) ? 0 : relatedExpression.hashCode());
112        return result;
113    }
114
115    @Override
116    public boolean equals(final Object obj) {
117        if (this == obj) {
118            return true;
119        }
120        if (obj == null) {
121            return false;
122        }
123        if (getClass() != obj.getClass()) {
124            return false;
125        }
126        final ChainElement other = (ChainElement) obj;
127        if (anaphor == null) {
128            if (other.anaphor != null) {
129                return false;
130            }
131        } else if (!anaphor.equals(other.anaphor)) {
132            return false;
133        }
134        if (anaphorAttachment == null) {
135            if (other.anaphorAttachment != null) {
136                return false;
137            }
138        } else if (!anaphorAttachment.equals(other.anaphorAttachment)) {
139            return false;
140        }
141        if (relatedExpression == null) {
142            if (other.relatedExpression != null) {
143                return false;
144            }
145        } else if (!relatedExpression.equals(other.relatedExpression)) {
146            return false;
147        }
148        return true;
149    }
150
151    @Override
152    public String toString() {
153        return "ChainElement [relatedExpression=" + relatedExpression + ", anaphor=" + anaphor + ", attachment="
154                + anaphorAttachment + "]";
155    }
156
157}