| /**
|
| * Copyright (c) 2009, 2019 Mia-Software and others.
|
| * All rights reserved. This program and the accompanying materials
|
| * are made available under the terms of the Eclipse Public License v2.0
|
| * which accompanies this distribution, and is available at
|
| * http://www.eclipse.org/legal/epl-v20.html
|
| *
|
| * Contributors:
|
| * Gregoire DUPE (Mia-Software) - initial API and implementation
|
| * Nicolas Bros (Mia-Software)
|
| */ |
| package org.eclipse.modisco.infra.query.core;
|
|
|
| import java.util.ArrayList;
|
| import java.util.Collection;
|
| import java.util.Iterator;
|
| import java.util.List;
|
|
|
| import org.eclipse.emf.common.util.TreeIterator;
|
| import org.eclipse.emf.ecore.EClass;
|
| import org.eclipse.emf.ecore.EObject;
|
| import org.eclipse.emf.ecore.resource.Resource;
|
| import org.eclipse.modisco.infra.query.ModelQuery;
|
| import org.eclipse.modisco.infra.query.ModelQuerySet;
|
| import org.eclipse.modisco.infra.query.core.exception.ModelQueryException;
|
| import org.eclipse.modisco.infra.query.core.exception.ModelQueryExecutionException;
|
| import org.eclipse.modisco.infra.query.core.exception.ModelQueryTypeCheckingException;
|
| import org.eclipse.modisco.infra.query.runtime.ModelQueryContext;
|
| import org.eclipse.modisco.infra.query.runtime.ModelQueryParameterValue;
|
| import org.eclipse.modisco.infra.query.runtime.ModelQueryResult;
|
| import org.eclipse.modisco.infra.query.runtime.RuntimeFactory;
|
|
|
| /**
|
| * To get a sub class instance of this class, the {@link ModelQuerySetCatalog}
|
| * must be used.
|
| *
|
| * <pre>
|
| * ModelQuerySetCatalog catalog = ModelQuerySetCatalog.getSingleton();
|
| * ModelQuerySet modelQuerySet = catalog.getModelQuerySet("modisco.infra.query.tests.01");
|
| * ModelQuery modelQuery = modelQuerySet.getQuery("test001");
|
| * AbstractModelQuery modelQueryInst = catalog.getModelQueryImpl(modelQuery);
|
| * </pre>
|
| *
|
| * @author Gregoire DUPE (Mia-Software)
|
| *
|
| * @deprecated replaced by EMF Facet, cf. https://bugs.eclipse.org/bugs/show_bug.cgi?id=470578
|
| */
|
| @Deprecated
|
| public abstract class AbstractModelQuery {
|
|
|
| private final ModelQuery modelQuery;
|
| private boolean checkResult = true;
|
|
|
| /**
|
| * AbstractModelQuery constructor
|
| *
|
| * @param modelQuery
|
| * the model query description (model element)
|
| */
|
| public AbstractModelQuery(final ModelQuery modelQuery) {
|
| this.modelQuery = modelQuery;
|
| }
|
|
|
| /**
|
| * This method returns the model query element passed as parameter to the
|
| * constructor
|
| *
|
| * @return The model query element passed as parameter to the constructor
|
| */
|
| public final ModelQuery getModelQuery() {
|
| return this.modelQuery;
|
| }
|
|
|
| /**
|
| * This method is used to evaluate the query on a set of models and model
|
| * elements described by the context parameter.
|
| *
|
| * The query is evaluated on each contextually referred model element and on
|
| * each element of a contextually referred model.
|
| *
|
| * @param context
|
| * The query evaluation context described by a ModelQueryContext
|
| * instance.
|
| * @param parameterValues
|
| * The query parameter values.
|
| * @return A list of ModelQueryResult (one per evaluation)
|
| */
|
| public final synchronized List<ModelQueryResult> evaluate(final ModelQueryContext context,
|
| final List<ModelQueryParameterValue> parameterValues) {
|
| List<ModelQueryResult> resultList = new ArrayList<ModelQueryResult>();
|
| try {
|
| startEvaluate();
|
| for (EObject eObject : context.getSelectedModelElements()) {
|
| executeQuery(parameterValues, resultList, eObject);
|
| }
|
| for (Resource resource : context.getSelectedModels()) {
|
| TreeIterator<EObject> treeIterator = resource.getAllContents();
|
| while (treeIterator.hasNext()) {
|
| EObject eObject = treeIterator.next();
|
| executeQuery(parameterValues, resultList, eObject);
|
| }
|
| }
|
| } finally {
|
| endEvaluate();
|
| }
|
| return resultList;
|
| }
|
|
|
| /**
|
| * Called when starting evaluating a query on one or several context
|
| * elements (when
|
| * {@link AbstractModelQuery#evaluate(ModelQueryContext, List)} is called).
|
| * <p>
|
| * A subclass will receive in order:<br>
|
| *
|
| * <pre>
|
| * startEvaluate()
|
| * basicEvaluate(context1, parameters)
|
| * basicEvaluate(context2, parameters)
|
| * ...
|
| * basicEvaluate(contextn, parameters)
|
| * endEvaluate()
|
| * </pre>
|
| *
|
| * </p>
|
| *
|
| * @see {@link AbstractModelQuery#endEvaluate()}
|
| */
|
| protected void startEvaluate() {
|
| // meant to be overridden
|
| }
|
|
|
| /**
|
| * Called when ending the evaluation of a query on one or several context
|
| * elements.
|
| *
|
| * @see {@link AbstractModelQuery#startEvaluate()}
|
| */
|
| protected void endEvaluate() {
|
| // meant to be overridden
|
| }
|
|
|
| /**
|
| * This method is used to evaluate the query on one model element. The
|
| * method is only usable for queries which do not have any parameters.
|
| *
|
| * @param context
|
| * The query evaluation context
|
| * @return A ModelQueryResult instance
|
| */
|
| public final ModelQueryResult evaluate(final EObject context) {
|
| ModelQueryResult modelQueryResult = RuntimeFactory.eINSTANCE.createModelQueryResult();
|
| try {
|
| modelQueryResult.setSource(context);
|
| modelQueryResult.setValue(basicEvaluate(context, null));
|
| } catch (Exception e) {
|
| modelQueryResult.setException(e);
|
| }
|
| return modelQueryResult;
|
| }
|
|
|
| /**
|
| * This method is used to evaluate the query on one model element. The
|
| * method is usable for queries which have parameters.
|
| *
|
| * @param context
|
| * The query evaluation context
|
| * @param parameterValues
|
| * The query parameter values
|
| * @return A ModelQueryResult instance
|
| */
|
| public final ModelQueryResult evaluate(final EObject context,
|
| final List<ModelQueryParameterValue> parameterValues) {
|
| ModelQueryResult modelQueryResult = RuntimeFactory.eINSTANCE.createModelQueryResult();
|
| try {
|
| modelQueryResult.setSource(context);
|
| modelQueryResult.setValue(basicEvaluate(context, parameterValues));
|
| } catch (Exception e) {
|
| modelQueryResult.setException(e);
|
| }
|
| return modelQueryResult;
|
| }
|
|
|
| private final void executeQuery(final List<ModelQueryParameterValue> parameterValues,
|
| final List<ModelQueryResult> resultList, final EObject context) {
|
| ModelQueryResult modelQueryResult = RuntimeFactory.eINSTANCE.createModelQueryResult();
|
| resultList.add(modelQueryResult);
|
| modelQueryResult.setSource(context);
|
| boolean matched = (this.modelQuery.getScope().size() == 0);
|
| Iterator<EClass> queryScopes = this.modelQuery.getScope().iterator();
|
| while (queryScopes.hasNext() && !matched) {
|
| EClass eClass = queryScopes.next();
|
| if (eClass.isInstance(context)) {
|
| matched = true;
|
| }
|
| }
|
|
|
| if (matched && this.modelQuery.getScope().size() != 0) {
|
| try {
|
| Object result = basicEvaluate(context, parameterValues);
|
| modelQueryResult.setValue(result);
|
| } catch (ModelQueryException e) {
|
| modelQueryResult.setException(e);
|
| }
|
| } else {
|
| StringBuffer message = new StringBuffer();
|
| message.append("Wrong context type (for query " + toString() + "): "); //$NON-NLS-1$ //$NON-NLS-2$
|
| message.append(context.eClass().getName());
|
| message.append(" found; expected scopes are {"); //$NON-NLS-1$
|
| for (int i = 0; i < this.modelQuery.getScope().size(); i++) {
|
| EClass scope = this.modelQuery.getScope().get(i);
|
| message.append(scope.getName());
|
| if (i != this.modelQuery.getScope().size() - 1) {
|
| message.append(", "); //$NON-NLS-1$
|
| }
|
| }
|
| message.append("}"); //$NON-NLS-1$
|
| ModelQueryTypeCheckingException e = new ModelQueryTypeCheckingException(
|
| message.toString());
|
| modelQueryResult.setException(e);
|
| }
|
| }
|
|
|
| /**
|
| * This method must be overridden by each sub class to implement query
|
| * evaluation.
|
| *
|
| * @param context
|
| * The query evaluation context
|
| * @param parameterValues
|
| * The query parameter values
|
| * @return A list of ModelQueryResult (one per evaluation)
|
| * @throws ModelQueryExecutionException
|
| */
|
| public abstract Object basicEvaluate(final EObject context,
|
| final List<ModelQueryParameterValue> parameterValues) throws ModelQueryException;
|
|
|
| /**
|
| * This method is equivalent to {@link AbstractModelQuery#evaluate(EObject)}
|
| * but rather than return the errors into a ModelQueryResult instance, it
|
| * throws an exception.
|
| *
|
| * @param context
|
| * The query evaluation context
|
| * @return The query result.
|
| * @throws ModelQueryExecutionException
|
| */
|
| public final Object basicEvaluate(final EObject context) throws ModelQueryException {
|
| return basicEvaluate(context, new ArrayList<ModelQueryParameterValue>());
|
| }
|
|
|
| protected final void checkResult(final Object object) throws ModelQueryTypeCheckingException {
|
| if (this.modelQuery.getUpperBound() > 1 || this.modelQuery.getUpperBound() == -1) {
|
| if (!(object instanceof Collection<?>)) {
|
| throw new ModelQueryTypeCheckingException(
|
| "A collection is expected as result. The result is: " //$NON-NLS-1$
|
| + object + " (on " + toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
|
| }
|
| for (Object collectionElement : (Collection<?>) object) {
|
| if (this.checkResult) {
|
| if (!(this.modelQuery.getReturnType().isInstance(collectionElement))) {
|
| ModelQueryTypeCheckingException e = new ModelQueryTypeCheckingException(
|
| "Wrong result collection element type (" //$NON-NLS-1$
|
| + this.modelQuery.getReturnType().getName()
|
| + " is expected): " //$NON-NLS-1$
|
| + collectionElement + " (on " //$NON-NLS-1$
|
| + toString() + ")"); //$NON-NLS-1$
|
| throw e;
|
| }
|
| }
|
| }
|
| } else {
|
| if (object instanceof Collection<?>) {
|
| throw new ModelQueryTypeCheckingException("A " //$NON-NLS-1$
|
| + this.modelQuery.getReturnType().getName()
|
| + " instance is expected as result. The result is: " //$NON-NLS-1$
|
| + object + " (on " + toString() + ")"); //$NON-NLS-1$//$NON-NLS-2$
|
| }
|
| if (this.checkResult) {
|
| if (!(this.modelQuery.getReturnType().isInstance(object))) {
|
| if (object != null) {
|
| throw new ModelQueryTypeCheckingException("Wrong result type: " //$NON-NLS-1$
|
| + object.getClass().getName()
|
| + " is returned while " //$NON-NLS-1$
|
| + this.modelQuery.getReturnType().getInstanceClassName()
|
| + " is expected." + " (on " + toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
| }
|
|
|
| }
|
| }
|
| }
|
| }
|
|
|
| public void setCheckResult(final boolean checkResult) {
|
| this.checkResult = checkResult;
|
| }
|
|
|
| @Override
|
| public String toString() {
|
| String queryName;
|
| String querySetName;
|
| if (this.modelQuery == null) {
|
| queryName = "null"; //$NON-NLS-1$
|
| querySetName = "null"; //$NON-NLS-1$
|
| } else {
|
| queryName = this.modelQuery.getName();
|
| ModelQuerySet modelQuerySet = this.modelQuery.getModelQuerySet();
|
| if (modelQuerySet != null) {
|
| querySetName = modelQuerySet.getName();
|
| } else {
|
| querySetName = "null"; //$NON-NLS-1$
|
| }
|
| }
|
| return querySetName + "::" + queryName; //$NON-NLS-1$
|
| }
|
| }
|