/****************************************************************************** * Copyright (c) 2007,2010 E.D.Willink 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 - initial API and implementation * * </copyright> * * $Id: CSTRootEnvironment.java,v 1.3 2010/04/08 06:26:26 ewillink Exp $ */ package org.eclipse.ocl.examples.parser.environment; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.emf.common.util.DiagnosticChain; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EGenericType; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EValidator; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.Diagnostician; import org.eclipse.emf.ecore.xmi.XMIResource; import org.eclipse.ocl.Environment; import org.eclipse.ocl.cst.CSTNode; import org.eclipse.ocl.cst.IsMarkedPreCS; import org.eclipse.ocl.ecore.CollectionType; import org.eclipse.ocl.ecore.TypeType; import org.eclipse.ocl.examples.common.utils.EcoreUtils; import org.eclipse.ocl.examples.common.utils.XMIUtils; import org.eclipse.ocl.examples.modelregistry.environment.AbstractModelResolver; import org.eclipse.ocl.examples.parser.utils.ErrorNode; import org.eclipse.ocl.expressions.InvalidLiteralExp; import org.eclipse.ocl.lpg.AbstractParser; import org.eclipse.ocl.utilities.UMLReflection; public abstract class CSTRootEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E, V extends ICSTNodeEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E>, CST extends CSTNode> extends CSTNodeEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E, V, XMIResource, CST> implements ICSTRootEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> { private final class WorkaroundDiagnostician extends Diagnostician { private final class WorkaroundOclValidator extends org.eclipse.ocl.ecore.util.EcoreValidator { public WorkaroundOclValidator(WorkaroundEmfValidator emfValidator) { ecoreValidator = emfValidator; } } private final class WorkaroundEmfValidator extends org.eclipse.emf.ecore.util.EcoreValidator { @Override public boolean validateEClassifier_WellFormedInstanceTypeName(EClassifier classifier, DiagnosticChain diagnostics, Map<Object, Object> context) { if (classifier instanceof TypeType) // FIXME Workaround Bug 241426 return true; return super.validateEClassifier_WellFormedInstanceTypeName(classifier, diagnostics, context); } } public WorkaroundDiagnostician() { WorkaroundEmfValidator newEmfValidator = new WorkaroundEmfValidator(); WorkaroundOclValidator newOclValidator = new WorkaroundOclValidator(newEmfValidator); eValidatorRegistry.put(org.eclipse.emf.ecore.EcorePackage.eINSTANCE, newEmfValidator); eValidatorRegistry.put(org.eclipse.ocl.ecore.EcorePackage.eINSTANCE, newOclValidator); } } protected final ICSTFileEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> fileEnvironment; private UnresolvedEnvironment unresolvedEnvironment = null; protected CSTRootEnvironment(ICSTFileEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> fileEnvironment, XMIResource astNode, CST cstNode) { super(fileEnvironment, astNode, cstNode); assert (astNode != null); this.fileEnvironment = fileEnvironment; initASTMapping(astNode, cstNode); } public UnresolvedEnvironment basicGetUnresolvedEnvironment() { return unresolvedEnvironment; } public void checkMappings() { EPackage rootUnresolvedEPackage = unresolvedEnvironment != null ? unresolvedEnvironment.getUnresolvedEPackage() : null; for (Iterator<EObject> i = ast.getAllContents(); i.hasNext(); ) { EObject astNode = i.next(); CSTNode cstNode = getASTMapping(astNode); if (cstNode != null) ; else if (astNode instanceof EGenericType) ; else if ((astNode instanceof EPackage) && (((EPackage)astNode).getEAnnotation(OCL_NAMESPACE_URI) != null)) // A shadow package ; else if ((astNode instanceof EClassifier) && (((EClassifier)astNode).getEAnnotation(OCL_NAMESPACE_URI) != null)) // A shadow class ; else if ((astNode instanceof EAttribute) && (((EAttribute)astNode).getEAnnotation(OCL_NAMESPACE_URI) != null)) // A shadow class attribute ; else if ((astNode instanceof EOperation) && (((EOperation)astNode).getEAnnotation(OCL_NAMESPACE_URI) != null)) // A shadow class operation ; else if ((astNode instanceof EParameter) && (((EParameter)astNode).getEOperation().getEAnnotation(OCL_NAMESPACE_URI) != null)) // A shadow class parameter ; else if ((astNode instanceof EAnnotation) && OCL_NAMESPACE_URI.equals(((EAnnotation)astNode).getSource())) // A shadow class annotation ; else if ((astNode instanceof CollectionType) && (((CollectionType)astNode).getEPackage().getEAnnotation(OCL_NAMESPACE_URI) != null)) // A shadow collection type ; else { boolean hasErrorNode = false; if (rootUnresolvedEPackage != null) { for (EObject eObject = astNode; eObject != null; eObject = eObject.eContainer()) { if (eObject == rootUnresolvedEPackage) { hasErrorNode = true; break; } } } if (!hasErrorNode) System.out.println("No AST to CST mapping for " + EcoreUtils.qualifiedNameFor(astNode)); } } for (Iterator<EObject> i = cst.eAllContents(); i.hasNext(); ) { CSTNode cstNode = (CSTNode) i.next(); Object astNode = cstNode.getAst(); if (astNode != null) ; else if (cstNode instanceof IsMarkedPreCS) ; else { boolean hasErrorNode = false; for (EObject eObject = cstNode; eObject instanceof CSTNode; eObject = eObject.eContainer()) { Object ast = ((CSTNode)eObject).getAst(); if ((ast instanceof ErrorNode) || (ast instanceof InvalidLiteralExp<?>)) { hasErrorNode = true; break; } } if (!hasErrorNode) System.out.println("No CST to AST mapping for " + EcoreUtils.qualifiedNameFor(cstNode) + " in " + String.valueOf(ast.getURI())); } } } /* public boolean checkFeatureCompatibility(CSTNode cstNode, EClassifier featureType, OCLExpression oclExpression) { if (featureType == null) return false; if (!isResolved(featureType)) return false; C expressionType = getUMLReflection().getOCLType(oclExpression.getType()); if (expressionType == null) return false; if (!isResolved(expressionType)) return false; if (featureType == expressionType) return true; else if (featureType instanceof EEnum) { String enumLiteralText = oclExpression.toString(); if (enumLiteralText.length() >= 2) enumLiteralText = enumLiteralText.substring(1, enumLiteralText.length()-1); EEnumLiteral enumLiteral = ((EEnum)featureType).getEEnumLiteral(enumLiteralText); if (enumLiteral != null) return true; String message = "Incompatible enum '" + formatType(featureType) + "' for match with " + enumLiteralText; analyzerError(message, "FeatureCompatibility", cstNode); } else if (featureType instanceof CollectionType) { CollectionKind featureKind = ((CollectionType) featureType).getKind(); EClassifier featureElementType = ((CollectionType) featureType).getElementType(); CollectionKind expressionKind = null; EClassifier expressionElementType = expressionType; if (expressionType instanceof CollectionType) { expressionKind = ((CollectionType) expressionType).getKind(); expressionElementType = ((CollectionType) expressionType).getElementType(); } if (expressionElementType == null) return false; if (!isResolved(expressionElementType)) return false; if (!(expressionElementType instanceof EClass)) { String message = "Incompatible class '" + formatType(featureElementType) + "' for match with '" + formatType(expressionElementType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } else if (!((EClass) featureElementType).isSuperTypeOf((EClass) expressionElementType)) { String message = "Incompatible class '" + formatType(featureElementType) + "' for match with '" + formatType(expressionElementType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } // else if ((expressionKind != null) && QVTrUtils.isOrdered(featureKind) && !QVTrUtils.isOrdered(expressionKind)) // analyzerWarning(cstNode, null, "Ordered collection '" + formatType(featureType) + "' for match with '" + formatType(expressionType) + "'"); else if ((expressionKind != null) && OCLUtils.isUnique(featureKind) && !OCLUtils.isUnique(expressionKind)) { String message = "Unique collection '" + formatType(featureType) + "' for match with '" + formatType(expressionType) + "'"; analyzerWarning(message, "FeatureCompatibility", cstNode); } else return true; } else if (featureType instanceof EDataType) { String message = "Incompatible data type '" + formatType(featureType) + "' for match with '" + formatType(expressionType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } else if (featureType instanceof TupleType) { String message = "Incompatible tuple type '" + formatType(featureType) + "' for match with '" + formatType(expressionType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } else if (featureType instanceof EClass) { if (!(expressionType instanceof EClass)) { String message = "Incompatible data type '" + formatType(featureType) + "' for match with '" + formatType(expressionType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } else if (!((EClass) featureType).isSuperTypeOf((EClass) expressionType)) { String message = "Incompatible class '" + formatType(featureType) + "' for match with '" + formatType(expressionType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } else return true; } else { String message = "Unsupported feature type '" + formatType(featureType) + "'"; analyzerError(message, "FeatureCompatibility", cstNode); } return false; } */ /** * Create the recipient of EValidator diagnostics. The default implementation creates a * ProblemHandlerDiagnosticChain to redirect diagnostics to the ProblemHandler. */ protected ProblemHandlerDiagnosticChain createDiagnosticChain() { return new ProblemHandlerDiagnosticChain(this); } /** * Create and return a Diagnostician for validator report processing. * * @return the Diagnostician */ protected Diagnostician createDiagnostician() { return new WorkaroundDiagnostician(); } /** * Create and return the SubstitutionLabelProvider to provide object descriptions * in validator messages. The diagnostician may be returned directly. The default * implementation returns getFormatter(). * * @param diagnostician processing the validator diagnostics * @return the SubstitutionLabelProvider */ protected EValidator.SubstitutionLabelProvider createSubstitutionLabelProvider(Diagnostician diagnostician) { return getFormatter(); } protected UnresolvedEnvironment createUnresolvedEnvironment() { return new UnresolvedEnvironment(this); } public int getCSTErrorTokens() { return getParser().getIPrsStream().getErrorTokens(); } public ICSTFileEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> getFileEnvironment() { return fileEnvironment; } @Override public AbstractParser getParser() { return fileEnvironment.getParser(); } public AbstractModelResolver getResolver() { return fileEnvironment.getResolver(); } public ICSTRootEnvironment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> getRootEnvironment() { return this; } public UMLReflection<PK, C, O, P, EL, PM, S, COA, SSA, CT> getUMLReflection() { return fileEnvironment.getUMLReflection(); } public UnresolvedEnvironment getUnresolvedEnvironment() { if (unresolvedEnvironment == null) unresolvedEnvironment = createUnresolvedEnvironment(); return unresolvedEnvironment; } public boolean isResolved(EObject eObject) { return (unresolvedEnvironment == null) || !unresolvedEnvironment.isUnresolved(eObject); } public void postParse() { if (unresolvedEnvironment != null) ast.getContents().add(unresolvedEnvironment.getUnresolvedEPackage()); } public void saveCST(CSTNode cstNode, URI uri) throws IOException { Resource resource = getFileEnvironment().getResourceSet().createResource(uri); XMIUtils.assignLinearIds(resource, "cst"); resource.save(null); } public void validate() { if (ast == null) return; Diagnostician diagnostician = createDiagnostician(); EValidator.SubstitutionLabelProvider substitutionLabelProvider = createSubstitutionLabelProvider(diagnostician); Map<Object, Object> context = new HashMap<Object, Object>(); context.put(EValidator.SubstitutionLabelProvider.class, substitutionLabelProvider); context.put(EValidator.class, diagnostician); context.put(ICSTEnvironment.class, this); context.put(Environment.class, this); //Used by derived EValidator that cannot see ICSTEnvironment DiagnosticChain diagnosticChain = createDiagnosticChain(); for (EObject astNode : ast.getContents()) diagnostician.validate(astNode, diagnosticChain, context); } }