001package de.monochromata.anaphors.ast.reference.strategy.concept;
002
003import java.util.function.Supplier;
004
005import de.monochromata.anaphors.ast.feature.FeatureContainer;
006import de.monochromata.anaphors.ast.reference.Referent;
007import de.monochromata.anaphors.ast.spi.AnaphorsSpi;
008
009/**
010 * Referentialization based on case-insensitive name recurrence.
011 *
012 * @param <N>  The node type in the AST
013 * @param <E>  The expression type
014 * @param <TB> The type binding type
015 * @param <S>  The scope type (optional)
016 * @param <I>  The type used to represent identifiers
017 * @param <QI> The type used to represent qualified identifiers
018 * @param <EV> The type of the event contained in the condition that is
019 *             evaluated to check when the perspectivations shall be applied.
020 * @param <PP> The type used for positions that carry perspectivations
021 */
022public class NameRecurrence<N, E, TB, S, I, QI, EV, PP>
023        extends AbstractConceptReferentializationStrategy<N, E, TB, S, I, QI, EV, PP> {
024
025    public static final String Rn_KIND = "Rn";
026
027    /**
028     * Used in contract testing.
029     */
030    @SuppressWarnings("unused")
031    protected NameRecurrence() {
032    }
033
034    public NameRecurrence(final AnaphorsSpi<N, E, TB, S, I, QI, EV, PP> anaphorsSpi) {
035        super(anaphorsSpi);
036    }
037
038    private boolean canReferToInternal(final Referent<TB, S, I, QI> potentialReferent, final S scope,
039            final Supplier<Boolean> comparison) {
040        return potentialReferent.hasName() && comparison.get();
041    }
042
043    /**
044     * Returns true, if the given definite expression is a simple name, the given
045     * potential referent has a name, and the simple name is equal to the name of
046     * the referent.
047     *
048     * @param idFromDefiniteExpression the ID created from the definite expression
049     *                                 that shall refer
050     * @param potentialReferent        the potential referent of the definite
051     *                                 expression
052     * @param scope                    the scope in which the definite expression
053     *                                 occurs
054     * @return {@code true}, if the definite expression is a simple name that is
055     *         equal to the (available) name of the referent, {@code false}
056     *         otherwise.
057     * @see #isCaseSensitive()
058     * @see #canReferToUsingConceptualType(Object, Referent, Object)
059     */
060    @Override
061    public boolean canReferTo(final I idFromDefiniteExpression, final Referent<TB, S, I, QI> potentialReferent,
062            final S scope) {
063        return canReferToInternal(potentialReferent, scope, () -> anaphorsSpi
064                .nameOfReferentEqualsIdentifier(potentialReferent, idFromDefiniteExpression, isCaseSensitive()));
065    }
066
067    /**
068     * Returns true, if the given definite expression is a simple name, the given
069     * potential referent has a name, and the conceptual type expressed in the
070     * simple name is equal to the conceptual type expressed in the name of the
071     * referent.
072     *
073     * <p>
074     * Note that during case-sensitive matching the first character of the
075     * conceptual type expressed in the referent name is matched case-insensitively
076     * to the character at that position in the definite expression because camel
077     * case is used in the definite expression, if there is a prefix to the
078     * conceptual type in the definite expression.
079     * </p>
080     *
081     * @param idFromDefiniteExpression the ID from the definite expression that
082     *                                 shall refer
083     * @param potentialReferent        the potential referent of the definite
084     *                                 expression
085     * @param scope                    the scope in which the definite expression
086     *                                 occurs
087     * @return {@code true}, if the definite expression is a simple name that is
088     *         identical to the (available) name of the referent, {@code false}
089     *         otherwise.
090     * @see #isCaseSensitive()
091     * @see #canReferTo(Object, Referent, Object)
092     */
093    @Override
094    public boolean canReferToUsingConceptualType(final I idFromDefiniteExpression,
095            final Referent<TB, S, I, QI> potentialReferent, final S scope) {
096        return canReferToInternal(potentialReferent, scope,
097                () -> anaphorsSpi.nameOfReferentMatchesConceptualTypeOfIdentifier(potentialReferent,
098                        idFromDefiniteExpression, isCaseSensitive()));
099    }
100
101    @Override
102    public FeatureContainer<QI> getFeaturesRemainingInIdentifierIfItCanReferUsingConceptualType(
103            final I idFromDefiniteExpression, final Referent<TB, S, I, QI> potentialReferent, final S scope) {
104        // TODO: This implementation actually performs a number of checks twice
105        // in canReferToUsingConceptualType and
106        // spi.getFeaturesRemainingInIdentifierBesidesConceptualTypeOfReferentName
107        // . It should be replaced by one that implements all checks in
108        // spi.getFeaturesRemainingInIdentifierBesidesConceptualTypeOfReferentName
109        // so that canReferToUsingConceptualType does not need to be invoked.
110        if (canReferToUsingConceptualType(idFromDefiniteExpression, potentialReferent, scope)) {
111            if (potentialReferent.hasName()) {
112                return anaphorsSpi.getFeaturesRemainingInIdentifierBesidesConceptualTypeOfReferentName(
113                        idFromDefiniteExpression, potentialReferent, isCaseSensitive());
114            }
115        }
116        return null;
117    }
118
119    /**
120     * Whether to match case
121     *
122     * @return false
123     */
124    protected boolean isCaseSensitive() {
125        return false;
126    }
127
128    @Override
129    public String getKind() {
130        return Rn_KIND;
131    }
132}