001package de.monochromata.anaphors.ast.relatedexp;
002
003import java.util.List;
004import java.util.function.BiFunction;
005import java.util.function.BiPredicate;
006import java.util.function.Function;
007import java.util.function.Supplier;
008
009import de.monochromata.anaphors.ast.relatedexp.strategy.RelatedExpressionStrategy;
010import de.monochromata.anaphors.ast.spi.RelatedExpressionsSpi;
011
012/**
013 * An abstract base class for implementing related expressions.
014 *
015 * @param <N>  The node type in the AST
016 * @param <T>  The type type
017 * @param <B>  The binding type
018 * @param <MB> The method binding type
019 * @param <TB> The type binding type
020 * @param <S>  The scope type (optional)
021 * @param <QI> The type used to represent qualified identifiers
022 * @param <EV> The type of the event contained in the condition that is
023 *             evaluated to check when the perspectivations shall be applied.
024 * @param <PP> The type used for positions that carry perspectivations
025 * @param <R>  The sub-type of related expression to use
026 *
027 * @deprecated {@link RelatedExpression} will be turned into a POJO instead
028 */
029@Deprecated
030public class DefaultRelatedExpression<N, T, B, MB extends B, TB extends B, S, QI, EV, PP, R extends DefaultRelatedExpression<N, T, B, MB, TB, S, QI, EV, PP, R>>
031        implements RelatedExpression<N, T, B, TB, S, QI, R> {
032
033    private final boolean isEffectivelyFinal;
034    private final Supplier<QI> nameSupplier;
035    private N relatedExpression;
036    private final RelatedExpressionStrategy<N, T, B, TB, S, QI, R> strategy;
037    protected final RelatedExpressionsSpi<N, ?, T, B, MB, TB, S, ?, QI, EV, PP, R> relatedExpressionsSpi;
038    private final Function<S, B> nameBindingResolver;
039    private final Function<S, Integer> lengthOfTypeForTempVarFunction;
040    private final BiFunction<S, Function<TB, T>, T> typeForTypeVarFunction;
041    private final Function<S, TB> typeResolver;
042    private final BiPredicate<? super DefaultRelatedExpression<N, T, B, MB, TB, S, QI, EV, PP, R>, R> canBeUsedInsteadOfBiPredicate;
043
044    /**
045     * Used in contract testing.
046     */
047    @SuppressWarnings("unused")
048    protected DefaultRelatedExpression() {
049        this(false, null, null, null, null, null, null, null, null, null);
050    }
051
052    public DefaultRelatedExpression(final boolean isEffectivelyFinal, final Supplier<QI> nameSupplier,
053            final N relatedExpression, final RelatedExpressionStrategy<N, T, B, TB, S, QI, R> strategy,
054            final RelatedExpressionsSpi<N, ?, T, B, MB, TB, S, ?, QI, EV, PP, R> relatedExpressionsSpi,
055            final Function<S, B> nameBindingResolver, final Function<S, Integer> lengthOfTypeForTempVarFunction,
056            final BiFunction<S, Function<TB, T>, T> typeForTypeVarFunction, final Function<S, TB> typeResolver,
057            final BiPredicate<? super DefaultRelatedExpression<N, T, B, MB, TB, S, QI, EV, PP, R>, R> canBeUsedInsteadOfBiPredicate) {
058        this.isEffectivelyFinal = isEffectivelyFinal;
059        this.nameSupplier = nameSupplier;
060        this.relatedExpression = relatedExpression;
061        this.strategy = strategy;
062        this.relatedExpressionsSpi = relatedExpressionsSpi;
063        this.nameBindingResolver = nameBindingResolver;
064        this.lengthOfTypeForTempVarFunction = lengthOfTypeForTempVarFunction;
065        this.typeForTypeVarFunction = typeForTypeVarFunction;
066        this.typeResolver = typeResolver;
067        this.canBeUsedInsteadOfBiPredicate = canBeUsedInsteadOfBiPredicate;
068    }
069
070    @Override
071    public boolean isEffectivelyFinal() {
072        return isEffectivelyFinal;
073    }
074
075    @Override
076    public QI getName() {
077        return nameSupplier.get();
078    }
079
080    @Override
081    public N getRelatedExpression() {
082        return relatedExpression;
083    }
084
085    @Override
086    public void setRelatedExpression(final N relatedExpression) {
087        this.relatedExpression = relatedExpression;
088    }
089
090    @Override
091    public RelatedExpressionStrategy<N, T, B, TB, S, QI, R> getStrategy() {
092        return strategy;
093    }
094
095    @Override
096    public B resolveNameBinding(final S scope) {
097        return nameBindingResolver.apply(scope);
098    }
099
100    @Override
101    public int getLengthOfTypeForTempVar(final S scope) {
102        return lengthOfTypeForTempVarFunction.apply(scope);
103    }
104
105    @Override
106    public T getTypeForTempVar(final S scope, final Function<TB, T> importRewrite) {
107        return typeForTypeVarFunction.apply(scope, importRewrite);
108    }
109
110    @Override
111    public TB resolveType(final S scope) {
112        return typeResolver.apply(scope);
113    }
114
115    @Override
116    public List<QI> getContainedNamesFromSurface() {
117        throw new RuntimeException("Not yet implemented");
118    }
119
120    @Override
121    public List<QI> getPartNames() {
122        throw new RuntimeException("Not yet implemented");
123    }
124
125    @Override
126    public List<QI> getAssociateNames() {
127        throw new RuntimeException("Not yet implemented");
128    }
129
130    @Override
131    public List<TB> resolveContainedTypesFromSurface(final S scope) {
132        throw new RuntimeException("Not yet implemented");
133    }
134
135    @Override
136    public List<TB> resolvePartTypes(final S scope) {
137        throw new RuntimeException("Not yet implemented");
138    }
139
140    @Override
141    public List<TB> resolveAssociateTypes(final S scope) {
142        throw new RuntimeException("Not yet implemented");
143    }
144
145    @Override
146    public boolean canBeUsedInsteadOf(final R other) {
147        return canBeUsedInsteadOfBiPredicate.test(this, other);
148    }
149
150    @Override
151    public String getDescription() {
152        return relatedExpressionsSpi.getDescription(relatedExpression);
153    }
154
155    @Override
156    public int getLine() {
157        return relatedExpressionsSpi.getLine(relatedExpression);
158    }
159
160    @Override
161    public int getColumn() {
162        return relatedExpressionsSpi.getColumn(relatedExpression);
163    }
164
165    @Override
166    public int hashCode() {
167        final int prime = 31;
168        int result = 1;
169        result = prime * result + ((this.relatedExpression == null) ? 0 : this.relatedExpression.hashCode());
170        result = prime * result + ((this.strategy == null) ? 0 : this.strategy.hashCode());
171        return result;
172    }
173
174    @Override
175    public boolean equals(final Object obj) {
176        if (this == obj) {
177            return true;
178        }
179        if (obj == null) {
180            return false;
181        }
182        if (getClass() != obj.getClass()) {
183            return false;
184        }
185        @SuppressWarnings("unchecked")
186        final DefaultRelatedExpression<N, T, B, MB, TB, S, QI, EV, PP, R> other = (DefaultRelatedExpression<N, T, B, MB, TB, S, QI, EV, PP, R>) obj;
187        if (this.relatedExpression == null) {
188            if (other.relatedExpression != null) {
189                return false;
190            }
191        } else if (!relatedExpressionsSpi.compare(this.relatedExpression, other.relatedExpression)) {
192            return false;
193        }
194        if (this.strategy == null) {
195            if (other.strategy != null) {
196                return false;
197            }
198        } else if (!this.strategy.equals(other.strategy)) {
199            return false;
200        }
201        return true;
202    }
203
204    @Override
205    public String toString() {
206        return "RelatedExpression [name=" + this.getName() + ", relatedExpression=" + this.relatedExpression
207                + ", strategy=" + this.strategy + "]";
208    }
209
210}