/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation, Borland Software 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 * Radek Dvorak - Bug 261128 *******************************************************************************/ package org.eclipse.ocl.internal.evaluation; import static org.eclipse.ocl.Environment.SELF_VARIABLE_NAME; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.util.BasicDiagnostic; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.ocl.Environment; import org.eclipse.ocl.EvaluationEnvironment; import org.eclipse.ocl.EvaluationHaltedException; import org.eclipse.ocl.EvaluationVisitor; import org.eclipse.ocl.Query; import org.eclipse.ocl.expressions.OCLExpression; import org.eclipse.ocl.internal.OCLPlugin; import org.eclipse.ocl.internal.helper.HelperUtil; import org.eclipse.ocl.internal.l10n.OCLMessages; import org.eclipse.ocl.util.ProblemAware; /** * <!-- begin-user-doc --> * An implementation of the model object '<em><b>Query</b></em>'. * <!-- end-user-doc --> * <p> * The following features are implemented: * <ul> * <li>{@link org.eclipse.ocl.internal.evaluation.QueryImpl#getExtentMap <em>Extent Map</em>}</li> * <li>{@link org.eclipse.ocl.internal.evaluation.QueryImpl#getExpression <em>Expression</em>}</li> * </ul> * </p> * * @generated */ public class QueryImpl<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> implements Query<C, CLS, E>, ProblemAware { private Map<CLS, ? extends Set<? extends E>> extentMap = null; private final OCLExpression<C> expression; private final Environment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> environment; private EvaluationEnvironment<C, O, P, CLS, E> evalEnv; private Diagnostic evalProblems; private BasicDiagnostic batchEvalProblems; /** * * @param environment * @param expr * @param extentMap may be <code>null</code>, in which case I will use my * evaluation environment to create a dynamic extent map */ public QueryImpl( Environment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> environment, OCLExpression<C> expr, Map<CLS, ? extends Set<? extends E>> extentMap) { this.environment = environment; this.expression = expr; this.extentMap = extentMap; } public Map<CLS, ? extends Set<? extends E>> getExtentMap() { if (extentMap == null) { EvaluationEnvironment<C, O, P, CLS, E> myEnv = getEvaluationEnvironment(); Object context = myEnv.getValueOf(SELF_VARIABLE_NAME); extentMap = myEnv.createExtentMap(context); } return extentMap; } public OCLExpression<C> getExpression() { return expression; } public Object evaluate(Object obj) { evalProblems = null; if (obj == null) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.NullArgExpectEObj_ERROR_); OCLPlugin.throwing(getClass(), "evaluate", error);//$NON-NLS-1$ throw error; } // can determine a more appropriate context from the context // variable of the expression, to account for stereotype constraints obj = HelperUtil.getConstraintContext( environment, obj, expression); // lazily create the evaluation environment, if not already done by // the client. Initialize it with the "self" context variable EvaluationEnvironment<C, O, P, CLS, E> myEnv = getEvaluationEnvironment(); myEnv.add(SELF_VARIABLE_NAME, obj); EvaluationVisitor<?, C, O, P, ?, ?, ?, ?, ?, CT, CLS, E> ev = environment.getFactory().createEvaluationVisitor( environment, myEnv, getExtentMap()); Object result; try { result = ev.visitExpression(expression); } catch (EvaluationHaltedException e) { evalProblems = e.getDiagnostic(); result = environment.getOCLStandardLibrary().getInvalid(); } finally { myEnv.remove(SELF_VARIABLE_NAME); } return result; } public Object evaluate() { evalProblems = null; // lazily create the evaluation environment, if not already done by // the client. There is no "self" context variable EvaluationVisitor<?, C, O, P, ?, ?, ?, ?, ?, CT, CLS, E> ev = environment.getFactory().createEvaluationVisitor( environment, getEvaluationEnvironment(), getExtentMap()); Object result; try { result = ev.visitExpression(expression); } catch (EvaluationHaltedException e) { evalProblems = e.getDiagnostic(); result = environment.getOCLStandardLibrary().getInvalid(); } return result; } public boolean check(Object obj) { if (resultType() != environment.getOCLStandardLibrary().getBoolean()) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.BooleanQuery_ERROR_); OCLPlugin.throwing(getClass(), "check", error);//$NON-NLS-1$ throw error; } Object result; if (obj == null) { result = evaluate(); } else { result = evaluate(obj); } return Boolean.TRUE.equals(result); } public List<?> evaluate(List<?> objList) { if (objList == null) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.NullArgExpectlist_ERROR_); OCLPlugin.throwing(getClass(), "evaluate", error);//$NON-NLS-1$ throw error; } List<Object> result = new BasicEList<Object>(); Iterator<?> iter = objList.iterator(); try { while (iter.hasNext()) { result.add(evaluate(iter.next())); handleNextEvaluateProblems(); } } finally { commitBatchEvaluateProblems(); } return result; } public boolean check(List<?> objList) { if (objList == null) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.NullArgExpectlist_ERROR_); OCLPlugin.throwing(getClass(), "check", error);//$NON-NLS-1$ throw error; } if (resultType() != environment.getOCLStandardLibrary().getBoolean()) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.BooleanQuery_ERROR_); OCLPlugin.throwing(getClass(), "check", error);//$NON-NLS-1$ throw error; } Iterator <?>iter = objList.iterator(); while (iter.hasNext()) { if (!check(iter.next())) { return false; } } return true; } public <T> List<T> select(List<T> objList) { if (objList == null) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.NullArgExpectlist_ERROR_); OCLPlugin.throwing(getClass(), "select", error);//$NON-NLS-1$ throw error; } List<T> result = new BasicEList<T>(); try { for (T obj : objList) { if (check(obj)) { result.add(obj); } handleNextEvaluateProblems(); } } finally { commitBatchEvaluateProblems(); } return result; } public <T> List<T> reject(List<T> objList) { if (objList == null) { IllegalArgumentException error = new IllegalArgumentException( OCLMessages.NullArgExpectlist_ERROR_); OCLPlugin.throwing(getClass(), "reject", error);//$NON-NLS-1$ throw error; } List<T> result = new BasicEList<T>(); try { for (T obj : objList) { if (!check(obj)) { result.add(obj); } handleNextEvaluateProblems(); } } finally { commitBatchEvaluateProblems(); } return result; } public C resultType() { return expression.getType(); } public String queryText() { return expression.toString(); } public EvaluationEnvironment<C, O, P, CLS, E> getEvaluationEnvironment() { if (evalEnv == null) { evalEnv = environment.getFactory().createEvaluationEnvironment(); } return evalEnv; } public Diagnostic getProblems() { return evalProblems; } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append("Query["); //$NON-NLS-1$ result.append(queryText()); result.append(']'); return result.toString(); } /** * Assigns collected interim diagnostics of batch evaluation to the * resulting evaluation problems. */ private void commitBatchEvaluateProblems() { evalProblems = batchEvalProblems; batchEvalProblems = null; } /** * Handles problems of single evaluation performed on behalf of batch * evaluate invocation. */ private void handleNextEvaluateProblems() { Diagnostic nextEvalProblems = getProblems(); if (nextEvalProblems != null) { if (batchEvalProblems == null) { BasicDiagnostic rootDiagnostic = new BasicDiagnostic( nextEvalProblems.getSeverity(), OCLPlugin.getPluginId(), nextEvalProblems.getCode(), nextEvalProblems.getMessage(), null); batchEvalProblems = rootDiagnostic; } batchEvalProblems.add(nextEvalProblems); } } } //QueryImpl