org.eclipse.reqcycle.ocl.utils.OCLUtilities.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.reqcycle.ocl.utils.OCLUtilities.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Atos.
 * 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:
 *     Atos - initial API and implementation
 ******************************************************************************/
package org.eclipse.reqcycle.ocl.utils;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.ocl.examples.pivot.utilities.BaseResource;
import org.eclipse.ocl.examples.xtext.base.baseCST.PrimitiveTypeRefCS;
import org.eclipse.ocl.examples.xtext.base.baseCST.TypedRefCS;
import org.eclipse.ocl.examples.xtext.completeocl.CompleteOCLStandaloneSetup;
import org.eclipse.ocl.examples.xtext.completeocl.completeOCLCST.ClassifierContextDeclCS;
import org.eclipse.ocl.examples.xtext.completeocl.completeOCLCST.CompleteOCLDocumentCS;
import org.eclipse.ocl.examples.xtext.completeocl.completeOCLCST.ContextDeclCS;
import org.eclipse.ocl.examples.xtext.completeocl.completeOCLCST.DefCS;
import org.eclipse.ocl.examples.xtext.completeocl.completeOCLCST.DefOperationCS;
import org.eclipse.reqcycle.ocl.ReqcycleOCLPlugin;
import org.eclipse.reqcycle.repository.data.types.IAttribute;
import org.eclipse.reqcycle.repository.data.types.IRequirementType;
import org.eclipse.ziggurat.ocl.OCLEvaluator;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

public class OCLUtilities {

    protected static Map<String, String> ecoreToOCLPrimitiveTypes = new HashMap<String, String>();
    static {
        ecoreToOCLPrimitiveTypes.put("EString", "String"); //$NON-NLS-1$
        ecoreToOCLPrimitiveTypes.put("EBoolean", "Boolean"); //$NON-NLS-1$
        ecoreToOCLPrimitiveTypes.put("EFloat", "Real"); //$NON-NLS-1$
        ecoreToOCLPrimitiveTypes.put("EInt", "Integer"); //$NON-NLS-1$
    }

    public static BaseResource loadOCLResource(ResourceSet resourceSet, URI oclURI) {
        BaseResource xtextResource = null;
        CompleteOCLStandaloneSetup.init();
        try {
            xtextResource = (BaseResource) resourceSet.getResource(oclURI, true);
        } catch (WrappedException e) {
            URI retryURI = null;
            Throwable cause = e.getCause();
            if (cause instanceof CoreException) {
                IStatus status = ((CoreException) cause).getStatus();
                if ((status.getCode() == IResourceStatus.RESOURCE_NOT_FOUND)
                        && status.getPlugin().equals(ResourcesPlugin.PI_RESOURCES)) {
                    if (oclURI.isPlatformResource()) {
                        retryURI = URI.createPlatformPluginURI(oclURI.toPlatformString(false), false);
                    }
                }
            }
            if (retryURI != null) {
                xtextResource = (BaseResource) resourceSet.getResource(retryURI, true);
            } else {
                throw e;
            }
        }
        return xtextResource;
    }

    public static Collection<DefOperationCS> getOperations(BaseResource resource) {
        Collection<DefOperationCS> result = Lists.newArrayList();
        EList<EObject> contents = resource.getContents();
        if (contents.size() == 1) {
            EObject root = contents.get(0);
            if (root instanceof CompleteOCLDocumentCS) {
                EList<ContextDeclCS> contexts = ((CompleteOCLDocumentCS) root).getContexts();
                for (ContextDeclCS context : contexts) {
                    if (context instanceof ClassifierContextDeclCS) {
                        EList<DefCS> definitions = ((ClassifierContextDeclCS) context).getDefinitions();
                        Iterables.addAll(result, Iterables.filter(definitions, DefOperationCS.class));
                    }
                }
            }
        }
        return result;
    }

    /**
     * Checks whether an OCL resource contains an operation allowing to test whether an uml element can
     * be associated to a given data type. The operation should be named "isX" where "X" is the name
     * of the data type.
     */
    public static IStatus isOperationPresent(final IRequirementType type, BaseResource resource) {
        if (Iterables.size(getMatchingOperations(type, resource)) > 0) {
            return Status.OK_STATUS;
        }
        ;
        return new Status(IStatus.ERROR, ReqcycleOCLPlugin.PLUGIN_ID,
                "Required operation : " + OCLUtilities.getOperationRequiredSignature(type) + " could not be found");
    }

    /**
     * Checks whether an OCL resource contains an operation allowing to retrieve a requirement's attribute
     * of a given data type. The operation should be named "isX" where "X" is the name
     * of the data type.
     */
    public static IStatus isOperationPresent(final IAttribute attribute, BaseResource resource) {
        String attributeTypeName = attribute.getName();
        if (ecoreToOCLPrimitiveTypes.get(attributeTypeName) == null) {
            return new Status(IStatus.WARNING, ReqcycleOCLPlugin.PLUGIN_ID,
                    "Type " + attributeTypeName + " cannot be used in OCL.");
        }
        if (Iterables.size(getMatchingOperations(attribute, resource)) > 0) {
            return Status.OK_STATUS;
        }
        ;
        return new Status(IStatus.ERROR, ReqcycleOCLPlugin.PLUGIN_ID, "Required operation : "
                + OCLUtilities.getOperationRequiredSignature(attribute) + " could not be found.");
    }

