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}