/******************************************************************************* * Copyright (c) 2013, 2015 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.oclinecore; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.emf.codegen.ecore.genmodel.GenClassifier; import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.ocl.examples.codegen.cgmodel.CGClass; import org.eclipse.ocl.examples.codegen.cgmodel.CGConstantExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGConstraint; import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorType; 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.CGProperty; import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement; import org.eclipse.ocl.examples.codegen.generator.TypeDescriptor; import org.eclipse.ocl.examples.codegen.java.CG2JavaVisitor; import org.eclipse.ocl.pivot.Constraint; import org.eclipse.ocl.pivot.Element; import org.eclipse.ocl.pivot.ExpressionInOCL; import org.eclipse.ocl.pivot.Feature; import org.eclipse.ocl.pivot.Operation; import org.eclipse.ocl.pivot.Property; import org.eclipse.ocl.pivot.utilities.ClassUtil; /** * An OCLinEcoreCG2JavaVisitor supports generation of the OCL embedded in an Ecore model * into the Java bodies of the code producxed by GenModel. */ public class OCLinEcoreCG2JavaVisitor extends CG2JavaVisitor<@NonNull OCLinEcoreCodeGenerator> { protected final @NonNull GenPackage genPackage; protected final @NonNull CGPackage cgPackage; protected ExpressionInOCL expInOcl; protected Feature feature; public OCLinEcoreCG2JavaVisitor(@NonNull OCLinEcoreCodeGenerator codeGenerator, @NonNull GenPackage genPackage, @NonNull CGPackage cgPackage) { super(codeGenerator); this.genPackage = genPackage; this.cgPackage = cgPackage; } @Override protected void appendGlobalPrefix() { js.append(getGlobalContext().getTablesClassName()); js.append("."); } public @NonNull Map<String, String> generateBodies() { Map<String, String> bodies = new HashMap<String, String>(); for (CGClass cgClass : cgPackage.getClasses()) { for (CGConstraint cgConstraint : cgClass.getInvariants()) { CGValuedElement cgBody = cgConstraint.getBody(); Element pivotClass = cgClass.getAst(); Element asElement = cgConstraint.getAst(); if ((cgBody != null) && (pivotClass instanceof org.eclipse.ocl.pivot.Class) && (asElement instanceof Constraint)) { Constraint asConstraint = (Constraint) asElement; localContext = globalContext.getLocalContext(cgConstraint); String bodyText = generateValidatorBody(cgBody, asConstraint, (org.eclipse.ocl.pivot.Class)pivotClass); String fragmentURI = getFragmentURI(pivotClass) + "==" + getRuleName(asConstraint); bodies.put(fragmentURI, bodyText); } } for (CGOperation cgOperation : cgClass.getOperations()) { CGValuedElement cgBody = cgOperation.getBody(); Element asOperation = cgOperation.getAst(); if ((cgBody != null) && (asOperation instanceof Operation)) { String returnClassName = genModelHelper.getOperationReturnType((Operation)asOperation); localContext = globalContext.getLocalContext(cgOperation); String bodyText = generateBody(cgBody, returnClassName); String fragmentURI = getFragmentURI(asOperation); bodies.put(fragmentURI, bodyText); } } for (CGProperty cgProperty : cgClass.getProperties()) { CGValuedElement cgBody = cgProperty.getBody(); Element asProperty = cgProperty.getAst(); if ((cgBody != null) && (asProperty instanceof Property)) { String returnClassName = genModelHelper.getPropertyResultType((Property)asProperty); localContext = globalContext.getLocalContext(cgProperty); String bodyText = generateBody(cgBody, returnClassName); String fragmentURI = getFragmentURI(asProperty); bodies.put(fragmentURI, bodyText); } } } localContext = null; return bodies; } protected @NonNull String generateBody(@NonNull CGValuedElement cgBody, @NonNull String returnClassName) { js.resetStream(); js.appendCommentWithOCL(null, cgBody.getAst()); js.appendLocalStatements(cgBody); CGInvalid cgInvalidValue = cgBody.getInvalidValue(); if (cgInvalidValue != null) { js.append("throw new "); js.appendValueName(cgInvalidValue); } else { TypeDescriptor typeDescriptor = context.getTypeDescriptor(cgBody); // String className = typeDescriptor.getClassName(); // Class<?> javaClass = typeDescriptor.getJavaClass(); js.append("return "); // if (returnClassName.contains("<")) { // js.append("(" + returnClassName + ")"); // } // js.appendValueName(cgBody); typeDescriptor.appendEcoreValue(js, returnClassName, cgBody); } js.append(";"); return toString(); } public @NonNull String generateConstants(List<CGValuedElement> sortedGlobals) { js.resetStream(); js.pushIndentation(null); if (sortedGlobals != null) { generateGlobals(sortedGlobals); } return toString(); } protected @NonNull String generateValidatorBody(@NonNull CGValuedElement cgBody, @NonNull Constraint asConstraint, org.eclipse.ocl.pivot.@NonNull Class asType) { js.resetStream(); String ecoreConstraintName = asConstraint.getName(); String constraintName = ecoreConstraintName; if (constraintName.startsWith("validate")) { // FIXME use genmodel constraintName = constraintName.substring(8); } GenClassifier genClassifier = genModelHelper.getGenClassifier(asType); String genClassifierName = genClassifier != null ? genClassifier.getName() : null; if (genClassifierName == null) { genClassifierName = ""; } // String constraintLiteralName = CodeGenUtil.upperName(genClassifierName) + "__" + CodeGenUtil.upperName(ecoreConstraintName != null ? ecoreConstraintName : ""); // String validatorClass = genModelHelper.getQualifiedValidatorClassName(genPackage); js.appendCommentWithOCL(null, asConstraint); /* CGVariable cgEvaluator = null; for (CGValuedElement cgElement = cgBody; cgElement instanceof CGLetExp; cgElement = ((CGLetExp)cgElement).getIn()) { CGLetExp cgLetExp = (CGLetExp)cgBody; CGVariable cgVariable = cgLetExp.getInit(); if (cgVariable.getASTypeId() == JavaConstants.EVALUATOR_TYPE_ID) { cgEvaluator = cgVariable; break; } } if (cgEvaluator == null) { js.append("final "); js.appendIsRequired(true); js.append(" "); js.appendClassReference(Evaluator.class); js.append(" "); js.append(JavaConstants.EVALUATOR_NAME); js.append(" = "); js.appendClassReference(PivotUtilInternal.class); js.append(".getEvaluator(this);\n"); } */ /* if (cgBody instanceof CGLetExp) { CGLetExp cgLetExp = (CGLetExp)cgBody; CGVariable cgInit = cgLetExp.getInit(); CGValuedElement cgIn = cgLetExp.getIn(); if ((cgInit != null) && (cgInit.getTypeId().getElementId() == JavaConstants.EVALUATOR_TYPE_ID) && (cgIn != null) && (constraintName != null)) { // Inject a validationKey bypass below the evaluator cgInit.accept(this); // js.append("int "); js.append(getLocalContext().getSeverityName()); js.append(" = "); js.append(JavaConstants.EVALUATOR_NAME); js.append(".getSeverity("); js.appendString(constraintName); js.append(");\n"); // js.append("if ("); js.append(getLocalContext().getSeverityName()); js.append(" <= 0) {\n"); // js.pushIndentation(null); js.append("return true;\n"); js.popIndentation(); // js.append("}\n"); // cgBody = cgIn; } } */ // js.appendLocalStatements(cgBody); // CGInvalid cgInvalidValue = cgBody.getInvalidValue(); // if (cgInvalidValue != null) { // js.append("throw new "); // js.appendValueName(cgInvalidValue); // } // else { js.append("return Boolean.TRUE == "); js.appendValueName(cgBody); // js.appendEcoreValue("boolean", cgBody); // } js.append(";"); return toString(); /* if (js.appendLocalStatements(cgBody)) { // FieldingAnalyzer override ensures this is caught if (cgBody.isTrue()) { js.append("return true;"); } else { js.append("if ("); js.appendValueName(cgBody); js.append(" == "); js.appendClassReference(ValueUtil.class); js.append(".TRUE_VALUE) {\n"); js.pushIndentation(null); js.append("return true;\n"); js.popIndentation(); js.append("}\n"); // // int diagnosticSeverity = evaluator.getDiagnosticSeverity(severity, CAUGHT_implies); // int severity = CAUGHT_implies == null ? Diagnostic.ERROR : Diagnostic.WARNING; js.append("if (diagnostics != null) {\n"); js.pushIndentation(null); js.append("int "); js.append(getLocalContext().getDiagnosticSeverityName()); js.append(" = "); js.append(JavaConstants.EVALUATOR_NAME); js.append(".getDiagnosticSeverity("); js.append(getLocalContext().getSeverityName()); js.append(", "); js.appendValueName(cgBody); js.append(");\n"); /* js.append(getLocalContext().getSeverityName()); if (cgBody.isNull()) { js.appendClassReference(Diagnostic.class); js.append(".ERROR : "); } else if (cgBody.isNonNull()) { js.appendClassReference(Diagnostic.class); js.append(".WARNING;\n"); } else { js.appendValueName(cgBody); js.append(" == null ? "); js.appendClassReference(Diagnostic.class); js.append(".ERROR : "); js.appendClassReference(Diagnostic.class); js.append(".WARNING;\n"); } * / // js.appendClassReference(String.class); js.append(" " + getLocalContext().getMessageName() + " = "); js.appendClassReference(StringUtil.class); js.append(".bind("); js.appendClassReference(PivotMessages.class); js.append(".ValidationConstraintIsNotSatisfied_ERROR_, new Object[]{\""); js.append(genClassifierName); js.append("\", \""); js.append(constraintName!= null ? constraintName : "UnnamedConstraint"); js.append("\", "); js.appendClassReference(EObjectValidator.class); js.append(".getObjectLabel(this, context)});\n"); // js.append("diagnostics.add(new "); js.appendClassReference(BasicDiagnostic.class); js.append("(" + getLocalContext().getDiagnosticSeverityName() + ", "); js.appendClassReference(validatorClass); js.append(".DIAGNOSTIC_SOURCE, "); js.appendClassReference(validatorClass); js.append("." + constraintLiteralName + ", " + getLocalContext().getMessageName() + ", new Object [] { this }));\n"); js.popIndentation(); js.append("}\n"); js.append("return false;"); } } return toString(); */ } protected String getFragmentURI(@NonNull Element element) { return EcoreUtil.getURI(element).fragment().toString(); } protected @NonNull OCLinEcoreGlobalContext getGlobalContext() { return (OCLinEcoreGlobalContext) globalContext; } protected @NonNull OCLinEcoreLocalContext getLocalContext() { return ClassUtil.nonNullState((OCLinEcoreLocalContext) localContext); } protected String getRuleName(@NonNull Constraint constraint) { String name = constraint.getName(); return name != null ? name : ""; } @Override public @NonNull Boolean visitCGClass(@NonNull CGClass cgClass) { return true; } @Override public @NonNull Boolean visitCGConstantExp(@NonNull CGConstantExp cgConstantExp) { CGValuedElement globalConstant = cgConstantExp.getReferredConstant(); if (globalConstant instanceof CGExecutorType) { // FIXME Why is this necessary to avoid a CG failure in CodeGenCompany return true; } if (globalConstant != null) { if (!cgConstantExp.isInlined()) { appendGlobalPrefix(); } js.appendValueName(globalConstant); } return true; } @Override public @NonNull Boolean visitCGOperation(@NonNull CGOperation cgOperation) { return true; } @Override public @NonNull Boolean visitCGPackage(@NonNull CGPackage cgPackage) { return true; } }