All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.ocl.internal.helper.OCLHelperImpl Maven / Gradle / Ivy

/**
 * 
 *
 * Copyright (c) 2002, 2010 IBM Corporation 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:
 *   IBM - Initial API and implementation
 *
 * 
 *
 * $Id: OCLHelperImpl.java,v 1.8 2010/12/15 17:33:43 ewillink Exp $
 */

package org.eclipse.ocl.internal.helper;

import java.util.List;

import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.EnvironmentFactory;
import org.eclipse.ocl.OCL;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.expressions.BooleanLiteralExp;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.expressions.UnspecifiedValueExp;
import org.eclipse.ocl.helper.Choice;
import org.eclipse.ocl.helper.ConstraintKind;
import org.eclipse.ocl.helper.OCLHelper;
import org.eclipse.ocl.helper.OCLSyntaxHelper;
import org.eclipse.ocl.internal.OCLPlugin;
import org.eclipse.ocl.options.ParsingOptions;
import org.eclipse.ocl.types.OCLStandardLibrary;
import org.eclipse.ocl.utilities.ExpressionInOCL;
import org.eclipse.ocl.utilities.OCLFactory;
import org.eclipse.ocl.utilities.UMLReflection;

/**
 * Default implementation of the {@link OCLHelper} interface.
 * 
 * @author Yasser Lulu
 * @author Christian W. Damus (cdamus)
 */
