/*
* $Id$
*
* File is automatically generated by the Xtext language generator.
* Do not change it.
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2017 the original authors or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sarl.lang.codebuilder.builders;
import io.sarl.lang.sarl.SarlEvent;
import io.sarl.lang.sarl.SarlField;
import io.sarl.lang.sarl.SarlScript;
import java.util.function.Predicate;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtend.core.xtend.XtendTypeDeclaration;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmIdentifiableElement;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.access.IJvmTypeProvider;
import org.eclipse.xtext.util.EmfFormatter;
import org.eclipse.xtext.util.StringInputStream;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.xbase.XBooleanLiteral;
import org.eclipse.xtext.xbase.XCastedExpression;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XFeatureCall;
import org.eclipse.xtext.xbase.XNumberLiteral;
import org.eclipse.xtext.xbase.XbaseFactory;
import org.eclipse.xtext.xbase.compiler.DocumentationAdapter;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.eclipse.xtext.xbase.lib.Pure;
/** Builder of a Sarl XExpression.
*/
@SuppressWarnings("all")
public class ExpressionBuilderImpl extends AbstractBuilder implements IExpressionBuilder {
private EObject context;
private Procedure1<XExpression> setter;
private XExpression expr;
/** Initialize the expression.
* @param context - the context of the expressions.
* @param setter - the object that permits to assign the expression to the context.
*/
public void eInit(EObject context, Procedure1<XExpression> setter, IJvmTypeProvider typeContext) {
setTypeResolutionContext(typeContext);
this.context = context;
this.setter = setter;
this.expr = null;
}
/** Replies the last created expression.
*
* @return the last created expression.
*/
@Pure
public XExpression getXExpression() {
return this.expr;
}
/** Replies the resource to which the XExpression is attached.
*/
@Pure
public Resource eResource() {
return getXExpression().eResource();
}
/** Change the expression in the container.
*
* @param expression - the textual representation of the expression.
*/
public void setExpression(String expression) {
this.expr = fromString(expression);
this.setter.apply(this.expr);
}
/** Change the expression in the container.
*
* @param expression - the expression.
*/
public void setXExpression(XExpression expression) {
this.expr = expression;
this.setter.apply(this.expr);
}
/** Generate a piece of Sarl code that permits to compile an XExpression.
*
* @param expression the expression to compile.
* @return the Sarl code.
*/
static String generateExpressionCode(String expression) {
return "event ____synthesis { var ____fakefield = " + expression + " }";
}
static String generateTypenameCode(String typeName) {
return "event ____synthesis { var ____fakefield : " + typeName + " }";
}
static JvmParameterizedTypeReference parseType(Notifier context, String typeName, AbstractBuilder caller) {
ResourceSet resourceSet = toResource(context).getResourceSet();
URI uri = caller.computeUnusedUri(resourceSet);
Resource resource = caller.getResourceFactory().createResource(uri);
resourceSet.getResources().add(resource);
try (StringInputStream is = new StringInputStream(generateTypenameCode(typeName))) {
resource.load(is, null);
SarlScript script = resource.getContents().isEmpty() ? null : (SarlScript) resource.getContents().get(0);
SarlEvent topElement = (SarlEvent) script.getXtendTypes().get(0);
SarlField member = (SarlField) topElement.getMembers().get(0);
JvmTypeReference reference = member.getType();
if (reference instanceof JvmParameterizedTypeReference) {
final JvmParameterizedTypeReference pref = (JvmParameterizedTypeReference) reference;
if (!pref.getArguments().isEmpty()) {
EcoreUtil2.resolveAll(resource);
return pref;
}
}
} catch (Exception exception) {
throw new TypeNotPresentException(typeName, exception);
} finally {
resourceSet.getResources().remove(resource);
}
throw new TypeNotPresentException(typeName, null);
}
/** Create an expression but does not change the container.
*
* @param expression - the textual representation of the expression.
* @return the expression.
*/
@Pure
protected XExpression fromString(String expression) {
if (!Strings.isEmpty(expression)) {
ResourceSet resourceSet = this.context.eResource().getResourceSet();
URI uri = computeUnusedUri(resourceSet);
Resource resource = getResourceFactory().createResource(uri);
resourceSet.getResources().add(resource);
try (StringInputStream is = new StringInputStream(generateExpressionCode(expression))) {
resource.load(is, null);
SarlScript script = resource.getContents().isEmpty() ? null : (SarlScript) resource.getContents().get(0);
SarlEvent topElement = (SarlEvent) script.getXtendTypes().get(0);
SarlField member = (SarlField) topElement.getMembers().get(0);
return member.getInitialValue();
} catch (Throwable exception) {
throw new RuntimeException(exception);
} finally {
resourceSet.getResources().remove(resource);
}
}
throw new IllegalArgumentException("not a valid expression");
}
/** Replies the XExpression for the default value associated to the given type.
* @param type - the type for which the default value should be determined.
* @return the default value.
*/
@Pure
public XExpression getDefaultXExpressionForType(String type) {
//TODO: Check if a similar function exists in the Xbase library.
XExpression expr = null;
if (type != null && !"void".equals(type) && !Void.class.getName().equals(type)) {
switch (type) {
case "boolean":
case "java.lang.Boolean":
XBooleanLiteral booleanLiteral = XbaseFactory.eINSTANCE.createXBooleanLiteral();
booleanLiteral.setIsTrue(false);
expr = booleanLiteral;
break;
case "float":
case "java.lang.Float":
XNumberLiteral numberLiteral = XbaseFactory.eINSTANCE.createXNumberLiteral();
numberLiteral.setValue("0.0f");
expr = numberLiteral;
break;
case "double":
case "java.lang.Double":
case "java.lang.BigDecimal":
numberLiteral = XbaseFactory.eINSTANCE.createXNumberLiteral();
numberLiteral.setValue("0.0");
expr = numberLiteral;
break;
case "int":
case "long":
case "java.lang.Integer":
case "java.lang.Long":
case "java.lang.BigInteger":
numberLiteral = XbaseFactory.eINSTANCE.createXNumberLiteral();
numberLiteral.setValue("0");
expr = numberLiteral;
break;
case "byte":
case "short":
case "char":
case "java.lang.Byte":
case "java.lang.Short":
case "java.lang.Character":
numberLiteral = XbaseFactory.eINSTANCE.createXNumberLiteral();
numberLiteral.setValue("0");
XCastedExpression castExpression = XbaseFactory.eINSTANCE.createXCastedExpression();
castExpression.setTarget(numberLiteral);
castExpression.setType(newTypeRef(this.context, type));
expr = numberLiteral;
break;
default:
expr = XbaseFactory.eINSTANCE.createXNullLiteral();
break;
}
}
return expr;
}
/** Replies the default value for the given type.
* @param type - the type for which the default value should be determined.
* @return the default value.
*/
@Pure
public String getDefaultValueForType(String type) {
//TODO: Check if a similar function exists in the Xbase library.
String defaultValue = "";
if (!Strings.isEmpty(type) && !"void".equals(type)) {
switch (type) {
case "boolean":
defaultValue = "true";
break;
case "double":
defaultValue = "0.0";
break;
case "float":
defaultValue = "0.0f";
break;
case "int":
defaultValue = "0";
break;
case "long":
defaultValue = "0";
break;
case "byte":
defaultValue = "(0 as byte)";
break;
case "short":
defaultValue = "(0 as short)";
break;
case "char":
defaultValue = "(0 as char)";
break;
default:
defaultValue = "null";
break;
}
}
return defaultValue;
}
/** Change the documentation of the element.
*
* <p>The documentation will be displayed just before the element.
*
* @param doc the documentation.
*/
public void setDocumentation(String doc) {
if (Strings.isEmpty(doc)) {
getXExpression().eAdapters().removeIf(new Predicate<Adapter>() {
public boolean test(Adapter adapter) {
return adapter.isAdapterForType(DocumentationAdapter.class);
}
});
} else {
DocumentationAdapter adapter = (DocumentationAdapter) EcoreUtil.getExistingAdapter(
getXExpression(), DocumentationAdapter.class);
if (adapter == null) {
adapter = new DocumentationAdapter();
getXExpression().eAdapters().add(adapter);
}
adapter.setDocumentation(doc);
}
}
@Override
@Pure
public String toString() {
return EmfFormatter.objToStr(getXExpression());
}
/** Create a reference to "this" object or to the current type.
*
* @return the reference.
*/
public XFeatureCall createReferenceToThis() {
final XExpression expr = getXExpression();
XtendTypeDeclaration type = EcoreUtil2.getContainerOfType(expr, XtendTypeDeclaration.class);
JvmType jvmObject = getAssociatedElement(JvmType.class, type, expr.eResource());
final XFeatureCall thisFeature = XbaseFactory.eINSTANCE.createXFeatureCall();
thisFeature.setFeature(jvmObject);
return thisFeature;
}
/** Create a reference to "super" object or to the super type.
*
* @return the reference.
*/
public XFeatureCall createReferenceToSuper() {
final XExpression expr = getXExpression();
XtendTypeDeclaration type = EcoreUtil2.getContainerOfType(expr, XtendTypeDeclaration.class);
JvmType jvmObject = getAssociatedElement(JvmType.class, type, expr.eResource());
final XFeatureCall superFeature = XbaseFactory.eINSTANCE.createXFeatureCall();
JvmIdentifiableElement feature;
if (jvmObject instanceof JvmDeclaredType) {
feature = ((JvmDeclaredType) jvmObject).getExtendedClass().getType();
} else {
feature = findType(expr, getQualifiedName(type)).getType();
if (feature instanceof JvmDeclaredType) {
feature = ((JvmDeclaredType) feature).getExtendedClass().getType();
} else {
feature = null;
}
}
if (feature == null) {
return null;
}
superFeature.setFeature(feature);
return superFeature;
}
}