blob: c8cb727b21f209b079980609d36c6b7ed88451f2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.acceleo.query.parser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.acceleo.query.ast.Binding;
import org.eclipse.acceleo.query.ast.BooleanLiteral;
import org.eclipse.acceleo.query.ast.Call;
import org.eclipse.acceleo.query.ast.CallType;
import org.eclipse.acceleo.query.ast.CollectionTypeLiteral;
import org.eclipse.acceleo.query.ast.Conditional;
import org.eclipse.acceleo.query.ast.EnumLiteral;
import org.eclipse.acceleo.query.ast.Expression;
import org.eclipse.acceleo.query.ast.IntegerLiteral;
import org.eclipse.acceleo.query.ast.Lambda;
import org.eclipse.acceleo.query.ast.Let;
import org.eclipse.acceleo.query.ast.NullLiteral;
import org.eclipse.acceleo.query.ast.RealLiteral;
import org.eclipse.acceleo.query.ast.SequenceInExtensionLiteral;
import org.eclipse.acceleo.query.ast.SetInExtensionLiteral;
import org.eclipse.acceleo.query.ast.StringLiteral;
import org.eclipse.acceleo.query.ast.TypeLiteral;
import org.eclipse.acceleo.query.ast.TypeSetLiteral;
import org.eclipse.acceleo.query.ast.VarRef;
import org.eclipse.acceleo.query.ast.VariableDeclaration;
import org.eclipse.acceleo.query.ast.util.AstSwitch;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.impl.EClassifierImpl;
/**
* Serialize a {@link Expression}.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
public class AstSerializer extends AstSwitch<Object> {
/**
* A dummy {@link Object} to prevent switching in super types.
*/
private static final Object DUMMY = new Object();
/**
* A space caracter.
*/
private static final String SPACE = " ";
/**
* The separator between ecore segments.
*/
private static final String ECORE_SEPARATOR = "::";
/**
* The mapping of an operator service call name to is precedence.
*/
private static final Map<String, Integer> OPERATOR_PRECEDENCE = initOperatorPrecedence();
/**
* The {@link StringBuilder} used to serialize.
*/
private StringBuilder builder;
/**
* The mapping form nsURI to name.
*/
private final Map<String, String> ePackagesURItoName = new HashMap<>();
/**
* Serializes the given {@link Expression}.
*
* @param expression
* the {@link Expression}
* @return the serialized {@link Expression}
*/
public String serialize(Expression expression) {
builder = new StringBuilder();
doSwitch(expression);
return builder.toString();
}
/**
* Initializes the operator precedence.
*
* @return the mapping of an operator service call name to is precedence
*/
private static Map<String, Integer> initOperatorPrecedence() {
final Map<String, Integer> res = new HashMap<String, Integer>();
int precedence = 0;
res.put(AstBuilderListener.NOT_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.UNARY_MIN_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.MULT_SERVICE_NAME, precedence);
res.put(AstBuilderListener.DIV_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.ADD_SERVICE_NAME, precedence);
res.put(AstBuilderListener.SUB_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.LESS_THAN_EQUAL_SERVICE_NAME, precedence);
res.put(AstBuilderListener.GREATER_THAN_EQUAL_SERVICE_NAME, precedence);
res.put(AstBuilderListener.DIFFERS_SERVICE_NAME, precedence);
res.put(AstBuilderListener.EQUALS_SERVICE_NAME, precedence);
res.put(AstBuilderListener.LESS_THAN_SERVICE_NAME, precedence);
res.put(AstBuilderListener.GREATER_THAN_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.AND_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.OR_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.XOR_SERVICE_NAME, precedence);
precedence++;
res.put(AstBuilderListener.IMPLIES_SERVICE_NAME, precedence);
return res;
}
@Override
public Object caseBinding(Binding binding) {
builder.append(binding.getName());
if (binding.getType() != null) {
builder.append(SPACE).append(':').append(SPACE);
builder.append(doSwitch(binding.getType()));
}
builder.append(SPACE).append('=').append(SPACE);
doSwitch(binding.getValue());
return DUMMY;
}
@Override
public Object caseBooleanLiteral(BooleanLiteral booleanLiteral) {
builder.append(booleanLiteral.isValue());
return DUMMY;
}
@Override
public Object caseCall(Call call) {
if (AstBuilderListener.FEATURE_ACCESS_SERVICE_NAME.equals(call.getServiceName())) {
aqlFeatureAccessCall(call);
} else if (AstBuilderListener.NOT_SERVICE_NAME.equals(call.getServiceName())) {
notCall(call);
} else if (AstBuilderListener.DIFFERS_SERVICE_NAME.equals(call.getServiceName())) {
differsCall(call);
} else if (AstBuilderListener.EQUALS_SERVICE_NAME.equals(call.getServiceName())) {
equalsCall(call);
} else if (AstBuilderListener.GREATER_THAN_EQUAL_SERVICE_NAME.equals(call.getServiceName())) {
greaterThanEqualCall(call);
} else if (AstBuilderListener.GREATER_THAN_SERVICE_NAME.equals(call.getServiceName())) {
greaterThanCall(call);
} else if (AstBuilderListener.LESS_THAN_EQUAL_SERVICE_NAME.equals(call.getServiceName())) {
lessThanEqualCall(call);
} else if (AstBuilderListener.LESS_THAN_SERVICE_NAME.equals(call.getServiceName())) {
lessThanCall(call);
} else if (AstBuilderListener.DIV_SERVICE_NAME.equals(call.getServiceName())) {
divOpCall(call);
} else if (AstBuilderListener.MULT_SERVICE_NAME.equals(call.getServiceName())) {
multCall(call);
} else if (AstBuilderListener.SUB_SERVICE_NAME.equals(call.getServiceName())) {
subCall(call);
} else if (AstBuilderListener.ADD_SERVICE_NAME.equals(call.getServiceName())) {
addCall(call);
} else if (AstBuilderListener.UNARY_MIN_SERVICE_NAME.equals(call.getServiceName())) {
unaryMinCall(call);
} else if (AstBuilderListener.AND_SERVICE_NAME.equals(call.getServiceName())) {
andCall(call);
} else if (AstBuilderListener.OR_SERVICE_NAME.equals(call.getServiceName())) {
orCall(call);
} else if (AstBuilderListener.XOR_SERVICE_NAME.equals(call.getServiceName())) {
xorCall(call);
} else if (AstBuilderListener.IMPLIES_SERVICE_NAME.equals(call.getServiceName())) {
impliesCall(call);
} else {
call(call);
}
return DUMMY;
}
/**
* A not {@link Call}.
*
* @param call
* the not {@link Call}.
*/
private void notCall(Call call) {
builder.append(AstBuilderListener.NOT_OPERATOR);
builder.append(SPACE);
if (!call.getArguments().isEmpty()) {
doSwitch(call.getArguments().get(0));
}
}
/**
* A differs {@link Call}.
*
* @param call
* the differs {@link Call}.
*/
private void differsCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.DIFFERS_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A equals {@link Call}.
*
* @param call
* the equals {@link Call}.
*/
private void equalsCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.EQUALS_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A greater than equal {@link Call}.
*
* @param call
* the greater than equal {@link Call}.
*/
private void greaterThanEqualCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.GREATER_THAN_EQUAL_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A greater than {@link Call}.
*
* @param call
* the greater than {@link Call}.
*/
private void greaterThanCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.GREATER_THAN_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A less than equal {@link Call}.
*
* @param call
* the less than equal {@link Call}.
*/
private void lessThanEqualCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.LESS_THAN_EQUAL_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A less than {@link Call}.
*
* @param call
* the less than {@link Call}.
*/
private void lessThanCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.LESS_THAN_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A div op {@link Call}.
*
* @param call
* the div op {@link Call}.
*/
private void divOpCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.DIV_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A mult {@link Call}.
*
* @param call
* the mult {@link Call}.
*/
private void multCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.MULT_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A sub {@link Call}.
*
* @param call
* the sub {@link Call}.
*/
private void subCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.SUB_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A add {@link Call}.
*
* @param call
* the add {@link Call}.
*/
private void addCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.ADD_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A unary min {@link Call}.
*
* @param call
* the unary min {@link Call}.
*/
private void unaryMinCall(Call call) {
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
builder.append(AstBuilderListener.UNARY_MIN_OPERATOR);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
}
/**
* A and {@link Call}.
*
* @param call
* the and {@link Call}.
*/
private void andCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.AND_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A or {@link Call}.
*
* @param call
* the or {@link Call}.
*/
private void orCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.OR_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A xor {@link Call}.
*
* @param call
* the xor {@link Call}.
*/
private void xorCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append(')');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.XOR_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* A implies {@link Call}.
*
* @param call
* the implies {@link Call}.
*/
private void impliesCall(Call call) {
final boolean needParenthesis = needParenthesis(call);
if (needParenthesis) {
builder.append('(');
}
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
builder.append(SPACE);
builder.append(AstBuilderListener.IMPLIES_OPERATOR);
builder.append(SPACE);
if (!arguments.isEmpty()) {
final Expression operand = arguments.remove(0);
doSwitch(operand);
}
if (needParenthesis) {
builder.append(')');
}
}
/**
* Tells if the given {@link Call} need to be surrounded with parenthesis.
*
* @param call
* the {@link Call}
* @return <code>true</code> if the given {@link Call} need to be surrounded with parenthesis,
* <code>false</code> otherwise
*/
private boolean needParenthesis(Call call) {
final boolean res;
final Integer precedence = OPERATOR_PRECEDENCE.get(call.getServiceName());
final Integer parentPrecedence;
if (call.eContainer() instanceof Call) {
parentPrecedence = OPERATOR_PRECEDENCE.get(((Call)call.eContainer()).getServiceName());
} else {
parentPrecedence = null;
}
if (precedence == null || parentPrecedence == null) {
res = false;
} else {
int delta = precedence - parentPrecedence;
if (delta > 0) {
res = true;
} else if (delta == 0) {
final Call parent = (Call)call.eContainer();
res = ((AstBuilderListener.SUB_SERVICE_NAME.equals(parent.getServiceName()))
|| (AstBuilderListener.DIV_SERVICE_NAME.equals(parent.getServiceName()))) && (parent
.getArguments().size() == 2 && parent.getArguments().get(1) == call);
} else {
res = false;
}
}
return res;
}
private void aqlFeatureAccessCall(Call call) {
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
final Expression receiver = arguments.remove(0);
doSwitch(receiver);
builder.append('.');
if (!arguments.isEmpty()) {
builder.append(((StringLiteral)arguments.get(0)).getValue());
}
}
private void call(Call call) {
final List<Expression> arguments = new ArrayList<Expression>(call.getArguments());
final Expression receiver = arguments.remove(0);
doSwitch(receiver);
if (call.getType() == CallType.COLLECTIONCALL) {
builder.append("->");
} else {
builder.append('.');
}
builder.append(call.getServiceName());
builder.append('(');
if (!arguments.isEmpty()) {
final StringBuilder previousBuilder = builder;
try {
builder = new StringBuilder();
for (Expression argument : arguments) {
doSwitch(argument);
builder.append(',').append(' ');
}
previousBuilder.append(builder.substring(0, builder.length() - 2));
} finally {
builder = previousBuilder;
}
}
builder.append(')');
}
@Override
public Object caseCollectionTypeLiteral(CollectionTypeLiteral collectionTypeLiteral) {
if (collectionTypeLiteral.getValue() == List.class) {
builder.append("Sequence(");
} else if (collectionTypeLiteral.getValue() == Set.class) {
builder.append("OrderedSet(");
} else {
builder.append("***invalid type of collection ***(");
}
doSwitch(collectionTypeLiteral.getElementType());
builder.append(")");
return DUMMY;
}
@Override
public Object caseConditional(Conditional conditional) {
builder.append("if ");
doSwitch(conditional.getPredicate());
builder.append(" then ");
doSwitch(conditional.getTrueBranch());
builder.append(" else ");
doSwitch(conditional.getFalseBranch());
builder.append(" endif");
return DUMMY;
}
@Override
public Object caseEnumLiteral(EnumLiteral enumLiteral) {
if (!enumLiteral.getLiteral().eIsProxy()) {
builder.append(enumLiteral.getLiteral().getEEnum().getEPackage().getName());
builder.append(ECORE_SEPARATOR);
builder.append(enumLiteral.getLiteral().getEEnum().getName());
builder.append(ECORE_SEPARATOR);
builder.append(enumLiteral.getLiteral().getName());
} else {
final URI proxyURI = ((org.eclipse.emf.ecore.impl.EEnumLiteralImpl)enumLiteral.getLiteral())
.eProxyURI();
final String packageName = ePackagesURItoName.getOrDefault(removeFragment(proxyURI),
"packageName");
final String[] segments = proxyURI.fragment().split("/");
builder.append(packageName);
builder.append(ECORE_SEPARATOR);
builder.append(segments[segments.length - 2]);
builder.append(ECORE_SEPARATOR);
builder.append(segments[segments.length - 1]);
}
return DUMMY;
}
@Override
public Object caseIntegerLiteral(IntegerLiteral object) {
builder.append(object.getValue());
return DUMMY;
}
@Override
public Object caseLambda(Lambda lambda) {
doSwitch(lambda.getParameters().get(0));
builder.append(" | ");
doSwitch(lambda.getExpression());
return DUMMY;
}
@Override
public Object caseLet(Let let) {
builder.append("let ");
if (!let.getBindings().isEmpty()) {
final StringBuilder previousBuilder = builder;
try {
builder = new StringBuilder();
for (Binding binding : let.getBindings()) {
doSwitch(binding);
builder.append(',').append(' ');
}
previousBuilder.append(builder.substring(0, builder.length() - 2));
} finally {
builder = previousBuilder;
}
}
builder.append(" in ");
doSwitch(let.getBody());
return super.caseLet(let);
}
@Override
public Object caseNullLiteral(NullLiteral nullLiteral) {
builder.append("null");
return DUMMY;
}
@Override
public Object caseSequenceInExtensionLiteral(SequenceInExtensionLiteral sequenceInExtensionLiteral) {
builder.append("Sequence{");
if (!sequenceInExtensionLiteral.getValues().isEmpty()) {
final StringBuilder previousBuilder = builder;
try {
builder = new StringBuilder();
for (Expression value : sequenceInExtensionLiteral.getValues()) {
doSwitch(value);
builder.append(',').append(' ');
}
previousBuilder.append(builder.substring(0, builder.length() - 2));
} finally {
builder = previousBuilder;
}
}
builder.append('}');
return DUMMY;
}
@Override
public Object caseRealLiteral(RealLiteral realLiteral) {
builder.append(realLiteral.getValue());
return DUMMY;
}
@Override
public Object caseSetInExtensionLiteral(SetInExtensionLiteral setInExtensionLiteral) {
builder.append("OrderedSet{");
if (!setInExtensionLiteral.getValues().isEmpty()) {
final StringBuilder previousBuilder = builder;
try {
builder = new StringBuilder();
for (Expression value : setInExtensionLiteral.getValues()) {
doSwitch(value);
builder.append(',').append(' ');
}
previousBuilder.append(builder.substring(0, builder.length() - 2));
} finally {
builder = previousBuilder;
}
}
builder.append('}');
return DUMMY;
}
@Override
public Object caseStringLiteral(StringLiteral stringLiteral) {
builder.append('\'');
builder.append(escape(stringLiteral.getValue()));
builder.append('\'');
return DUMMY;
}
/**
* Escapes the given {@link String}.
*
* @param value
* the {@link String}
* @return the escaped {@link String}
*/
private String escape(String value) {
final StringBuilder res = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
final char currentChar = value.charAt(i);
switch (currentChar) {
case '\'':
case '\\':
res.append('\\');
res.append(currentChar);
break;
default:
res.append(currentChar);
break;
}
}
return res.toString();
}
@Override
public Object caseTypeSetLiteral(TypeSetLiteral typeSetLiteral) {
builder.append('{');
if (!typeSetLiteral.getTypes().isEmpty()) {
final StringBuilder previousBuilder = builder;
try {
builder = new StringBuilder();
for (TypeLiteral type : typeSetLiteral.getTypes()) {
doSwitch(type);
builder.append(" | ");
}
previousBuilder.append(builder.substring(0, builder.length() - 3));
} finally {
builder = previousBuilder;
}
}
builder.append('}');
return DUMMY;
}
@Override
public Object caseTypeLiteral(TypeLiteral object) {
if (!(object instanceof TypeSetLiteral) && !(object instanceof CollectionTypeLiteral)) {
if (object.getValue() instanceof Class) {
if (object.getValue() == Double.class) {
builder.append("Real");
} else {
builder.append(((Class<?>)object.getValue()).getSimpleName());
}
} else if (object.getValue() instanceof EClassifier) {
final EClassifier eClassifier = (EClassifier)object.getValue();
if (!eClassifier.eIsProxy()) {
builder.append(eClassifier.getEPackage().getName());
builder.append(ECORE_SEPARATOR);
builder.append(eClassifier.getName());
} else {
final URI proxyURI = ((EClassifierImpl)eClassifier).eProxyURI();
final String[] segments = proxyURI.fragment().split("/");
ePackagesURItoName.put(removeFragment(proxyURI), segments[segments.length - 2]);
builder.append(segments[segments.length - 2]);
builder.append(ECORE_SEPARATOR);
builder.append(segments[segments.length - 1]);
}
}
}
return DUMMY;
}
private String removeFragment(URI uri) {
return uri.toString().substring(0, uri.toString().length() - uri.fragment().length());
}
@Override
public Object caseVariableDeclaration(VariableDeclaration variableDeclaration) {
builder.append(variableDeclaration.getName());
if (variableDeclaration.getType() != null) {
builder.append(SPACE).append(':').append(SPACE);
doSwitch(variableDeclaration.getType());
}
return DUMMY;
}
@Override
public Object caseVarRef(VarRef varRef) {
builder.append(varRef.getVariableName());
return DUMMY;
}
}