blob: e8ec51af3e622df6cd952f7873770108b53726f2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2017 CEA LIST and others.
* 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:
* E.D.Willink(CEA LIST) - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.examples.codegen.java;
import java.lang.annotation.Annotation;
import java.lang.reflect.TypeVariable;
import java.util.List;
import java.util.Stack;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
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.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.codegen.analyzer.CodeGenAnalyzer;
import org.eclipse.ocl.examples.codegen.cgmodel.CGClass;
import org.eclipse.ocl.examples.codegen.cgmodel.CGInvalid;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGPackage;
import org.eclipse.ocl.examples.codegen.cgmodel.CGParameter;
import org.eclipse.ocl.examples.codegen.cgmodel.CGUnboxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGVariableExp;
import org.eclipse.ocl.examples.codegen.generator.AbstractCodeGenerator;
import org.eclipse.ocl.examples.codegen.generator.AbstractGenModelHelper;
import org.eclipse.ocl.examples.codegen.generator.CodeGenOptions;
import org.eclipse.ocl.examples.codegen.generator.CodeGenerator;
import org.eclipse.ocl.examples.codegen.generator.TypeDescriptor;
import org.eclipse.ocl.examples.codegen.java.types.EObjectDescriptor;
import org.eclipse.ocl.examples.codegen.utilities.CGUtil;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.Namespace;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.ids.ElementId;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.internal.prettyprint.PrettyPrintOptions;
import org.eclipse.ocl.pivot.internal.prettyprint.PrettyPrinter;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.xtext.util.Strings;
/**
* A JavaStream provides many appendXXX helper methods and a push/pop facility for auto-indentation of Java text.
*/
public class JavaStream
{
/**
* Return an encoding of theString that is suitable for use as a Java Identifier.
* Awkward characters are replaced by an underscore prefixed decimal string.
* The first character and the character following a decimal string may not be a decimal.
*/
public static @NonNull String convertToJavaIdentifier(@NonNull String theString) {
int len = theString.length();
int bufLen = len * 2;
if (bufLen < 0) {
bufLen = Integer.MAX_VALUE;
}
StringBuilder outBuffer = new StringBuilder(bufLen);
boolean isStart = true;
for (int x = 0; x < len; x++) {
char aChar = theString.charAt(x);
if (/*(aChar != '_') &&*/ isStart ? Character.isJavaIdentifierStart(aChar) : Character.isJavaIdentifierPart(aChar)) {
outBuffer.append(aChar);
isStart = false;
}
else {
outBuffer.append("_");
outBuffer.append((int)aChar);
isStart = true;
}
}
return outBuffer.toString();
}
public static PrettyPrintOptions.@NonNull Global createOptions(@NonNull Visitable element) {
Namespace scope = null;
if (element instanceof EObject) {
for (EObject eObject = (EObject) element; eObject != null; ) {
if (eObject instanceof Model) {
break;
}
if (eObject instanceof Type) {
scope = (Namespace) eObject;
break;
}
if (eObject instanceof org.eclipse.ocl.pivot.Package) {
scope = (Namespace) eObject;
break;
}
if ((eObject instanceof ExpressionInOCL) && (((ExpressionInOCL)eObject).getOwnedContext() != null)) {
eObject = ((ExpressionInOCL)eObject).getOwnedContext().getType();
}
else {
eObject = eObject.eContainer();
}
}
}
PrettyPrintOptions.Global createOptions = PrettyPrinter.createOptions(scope);
createOptions.setLinelength(80);
if (element instanceof EObject) {
Resource asResource = EcoreUtil.getRootContainer((EObject)element).eResource();
if (asResource != null) {
ResourceSet asResourceSet = asResource.getResourceSet();
if (asResourceSet != null) {
PivotMetamodelManager metamodelManager = PivotMetamodelManager.getAdapter(asResourceSet);
createOptions.setEnvironmentFactory(metamodelManager.getEnvironmentFactory());
}
}
}
return createOptions;
}
public static interface SubStream
{
void append();
}
protected @NonNull JavaCodeGenerator codeGenerator;
protected @NonNull CG2JavaVisitor<@NonNull ?> cg2java;
protected @NonNull CodeGenAnalyzer analyzer;
protected final @NonNull Id2JavaExpressionVisitor id2JavaExpressionVisitor;
protected final boolean useNullAnnotations;
protected final boolean suppressNullWarnings;
private @NonNull StringBuilder s = new StringBuilder();
private @NonNull Stack<@NonNull String> indentationStack = new Stack<>();
private @NonNull String defaultIndentationString = "\t";
private @NonNull Stack<@NonNull String> classNameStack = new Stack<>();
public JavaStream(@NonNull JavaCodeGenerator codeGenerator, @NonNull CG2JavaVisitor<@NonNull ?> cg2java) {
this.codeGenerator = codeGenerator;
this.cg2java = cg2java;
this.analyzer = codeGenerator.getAnalyzer();
this.id2JavaExpressionVisitor = cg2java.createId2JavaExpressionVisitor(this);
CodeGenOptions options = codeGenerator.getOptions();
this.useNullAnnotations = options.useNullAnnotations();
this.suppressNullWarnings = useNullAnnotations && options.suppressNonNullWarningsForEMFCollections();
}
public void append(@Nullable String string) {
if (string != null) {
if (indentationStack.isEmpty()) {
s.append(string);
}
else {
int sLength = s.length();
boolean atStartOfLine = (sLength == 0) || (s.charAt(sLength-1) == '\n');
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (c == '\r') { /* ignore */ }
else {
if (atStartOfLine){
atStartOfLine = false;
s.append(indentationStack.peek());
}
boolean newLine = c == '\n';
if (newLine) {
for (int len = s.length(); len-- > 0; ) {
char ch = s.charAt(len);
if ((ch != '\n') && Character.isWhitespace(ch)) {
s.setLength(len);
}
else {
break;
}
}
}
s.append(c);
atStartOfLine = newLine;
}
}
}
}
}
public boolean appendAssignment(@NonNull CGValuedElement toVariable, @NonNull CGValuedElement cgExpression) {
CGInvalid cgInvalidValue = cgExpression.getInvalidValue();
if (cgInvalidValue != null) {
append("throw ");
// append("(");
// appendClassReference(InvalidValueException.class);
// append(")");
appendValueName(cgInvalidValue);
append(";\n");
return false;
}
else {
TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(toVariable);
if (!appendLocalStatements(cgExpression)) {
return false;
}
appendValueName(toVariable);
append(" = ");
appendReferenceTo(typeDescriptor, cgExpression);
append(";\n");
}
return true;
}
public void appendAtomicReferenceTo(@NonNull Class<?> requiredClass, @Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendAtomicReferenceTo>>");
}
else {
TypeDescriptor actualTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
Class<?> actualClass = actualTypeDescriptor.getJavaClass();
if (cgValue.getNamedValue().isCaught() || !requiredClass.isAssignableFrom(actualClass)) {
append("((");
appendClassReference(requiredClass.getName());
append(")");
appendValueName(cgValue);
append(")");
}
else {
appendValueName(cgValue);
}
}
}
public void appendAtomicReferenceTo(@NonNull TypeDescriptor requiredTypeDescriptor, @Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendAtomicReferenceTo>>");
}
else {
TypeDescriptor actualTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
if (cgValue.getNamedValue().isCaught() || !requiredTypeDescriptor.isAssignableFrom(actualTypeDescriptor)) {
append("(");
requiredTypeDescriptor.appendCast(this, null, null);
appendValueName(cgValue);
append(")");
}
else {
appendValueName(cgValue);
}
}
}
public void appendAtomicReferenceTo(@Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendAtomicReferenceTo>>");
}
else {
TypeDescriptor actualTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
if (cgValue.getNamedValue().isCaught()) {
append("(");
actualTypeDescriptor.appendCast(this, null, null);
appendValueName(cgValue);
append(")");
}
else {
appendValueName(cgValue);
}
}
}
public void appendBooleanString(boolean isTrue) {
append(isTrue ? "true" : "false");
}
public void appendBooleanValueName(@NonNull CGValuedElement cgValue, boolean isTrue) {
@NonNull TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
if (!cgValue.isNonNull() || cgValue.isCaught() || cgValue.getNamedValue().isCaught() || (typeDescriptor.getJavaClass() == Object.class)) {
appendValueName(cgValue);
append(" == ");
append(isTrue ? "Boolean.TRUE" : "Boolean.FALSE");
}
else {
if (!isTrue) {
append("!");
}
appendValueName(cgValue);
}
}
public void appendClassCast(@Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendClassCast>>");
}
else {
@NonNull TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
typeDescriptor.appendCast(this, null, null);
}
}
public void appendClassCast(@Nullable CGValuedElement cgValue, @Nullable Class<?> actualJavaClass) {
if (cgValue == null) {
append("<<null-appendClassCast>>");
}
else {
@NonNull TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
Class<?> requiredJavaClass = typeDescriptor.getJavaClass();
if ((actualJavaClass == null) || !requiredJavaClass.isAssignableFrom(actualJavaClass)) {
typeDescriptor.appendCast(this, actualJavaClass, null);
}
}
}
public void appendClassCast(@NonNull CGValuedElement cgValue, @Nullable Class<?> actualJavaClass, @NonNull SubStream subStream) {
@NonNull TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
Class<?> requiredJavaClass = typeDescriptor.getJavaClass();
if ((actualJavaClass == null) || !requiredJavaClass.isAssignableFrom(actualJavaClass)) {
typeDescriptor.appendCast(this, actualJavaClass, subStream);
}
else {
subStream.append();
}
}
public void appendClassHeader(@Nullable CGPackage cgPackage) {
appendCopyrightHeader();
if (cgPackage != null) {
append("package ");
appendClassHeaderInternal(cgPackage);
append(";\n");
}
append("\n");
append(ImportUtils.IMPORTS_MARKER + "\n");
}
private void appendClassHeaderInternal(@NonNull CGPackage cgPackage) {
CGPackage cgParentPackage = cgPackage.getContainingPackage();
if (cgParentPackage != null) {
appendClassHeaderInternal(cgParentPackage);
append(".");
}
append(String.valueOf(cgPackage.getName()));
}
public void appendClassReference(@Nullable Boolean isRequired, @Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null->>");
}
else if (cgValue.getNamedValue().isCaught()) {
if (isRequired != null) {
appendIsRequired(isRequired);
append(" ");
}
appendClassReference(Object.class);
}
else {
TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
if ((cgValue instanceof CGParameter) && (cgValue.eContainer() instanceof CGOperation) && (typeDescriptor instanceof EObjectDescriptor)) { // FIXME eliminate reclassing
Class<?> originalJavaClass = ((EObjectDescriptor)typeDescriptor).getOriginalJavaClass();
appendClassReference(isRequired, originalJavaClass);
}
else {
typeDescriptor.append(this, isRequired);
}
}
}
/**
* deprecated Provide isRequired argument.
*/
//@Deprecated
public void appendClassReference(@Nullable Class<?> javaClass) {
appendClassReference(null, javaClass);
}
public void appendClassReference(@Nullable Boolean isRequired, @Nullable Class<?> javaClass) {
if (javaClass != null) {
appendClassReference(isRequired, javaClass.getName());
TypeVariable<?>[] typeParameters = javaClass.getTypeParameters();
if (typeParameters.length > 0) {
append("<");
for (int i = 0; i < typeParameters.length; i++) {
if (i != 0) {
append(",");
}
append("?");
}
append(">");
}
}
else {
if (isRequired != null) {
appendIsRequired(isRequired);
append(" ");
}
appendClassReference(Object.class);
}
}
/**
* deprecated Provide isRequired argument.
*/
//@Deprecated
public void appendClassReference(@NonNull TypeDescriptor typeDescriptor) {
appendClassReference(null, typeDescriptor);
}
public void appendClassReference(@Nullable Boolean isRequired, @NonNull TypeDescriptor typeDescriptor) {
typeDescriptor.append(this, isRequired);
}
public void appendClassReference(@Nullable Class<?> javaClass, @NonNull Class<?>... typeParameters) {
if (javaClass != null) {
appendClassReference(javaClass.getName());
appendTypeParameters(false, typeParameters);
}
else {
appendClassReference(Object.class);
}
}
public void appendClassReference(@Nullable Boolean isRequired, @Nullable Class<?> javaClass, boolean useExtends, @NonNull Class<?>... typeParameters) {
if (javaClass != null) {
appendClassReference(isRequired, javaClass.getName());
appendTypeParameters(useExtends, typeParameters);
}
else {
appendClassReference(isRequired, Object.class);
}
}
public void appendClassReference(@Nullable Class<?> javaClass, boolean useExtends, @NonNull Class<?>... typeParameters) {
if (javaClass != null) {
appendClassReference(javaClass.getName());
appendTypeParameters(useExtends, typeParameters);
}
else {
appendClassReference(Object.class);
}
}
public void appendClassReference(@Nullable Class<?> javaClass, boolean useExtends, @NonNull String... typeParameters) {
if (javaClass != null) {
appendClassReference(javaClass.getName());
appendTypeParameters(useExtends, typeParameters);
}
else {
appendClassReference(Object.class);
}
}
/* public void appendClassReference(@Nullable String className, boolean useExtends, @NonNull Class<?>... typeParameters) {
if (className != null) {
appendClassReference(className);
appendTypeParameters(useExtends, typeParameters);
}
else {
appendClassReference(Object.class);
}
} */
/**
* @deprecated Provide isRequired argument.
*/
@Deprecated
public void appendClassReference(Class<?> javaClass, boolean useExtends, @NonNull TypeDescriptor @NonNull ... typeDescriptors) {
appendClassReference(null, javaClass, useExtends, typeDescriptors);
}
public void appendClassReference(Boolean isRequired, Class<?> javaClass, boolean useExtends, @NonNull TypeDescriptor @NonNull ... typeDescriptors) {
if (javaClass != null) {
appendClassReference(isRequired, javaClass.getName());
if (typeDescriptors.length > 0) {
append("<");
for (int i = 0; i < typeDescriptors.length; i++) {
if (i != 0) {
append(",");
}
if (useExtends) {
append("? extends ");
}
TypeDescriptor typeDescriptor = typeDescriptors[i];
typeDescriptor.append(this, null);
// Class<?> javaClass2 = typeDescriptor.getJavaClass();
// if ((javaClass2 != null) && (javaClass2 != Object.class)) {
// appendClassReference(javaClass2, new Class<?>[]{});
// }
// else {
// appendClassReference(typeDescriptor.getClassName());
// }
}
append(">");
}
}
else {
appendClassReference(Object.class);
}
}
public void appendClassReference(@Nullable String className) {
appendClassReference(null, className);
}
public void appendClassReference(@Nullable Boolean isRequired, @Nullable String className) {
if (className != null) {
StringBuilder s = new StringBuilder();
int dollar = className.indexOf("$");
if (dollar > 0) {
@NonNull String importClassName = className.substring(0, dollar);
s.append(ImportUtils.getAffixedName(importClassName));
cg2java.addImport(importClassName);
s.append(className.substring(dollar).replace('$', '.'));
}
else if (className.contains(".")){
s.append(ImportUtils.getAffixedName(className));
cg2java.addImport(className);
}
else {
s.append(className);
}
String resolvedClassName = s.toString();
if ((isRequired == null) || !useNullAnnotations) {
append(resolvedClassName);
}
else {
Class<? extends Annotation> annotationClass = isRequired ? NonNull.class : Nullable.class;
String annotationClassName = annotationClass.getName();
assert annotationClassName != null;
cg2java.addImport(annotationClassName);
String annotation = "@" + annotationClass.getName() + " ";
int index = resolvedClassName.lastIndexOf(".");
if (index < 0) {
append(annotation + resolvedClassName);
}
else {
append(resolvedClassName.substring(0, index+1) + annotation + resolvedClassName.substring(index+1));
}
}
}
}
public void appendClassReference(@NonNull CGClass cgClass) {
StringBuilder s = new StringBuilder();
CGPackage cgPackage = cgClass.getContainingPackage();
if ((cgPackage != null) && (cgPackage.getName() != null)) {
appendQualifyingPackage(s, cgPackage);
s.append(cgClass.getName());
appendClassReference(s.toString());
List<CGClass> cgTemplateParameters = cgClass.getTemplateParameters();
if (cgTemplateParameters.size() > 0) {
append("<");
boolean isFirst = true;
for (CGClass cgTemplateParameter : cgTemplateParameters) {
if (!isFirst) {
append(", ");
}
if (cgTemplateParameter != null) {
appendClassReference(cgTemplateParameter);
}
else {
append("?");
}
isFirst = false;
}
append(">");
}
}
else {
append(cgClass.getName()); // the ? wildcard
}
}
public void appendCommentWithOCL(@Nullable String title, @Nullable Element element) {
append("/**\n");
pushIndentation(" * ");
if (title != null) {
append(title + "\n");
}
if (element != null) {
PrettyPrintOptions.Global createOptions = createOptions(element);
append(PrettyPrinter.print(element, createOptions).replace("*/", "* /") + "\n");
// append("«IF expInOcl.messageExpression != null»«(expInOcl.messageExpression as StringLiteralExp).stringSymbol»«ENDIF»\n");
}
popIndentation();
append(" */\n");
}
public void appendCopyrightHeader() {
append("/*******************************************************************************\n");
pushIndentation(" *");
append(" «codeGenHelper.getCopyright(' * ')»\n");
append("\n");
append(" This code is 100% auto-generated\n");
append(" using: " + getCodeGenerator().getClass().getName() + "\n");
append("\n");
append(" Do not edit it.\n");
append("*******************************************************************************/\n");
popIndentation();
append("\n");
}
public void appendDeclaration(@NonNull CGValuedElement cgElement) {
boolean isGlobal = cgElement.isGlobal();
if (isGlobal) {
append("public static ");
}
if (!cgElement.isSettable()) {
append("final ");
}
appendTypeDeclaration(cgElement);
append(" ");
String valueName = cg2java.getValueName(cgElement);
append(valueName);
}
/**
* Append the value of cgValue, ensuring that it has the returnClassname type.
*/
public void appendEcoreValue(@NonNull String returnClassName, @NonNull CGValuedElement cgValue) {
TypeDescriptor javaTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
Class<?> javaClass = javaTypeDescriptor.hasJavaClass();
if (cgValue.getNamedValue() instanceof CGParameter) {
appendValueName(cgValue);
}
else if (javaClass == null) {
append("(");
appendClassReference(returnClassName);
append(")");
appendValueName(cgValue);
}
else if (!returnClassName.equals(javaClass.getName())) {
if (javaClass == Boolean.class) {
appendValueName(cgValue);
// if ("boolean".equals(returnClassName) || "java.lang.Boolean".equals(returnClassName)) {
// append(".booleanValue()");
// }
}
else if (javaClass == Number.class) { // Real or Integer or UnlimitedNatural (source isn't a Character but target may be)
if ("java.math.BigDecimal".equals(returnClassName)) {
appendClassReference(ValueUtil.class);
append(".bigDecimalValueOf(");
appendValueName(cgValue);
append(")");
}
else if ("java.math.BigInteger".equals(returnClassName)) {
appendClassReference(ValueUtil.class);
append(".bigIntegerValueOf(");
appendValueName(cgValue);
append(")");
}
else if ("char".equals(returnClassName)) {
append("(char)");
appendAtomicReferenceTo(cgValue);
append(".intValue()");
}
else if ("java.lang.Character".equals(returnClassName)) {
appendClassReference(Character.class);
append(".valueOf((char)");
appendAtomicReferenceTo(cgValue);
append(".intValue())");
}
else if ("java.lang.Double".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".doubleValue()");
}
else if ("java.lang.Float".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".floatValue()");
}
else if ("java.lang.Integer".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".intValue()");
}
else if ("java.lang.Long".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".longValue()");
}
else if ("java.lang.Short".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".shortValue()");
}
else if ("double".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".doubleValue()");
}
else if ("float".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".floatValue()");
}
else if ("int".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".intValue()");
}
else if ("long".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".longValue()");
}
else if ("short".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".shortValue()");
}
else {
appendValueName(cgValue);
}
}
else if ((javaClass == Object.class) // Integer or UnlimitedNatural (source isn't a Real)
|| (javaClass == byte.class)
|| (javaClass == char.class)
|| (javaClass == int.class)
|| (javaClass == long.class)
|| (javaClass == short.class)) {
if ("java.math.BigDecimal".equals(returnClassName)) {
appendClassReference(ValueUtil.class);
append(".bigDecimalValueOf(");
appendValueName(cgValue);
append(")");
}
else if ("java.math.BigInteger".equals(returnClassName)) {
appendClassReference(ValueUtil.class);
append(".bigIntegerValueOf(");
appendValueName(cgValue);
append(")");
}
else if ("char".equals(returnClassName) || "java.lang.Character".equals(returnClassName)) {
appendClassReference(ValueUtil.class);
append(".characterValueOf(");
appendValueName(cgValue);
append(")");
}
else if ("java.lang.Double".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".doubleValue()");
}
else if ("java.lang.Float".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".floatValue()");
}
else if ("java.lang.Integer".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".intValue()");
}
else if ("java.lang.Long".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".longValue()");
}
else if ("java.lang.Short".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".shortValue()");
}
else if ("double".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".doubleValue()");
}
else if ("float".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".floatValue()");
}
else if ("int".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".intValue()");
}
else if ("long".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".longValue()");
}
else if ("short".equals(returnClassName)) {
appendAtomicReferenceTo(Number.class, cgValue);
append(".shortValue()");
}
else {
appendValueName(cgValue);
}
}
else {
append("(");
appendClassReference(returnClassName);
append(")");
appendValueName(cgValue);
}
}
else {
appendValueName(cgValue);
}
}
public void appendFalse() {
appendClassReference(ValueUtil.class);
append(".FALSE_VALUE");
}
public void appendIdReference(@Nullable ElementId elementId) {
if (elementId == null) {
append("<<null-appendIdReference>>");
}
else if (CGUtil.isInlinedId(elementId)) {
elementId.accept(id2JavaExpressionVisitor);
}
else {
appendValueName(analyzer.getElementId(elementId));
}
}
public void appendIdReference2(@NonNull ElementId elementId) {
elementId.accept(id2JavaExpressionVisitor);
}
public void appendIsCaught(boolean isNonInvalid, boolean isCaught) {
append("/*");
append(isNonInvalid ? "@NonInvalid" : isCaught ? "@Caught" : "@Thrown");
append("*/");
}
public void appendIsRequired(boolean isRequired) {
if (!useNullAnnotations) {
append("/*");
append(isRequired ? "@NonNull" : "@Nullable");
append("*/");
}
else {
append("@");
appendClassReference(isRequired ? AbstractCodeGenerator.ORG_ECLIPSE_JDT_ANNOTATION_NON_NULL
: AbstractCodeGenerator.ORG_ECLIPSE_JDT_ANNOTATION_NULLABLE);
}
}
/**
* Append the complete statements for cgElement for use with in a local operation context.
* Inline and global contributions are excluded.
*/
public boolean appendLocalStatements(@NonNull CGValuedElement cgElement) {
// if (!cgElement.isInlineable() && !cgElement.isConstant() && !cgElement.isGlobal()) { // Exclude global constants and inline constants
if (!cgElement.isInlined() // Exclude inline constants
&& !cgElement.isGlobal()) { // Exclude global constant expressions
return cgElement.accept(cg2java) == Boolean.TRUE;
}
return true;
}
public void appendQualifiedLiteralName(@NonNull Operation anOperation) {
org.eclipse.ocl.pivot.Class type = anOperation.getOwningClass();
if (type != null) {
GenPackage genPackage = codeGenerator.getGenModelHelper().getGenPackage(type);
if (genPackage != null) {
String qualifiedPackageName = genPackage.getQualifiedPackageName() + AbstractGenModelHelper.TABLES_PACKAGE_NAME;
String tablesClassName = genPackage.getPrefix() + AbstractGenModelHelper.TABLES_CLASS_SUFFIX;
appendClassReference(qualifiedPackageName + "." + tablesClassName);
append(".Operations._" + type.getName() + "__" + AbstractGenModelHelper.encodeName(anOperation));
}
}
}
private void appendQualifyingPackage(@NonNull StringBuilder s, @NonNull CGPackage cgPackage) {
CGPackage cgParentPackage = cgPackage.getContainingPackage();
if (cgParentPackage != null) {
appendQualifyingPackage(s, cgParentPackage);
}
String packageName = cgPackage.getName();
if (packageName != null) {
s.append(packageName);
s.append(".");
}
}
public void appendReferenceTo(@NonNull Class<?> requiredClass, @Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendReferenceTo>>");
}
else {
TypeDescriptor actualTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
if (cgValue.getNamedValue().isCaught() || !actualTypeDescriptor.isAssignableTo(requiredClass)) {
append("(");
appendClassReference(requiredClass.getName());
append(")");
}
appendValueName(cgValue);
}
}
public void appendReferenceTo(@NonNull TypeDescriptor requiredTypeDescriptor, @Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendReferenceTo>>");
}
else {
TypeDescriptor actualTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
if (!cgValue.isNull()) {
boolean isCaught = cgValue.getNamedValue().isCaught();
if (isCaught || !requiredTypeDescriptor.isAssignableFrom(actualTypeDescriptor)) {
requiredTypeDescriptor.appendCast(this, isCaught ? null : actualTypeDescriptor.getJavaClass(), null);
}
}
appendValueName(cgValue);
}
}
public void appendReferenceTo(@Nullable CGValuedElement cgValue) {
if (cgValue == null) {
append("<<null-appendReferenceTo>>");
}
else {
if (cgValue.getNamedValue().isCaught()) {
TypeDescriptor actualTypeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
append("(");
actualTypeDescriptor.append(this, null);
append(")");
}
appendValueName(cgValue);
}
}
public void appendString(@NonNull String string) {
@SuppressWarnings("null")@NonNull String javaString = Strings.convertToJavaString(string);
append("\"");
append(javaString);
append("\"");
}
public boolean appendSuppressWarningsNull(boolean newLine) {
if (!isUseNullAnnotations()) {
return false;
}
append("@SuppressWarnings(\"null\")");
if (newLine) {
append("\n");
}
return true;
}
public void appendThis(@NonNull String className) {
String currentClassName = classNameStack.peek();
if (!className.equals(currentClassName)) {
append(className);
append(".");
}
append("this");
}
public boolean appendThrowBooleanInvalidValueException(/*@NonNull*/ String message, @NonNull String... arguments) {
appendClassReference(ValueUtil.class);
append(".throwBooleanInvalidValueException(");
appendString(ClassUtil.nonNullState(message));
for (String argument : arguments) {
append(", ");
appendString(ClassUtil.nonNullState(argument));
}
append(");\n");
return false;
}
public boolean appendThrowInvalidValueException(/*@NonNull*/ String message, @NonNull String... arguments) {
append("throw new ");
appendClassReference(InvalidValueException.class);
append("(");
appendString(ClassUtil.nonNullState(message));
for (String argument : arguments) {
append(", ");
appendString(ClassUtil.nonNullState(argument));
}
append(");\n");
return false;
}
public void appendTrue() {
appendClassReference(ValueUtil.class);
append(".TRUE_VALUE");
}
public void appendTypeDeclaration(@NonNull CGValuedElement cgElement) {
boolean isPrimitive = isPrimitive(cgElement);
boolean isRequired = !isPrimitive && !cgElement.isAssertedNonNull() && cgElement.isNonNull() && !(cgElement instanceof CGUnboxExp)/*|| cgElement.isRequired()*/; // FIXME Ugh!
appendIsCaught(cgElement.isNonInvalid(), cgElement.isCaught());
append(" ");
appendClassReference(isPrimitive ? null : isRequired, cgElement);
}
public void appendTypeParameters(boolean useExtends, @NonNull Class<?>... typeParameters) {
if (typeParameters.length > 0) {
append("<");
for (int i = 0; i < typeParameters.length; i++) {
if (i != 0) {
append(",");
}
if (useExtends) {
append("? extends ");
}
appendClassReference(typeParameters[i]);
}
append(">");
}
}
public void appendTypeParameters(boolean useExtends, @NonNull String... typeParameters) {
if (typeParameters.length > 0) {
append("<");
for (int i = 0; i < typeParameters.length; i++) {
if (i != 0) {
append(",");
}
if (useExtends) {
append("? extends ");
}
appendClassReference(typeParameters[i]);
}
append(">");
}
}
/**
* Append the code name for the value of cgElement, lazily creating one if necessary.
*/
public void appendValueName(@Nullable CGValuedElement cgElement) {
if (cgElement == null) {
append("<<null-appendValueName>>");
}
else if (cgElement.isInlined()) {
if (cgElement instanceof CGVariableExp) { // FIXME without this we get a blank name for a VariableExp
appendValueName(cgElement.getNamedValue());
}
else {
cgElement.accept(cg2java);
}
}
// else if (cgElement.isInlined() && (cgElement.isInvalid() || cgElement.isNull() || cgElement.isTrue() || cgElement.isFalse() || !cgElement.isGlobal())) { // FIXME
// CGValuedElement cgValue = cgElement;
// for (CGValuedElement cgNext; (cgNext = cgValue.getReferredValuedElement()) != cgValue; cgValue = cgNext) {}
// cgValue.accept(cg2java);
// }
else if ("this".equals(cgElement.toString())) { // FIXME use a CGThisVariable that is inlined
appendThis(cg2java.getThisName(cgElement));
}
else {
if (cgElement.isGlobal()) {
cg2java.appendGlobalPrefix();
}
String valueName = cg2java.getValueName(cgElement);
append(valueName);
}
}
public @NonNull CodeGenerator getCodeGenerator() {
return codeGenerator;
}
protected @NonNull String getValueName(@NonNull CGValuedElement cgElement) {
String name = cgElement.getValueName();
if (name == null) {
name = cgElement.getName();
}
if (name == null) {
name = "<null-" + cgElement.eClass().getName() + ">";
}
return name;
}
/** @deprecated use isPrimitive() */
@Deprecated
public boolean is_boolean(@NonNull CGValuedElement cgValue) {
if (cgValue.getNamedValue().isCaught()) {
return false;
}
else {
TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgValue);
Class<?> javaClass = typeDescriptor.getJavaClass();
return (javaClass == boolean.class) || ((javaClass == Boolean.class) && cgValue.isNonNull());
}
}
public boolean isUseNullAnnotations() {
return useNullAnnotations;
}
/**
* Return true is this is a built-in primitive type such as boolean or int.
* Such types cannot have @NonNull annotations.
*/
public boolean isPrimitive(@NonNull CGValuedElement cgValue) {
return codeGenerator.isPrimitive(cgValue);
}
public int length() {
return s.length();
}
public @Nullable String peekClassNameStack() {
return classNameStack.isEmpty() ? null : classNameStack.peek();
}
public void popClassBody(boolean isAnonymous) {
popIndentation();
append("}");
if (isAnonymous) {
append(";");
}
append("\n");
classNameStack.pop();
}
public void popIndentation() {
indentationStack.pop();
}
public void pushClassBody(@NonNull String className) {
classNameStack.push(className);
append("\n");
append("{\n");
pushIndentation(null);
}
public void pushIndentation(@Nullable String extraIndentation) {
if (extraIndentation == null) {
extraIndentation = defaultIndentationString;
}
if (indentationStack.isEmpty()) {
indentationStack.push(extraIndentation);
}
else {
indentationStack.push(indentationStack.peek() + extraIndentation);
}
}
public void resetStream() {
s.setLength(0);
}
@Override
public @NonNull String toString() {
return s.toString();
}
}