class OCLHelperImpl
		implements OCLHelper {
	
	private final EnvironmentFactory
	environmentFactory;
    private final UMLReflection uml;
    private final OCLFactory oclFactory;
	private Environment env;

	private OCLSyntaxHelper syntaxHelper;
	
	private boolean validating = true;
    private final OCL ocl;
    
    private Diagnostic problems;
    
	/**
	 * Initializes me with my environment.
	 * 
	 * @param ocl the OCL environment
	 */
	OCLHelperImpl(OCL ocl) {
        this.ocl = ocl;
        
        uml = ocl.getEnvironment().getUMLReflection();
        oclFactory = ocl.getEnvironment().getOCLFactory();
		environmentFactory = ocl.getEnvironment().getFactory();
	}
	
	public Environment
	getEnvironment() {
		return env == null? ocl.getEnvironment() : env;
	}
	
    public OCL getOCL() {
        return ocl;
    }
    
	public boolean isValidating() {
		return validating;
	}
	
	public void setValidating(boolean validating) {
		this.validating = validating;
	}
	
	/**
	 * Strips any leading, trailing, or embedded comments from the specified OCL
	 * expression text.
	 * 
	 * @param txt an OCL expression
	 * @return the same, but without any comments.  Note that the result
	 *     may be an empty String if txt has only comments
	 */
	private String removeOCLComments(String txt) {
		try {
			return HelperUtil.getLogicalLine(txt);
		} catch (Exception ex) {
			HelperUtil.catchException(ex, getClass(), "removeOCLComments");//$NON-NLS-1$
		}
		return HelperUtil.EMPTY;
	}

	private void setEnvironment(Environment env) {
		this.env = env;
		
		// forget the cached syntax helper, as its environment is now obsolete
		syntaxHelper = null;
	}
	
	public void setContext(C context) {
		setEnvironment(environmentFactory.createClassifierContext(
            ocl.getEnvironment(), context));
	}
	
	public void setOperationContext(C context, O operation) {
        setContext(context);
		setEnvironment(environmentFactory.createOperationContext(env, operation));
	}
	
	public void setAttributeContext(C context, P property) {
        setContext(context);
		setEnvironment(environmentFactory.createAttributeContext(env, property));
	}
    
    public void setInstanceContext(Object instance) {
        setEnvironment(environmentFactory.createInstanceContext(
            ocl.getEnvironment(), instance));
    }
    
    public void setInstanceOperationContext(Object instance, O operation) {
        setInstanceContext(instance);
        setEnvironment(environmentFactory.createOperationContext(env, operation));
    }
    
    public void setInstanceAttributeContext(Object instance, P property) {
        setInstanceContext(instance);
        setEnvironment(environmentFactory.createAttributeContext(env, property));
    }
	
	public C getContextClassifier() {
		return env.getContextClassifier();
	}
	
	public O getContextOperation() {
		return env.getContextOperation();
	}
	
	public P getContextAttribute() {
		return env.getContextProperty();
	}

	public List getSyntaxHelp(ConstraintKind constraintType, String txt) {
	    if (constraintType == null) {
	        // query expressions cannot use post-condition constructs such
	        // as @pre or oclIsNew(), so pretend an invariant constraint
	        constraintType = ConstraintKind.INVARIANT;
	    }
	    
		return createSyntaxHelper().getSyntaxHelp(constraintType, txt);
	}

    public OCLExpression
    createQuery(String expression) throws ParserException {
        if (removeOCLComments(expression).length() > 0) {
            // be sure to pass the original expression along to get the right
            //    position information when parse fails
            try {
                return HelperUtil.parseQuery(
                    this, expression, validating, ocl.isParseTracingEnabled());
            } catch (RuntimeException e) {
                propagate(e, "createQuery"); //$NON-NLS-1$
            }
        }
        
        // may as well create a boolean-valued expression if none was supplied
        return uml.getSpecification(
                createNullCondition(
                        env.getOCLStandardLibrary().getBoolean())).getBodyExpression();
    }

    public CT createConstraint(ConstraintKind kind, String expression)
        throws ParserException {
        
        switch (kind) {
        case PRECONDITION:
            return createPrecondition(expression);
        case BODYCONDITION:
            return createBodyCondition(expression);
        case POSTCONDITION:
            return createPostcondition(expression);
        case INITIAL:
            return createInitialValueExpression(expression);
        case DERIVATION:
            return createDerivedValueExpression(expression);
        case DEFINITION:
            return HelperUtil.parseDefExpression(
                this, expression, validating, ocl.isParseTracingEnabled());
        default:
            return createInvariant(expression);
        }
    }
    
	public CT createInvariant(String expression) throws ParserException {
		if (removeOCLComments(expression).length() > 0) {
			// be sure to pass the original expression along to get the right
			//    position information when parse fails
			try {
				return HelperUtil.parseInvariant(
                    this, expression, validating, ocl.isParseTracingEnabled());
			} catch (RuntimeException e) {
				propagate(e, "createInvariant"); //$NON-NLS-1$
			}
		}
		
		return createNullCondition(env.getOCLStandardLibrary().getBoolean());
	}

	public CT createPrecondition(String expression) throws ParserException {
		if (removeOCLComments(expression).length() > 0) {
			// be sure to pass the original expression along to get the right
			//    position information when parse fails
			try {
				return HelperUtil.parsePrecondition(
                    this, expression, validating, ocl.isParseTracingEnabled());
			} catch (RuntimeException e) {
				propagate(e, "createPrecondition"); //$NON-NLS-1$
			}
		}
		
		return createNullCondition(env.getOCLStandardLibrary().getBoolean());
	}
	
	public CT createPostcondition(String expression) throws ParserException {
		if (removeOCLComments(expression).length() > 0) {
			// be sure to pass the original expression along to get the right
			//    position information when parse fails
			try {
				return HelperUtil.parsePostcondition(
                    this, expression, validating, ocl.isParseTracingEnabled());
			} catch (RuntimeException e) {
				propagate(e, "createPostcondition"); //$NON-NLS-1$
			}
		}
		
		return createNullCondition(env.getOCLStandardLibrary().getBoolean());
	}
	
	public CT createBodyCondition(String expression) throws ParserException {
		if (removeOCLComments(expression).length() > 0) {
			// be sure to pass the original expression along to get the right
			//    position information when parse fails
			try {
				return HelperUtil.parseBodyCondition(
                    this, expression, validating, ocl.isParseTracingEnabled());
			} catch (RuntimeException e) {
				propagate(e, "createBodyCondition"); //$NON-NLS-1$
			}
		}
		
		return createNullCondition(env.getOCLStandardLibrary().getOclVoid());
	}
	
	public CT createInitialValueExpression(String expression) throws ParserException {
		if (removeOCLComments(expression).length() > 0) {
			// be sure to pass the original expression along to get the right
			//    position information when parse fails
			try {
				return HelperUtil.parseInitialValueExpression(
                    this, expression, validating, ocl.isParseTracingEnabled());
			} catch (RuntimeException e) {
				propagate(e, "createInitialValueExpression"); //$NON-NLS-1$
			}
		}
		
		return createNullCondition(env.getOCLStandardLibrary().getOclVoid());
	}
	
	public CT createDerivedValueExpression(String expression) throws ParserException {
		if (removeOCLComments(expression).length() > 0) {
			// be sure to pass the original expression along to get the right
			//    position information when parse fails
			try {
				return HelperUtil.parseDerivedValueExpression(
                    this, expression, validating, ocl.isParseTracingEnabled());
			} catch (RuntimeException e) {
				propagate(e, "createDerivedValueExpression"); //$NON-NLS-1$
			}
		}
		
		return createNullCondition(env.getOCLStandardLibrary().getOclVoid());
	}
	
	@SuppressWarnings("unchecked")
	public O defineOperation(String defExpression) throws ParserException {
		try {
			EObject operation = define(defExpression);
			
			if (!uml.isOperation(operation)) {
				// assert that the correct type of feature was defined
				throw new ClassCastException();
			}
			
			return (O) operation;
		} catch (RuntimeException e) {
			propagate(e, "define"); //$NON-NLS-1$
		}
		
		return null;  // make the compiler happy
	}
	
	@SuppressWarnings("unchecked")
	public P defineAttribute(String defExpression) throws ParserException {
		try {
			EObject property = define(defExpression);
			
			if (!uml.isProperty(property)) {
				// assert that the correct type of feature was defined
				throw new ClassCastException();
			}
			
			return (P) property;
		} catch (RuntimeException e) {
			propagate(e, "define"); //$NON-NLS-1$
		}
		
		return null;  // make the compiler happy
	}
	
	EObject define(String defExpression) throws ParserException {
		CT constraint = HelperUtil.parseDefExpression(
            this, defExpression, validating, ocl.isParseTracingEnabled());
		
		List constrainedElement = uml.getConstrainedElements(constraint);
		EObject result = constrainedElement.get(1);
		
		if (!ParsingOptions.getValue(getEnvironment(), ParsingOptions.DEFINITION_CONSTRAINS_FEATURE)) {
		    // remove it for good measure
		    constrainedElement.remove(result);
		}
		
		return result;
	}

	/**
	 * Creates a null condition of the specified type.
	 * 
	 * @param type the condition type
	 * 
	 * @return an expression whose value is false for boolean type
	 *     or null for anything else
	 */
	private CT createNullCondition(C type) {
		OCLExpression condition;
		
        OCLStandardLibrary stdlib = env.getOCLStandardLibrary();
        
		if (type == stdlib.getBoolean()) {
			BooleanLiteralExp literal =
				oclFactory.createBooleanLiteralExp();
			condition = literal;
			uml.setType(literal, env.getOCLStandardLibrary().getBoolean());
			literal.setBooleanSymbol(Boolean.FALSE);
		} else {
			UnspecifiedValueExp unspec =
				oclFactory.createUnspecifiedValueExp();
			condition = unspec;
			
			if (type == null) {
				type = env.getOCLStandardLibrary().getOclVoid();
			}
			
			uml.setType(unspec, type);
		}
		
		CT result = uml.createConstraint();
		
		ExpressionInOCL spec = uml.createExpressionInOCL();
		spec.setBodyExpression(condition);
		spec.setContextVariable(env.getSelfVariable());
		
		uml.setSpecification(result, spec);
		return result;
	}
	
	/**
	 * Propagates the specified exception as a parsing exception, with
	 * the requisite tracing.
	 * 
	 * @param e the exception to propagate
	 * @param method the name of the method that caught the exception
	 * 
	 * @throws the exception wrapped in an {@link ParserException}
	 */
	private void propagate(Exception e, String method) throws ParserException {
		OCLPlugin.catching(getClass(), method, e);
		ParserException ope = new ParserException(e.getLocalizedMessage(), e);
		OCLPlugin.throwing(getClass(), method, ope);
		
		throw ope;
	}

	/**
	 * returns the ocl syntax helper object
	 * 
	 * @return OCLSyntaxHelper
	 */
	protected OCLSyntaxHelper createSyntaxHelper() {
		if (syntaxHelper == null) {
			syntaxHelper = getEnvironment().getFactory().createOCLSyntaxHelper(getEnvironment());
		}
		return syntaxHelper;
	}
	
	public Diagnostic getProblems() {
		return problems;
	}
	
	void setProblems(Diagnostic problems) {
		this.problems = problems;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy