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

org.eclipse.ocl.util.OCLStandardLibraryUtil Maven / Gradle / Ivy

/**
 *  
 *
 * Copyright (c) 2006, 2009, 2011 IBM Corporation, Zeligsoft Inc., 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
 *   E.D.Willink - Refactoring to support extensibility and flexible error handling
 *       - Bug 259819
 *   Zeligsoft - Bug 244948
 *   Axel Uhl (SAP AG) - Bug 342644
 *   
 * 
 *
 * $Id: OCLStandardLibraryUtil.java,v 1.16 2011/05/01 10:56:50 auhl Exp $
 */
package org.eclipse.ocl.util;

import static org.eclipse.ocl.utilities.PredefinedType.*;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.SemanticException;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.expressions.TypeExp;
import org.eclipse.ocl.expressions.Variable;
import org.eclipse.ocl.internal.l10n.OCLMessages;
import org.eclipse.ocl.lpg.AbstractParser;
import org.eclipse.ocl.lpg.BasicEnvironment;
import org.eclipse.ocl.lpg.ProblemHandler;
import org.eclipse.ocl.lpg.StringProblemHandler;
import org.eclipse.ocl.options.ParsingOptions;
import org.eclipse.ocl.types.AnyType;
import org.eclipse.ocl.types.BagType;
import org.eclipse.ocl.types.CollectionType;
import org.eclipse.ocl.types.MessageType;
import org.eclipse.ocl.types.OCLStandardLibrary;
import org.eclipse.ocl.types.OrderedSetType;
import org.eclipse.ocl.types.PrimitiveType;
import org.eclipse.ocl.types.SequenceType;
import org.eclipse.ocl.types.SetType;
import org.eclipse.ocl.types.TypeType;
import org.eclipse.ocl.utilities.OCLFactory;
import org.eclipse.ocl.utilities.PredefinedType;
import org.eclipse.ocl.utilities.TypedElement;
import org.eclipse.ocl.utilities.UMLReflection;

