blob: 072e829ca3ee544ce5dd8ae8a7f7b3dc083c6195 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2018 CEA LIST and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink(CEA LIST) - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.examples.codegen.analyzer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBoxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCatchExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGEcoreExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGGuardExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOppositePropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGPropertyCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGString;
import org.eclipse.ocl.examples.codegen.cgmodel.CGThrowExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeId;
import org.eclipse.ocl.examples.codegen.cgmodel.CGUnboxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement;
import org.eclipse.ocl.pivot.BagType;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionRange;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.IntegerLiteralExp;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.LiteralExp;
import org.eclipse.ocl.pivot.LoopExp;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.OppositePropertyCallExp;
import org.eclipse.ocl.pivot.OrderedSetType;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.PropertyCallExp;
import org.eclipse.ocl.pivot.RealLiteralExp;
import org.eclipse.ocl.pivot.SequenceType;
import org.eclipse.ocl.pivot.SetType;
import org.eclipse.ocl.pivot.StringLiteralExp;
import org.eclipse.ocl.pivot.TupleLiteralExp;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
import org.eclipse.ocl.pivot.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.ids.ClassId;
import org.eclipse.ocl.pivot.ids.CollectionTypeId;
import org.eclipse.ocl.pivot.ids.DataTypeId;
import org.eclipse.ocl.pivot.ids.ElementId;
import org.eclipse.ocl.pivot.ids.EnumerationId;
import org.eclipse.ocl.pivot.ids.EnumerationLiteralId;
import org.eclipse.ocl.pivot.ids.IdVisitor;
import org.eclipse.ocl.pivot.ids.LambdaTypeId;
import org.eclipse.ocl.pivot.ids.MapTypeId;
import org.eclipse.ocl.pivot.ids.NestedPackageId;
import org.eclipse.ocl.pivot.ids.NestedTypeId;
import org.eclipse.ocl.pivot.ids.NsURIPackageId;
import org.eclipse.ocl.pivot.ids.OclInvalidTypeId;
import org.eclipse.ocl.pivot.ids.OclVoidTypeId;
import org.eclipse.ocl.pivot.ids.OperationId;
import org.eclipse.ocl.pivot.ids.PackageId;
import org.eclipse.ocl.pivot.ids.PrimitiveTypeId;
import org.eclipse.ocl.pivot.ids.PropertyId;
import org.eclipse.ocl.pivot.ids.RootPackageId;
import org.eclipse.ocl.pivot.ids.TemplateBinding;
import org.eclipse.ocl.pivot.ids.TemplateParameterId;
import org.eclipse.ocl.pivot.ids.TemplateableTypeId;
import org.eclipse.ocl.pivot.ids.TuplePartId;
import org.eclipse.ocl.pivot.ids.TupleTypeId;
import org.eclipse.ocl.pivot.ids.TypeId;
import org.eclipse.ocl.pivot.ids.UnspecifiedId;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.Nameable;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.values.CollectionValue;
import org.eclipse.ocl.pivot.values.IntegerRange;
import org.eclipse.ocl.pivot.values.IntegerValue;
import org.eclipse.ocl.pivot.values.InvalidValue;
import org.eclipse.ocl.pivot.values.RealValue;
/**
* A NameManager provides suggestions for names and maintains caches of used names so that model elements are consistently
* named without collisions.
*/
public class NameManager
{
public static final String BAG_NAME_HINT_PREFIX = "BAG";
public static final String COLLECTION_NAME_HINT_PREFIX = "COL";
public static final String DEFAULT_NAME_PREFIX = "symbol";
// public static final String ID_NAME_HINT_PREFIX = "TID";
public static final String EXPRESSION_IN_OCL_NAME_HINT_PREFIX = PivotConstants.RESULT_NAME;
public static final String INTEGER_NAME_HINT_PREFIX = "INT_";
public static final String INVALID_NAME_HINT_PREFIX = "IVE_";
public static final String ITERATION_NAME_HINT_PREFIX = "";
public static final String OPERATION_NAME_HINT_PREFIX = "OP_";
public static final String OPERATION_CALL_EXP_NAME_HINT_PREFIX = ""; //"RES_";
public static final String ORDERED_SET_NAME_HINT_PREFIX = "ORD";
public static final String PROPERTY_NAME_HINT_PREFIX = "";
public static final String REAL_NAME_HINT_PREFIX = "REA_";
public static final String RANGE_NAME_HINT_PREFIX = "RNG";
public static final String SEQUENCE_NAME_HINT_PREFIX = "SEQ";
public static final String SET_NAME_HINT_PREFIX = "SET";
public static final String STRING_NAME_HINT_PREFIX = "STR_";
public static final int STRING_NAME_HINT_LIMIT = 64;
public static final String TUPLE_NAME_HINT_PREFIX = "TUP_";
public static final String TYPE_NAME_HINT_PREFIX = "TYP_";
public static final String VARIABLE_DECLARATION_NAME_HINT_PREFIX = "";
/**
* Names that will not be allocated to temporary variables.
* <p>
* This Set is public and unsynchronized. Clients may change it in arbitrary ways at their own risk.
* <p>
* It is strongly recommended that clients do no more than add additional names.
*/
public static final Set<@NonNull String> reservedJavaNames = new HashSet<>();
{
reservedJavaNames.add("Boolean");
reservedJavaNames.add("Character");
reservedJavaNames.add("Class");
reservedJavaNames.add("Double");
reservedJavaNames.add("Float");
reservedJavaNames.add("Integer");
reservedJavaNames.add("List");
reservedJavaNames.add("Long");
reservedJavaNames.add("Map");
reservedJavaNames.add("Package");
reservedJavaNames.add("String");
reservedJavaNames.add("boolean");
reservedJavaNames.add("byte");
reservedJavaNames.add("char");
reservedJavaNames.add("double");
reservedJavaNames.add("float");
reservedJavaNames.add("int");
reservedJavaNames.add("long");
reservedJavaNames.add("short");
reservedJavaNames.add("void");
reservedJavaNames.add("abstract"); // FIXME Exploit CodeGenUtil.getJavaReservedWords()
reservedJavaNames.add("assert");
reservedJavaNames.add("break");
reservedJavaNames.add("case");
reservedJavaNames.add("catch");
reservedJavaNames.add("class");
reservedJavaNames.add("const");
reservedJavaNames.add("continue");
reservedJavaNames.add("default");
reservedJavaNames.add("do");
reservedJavaNames.add("else");
reservedJavaNames.add("enum");
reservedJavaNames.add("extends");
reservedJavaNames.add("final");
reservedJavaNames.add("finally");
reservedJavaNames.add("for");
reservedJavaNames.add("goto");
reservedJavaNames.add("if");
reservedJavaNames.add("implements");
reservedJavaNames.add("import");
reservedJavaNames.add("instanceof");
reservedJavaNames.add("interface");
reservedJavaNames.add("native");
reservedJavaNames.add("new");
reservedJavaNames.add("package");
reservedJavaNames.add("private");
reservedJavaNames.add("protected");
reservedJavaNames.add("public");
reservedJavaNames.add("return");
reservedJavaNames.add("static");
reservedJavaNames.add("strictfp");
reservedJavaNames.add("switch");
reservedJavaNames.add("synchronized");
reservedJavaNames.add("throw");
reservedJavaNames.add("throws");
reservedJavaNames.add("transient");
reservedJavaNames.add("try");
reservedJavaNames.add("volatile");
reservedJavaNames.add("while");
reservedJavaNames.add("false");
reservedJavaNames.add("null");
reservedJavaNames.add("super");
reservedJavaNames.add("this");
reservedJavaNames.add("true");
}
public static @NonNull IdVisitor<@NonNull String> idVisitor = new IdVisitor<@NonNull String>()
{
@Override
public @NonNull String visitClassId(@NonNull ClassId id) {
return "CLSSid_" + id.getName();
}
@Override
public @NonNull String visitCollectionTypeId(@NonNull CollectionTypeId id) {
CollectionTypeId generalizedId = id.getGeneralizedId();
String idPrefix;
if (generalizedId == TypeId.BAG) {
idPrefix = "BAG_";
}
else if (generalizedId == TypeId.ORDERED_SET) {
idPrefix = "ORD_";
}
else if (generalizedId == TypeId.SEQUENCE) {
idPrefix = "SEQ_";
}
else if (generalizedId == TypeId.SET) {
idPrefix = "SET_";
}
else {
idPrefix = "COL_";
}
if (generalizedId == id) {
return idPrefix;
}
else {
return idPrefix + id.getElementTypeId().accept(this);
}
}
@Override
public @NonNull String visitDataTypeId(@NonNull DataTypeId id) {
return "DATAid_" + id.getName();
}
@Override
public @NonNull String visitEnumerationId(@NonNull EnumerationId id) {
return "ENUMid_" + id.getName();
}
@Override
public @NonNull String visitEnumerationLiteralId(@NonNull EnumerationLiteralId id) {
return "ELITid_" + id.getName();
}
@Override
public @NonNull String visitInvalidId(@NonNull OclInvalidTypeId id) {
return "INVid";
}
@Override
public @NonNull String visitLambdaTypeId(@NonNull LambdaTypeId id) {
return "LAMBid_" + id.getName();
}
@Override
public @NonNull String visitMapTypeId(@NonNull MapTypeId id) {
MapTypeId generalizedId = id.getGeneralizedId();
String idPrefix = "MAP_";
if (generalizedId == id) {
return idPrefix;
}
else {
return idPrefix + id.getKeyTypeId().accept(this) + id.getValueTypeId().accept(this);
}
}
@Override
public @NonNull String visitNestedPackageId(@NonNull NestedPackageId id) {
return "PACKid_" + id.getName();
}
@Override
public @NonNull String visitNsURIPackageId(@NonNull NsURIPackageId id) {
return "PACKid_" + id.getNsURI();
}
@Override
public @NonNull String visitNullId(@NonNull OclVoidTypeId id) {
return "NULLid";
}
@Override
public @NonNull String visitOperationId(@NonNull OperationId id) {
return "OPid_" + id.getName();
}
@Override
public @NonNull String visitPrimitiveTypeId(@NonNull PrimitiveTypeId id) {
return "PRIMid_" + id.getName();
}
@Override
public @NonNull String visitPropertyId(@NonNull PropertyId id) {
return "PROPid_" + id.getName();
}
@Override
public @NonNull String visitRootPackageId(@NonNull RootPackageId id) {
return "PACKid_" + id.getName();
}
@Override
public @NonNull String visitTemplateBinding(@NonNull TemplateBinding id) {
return "BINDid_";
}
@Override
public @NonNull String visitTemplateParameterId(@NonNull TemplateParameterId id) {
return "TMPLid_";
}
@Override
public @NonNull String visitTemplateableTypeId(@NonNull TemplateableTypeId id) {
return "TYPEid_";
}
@Override
public @NonNull String visitTuplePartId(@NonNull TuplePartId id) {
return "PARTid_";
}
@Override
public @NonNull String visitTupleTypeId(@NonNull TupleTypeId id) {
return "TUPLid_";
}
@Override
public @NonNull String visitUnspecifiedId(@NonNull UnspecifiedId id) {
return "UNSPid_";
}
};
protected static void appendJavaCharacters(StringBuilder s, String string) {
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (Character.isJavaIdentifierPart(c)) {
s.append(c);
}
else {
s.append('_');
}
}
}
protected static void appendJavaCharacters(StringBuilder s, String string, int iMax) {
for (int i = 0; i < Math.min(iMax, string.length()); i++) {
char c = string.charAt(i);
if (Character.isJavaIdentifierPart(c)) {
s.append(c);
}
else {
s.append('_');
}
}
}
/**
* Return a valid Java identifier based on nameHint. hasPrefix may be true to indicate that the
* caller will supply an additional valid prefix relieving this routine of the need to avoid
* leading numeric characters.
* <p>
* This is not intended to be a reversible algorithm; just to provide something reasonably readable.
*/
private static @NonNull String getValidJavaIdentifier(@NonNull String nameHint, boolean hasPrefix, @Nullable Object anObject) {
if (nameHint.equals("<")) {
return("lt");
}
else if (nameHint.equals("<=")) {
return("le");
}
else if (nameHint.equals("=")) {
return("eq");
}
else if (nameHint.equals("<>")) {
return("ne");
}
else if (nameHint.equals(">=")) {
return("ge");
}
else if (nameHint.equals(">")) {
return("gt");
}
else if (nameHint.equals("+")) {
return("sum");
}
else if (nameHint.equals("-")) {
return((anObject instanceof Operation) && ((Operation)anObject).getOwnedParameters().size() <= 0 ? "neg" : "diff");
}
else if (nameHint.equals("*")) {
return("prod");
}
else if (nameHint.equals("/")) {
return("quot");
}
else if (nameHint.equals("1_")) {
return("_1");
}
else if (nameHint.equals("2_")) {
return("_2");
}
StringBuilder s = new StringBuilder();
Character prefix = null;
int length = nameHint.length();
for (int i = 0; i < length; i++) {
char c = nameHint.charAt(i);
if (((i == 0) && !hasPrefix) ? Character.isJavaIdentifierStart(c) : Character.isJavaIdentifierPart(c)) {
if (prefix != null) {
s.append(prefix);
prefix = null;
}
s.append(c);
}
else {
if (c == '*') {
s.append("_a");
}
else if (c == ':') {
s.append("_c");
}
else if (c == '.') {
if (prefix != null) {
s.append(prefix);
prefix = null;
}
}
else if (c == ')') {
s.append("_e");
}
else if (c == '>') {
s.append("_g");
}
else if (c == '<') {
s.append("_l");
}
else if (c == '-') {
s.append("_m");
}
else if (c == '(') {
s.append("_o");
}
else if (c == '+') {
s.append("_p");
}
else if (c == '=') {
s.append("_q");
}
else if (c == '/') {
s.append("_s");
}
else {
s.append('_' + Integer.toString(c));
}
prefix = '_';
}
}
return s.toString();
}
public class Context {
private final @Nullable Context context; // Pushed context
private final @NonNull Map<String, Object> name2object; // User of each name, null if name ambiguous
private final @NonNull Map<Object, String> object2name; // Unambiguous name for each object, null if not determined
private Map<String, Integer> name2counter; // Auto-generation counter for each colliding name
// private boolean frozen = false; // Set true once pushed
public Context() {
this.context = null;
this.name2object = new HashMap<String, Object>();
this.object2name = new HashMap<Object, String>();
this.name2counter = null;
}
public Context(@NonNull Context context) {
this.context = context;
this.name2object = new HashMap<String, Object>(context.name2object);
this.object2name = new HashMap<Object, String>(context.object2name);
this.name2counter = context.name2counter != null ? new HashMap<String, Integer>(context.name2counter) : null;
// context.frozen = true;
}
public @NonNull Context createNestedContext() {
return new Context(this);
}
public @NonNull Context getContext() {
return ClassUtil.nonNullState(context);
}
protected @NonNull String getGlobalUniqueName(@Nullable Object anObject, @Nullable String... nameHints) {
if (context != null) {
return context.getGlobalUniqueName(anObject, nameHints);
}
else {
return getUniqueName(anObject, nameHints);
}
}
public @NonNull String getSymbolName(@Nullable Object anObject, @Nullable String... nameHints) {
if ((nameHints != null) && (nameHints.length > 0) && (nameHints[0] != null)) {
return getUniqueName(anObject, nameHints);
}
else {
return getUniqueName(anObject, anObject != null ? getNameHint(anObject) : null);
}
}
/**
* Return a unique name using some nameHints to suggest preferred names and allocate that name to anObject.
* <p>
* If anObject is non-null, any already allocated name is returned rather than allocating another name.
* <p>
* If anObject is null, the returned name is allocated to no object; not to the null value.
* <p>
* If nameHints is null a default name is generated.
* <p>
*/
public @NonNull String getUniqueName(@Nullable Object anObject, @Nullable String... nameHints) {
if ((anObject instanceof RealValue) && !(anObject instanceof InvalidValue)) {
anObject = ((RealValue)anObject).asNumber();
}
if (anObject != null) {
String knownName = object2name.get(anObject);
if (knownName != null) {
return knownName;
}
}
String lastResort = null;
if (nameHints != null) {
for (String nameHint : nameHints) {
if (nameHint != null) {
String validHint = getValidJavaIdentifier(nameHint, false, anObject);
if (!reservedJavaNames.contains(validHint) || ((anObject instanceof CGValuedElement) && isNative((CGValuedElement)anObject))) {
if (anObject != null) {
Object oldElement = name2object.get(validHint);
if (oldElement == anObject) {
return validHint;
}
if ((oldElement == null) && !name2object.containsKey(validHint)) {
install(validHint, anObject);
return validHint;
}
else {
nameHint.toString();
}
}
else {
if (!name2object.containsKey(validHint)) {
install(validHint, anObject);
return validHint;
}
}
if (lastResort == null) {
lastResort = validHint;
}
}
}
}
}
if (lastResort == null) {
lastResort = DEFAULT_NAME_PREFIX;
}
if (name2counter == null) {
name2counter = new HashMap<String, Integer>();
}
Integer counter = name2counter.get(lastResort);
int count = counter != null ? counter : 0;
for ( ; true; count++) {
String attempt = lastResort + "_" + Integer.toString(count);
if (!name2object.containsKey(attempt)) { // Assumes that reserved names do not end in _ count
install(attempt, anObject);
name2counter.put(lastResort, ++count);
return attempt;
}
}
}
private void install(@NonNull String name, @Nullable Object anObject) {
//FIXME assert !frozen;
assert !(anObject instanceof RealValue) || (anObject instanceof InvalidValue);
name2object.put(name, anObject);
if (anObject != null) {
object2name.put(anObject, name);
}
}
private boolean isNative(@NonNull CGValuedElement cgElement) {
TypeId asTypeId = cgElement.getASTypeId();
if (asTypeId instanceof NestedTypeId) {
PackageId packageId = ((NestedTypeId)asTypeId).getParent();
if ((packageId instanceof RootPackageId) && ((RootPackageId)packageId).getName().contains("://")) { // e.g. java://
return true;
}
}
return false;
}
/**
* Reserve name for use by anObject. If anObject is null, the reservation is for an unspecified object not for the null value.
*
public @NonNull String reserveName(@NonNull String name, @Nullable Object anObject) {
assert !frozen;
assert !(anObject instanceof RealValue);
String validJavaIdentifier = getUniqueName(anObject, getValidJavaIdentifier(name, true, anObject));
Object oldElement = name2object.put(validJavaIdentifier, anObject); // FIXME redundant
assert (oldElement == null) || (oldElement == anObject);
return validJavaIdentifier;
} */
@Override
public @NonNull String toString() {
StringBuilder s = new StringBuilder();
List<String> names = new ArrayList<>(name2object.keySet());
Collections.sort(names);
for (String name : names) {
if (s.length() > 0) {
s.append("\n");
}
s.append(name);
s.append(" = ");
s.append(name2object.get(name));
}
return s.toString();
}
}
private @NonNull Context context = new Context();
public NameManager() {}
public @NonNull Context createNestedContext() {
return new Context(context);
}
public @NonNull String getExplicitName(@Nullable Object anObject) {
if (anObject == null) {
return "null";
}
else if (anObject instanceof Boolean) {
return ((Boolean)anObject).booleanValue() ? "true" : "false";
}
else {
return "<null-" + anObject.getClass().getSimpleName() + ">";
}
}
public @NonNull String getGlobalSymbolName(@Nullable Object anObject, @Nullable String... nameHints) {
if ((nameHints != null) && (nameHints.length > 0)) {
return getGlobalUniqueName(anObject, nameHints);
}
else {
return getGlobalUniqueName(anObject, anObject != null ? getNameHint(anObject) : null);
}
}
protected @NonNull String getGlobalUniqueName(@Nullable Object anObject, @Nullable String... nameHints) {
return context.getGlobalUniqueName(anObject, nameHints);
}
protected String getIterationNameHint(@NonNull Iteration anIteration) {
@SuppressWarnings("null") @NonNull String string = anIteration.getName();
return ITERATION_NAME_HINT_PREFIX + getValidJavaIdentifier(string, ITERATION_NAME_HINT_PREFIX.length() > 0, anIteration);
}
protected String getKindHint(@NonNull String kind) {
if (TypeId.BAG_NAME.equals(kind)) {
return BAG_NAME_HINT_PREFIX;
}
else if (TypeId.ORDERED_SET_NAME.equals(kind)) {
return ORDERED_SET_NAME_HINT_PREFIX;
}
else if (TypeId.SEQUENCE_NAME.equals(kind)) {
return SEQUENCE_NAME_HINT_PREFIX;
}
else if (TypeId.SET_NAME.equals(kind)) {
return SET_NAME_HINT_PREFIX;
}
else {
return COLLECTION_NAME_HINT_PREFIX;
}
}
/**
* Return a suggestion for the name of anObject.
* <p>
* The returned name is not guaranteed to be unique. Uniqueness is enforced when the hint is passed to getSymbolName().
*/
public @Nullable String getNameHint(@NonNull Object anObject) {
if (anObject instanceof CGValuedElement) {
anObject = ((CGValuedElement)anObject).getNamedValue();
}
if (anObject instanceof CollectionLiteralExp) {
Type type = ((CollectionLiteralExp)anObject).getType();
return type != null ? getTypeNameHint(type) : null;
}
else if (anObject instanceof CollectionRange) {
return RANGE_NAME_HINT_PREFIX;
}
else if (anObject instanceof CGCollectionPart) {
return RANGE_NAME_HINT_PREFIX;
}
else if (anObject instanceof InvalidValue) {
return INVALID_NAME_HINT_PREFIX;
}
else if (anObject instanceof CollectionValue) {
String kind = ((CollectionValue)anObject).getKind();
return kind != null ? getKindHint(kind) : null;
}
else if (anObject instanceof CGCollectionExp) {
String kind = ((CGCollectionExp)anObject).getName();
return kind != null ? getKindHint(kind) : null;
}
else if (anObject instanceof ElementId) {
String nameHint = ((ElementId)anObject).accept(idVisitor);
return nameHint;
}
else if (anObject instanceof ExpressionInOCL) {
return EXPRESSION_IN_OCL_NAME_HINT_PREFIX;
}
else if (anObject instanceof IntegerLiteralExp) {
Number numberSymbol = ((IntegerLiteralExp)anObject).getIntegerSymbol();
return numberSymbol != null ? getNumericNameHint(numberSymbol) : null;
}
else if (anObject instanceof IntegerRange) {
return RANGE_NAME_HINT_PREFIX;
}
else if (anObject instanceof IntegerValue) {
Number numberSymbol = ((IntegerValue)anObject).asNumber();
return getNumericNameHint(numberSymbol);
}
else if (anObject instanceof LoopExp) {
Iteration referredIteration = ((LoopExp)anObject).getReferredIteration();
return referredIteration != null ? getIterationNameHint(referredIteration) : null;
}
else if (anObject instanceof Number) {
return getNumericNameHint((Number)anObject);
}
else if (anObject instanceof Operation) {
return getOperationNameHint((Operation)anObject);
}
else if (anObject instanceof OperationCallExp) {
Operation referredOperation = ((OperationCallExp)anObject).getReferredOperation();
return referredOperation != null ? getOperationCallExpNameHint(referredOperation) : null;
}
else if (anObject instanceof OppositePropertyCallExp) {
Property referredOppositeProperty = ((OppositePropertyCallExp)anObject).getReferredProperty();
Property referredProperty = referredOppositeProperty != null ? referredOppositeProperty.getOpposite() : null;
return referredProperty != null ? getPropertyNameHint(referredProperty) : null;
}
else if (anObject instanceof PropertyCallExp) {
Property referredProperty = ((PropertyCallExp)anObject).getReferredProperty();
return referredProperty != null ? getPropertyNameHint(referredProperty) : null;
}
else if (anObject instanceof TupleLiteralExp) {
return TUPLE_NAME_HINT_PREFIX;
}
else if (anObject instanceof CGCallExp) {
if (anObject instanceof CGOppositePropertyCallExp) {
Property referredOppositeProperty = ((OppositePropertyCallExp)((CGOppositePropertyCallExp)anObject).getAst()).getReferredProperty();
Property referredProperty = referredOppositeProperty != null ? referredOppositeProperty.getOpposite() : null;
return referredProperty != null ? getPropertyNameHint(referredProperty) : null;
}
else if (anObject instanceof CGPropertyCallExp) {
Property referredProperty = ((PropertyCallExp)((CGPropertyCallExp)anObject).getAst()).getReferredProperty();
return referredProperty != null ? getPropertyNameHint(referredProperty) : null;
}
else if (anObject instanceof CGIterationCallExp) {
Iteration referredIteration = ((LoopExp)((CGIterationCallExp)anObject).getAst()).getReferredIteration();
return referredIteration != null ? getIterationNameHint(referredIteration) : null;
}
else if (anObject instanceof CGOperationCallExp) {
Operation referredOperation = ((OperationCallExp)((CGOperationCallExp)anObject).getAst()).getReferredOperation();
return referredOperation != null ? getOperationCallExpNameHint(referredOperation) : null;
}
else if (anObject instanceof CGBoxExp) {
return "BOXED_" + ((CGBoxExp)anObject).getSourceValue().getValueName();
}
else if (anObject instanceof CGEcoreExp) {
return "ECORE_" + ((CGEcoreExp)anObject).getSourceValue().getValueName();
}
else if (anObject instanceof CGUnboxExp) {
return "UNBOXED_" + ((CGUnboxExp)anObject).getSourceValue().getValueName();
}
else if (anObject instanceof CGCatchExp) {
return "CAUGHT_" + ((CGCatchExp)anObject).getSourceValue().getValueName();
}
else if (anObject instanceof CGGuardExp) {
return "GUARDED_" + ((CGGuardExp)anObject).getSourceValue().getValueName();
}
else if (anObject instanceof CGThrowExp) {
return "THROWN_" + ((CGThrowExp)anObject).getSourceValue().getValueName();
}
else {
return null;
}
}
else if (anObject instanceof RealLiteralExp) {
Number numberSymbol = ((RealLiteralExp)anObject).getRealSymbol();
return numberSymbol != null ? getNumericNameHint(numberSymbol) : null;
}
else if (anObject instanceof RealValue) {
Number numberSymbol = ((RealValue)anObject).asNumber();
return getNumericNameHint(numberSymbol);
}
else if (anObject instanceof String) {
return getStringNameHint((String)anObject);
}
else if (anObject instanceof CGString) {
String stringValue = ((CGString)anObject).getStringValue();
return stringValue != null ? getStringNameHint(stringValue) : null;
}
else if (anObject instanceof StringLiteralExp) {
String stringSymbol = ((StringLiteralExp)anObject).getStringSymbol();
return stringSymbol != null ? getStringNameHint(stringSymbol) : null;
}
else if (anObject instanceof Type) {
return getTypeNameHint((Type)anObject);
}
else if (anObject instanceof CGTypeId) {
Element type = ((CGTypeId)anObject).getAst();
return (type instanceof Type) ? getTypeNameHint((Type) type) : null;
}
else if (anObject instanceof TypeExp) {
Type referredType = ((TypeExp)anObject).getType();
return referredType != null ? getTypeNameHint(referredType) : null;
}
// else if (anObject instanceof TypeValue) {
// DomainType referredType = ((TypeValue)anObject).getInstanceType();
// return getTypeNameHint(referredType);
// }
else if (anObject instanceof UnlimitedNaturalLiteralExp) {
Number numberSymbol = ((UnlimitedNaturalLiteralExp)anObject).getUnlimitedNaturalSymbol();
return numberSymbol != null ? getNumericNameHint(numberSymbol) : null;
}
else if (anObject instanceof VariableExp) {
VariableDeclaration referredVariable = ((VariableExp)anObject).getReferredVariable();
return referredVariable != null ? getVariableDeclarationNameHint(referredVariable) : null;
}
else if (anObject instanceof LiteralExp) {
return "literal";
}
else if (anObject instanceof Nameable) {
String name = ((Nameable)anObject).getName();
return name != null ? getValidJavaIdentifier(name, false, anObject) : null;
}
else {
return null;
}
}
protected String getNumericNameHint(@NonNull Number aNumber) {
@SuppressWarnings("null") @NonNull String string = aNumber.toString();
if ((aNumber instanceof BigInteger) || (aNumber instanceof Long) || (aNumber instanceof Integer) || (aNumber instanceof Short)) {
return INTEGER_NAME_HINT_PREFIX + string;
}
else if ((aNumber instanceof BigDecimal) || (aNumber instanceof Double) || (aNumber instanceof Float)) {
return REAL_NAME_HINT_PREFIX + getValidJavaIdentifier(string, REAL_NAME_HINT_PREFIX.length() > 0, aNumber);
}
else {
return null;
}
}
protected String getOperationNameHint(@NonNull Operation anOperation) {
@SuppressWarnings("null") @NonNull String string = anOperation.toString();
return OPERATION_NAME_HINT_PREFIX + getValidJavaIdentifier(string, OPERATION_NAME_HINT_PREFIX.length() > 0, anOperation);
}
protected String getOperationCallExpNameHint(@NonNull Operation anOperation) {
@SuppressWarnings("null") @NonNull String string = anOperation.getName();
return OPERATION_CALL_EXP_NAME_HINT_PREFIX + getValidJavaIdentifier(string, OPERATION_CALL_EXP_NAME_HINT_PREFIX.length() > 0, anOperation);
}
protected String getPropertyNameHint(@NonNull Property aProperty) {
@SuppressWarnings("null") @NonNull String string = aProperty.getName();
return PROPERTY_NAME_HINT_PREFIX + getValidJavaIdentifier(string, PROPERTY_NAME_HINT_PREFIX.length() > 0, aProperty);
}
protected String getStringNameHint(@NonNull String aString) {
@NonNull String string = aString.length() > STRING_NAME_HINT_LIMIT ? aString.substring(0, STRING_NAME_HINT_LIMIT) : aString;
return STRING_NAME_HINT_PREFIX + getValidJavaIdentifier(string, STRING_NAME_HINT_PREFIX.length() > 0, aString);
}
protected String getTypeNameHint(@NonNull Type aType) {
if (aType instanceof CollectionType) {
if (aType instanceof OrderedSetType) {
return ORDERED_SET_NAME_HINT_PREFIX;
}
else if (aType instanceof SetType) {
return SET_NAME_HINT_PREFIX;
}
else if (aType instanceof SequenceType) {
return SEQUENCE_NAME_HINT_PREFIX;
}
else if (aType instanceof BagType) {
return BAG_NAME_HINT_PREFIX;
}
else {
return COLLECTION_NAME_HINT_PREFIX;
}
}
@SuppressWarnings("null") @NonNull String string = aType.toString();
return TYPE_NAME_HINT_PREFIX + getValidJavaIdentifier(string, TYPE_NAME_HINT_PREFIX.length() > 0, aType);
}
protected String getVariableDeclarationNameHint(@NonNull VariableDeclaration aVariableDeclaration) {
String string = ClassUtil.nonNullModel(aVariableDeclaration.getName());
return VARIABLE_DECLARATION_NAME_HINT_PREFIX + getValidJavaIdentifier(string, VARIABLE_DECLARATION_NAME_HINT_PREFIX.length() > 0, aVariableDeclaration);
}
/**
* Reserve name for use by anObject. If anObject is null, the reservation is for an unspecified object not for the null value.
*/
public @NonNull String reserveName(@NonNull String name, @Nullable Object anObject) {
return context.getSymbolName(anObject, name);
}
}