    /**
     * Gets operations that could be used to match uml elements to a data type. These operations
     * must have a specific name and signature (no parameter, return boolean).
     */
    public static Iterable<DefOperationCS> getMatchingOperations(final IRequirementType type,
            BaseResource resource) {
        Collection<DefOperationCS> operations = getOperations(resource);
        if (operations == null || Iterables.isEmpty(operations)) {
            return Collections.emptyList();
        }
        return Iterables.filter(operations, new Predicate<DefOperationCS>() {

            @Override
            public boolean apply(DefOperationCS arg0) {
                TypedRefCS operationReturnType = arg0.getOwnedType();
                if (!arg0.getParameters().isEmpty()) {
                    return false;
                }
                if (operationReturnType instanceof PrimitiveTypeRefCS) {
                    String returnType = ((PrimitiveTypeRefCS) operationReturnType).getName();
                    if (!"Boolean".equals(returnType)) { //$NON-NLS-1$
                        return false;
                    }
                }
                return arg0.getName().equalsIgnoreCase(getOperationRequiredName(type));
            }
        });
    }

    /**
     * Gets operations that could be used to match uml elements to a data type. These operations
     * must have a specific name and signature (no parameter, return boolean).
     */
    public static Iterable<DefOperationCS> getMatchingOperations(final IAttribute attribute,
            BaseResource resource) {
        Collection<DefOperationCS> operations = getOperations(resource);
        if (operations == null || Iterables.isEmpty(operations)) {
            return Collections.emptyList();
        }
        return Iterables.filter(operations, new Predicate<DefOperationCS>() {

            @Override
            public boolean apply(DefOperationCS arg0) {
                TypedRefCS operationReturnType = arg0.getOwnedType();
                if (!arg0.getParameters().isEmpty()) {
                    return false;
                }
                if (operationReturnType instanceof PrimitiveTypeRefCS) {
                    String returnType = ((PrimitiveTypeRefCS) operationReturnType).getName();
                    String attributeTypeName = attribute.getName();
                    String lookupResult = ecoreToOCLPrimitiveTypes.get(attributeTypeName);
                    if (lookupResult == null || !lookupResult.equals(returnType)) {
                        return false;
                    }
                }
                return arg0.getName().equalsIgnoreCase(getOperationRequiredName(attribute));
            }
        });
    }

    public static String getOperationRequiredName(IRequirementType type) {
        StringBuilder builder = new StringBuilder("is"); //$NON-NLS-1$
        String dataTypeName = type.getName();
        builder.append(Character.toUpperCase(dataTypeName.charAt(0))).append(dataTypeName.substring(1));
        return builder.toString();
    }

    public static String getOperationRequiredName(IAttribute attribute) {
        StringBuilder builder = new StringBuilder("get"); //$NON-NLS-1$
        String dataTypeName = attribute.getName();
        builder.append(Character.toUpperCase(dataTypeName.charAt(0))).append(dataTypeName.substring(1));
        return builder.toString();
    }

    public static String getOperationRequiredSignature(IRequirementType type) {
        return getOperationRequiredName(type) + "() : Boolean"; //$NON-NLS-1$
    }

    public static String getOperationRequiredSignature(IAttribute attribute) {
        String returnTypeName = attribute.getName();
        String lookupType = ecoreToOCLPrimitiveTypes.get(returnTypeName);
        return getOperationRequiredName(attribute) + "() : " + lookupType; //$NON-NLS-1$
    }

    public static boolean isDataType(OCLEvaluator evaluator, EObject eObject, IRequirementType type) {
        String operationName = OCLUtilities.getOperationRequiredName(type);
        EOperation eOperation = evaluator.getCompiledOperation(operationName, eObject);
        if (eOperation != null) {
            Object result = evaluator.evaluateOperation(eOperation, eObject, new Object[0]);
            if (result instanceof Boolean) {
                return (Boolean) result;
            }
        }
        return false;
    }

    public static Object getAttributeValue(OCLEvaluator evaluator, EObject eObject, IAttribute attribute) {
        String operationName = OCLUtilities.getOperationRequiredName(attribute);
        EOperation eOperation = evaluator.getCompiledOperation(operationName, eObject);
        if (eOperation != null) {
            Object result = evaluator.evaluateOperation(eOperation, eObject, new Object[0]);

            EDataType type = getDataType(attribute);

            if (type == null) {
                return null;
            }

            if (type.isInstance(result)) {
                return result;
            } else {
                Object converted = convertResult(result, attribute);
                if (type.isInstance(converted)) {
                    return converted;
                }
            }
        }
        return null;
    }

    private static EDataType getDataType(IAttribute attribute) {
        EDataType type = null;

        if (attribute instanceof IAdaptable) {
            type = (EDataType) ((IAdaptable) attribute).getAdapter(EDataType.class);
        }
        return type;
    }

    protected static Object convertResult(Object result, IAttribute attribute) {
        EDataType type = getDataType(attribute);

        if (type == null) {
            return null;
        }

        String instanceClass = type.getInstanceClassName();
        if ("float".equalsIgnoreCase(instanceClass) && result instanceof Double) { //$NON-NLS-1$
            return ((Double) result).floatValue();
        }
        return null;
    }

}