/**
 * Convenience utilities for working with the types defined by the
 * {@linkplain OCLStandardLibrary OCL Standard Library}.
 * 

* See the {@link Environment} class for a description of the generic type * parameters of this class. *

* * @author Christian W. Damus (cdamus) */ public final class OCLStandardLibraryUtil { /** * The name of the tuple part carrying elements of the source collection in * a product operation. */ public static final String PRODUCT_FIRST = "first"; //$NON-NLS-1$ /** * The name of the tuple part carrying elements of the argument collection * in a product operation. */ public static final String PRODUCT_SECOND = "second"; //$NON-NLS-1$ private static final Map operationCodes = new java.util.HashMap(); private static final Map oclAnyOperationCodes = new java.util.HashMap(); static { operationCodes.put(PLUS_NAME, PLUS); operationCodes.put(MINUS_NAME, MINUS); operationCodes.put(TIMES_NAME, TIMES); operationCodes.put(DIVIDE_NAME, DIVIDE); operationCodes.put(AND_NAME, AND); operationCodes.put(NOT_NAME, NOT); operationCodes.put(OR_NAME, OR); operationCodes.put(IMPLIES_NAME, IMPLIES); operationCodes.put(ABS_NAME, ABS); operationCodes.put(DIV_NAME, DIV); operationCodes.put(MOD_NAME, MOD); operationCodes.put(MAX_NAME, MAX); operationCodes.put(MIN_NAME, MIN); operationCodes.put(SIZE_NAME, SIZE); operationCodes.put(CONCAT_NAME, CONCAT); operationCodes.put(SUBSTRING_NAME, SUBSTRING); operationCodes.put(TO_INTEGER_NAME, TO_INTEGER); operationCodes.put(TO_REAL_NAME, TO_REAL); operationCodes.put(XOR_NAME, XOR); operationCodes.put(FLOOR_NAME, FLOOR); operationCodes.put(ROUND_NAME, ROUND); operationCodes.put(TO_LOWER_NAME, TO_LOWER); operationCodes.put(TO_UPPER_NAME, TO_UPPER); operationCodes.put(ALL_INSTANCES_NAME, ALL_INSTANCES); operationCodes.put(EQUAL_NAME, EQUAL); operationCodes.put(NOT_EQUAL_NAME, NOT_EQUAL); operationCodes.put(OCL_AS_TYPE_NAME, OCL_AS_TYPE); operationCodes.put(OCL_IS_KIND_OF_NAME, OCL_IS_KIND_OF); operationCodes.put(OCL_IS_TYPE_OF_NAME, OCL_IS_TYPE_OF); operationCodes.put(OCL_IS_UNDEFINED_NAME, OCL_IS_UNDEFINED); operationCodes.put(OCL_IS_INVALID_NAME, OCL_IS_INVALID); operationCodes.put(LESS_THAN_NAME, LESS_THAN); operationCodes.put(GREATER_THAN_NAME, GREATER_THAN); operationCodes.put(LESS_THAN_EQUAL_NAME, LESS_THAN_EQUAL); operationCodes.put(GREATER_THAN_EQUAL_NAME, GREATER_THAN_EQUAL); operationCodes.put(OCL_IS_NEW_NAME, OCL_IS_NEW); operationCodes.put(OCL_IS_IN_STATE_NAME, OCL_IS_IN_STATE); operationCodes.put(HAS_RETURNED_NAME, HAS_RETURNED); operationCodes.put(RESULT_NAME, RESULT); operationCodes.put(IS_SIGNAL_SENT_NAME, IS_SIGNAL_SENT); operationCodes.put(IS_OPERATION_CALL_NAME, IS_OPERATION_CALL); operationCodes.put(COUNT_NAME, COUNT); operationCodes.put(EXCLUDES_NAME, EXCLUDES); operationCodes.put(EXCLUDES_ALL_NAME, EXCLUDES_ALL); operationCodes.put(INCLUDES_NAME, INCLUDES); operationCodes.put(INCLUDES_ALL_NAME, INCLUDES_ALL); operationCodes.put(IS_EMPTY_NAME, IS_EMPTY); operationCodes.put(NOT_EMPTY_NAME, NOT_EMPTY); operationCodes.put(PRODUCT_NAME, PRODUCT); operationCodes.put(SUM_NAME, SUM); operationCodes.put(AS_BAG_NAME, AS_BAG); operationCodes.put(AS_ORDERED_SET_NAME, AS_ORDERED_SET); operationCodes.put(AS_SEQUENCE_NAME, AS_SEQUENCE); operationCodes.put(AS_SET_NAME, AS_SET); operationCodes.put(EXCLUDING_NAME, EXCLUDING); operationCodes.put(FLATTEN_NAME, FLATTEN); operationCodes.put(INCLUDING_NAME, INCLUDING); operationCodes.put(INTERSECTION_NAME, INTERSECTION); operationCodes.put(UNION_NAME, UNION); operationCodes.put(AT_NAME, AT); operationCodes.put(FIRST_NAME, FIRST); operationCodes.put(INDEX_OF_NAME, INDEX_OF); operationCodes.put(INSERT_AT_NAME, INSERT_AT); operationCodes.put(LAST_NAME, LAST); operationCodes.put(PREPEND_NAME, PREPEND); operationCodes.put(SUB_SEQUENCE_NAME, SUB_SEQUENCE); operationCodes.put(APPEND_NAME, APPEND); operationCodes.put(SUB_ORDERED_SET_NAME, SUB_ORDERED_SET); operationCodes.put(SYMMETRIC_DIFFERENCE_NAME, SYMMETRIC_DIFFERENCE); operationCodes.put(EXISTS_NAME, EXISTS); operationCodes.put(FOR_ALL_NAME, FOR_ALL); operationCodes.put(IS_UNIQUE_NAME, IS_UNIQUE); operationCodes.put(ONE_NAME, ONE); operationCodes.put(ANY_NAME, ANY); operationCodes.put(COLLECT_NAME, COLLECT); operationCodes.put(COLLECT_NESTED_NAME, COLLECT_NESTED); operationCodes.put(CLOSURE_NAME, CLOSURE); operationCodes.put(SELECT_NAME, SELECT); operationCodes.put(REJECT_NAME, REJECT); operationCodes.put(SORTED_BY_NAME, SORTED_BY); oclAnyOperationCodes.put(EQUAL_NAME, EQUAL); oclAnyOperationCodes.put(NOT_EQUAL_NAME, NOT_EQUAL); oclAnyOperationCodes.put(OCL_AS_TYPE_NAME, OCL_AS_TYPE); oclAnyOperationCodes.put(OCL_IS_KIND_OF_NAME, OCL_IS_KIND_OF); oclAnyOperationCodes.put(OCL_IS_TYPE_OF_NAME, OCL_IS_TYPE_OF); oclAnyOperationCodes.put(OCL_IS_UNDEFINED_NAME, OCL_IS_UNDEFINED); oclAnyOperationCodes.put(OCL_IS_INVALID_NAME, OCL_IS_INVALID); oclAnyOperationCodes.put(LESS_THAN_NAME, LESS_THAN); oclAnyOperationCodes.put(GREATER_THAN_NAME, GREATER_THAN); oclAnyOperationCodes.put(LESS_THAN_EQUAL_NAME, LESS_THAN_EQUAL); oclAnyOperationCodes.put(GREATER_THAN_EQUAL_NAME, GREATER_THAN_EQUAL); oclAnyOperationCodes.put(OCL_IS_NEW_NAME, OCL_IS_NEW); oclAnyOperationCodes.put(OCL_IS_IN_STATE_NAME, OCL_IS_IN_STATE); } // not instantiable by clients private OCLStandardLibraryUtil() { super(); } /** * Obtains the numeric code of the specified pre-defined (by OCL) operaiton. * * @param operName * the operation name * @return the corresponding code (as defined by the {@link PredefinedType} * interface), or 0 if the operation name is not a * pre-defined operation * * @see #getOperationName(int) */ public static int getOperationCode(String operName) { Integer code = operationCodes.get(operName); return code == null ? 0 : code; } /** * Obtains the numeric code of the specified OclAny operaiton. * * @param operName * the operation name * @return the corresponding code (as defined by the {@link PredefinedType} * interface), or 0 if the operation name is not an * operation of the OclAny type */ public static int getOclAnyOperationCode(String operName) { Integer code = oclAnyOperationCodes.get(operName); return code == null ? 0 : code; } /** * Returns the operation name corresponding to the opcode. * * @param opcode * an operation code * @return the name corresponding to the opcode, or null if the * code is not one defined by the {@link PredefinedType} interface * * @see #getOperationCode(String) */ public static String getOperationName(int opcode) { switch (opcode) { case PLUS : return PLUS_NAME; case MINUS : return MINUS_NAME; case TIMES : return TIMES_NAME; case DIVIDE : return DIVIDE_NAME; case AND : return AND_NAME; case NOT : return NOT_NAME; case OR : return OR_NAME; case IMPLIES : return IMPLIES_NAME; case ABS : return ABS_NAME; case DIV : return DIV_NAME; case MOD : return MOD_NAME; case MAX : return MAX_NAME; case MIN : return MIN_NAME; case SIZE : return SIZE_NAME; case CONCAT : return CONCAT_NAME; case SUBSTRING : return SUBSTRING_NAME; case TO_INTEGER : return TO_INTEGER_NAME; case TO_REAL : return TO_REAL_NAME; case XOR : return XOR_NAME; case FLOOR : return FLOOR_NAME; case ROUND : return ROUND_NAME; case TO_LOWER : return TO_LOWER_NAME; case TO_UPPER : return TO_UPPER_NAME; case ALL_INSTANCES : return ALL_INSTANCES_NAME; case EQUAL : return EQUAL_NAME; case NOT_EQUAL : return NOT_EQUAL_NAME; case OCL_AS_TYPE : return OCL_AS_TYPE_NAME; case OCL_IS_KIND_OF : return OCL_IS_KIND_OF_NAME; case OCL_IS_TYPE_OF : return OCL_IS_TYPE_OF_NAME; case OCL_IS_UNDEFINED : return OCL_IS_UNDEFINED_NAME; case OCL_IS_INVALID : return OCL_IS_INVALID_NAME; case LESS_THAN : return LESS_THAN_NAME; case GREATER_THAN : return GREATER_THAN_NAME; case LESS_THAN_EQUAL : return LESS_THAN_EQUAL_NAME; case GREATER_THAN_EQUAL : return GREATER_THAN_EQUAL_NAME; case OCL_IS_NEW : return OCL_IS_NEW_NAME; case OCL_IS_IN_STATE : return OCL_IS_IN_STATE_NAME; case HAS_RETURNED : return HAS_RETURNED_NAME; case RESULT : return RESULT_NAME; case IS_SIGNAL_SENT : return IS_SIGNAL_SENT_NAME; case IS_OPERATION_CALL : return IS_OPERATION_CALL_NAME; case COUNT : return COUNT_NAME; case EXCLUDES : return EXCLUDES_NAME; case EXCLUDES_ALL : return EXCLUDES_ALL_NAME; case INCLUDES : return INCLUDES_NAME; case INCLUDES_ALL : return INCLUDES_ALL_NAME; case IS_EMPTY : return IS_EMPTY_NAME; case NOT_EMPTY : return NOT_EMPTY_NAME; case PRODUCT : return PRODUCT_NAME; case SUM : return SUM_NAME; case AS_BAG : return AS_BAG_NAME; case AS_ORDERED_SET : return AS_ORDERED_SET_NAME; case AS_SEQUENCE : return AS_SEQUENCE_NAME; case AS_SET : return AS_SET_NAME; case EXCLUDING : return EXCLUDING_NAME; case FLATTEN : return FLATTEN_NAME; case INCLUDING : return INCLUDING_NAME; case INTERSECTION : return INTERSECTION_NAME; case UNION : return UNION_NAME; case AT : return AT_NAME; case FIRST : return FIRST_NAME; case INDEX_OF : return INDEX_OF_NAME; case INSERT_AT : return INSERT_AT_NAME; case LAST : return LAST_NAME; case PREPEND : return PREPEND_NAME; case SUB_SEQUENCE : return SUB_SEQUENCE_NAME; case APPEND : return APPEND_NAME; case SUB_ORDERED_SET : return SUB_ORDERED_SET_NAME; case SYMMETRIC_DIFFERENCE : return SYMMETRIC_DIFFERENCE_NAME; case EXISTS : return EXISTS_NAME; case FOR_ALL : return FOR_ALL_NAME; case IS_UNIQUE : return IS_UNIQUE_NAME; case ONE : return ONE_NAME; case ANY : return ANY_NAME; case COLLECT : return COLLECT_NAME; case COLLECT_NESTED : return COLLECT_NESTED_NAME; case CLOSURE : return CLOSURE_NAME; case SELECT : return SELECT_NAME; case REJECT : return REJECT_NAME; case SORTED_BY : return SORTED_BY_NAME; default : return ""; //$NON-NLS-1$ } } /** * Obtains the result type of the specified operation from the OCL Standard * Library. Many of the OCL Standard Library operations are either generic * themselves or defined by generic types, so the return results depend on * the argument and source types. * * @param env * an OCL environment (indicating the metamodel binding) * @param sourceType * the type of the operation source (object on which the * operation is called) * @param opcode * the operation's code * @param args * the arguments of the operation call, as expressions or * variables * @return the result type of the corresponding operation * * @throws SemanticException * if any of the argument types does not correspond to the * source type and/or expected parameter types of the operation * * @see #getOperationCode(String) * * @deprecated Use the * {@link #getResultTypeOf(Object, Environment, Object, int, List)} * method, instead, which doesn't fail on the first problem */ @Deprecated public static C getResultTypeOf( Environment env, C sourceType, int opcode, List> args) throws SemanticException { StringProblemHandler handler = null; ProblemHandler oldHandler = null; BasicEnvironment benv = OCLUtil.getAdapter(env, BasicEnvironment.class); if (benv != null) { AbstractParser parser = benv.getParser(); oldHandler = benv.getProblemHandler(); handler = new StringProblemHandler(parser); benv.setProblemHandler(new ProblemHandlerWrapper.Tee(oldHandler, handler)); } try { C result = getResultTypeOf(null, env, sourceType, opcode, args); if (result == null) { String message = handler != null ? handler.getProblemString() : "No handler"; //$NON-NLS-1$ throw new SemanticException(message); } return result; } finally { if (benv != null) { benv.setProblemHandler(oldHandler); } } } /** * Obtains the result type of the specified operation from the OCL Standard * Library. Many of the OCL Standard Library operations are either generic * themselves or defined by generic types, so the return results depend on * the argument and source types. * * @param env * an OCL environment (indicating the metamodel binding) * @param sourceType * the type of the operation source (object on which the * operation is called) * @param opcode * the operation's code * @param args * the arguments of the operation call, as expressions or * variables * @return the result type of the corresponding operation, or null after * reporting a problem to env if any of the argument types do not * correspond to the source type and/or expected parameter types of * the operation * * @see #getOperationCode(String) */ public static C getResultTypeOf( Object problemObject, Environment env, C sourceType, int opcode, List> args) { if (sourceType instanceof PrimitiveType) { return getPrimitiveTypeResultTypeOf(problemObject, env, sourceType, opcode, args); } else if (sourceType instanceof CollectionType) { if (sourceType instanceof BagType) { @SuppressWarnings("unchecked") BagType bagType = (BagType) sourceType; return getBagTypeResultTypeOf(problemObject, env, bagType, opcode, args); } else if (sourceType instanceof SetType) { @SuppressWarnings("unchecked") SetType setType = (SetType) sourceType; return getSetTypeResultTypeOf(problemObject, env, setType, opcode, args); } else if (sourceType instanceof OrderedSetType) { @SuppressWarnings("unchecked") OrderedSetType orderedSetType = (OrderedSetType) sourceType; return getOrderedSetTypeResultTypeOf(problemObject, env, orderedSetType, opcode, args); } else if (sourceType instanceof SequenceType) { @SuppressWarnings("unchecked") SequenceType seqType = (SequenceType) sourceType; return getSequenceTypeResultTypeOf(problemObject, env, seqType, opcode, args); } @SuppressWarnings("unchecked") CollectionType collType = (CollectionType) sourceType; return getCollectionTypeResultTypeOf(problemObject, env, collType, opcode, args); } else if (sourceType instanceof TypeType) { @SuppressWarnings("unchecked") TypeType typeType = (TypeType) sourceType; return getTypeTypeResultTypeOf(problemObject, env, typeType, opcode, args); } else if (sourceType instanceof MessageType) { @SuppressWarnings("unchecked") MessageType messageType = (MessageType) sourceType; return getMessageTypeResultTypeOf(problemObject, env, messageType, opcode, args); } return getAnyTypeResultTypeOf(problemObject, env, sourceType, opcode, args); } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link AnyType}s. */ private static C getAnyTypeResultTypeOf( Object problemObject, Environment env, C sourceType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); TypedElement arg; C argType; switch (opcode) { case NOT_EQUAL : case EQUAL : /* * Performs a conformance test for primitives, EClass, EEnum, * TupleType */ arg = args.get(0); argType = arg.getType(); return stdlib.getBoolean(); case LESS_THAN : case GREATER_THAN : case LESS_THAN_EQUAL : case GREATER_THAN_EQUAL : arg = args.get(0); argType = arg.getType(); O oper = null; try { oper = TypeUtil.findOperationMatching(env, sourceType, getOperationName(opcode), args); if ((oper == null) && ParsingOptions.getValue(env, ParsingOptions.USE_COMPARE_TO_OPERATION)) { // source must either be a DataType that is Comparable, // or // else be a Elass, with an operation: // int compareTo(object) if (uml.isDataType(sourceType)) { if (uml.isComparable(sourceType)) { TypeUtil.checkMutuallyComparable(problemObject, env, sourceType, argType, opcode); // warn about non-standard Java-ism warning(env, OCLMessages.NonStd_CompareTo_, "getAnyTypeResultOf", problemObject); //$NON-NLS-1$ return stdlib.getBoolean(); } String message = OCLMessages.bind( OCLMessages.SourceEClass_ERROR_, getOperationName(opcode)); error(env, message, "anyTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } // Check that the type has a method named "compareTo" oper = TypeUtil.findOperationMatching(env, sourceType, "compareTo", //$NON-NLS-1$ args); if (oper != null) { // warn about non-standard Java-ism warning(env, OCLMessages.NonStd_CompareTo_, "getAnyTypeResultOf", problemObject); //$NON-NLS-1$ } } } catch (Exception e) { String message = OCLMessages.bind( OCLMessages.SourceOperationCompareTo_ERROR_, getOperationName(opcode)); error(env, message, "anyTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } if ((oper != null) && "compareTo".equals(uml.getName(oper)) //$NON-NLS-1$ && (TypeUtil.resolveType(env, uml.getOCLType(oper)) != stdlib .getInteger())) { String message = OCLMessages.ResultCompareToInt_ERROR_; error(env, message, "anyTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } return stdlib.getBoolean(); case OCL_IS_KIND_OF : case OCL_IS_TYPE_OF : case OCL_IS_NEW : case OCL_IS_IN_STATE : return stdlib.getBoolean(); case OCL_AS_TYPE : arg = args.get(0); if (arg instanceof TypeExp) { TypeExp typeExp = (TypeExp) arg; argType = typeExp.getReferredType(); } else { argType = arg.getType(); } if (sourceType instanceof CollectionType) { String message = OCLMessages.bind( OCLMessages.Noncomforming_ERROR_, uml .getName(sourceType), getOperationName(opcode)); error(env, message, "anyTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } // we can require neither a common supertype nor that type2 // and type1 have any conformance relationship whatsoever // because the run-time 'type' may conform to 'arg' // commonSuperType(argEType, type); // type1AsType2(type, argEType); return argType; case OCL_IS_UNDEFINED : case OCL_IS_INVALID : return stdlib.getBoolean(); } // unknown operation (shouldn't get here) return null; } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link PrimitiveType}s. */ private static C getPrimitiveTypeResultTypeOf( Object problemObject, Environment env, C sourceType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); C argType; switch (opcode) { case PLUS : case TIMES : argType = args.get(0).getType(); return TypeUtil.commonSuperType(problemObject, env, argType, sourceType); case DIVIDE : argType = args.get(0).getType(); // assert the relationship between the types TypeUtil.commonSuperType(problemObject, env, argType, sourceType); return stdlib.getReal(); case MINUS : // unary minus if (args == null || args.size() == 0) { return sourceType; } argType = args.get(0).getType(); return TypeUtil.commonSuperType(problemObject, env, argType, sourceType); case GREATER_THAN : case LESS_THAN : case GREATER_THAN_EQUAL : case LESS_THAN_EQUAL : case IMPLIES : case XOR : case NOT : case AND : case OR : return stdlib.getBoolean(); case MIN : case MAX : case ABS : case DIV : case MOD : case SUBSTRING : case CONCAT : return sourceType; case FLOOR : case TO_INTEGER : case SIZE : case ROUND : return stdlib.getInteger(); case TO_REAL : return stdlib.getReal(); case TO_LOWER : case TO_UPPER : return stdlib.getString(); } // must be an operation defined for all types, then return getAnyTypeResultTypeOf(problemObject, env, sourceType, opcode, args); } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link BagType}s. */ private static C getBagTypeResultTypeOf( Object problemObject, Environment env, BagType bagType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); OCLFactory oclFactory = env.getOCLFactory(); @SuppressWarnings("unchecked") C sourceType = (C) bagType; C argType; C argElementType; C elemType = bagType.getElementType(); switch (opcode) { case EQUAL : case NOT_EQUAL : return stdlib.getBoolean(); case UNION : argType = args.get(0).getType(); argElementType = getElementType(argType); return getBagType(env, oclFactory, TypeUtil.commonSuperType( problemObject, env, elemType, argElementType)); case INCLUDING : argType = args.get(0).getType(); return getBagType(env, oclFactory, TypeUtil.commonSuperType( problemObject, env, elemType, argType)); case INTERSECTION : argType = args.get(0).getType(); argElementType = getElementType(argType); if (argType instanceof SetType) { return getSetType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argElementType)); } else { return getBagType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argElementType)); } case EXCLUDING : return sourceType; case COUNT : return stdlib.getInteger(); case FLATTEN : if (!(elemType instanceof CollectionType)) { return sourceType; } return getBagType(env, oclFactory, CollectionUtil .getFlattenedElementType(bagType)); case AS_BAG : return sourceType; case AS_SEQUENCE : return getSequenceType(env, oclFactory, elemType); case AS_SET : return getSetType(env, oclFactory, elemType); case AS_ORDERED_SET : return getOrderedSetType(env, oclFactory, elemType); case SELECT : case REJECT : return sourceType; case SORTED_BY : return getSequenceType(env, oclFactory, elemType); case COLLECT_NESTED : return getBagType(env, oclFactory, stdlib.getT2()); } return getCollectionTypeResultTypeOf(problemObject, env, bagType, opcode, args); } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link SetType}s. */ private static C getSetTypeResultTypeOf( Object problemObject, Environment env, SetType setType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); OCLFactory oclFactory = env.getOCLFactory(); @SuppressWarnings("unchecked") C sourceType = (C) setType; C argType; C argElementType; C elemType = setType.getElementType(); C resultType; switch (opcode) { case EQUAL : case NOT_EQUAL : return stdlib.getBoolean(); case UNION : argType = args.get(0).getType(); argElementType = getElementType(argType); C newElementType = TypeUtil.commonSuperType(problemObject, env, elemType, argElementType); if (argType instanceof BagType) { resultType = getBagType(env, oclFactory, newElementType); } else { resultType = getSetType(env, oclFactory, newElementType); } return resultType; case MINUS : case SYMMETRIC_DIFFERENCE : argType = args.get(0).getType(); argElementType = getElementType(argType); resultType = getSetType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argElementType)); return resultType; case INCLUDING : argType = args.get(0).getType(); resultType = getSetType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argType)); return resultType; case INTERSECTION : argType = args.get(0).getType(); argElementType = getElementType(argType); resultType = getSetType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argElementType)); // both variants in both set and bag return the source type return sourceType; case EXCLUDING : return sourceType; case COUNT : return stdlib.getInteger(); case FLATTEN : if (!(elemType instanceof CollectionType)) { return sourceType; } resultType = getSetType(env, oclFactory, CollectionUtil .getFlattenedElementType(setType)); return resultType; case AS_BAG : return getBagType(env, oclFactory, elemType); case AS_SEQUENCE : return getSequenceType(env, oclFactory, elemType); case AS_SET : return sourceType; case AS_ORDERED_SET : return getOrderedSetType(env, oclFactory, elemType); case SELECT : case REJECT : return sourceType; case SORTED_BY : return getOrderedSetType(env, oclFactory, elemType); case COLLECT_NESTED : return getBagType(env, oclFactory, stdlib.getT2()); } return getCollectionTypeResultTypeOf(problemObject, env, setType, opcode, args); } private static C getElementType(C type) { if (type instanceof CollectionType) { @SuppressWarnings("unchecked") CollectionType castType = (CollectionType) type; return castType.getElementType(); } else { return null; } } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link OrderedSetType}s. */ private static C getOrderedSetTypeResultTypeOf( Object problemObject, Environment env, OrderedSetType orderedSetType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); OCLFactory oclFactory = env.getOCLFactory(); @SuppressWarnings("unchecked") C sourceType = (C) orderedSetType; C argType; C elemType = orderedSetType.getElementType(); switch (opcode) { case EQUAL : case NOT_EQUAL : return stdlib.getBoolean(); case INDEX_OF : return stdlib.getInteger(); case APPEND : case PREPEND : argType = args.get(0).getType(); return getOrderedSetType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argType)); case INSERT_AT : argType = args.get(1).getType(); // arg 0 is the index return getOrderedSetType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argType)); case SUB_ORDERED_SET : return sourceType; case AT : case FIRST : case LAST : return elemType; case AS_SET : return getSetType(env, oclFactory, elemType); case AS_BAG : return getBagType(env, oclFactory, elemType); case AS_SEQUENCE : return getSequenceType(env, oclFactory, elemType); } @SuppressWarnings("unchecked") SetType setType = (SetType) getSetType(env, oclFactory, elemType); return getSetTypeResultTypeOf(problemObject, env, setType, opcode, args); } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link SequenceType}s. */ private static C getSequenceTypeResultTypeOf( Object problemObject, Environment env, SequenceType seqType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); OCLFactory oclFactory = env.getOCLFactory(); @SuppressWarnings("unchecked") C sourceType = (C) seqType; C argType; C argElementType; C elemType = seqType.getElementType(); switch (opcode) { case COUNT : case INDEX_OF : return stdlib.getInteger(); case EQUAL : case NOT_EQUAL : return stdlib.getBoolean(); case UNION : argType = args.get(0).getType(); argElementType = getElementType(argType); return getSequenceType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argElementType)); case INCLUDING : case APPEND : case PREPEND : argType = args.get(0).getType(); return getSequenceType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argType)); case INSERT_AT : argType = args.get(1).getType(); // arg 0 is the index return getSequenceType(env, oclFactory, TypeUtil .commonSuperType(problemObject, env, elemType, argType)); case EXCLUDING : return sourceType; case FLATTEN : if (!(elemType instanceof CollectionType)) { return sourceType; } return getSequenceType(env, oclFactory, CollectionUtil .getFlattenedElementType(seqType)); case AT : case FIRST : case LAST : return elemType; case AS_BAG : return getBagType(env, oclFactory, elemType); case AS_SEQUENCE : case SUB_SEQUENCE : return sourceType; case AS_SET : return getSetType(env, oclFactory, elemType); case AS_ORDERED_SET : return getOrderedSetType(env, oclFactory, elemType); case SELECT : case REJECT : case SORTED_BY : return sourceType; case COLLECT_NESTED : return getSequenceType(env, oclFactory, stdlib.getT2()); } return getCollectionTypeResultTypeOf(problemObject, env, seqType, opcode, args); } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the general {@link CollectionType}s. */ private static C getCollectionTypeResultTypeOf( Object problemObject, Environment env, CollectionType collType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); C argType; switch (opcode) { case SIZE : case COUNT : return stdlib.getInteger(); case INCLUDES : case EXCLUDES : case INCLUDES_ALL : case EXCLUDES_ALL : case IS_EMPTY : case NOT_EMPTY : case EQUAL : case NOT_EQUAL : return stdlib.getBoolean(); case SUM : C type = collType.getElementType(); if (type != stdlib.getReal() && type != stdlib.getInteger()) { String message = OCLMessages.SumOperator_ERROR_; error(env, message, "collectionTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } return type; case PRODUCT : /* * The result type is: Set(Tuple(first:T, second:T2) where T is * the elementType of the source, and T2 is the elementType of * the argument. */ C t = collType.getElementType(); argType = args.get(0).getType(); C t2 = getElementType(argType); OCLFactory oclFactory = env.getOCLFactory(); return getSetType(env, oclFactory, getTupleType(env, oclFactory, createTupleParts(env, t, t2))); case EXISTS : case FOR_ALL : case IS_UNIQUE : case ONE : return stdlib.getBoolean(); case ANY : return collType.getElementType(); case COLLECT : return getCollectionType(env, env.getOCLFactory(), stdlib .getT2()); case CLOSURE : return getSetType(env, env.getOCLFactory(), stdlib.getT2()); } String message = OCLMessages.bind(OCLMessages.CollectionType_ERROR_, collType.getName(), getOperationName(opcode)); error(env, message, "collectionTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } private static EList> createTupleParts( Environment env, C firstType, C secondType) { EList> result = new BasicEList>(); UMLReflection uml = env .getUMLReflection(); OCLFactory oclFactory = env.getOCLFactory(); Variable var = oclFactory.createVariable(); uml.setName(var, PRODUCT_FIRST); uml.setType(var, firstType); result.add(var); var = oclFactory.createVariable(); uml.setName(var, PRODUCT_SECOND); uml.setType(var, secondType); result.add(var); return result; } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link TypeType}s. */ private static C getTypeTypeResultTypeOf( Object problemObject, Environment env, TypeType typeType, int opcode, List> args) { switch (opcode) { case ALL_INSTANCES : return getSetType(env, env.getOCLFactory(), typeType .getReferredType()); } @SuppressWarnings("unchecked") C sourceType = (C) typeType; return getAnyTypeResultTypeOf(problemObject, env, sourceType, opcode, args); } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link MessageType}s. */ private static C getMessageTypeResultTypeOf( Object problemObject, Environment env, MessageType messageType, int opcode, List> args) { OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); switch (opcode) { case HAS_RETURNED : case IS_SIGNAL_SENT : case IS_OPERATION_CALL : return stdlib.getBoolean(); case RESULT : return (messageType.getReferredOperation() == null) ? stdlib.getOclInvalid() : TypeUtil.resolveType(env, uml.getOCLType(messageType .getReferredOperation())); } @SuppressWarnings("unchecked") C sourceType = (C) messageType; return getAnyTypeResultTypeOf(problemObject, env, sourceType, opcode, args); } // // Factories of standard library operations // private static final int ANY_OPERATION_COUNT = 9; private static List createAnyOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUAL_NAME, stdlib.getOclAny(), "object")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), NOT_EQUAL_NAME, stdlib.getOclAny(), "object")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getT(), OCL_AS_TYPE_NAME, stdlib.getOclType(), "typespec")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), OCL_IS_KIND_OF_NAME, stdlib.getOclType(), "typespec"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), OCL_IS_TYPE_OF_NAME, stdlib.getOclType(), "typespec"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getBoolean(), OCL_IS_UNDEFINED_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), OCL_IS_INVALID_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), OCL_IS_NEW_NAME)); result.add(createBinaryOperation(uml, stdlib.getBoolean(), OCL_IS_IN_STATE_NAME, stdlib.getState(), "statespec")); //$NON-NLS-1$ return result; } /** * Utility method creating the operations of the OclAny type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the OclAny. * * @param env * an OCL environment * @return a list of new operations representing the standard * OclAny operations */ public static List createAnyTypeOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 4); result.addAll(createAnyOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_EQUAL_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_EQUAL_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ return result; } /** * Utility method creating the operations of the OclType type * of the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the OclType. * * @param env * an OCL environment * @return a list of new operations representing the standard * OclType operations */ public static List createTypeTypeOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 1); result.addAll(createAnyOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); result.add(createUnaryOperation(env.getUMLReflection(), stdlib.getSet(), ALL_INSTANCES_NAME)); return result; } /** * Utility method creating the operations of the OclMessage * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the OclMessage. * * @param env * an OCL environment * @return a list of new operations representing the standard * OclMessage operations */ public static List createMessageTypeOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 4); result.addAll(createAnyOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createUnaryOperation(uml, stdlib.getBoolean(), HAS_RETURNED_NAME)); result.add(createUnaryOperation(uml, stdlib.getT(), RESULT_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), IS_SIGNAL_SENT_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), IS_OPERATION_CALL_NAME)); return result; } /** * Utility method creating the operations of the String type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the String. * * @param env * an OCL environment * @return a list of new operations representing the standard * String operations */ public static List createStringOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 11); result.addAll(createAnyOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_EQUAL_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_EQUAL_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getInteger(), SIZE_NAME)); result.add(createBinaryOperation(uml, stdlib.getString(), CONCAT_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getString(), SUBSTRING_NAME, stdlib.getInteger(), "lower", stdlib.getInteger(), "upper"));//$NON-NLS-1$ //$NON-NLS-2$ result.add(createUnaryOperation(uml, stdlib.getInteger(), TO_INTEGER_NAME)); result.add(createUnaryOperation(uml, stdlib.getReal(), TO_REAL_NAME)); result .add(createUnaryOperation(uml, stdlib.getString(), TO_LOWER_NAME)); result .add(createUnaryOperation(uml, stdlib.getString(), TO_UPPER_NAME)); return result; } /** * Utility method creating the operations of the Real type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the Real. * * @param env * an OCL environment * @return a list of new operations representing the standard * Real operations */ public static List createRealOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 14); result.addAll(createAnyOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_EQUAL_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_EQUAL_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getReal(), PLUS_NAME, stdlib.getReal(), "r")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getReal(), MINUS_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getReal(), MINUS_NAME)); result.add(createBinaryOperation(uml, stdlib.getReal(), TIMES_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getReal(), DIVIDE_NAME, stdlib.getReal(), "r")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getReal(), MIN_NAME, stdlib.getReal(), "r"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getReal(), MAX_NAME, stdlib.getReal(), "r")); //$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getReal(), ABS_NAME)); result.add(createUnaryOperation(uml, stdlib.getInteger(), FLOOR_NAME)); result.add(createUnaryOperation(uml, stdlib.getInteger(), ROUND_NAME)); return result; } /** * Utility method creating the operations of the Integer type * of the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the Integer. * * @param env * an OCL environment * @return a list of new operations representing the standard * Integer operations */ public static List createIntegerOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 20); result.addAll(createRealOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_NAME, stdlib.getInteger(), "i"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_NAME, stdlib.getInteger(), "i"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_EQUAL_NAME, stdlib.getInteger(), "i"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_EQUAL_NAME, stdlib.getInteger(), "i"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), DIV_NAME, stdlib.getInteger(), "i")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), MOD_NAME, stdlib.getInteger(), "i")); //$NON-NLS-1$ return result; } /** * Utility method creating the operations of the * UnlimitedNatural type of the OCL Standard library. This is * useful for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the Integer. * * @param env * an OCL environment * @return a list of new operations representing the standard * UnlimitedNatural operations */ public static List createUnlimitedNaturalOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 20); result.addAll(createRealOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_NAME, stdlib.getUnlimitedNatural(), "n"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_NAME, stdlib.getUnlimitedNatural(), "n"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), LESS_THAN_EQUAL_NAME, stdlib.getUnlimitedNatural(), "n"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), GREATER_THAN_EQUAL_NAME, stdlib.getUnlimitedNatural(), "n"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), DIV_NAME, stdlib.getUnlimitedNatural(), "n")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), MOD_NAME, stdlib.getUnlimitedNatural(), "n")); //$NON-NLS-1$ return result; } /** * Utility method creating the operations of the Boolean type * of the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the Boolean. * * @param env * an OCL environment * @return a list of new operations representing the standard * Boolean operations */ public static List createBooleanOperations( Environment env) { List result = new java.util.ArrayList(ANY_OPERATION_COUNT + 5); result.addAll(createAnyOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createUnaryOperation(uml, stdlib.getBoolean(), NOT_NAME)); result.add(createBinaryOperation(uml, stdlib.getBoolean(), AND_NAME, stdlib.getBoolean(), "b")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), OR_NAME, stdlib.getBoolean(), "b")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), IMPLIES_NAME, stdlib.getBoolean(), "b"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), XOR_NAME, stdlib.getBoolean(), "b"));//$NON-NLS-1$ return result; } private static final int COLLECTION_OPERATION_COUNT = 10; /** * Utility method creating the operations of the Collection(T) * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the Collection(T). * * @param env * an OCL environment * @return a list of new operations representing the standard * Collection(T) operations */ public static List createCollectionOperations( Environment env) { List result = new java.util.ArrayList(COLLECTION_OPERATION_COUNT); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUAL_NAME, stdlib.getCollection(), "c"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), NOT_EQUAL_NAME, stdlib.getCollection(), "c"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), COUNT_NAME, stdlib.getT(), "object")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), EXCLUDES_NAME, stdlib.getT(), "object")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), EXCLUDES_ALL_NAME, stdlib.getCollection(), "c2"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), INCLUDES_NAME, stdlib.getT(), "object")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), INCLUDES_ALL_NAME, stdlib.getCollection(), "c2"));//$NON-NLS-1$ result .add(createUnaryOperation(uml, stdlib.getBoolean(), IS_EMPTY_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), NOT_EMPTY_NAME)); OCLFactory oclFactory = env.getOCLFactory(); C resultType = getSetType(env, oclFactory, getTupleType(env, oclFactory, createTupleParts(env, stdlib.getT(), stdlib.getT2()))); result.add(createBinaryOperation(uml, resultType, PRODUCT_NAME, getCollectionType(env, oclFactory, stdlib.getT2()), "c2"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getReal(), SUM_NAME)); result.add(createUnaryOperation(uml, stdlib.getInteger(), SIZE_NAME)); return result; } private static final int SET_OPERATION_COUNT = COLLECTION_OPERATION_COUNT + 15; /** * Utility method creating the operations of the Set(T) type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the Set(T). * * @param env * an OCL environment * @return a list of new operations representing the standard * Set(T) operations */ public static List createSetOperations( Environment env) { List result = new java.util.ArrayList(SET_OPERATION_COUNT); result.addAll(createCollectionOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUAL_NAME, stdlib.getSet(), "set"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), NOT_EQUAL_NAME, stdlib.getSet(), "set")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), UNION_NAME, stdlib.getBag(), "bag")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), UNION_NAME, stdlib.getSet(), "set"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), MINUS_NAME, stdlib.getSet(), "set"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), INTERSECTION_NAME, stdlib.getBag(), "bag"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), INTERSECTION_NAME, stdlib.getSet(), "set"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), INCLUDING_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), EXCLUDING_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), SYMMETRIC_DIFFERENCE_NAME, stdlib.getSet(), "s"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, getSetType(env, env .getOCLFactory(), stdlib.getT2()), FLATTEN_NAME)); result.add(createUnaryOperation(uml, stdlib.getBag(), AS_BAG_NAME)); result.add(createUnaryOperation(uml, stdlib.getSet(), AS_SET_NAME)); result.add(createUnaryOperation(uml, stdlib.getSequence(), AS_SEQUENCE_NAME)); result.add(createUnaryOperation(uml, stdlib.getOrderedSet(), AS_ORDERED_SET_NAME)); return result; } /** * Utility method creating the operations of the OrderedSet(T) * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the OrderedSet(T). * * @param env * an OCL environment * @return a list of new operations representing the standard * OrderedSet(T) operations */ public static List createOrderedSetOperations( Environment env) { List result = new java.util.ArrayList(SET_OPERATION_COUNT + 10); result.addAll(createSetOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUAL_NAME, stdlib.getOrderedSet(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), NOT_EQUAL_NAME, stdlib.getOrderedSet(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getOrderedSet(), APPEND_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getT(), AT_NAME, stdlib .getInteger(), "index"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), INDEX_OF_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getOrderedSet(), INSERT_AT_NAME, stdlib.getInteger(), "index", //$NON-NLS-1$ stdlib.getT(), "object")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getOrderedSet(), PREPEND_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getOrderedSet(), SUB_ORDERED_SET_NAME, stdlib.getInteger(), "lower", //$NON-NLS-1$ stdlib.getInteger(), "upper"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getT(), FIRST_NAME)); result.add(createUnaryOperation(uml, stdlib.getT(), LAST_NAME)); return result; } /** * Utility method creating the operations of the Bag(T) type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the Bag(T). * * @param env * an OCL environment * @return a list of new operations representing the standard * Bag(T) operations */ public static List createBagOperations( Environment env) { List result = new java.util.ArrayList( COLLECTION_OPERATION_COUNT + 13); result.addAll(createCollectionOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUAL_NAME, stdlib.getBag(), "bag"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), NOT_EQUAL_NAME, stdlib.getBag(), "bag")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), UNION_NAME, stdlib.getBag(), "bag")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), UNION_NAME, stdlib.getSet(), "set"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), INTERSECTION_NAME, stdlib.getBag(), "bag"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), INTERSECTION_NAME, stdlib.getSet(), "set"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), INCLUDING_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), EXCLUDING_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, getBagType(env, env .getOCLFactory(), stdlib.getT2()), FLATTEN_NAME)); result.add(createUnaryOperation(uml, stdlib.getBag(), AS_BAG_NAME)); result.add(createUnaryOperation(uml, stdlib.getSet(), AS_SET_NAME)); result.add(createUnaryOperation(uml, stdlib.getSequence(), AS_SEQUENCE_NAME)); result.add(createUnaryOperation(uml, stdlib.getOrderedSet(), AS_ORDERED_SET_NAME)); return result; } /** * Utility method creating the operations of the Sequence(T) * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the Sequence(T). * * @param env * an OCL environment * @return a list of new operations representing the standard * Sequence(T) operations */ public static List createSequenceOperations( Environment env) { List result = new java.util.ArrayList( COLLECTION_OPERATION_COUNT + 18); result.addAll(createCollectionOperations(env)); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUAL_NAME, stdlib.getSequence(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), NOT_EQUAL_NAME, stdlib.getSequence(), "s")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSequence(), UNION_NAME, stdlib.getSequence(), "s")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), APPEND_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), PREPEND_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getBoolean(), INSERT_AT_NAME, stdlib.getInteger(), "index", //$NON-NLS-1$ stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getBoolean(), SUB_SEQUENCE_NAME, stdlib.getInteger(), "lower", //$NON-NLS-1$ stdlib.getInteger(), "upper"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getT(), AT_NAME, stdlib .getInteger(), "index")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), INDEX_OF_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), INCLUDING_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), EXCLUDING_NAME, stdlib.getT(), "object"));//$NON-NLS-1$ result.add(createUnaryOperation(uml, stdlib.getT(), FIRST_NAME)); result.add(createUnaryOperation(uml, stdlib.getT(), LAST_NAME)); result.add(createUnaryOperation(uml, getSequenceType(env, env .getOCLFactory(), stdlib.getT2()), FLATTEN_NAME)); result.add(createUnaryOperation(uml, stdlib.getBag(), AS_BAG_NAME)); result.add(createUnaryOperation(uml, stdlib.getSet(), AS_SET_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), AS_SEQUENCE_NAME)); result.add(createUnaryOperation(uml, stdlib.getOrderedSet(), AS_ORDERED_SET_NAME)); return result; } private static final int COLLECTION_ITERATOR_COUNT = 7; /** * Utility method creating the pre-defined iterators of the * Collection(T) type of the OCL Standard library. This is * useful for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the Collection(T). * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the Collection(T) type */ public static List createCollectionIterators( Environment env) { List result = new java.util.ArrayList(COLLECTION_ITERATOR_COUNT); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBoolean(), EXISTS_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), FOR_ALL_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), IS_UNIQUE_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), ONE_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getT(), ANY_NAME, stdlib .getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, getCollectionType(env, env .getOCLFactory(), stdlib.getT2()), COLLECT_NAME, stdlib .getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, getSetType(env, env .getOCLFactory(), stdlib.getT2()), CLOSURE_NAME, stdlib .getOclExpression(), "expr")); //$NON-NLS-1$ return result; } private static final int SET_ITERATOR_COUNT = COLLECTION_ITERATOR_COUNT + 4; /** * Utility method creating the pre-defined iterators of the * Set(T) type of the OCL Standard library. This is useful for * implementors of metamodel bindings ({@link Environment}s) to initialize * their implementations of the Set(T). * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the Set(T) type */ public static List createSetIterators( Environment env) { List result = new java.util.ArrayList(SET_ITERATOR_COUNT); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); result.addAll(createCollectionIterators(env)); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getSet(), SELECT_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSet(), REJECT_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getOrderedSet(), SORTED_BY_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, getBagType(env, env .getOCLFactory(), stdlib.getT2()), COLLECT_NESTED_NAME, stdlib .getOclExpression(), "expr")); //$NON-NLS-1$ return result; } /** * Utility method creating the pre-defined iterators of the * OrderedSet(T) type of the OCL Standard library. This is * useful for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the OrderedSet(T). * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the OrderedSet(T) type */ public static List createOrderedSetIterators( Environment env) { List result = new java.util.ArrayList(SET_ITERATOR_COUNT); result.addAll(createSetIterators(env)); return result; } /** * Utility method creating the pre-defined iterators of the * Bag(T) type of the OCL Standard library. This is useful for * implementors of metamodel bindings ({@link Environment}s) to initialize * their implementations of the Bag(T). * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the Bag(T) type */ public static List createBagIterators( Environment env) { List result = new java.util.ArrayList( COLLECTION_ITERATOR_COUNT + 4); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); result.addAll(createCollectionIterators(env)); UMLReflection uml = env .getUMLReflection(); result.add(createBinaryOperation(uml, stdlib.getBag(), SELECT_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBag(), REJECT_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSequence(), SORTED_BY_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, getBagType(env, env .getOCLFactory(), stdlib.getT2()), COLLECT_NESTED_NAME, stdlib .getOclExpression(), "expr")); //$NON-NLS-1$ return result; } /** * Utility method creating the pre-defined iterators of the * Sequence(T) type of the OCL Standard library. This is useful * for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the Sequence(T). * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the Sequence(T) type */ public static List createSequenceIterators( Environment env) { List result = new java.util.ArrayList( COLLECTION_ITERATOR_COUNT + 4); OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); UMLReflection uml = env .getUMLReflection(); result.addAll(createCollectionIterators(env)); result.add(createBinaryOperation(uml, stdlib.getSequence(), SELECT_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSequence(), REJECT_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getSequence(), SORTED_BY_NAME, stdlib.getOclExpression(), "expr")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, getSequenceType(env, env .getOCLFactory(), stdlib.getT2()), COLLECT_NESTED_NAME, stdlib .getOclExpression(), "expr")); //$NON-NLS-1$ return result; } private static O createUnaryOperation( UMLReflection uml, C resultType, String name) { List paramNames = Collections.emptyList(); List paramTypes = Collections.emptyList(); return uml.createOperation(name, resultType, paramNames, paramTypes); } private static O createBinaryOperation( UMLReflection uml, C resultType, String name, C paramType, String paramName) { List paramNames = Collections.singletonList(paramName); List paramTypes = Collections.singletonList(paramType); return uml.createOperation(name, resultType, paramNames, paramTypes); } private static O createTernaryOperation( UMLReflection uml, C resultType, String name, C param1Type, String param1Name, C param2Type, String param2Name) { List paramNames = new java.util.ArrayList(2); List paramTypes = new java.util.ArrayList(2); paramNames.add(param1Name); paramTypes.add(param1Type); paramNames.add(param2Name); paramTypes.add(param2Type); return uml.createOperation(name, resultType, paramNames, paramTypes); } @SuppressWarnings("unchecked") private static C getBagType( Environment env, OCLFactory factory, C elementType) { return TypeUtil .resolveType(env, (C) factory.createBagType(elementType)); } @SuppressWarnings("unchecked") private static C getSetType( Environment env, OCLFactory factory, C elementType) { return TypeUtil .resolveType(env, (C) factory.createSetType(elementType)); } @SuppressWarnings("unchecked") private static C getOrderedSetType( Environment env, OCLFactory factory, C elementType) { return TypeUtil.resolveType(env, (C) factory .createOrderedSetType(elementType)); } @SuppressWarnings("unchecked") private static C getSequenceType( Environment env, OCLFactory factory, C elementType) { return TypeUtil.resolveType(env, (C) factory .createSequenceType(elementType)); } @SuppressWarnings("unchecked") private static C getCollectionType( Environment env, OCLFactory factory, C elementType) { return TypeUtil.resolveType(env, (C) factory .createCollectionType(elementType)); } @SuppressWarnings("unchecked") private static C getTupleType( Environment env, OCLFactory factory, List> parts) { return TypeUtil.resolveType(env, (C) factory.createTupleType(parts)); } /** * Convenience method invoking * getProblemHandler().utilityProblem with an error severity. * * @param problemMessage * message describing the problem * @param problemContext * optional message describing the reporting context * @param problemObject * optional object associated with the problem */ private static void error( Environment env, String problemMessage, String problemContext, Object problemObject) { OCLUtil.getAdapter(env, BasicEnvironment.class).utilityError( problemMessage, problemContext, problemObject); } /** * Convenience method invoking * getProblemHandler().utilityProblem with a warning severity. * * @param problemMessage * message describing the problem * @param problemContext * optional message describing the reporting context * @param problemObject * optional object associated with the problem */ private static void warning( Environment env, String problemMessage, String problemContext, Object problemObject) { BasicEnvironment benv = OCLUtil.getAdapter(env, BasicEnvironment.class); if (benv != null) { CSTNode cstNode = benv.getASTMapping(problemObject); int startOffset = (cstNode != null) ? cstNode.getStartOffset() : -1; int endOffset = (cstNode != null) ? cstNode.getEndOffset() : -1; benv.getProblemHandler().utilityProblem( ProblemHandler.Severity.WARNING, problemMessage, problemContext, startOffset, endOffset); } } /** * Queries all of the supertypes of a pre-defined type. Note that this is * only useful for operations on the OCL standard library types themselves, * especially in the case of generic types such as the collection types, * OclMessage, and the like. Thus, it helps to find inherited * operations and attributes, etc., but not actual type conformance. For * example, {@literal Set} is not returned as a supertype of * {@literal Set}. Rather, only * {@literal Collection} is. This method also does not handle * the void and invalid types. * * @param env * the contextual environment * @param type * an OCL re-defined type * @return an unmodifiable collection of the supertypes, which may be empty * in some cases * * @since 1.3 */ @SuppressWarnings("unchecked") public static Collection getAllSupertypes( Environment env, PredefinedType type) { Collection result; OCLStandardLibrary stdlib = env.getOCLStandardLibrary(); if (type instanceof CollectionType) { CollectionType collType = (CollectionType) type; switch (collType.getKind()) { case ORDERED_SET_LITERAL : result = Arrays.asList(stdlib.getSet(), stdlib .getCollection()); break; case COLLECTION_LITERAL : result = Collections.emptySet(); break; default : result = Collections.singleton(stdlib.getCollection()); break; } } else if (type == stdlib.getInteger()) { result = Arrays.asList(stdlib.getReal(), stdlib.getOclAny()); } else if (type instanceof AnyType) { result = Collections.emptySet(); } else { result = Collections.singleton(stdlib.getOclAny()); } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy