/******************************************************************************* * Copyright (c) 2006, 2014, 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 *******************************************************************************/ 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}. * <p> * See the {@link Environment} class for a description of the generic type * parameters of this class. * </p> * * @author Christian W. Damus (cdamus) */ public final class OCLStandardLibraryUtil { /** * The name of the tuple part carrying elements of the source collection in * a <tt>product</tt> 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 <tt>product</tt> operation. */ public static final String PRODUCT_SECOND = "second"; //$NON-NLS-1$ private static final Map<String, Integer> operationCodes = new java.util.HashMap<String, Integer>(); private static final Map<String, Integer> oclAnyOperationCodes = new java.util.HashMap<String, Integer>(); 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); operationCodes.put(TO_BOOLEAN_NAME, TO_BOOLEAN); operationCodes.put(TO_STRING_NAME, TO_STRING); operationCodes.put(CHARACTERS_NAME, CHARACTERS); operationCodes.put(ENDS_WITH_NAME, ENDS_WITH); operationCodes.put(EQUALS_IGNORE_CASE_NAME, EQUALS_IGNORE_CASE); operationCodes.put(LAST_INDEX_OF_NAME, LAST_INDEX_OF); operationCodes.put(MATCHES_NAME, MATCHES); operationCodes.put(REPLACE_ALL_NAME, REPLACE_ALL); operationCodes.put(REPLACE_FIRST_NAME, REPLACE_FIRST); operationCodes.put(STARTS_WITH_NAME, STARTS_WITH); operationCodes.put(SUBSTITUTE_ALL_NAME, SUBSTITUTE_ALL); operationCodes.put(SUBSTITUTE_FIRST_NAME, SUBSTITUTE_FIRST); operationCodes.put(TOKENIZE_NAME, TOKENIZE); operationCodes.put(TRIM_NAME, TRIM); operationCodes.put(TO_LOWER_CASE_NAME, TO_LOWER_CASE); operationCodes.put(TO_UPPER_CASE_NAME, TO_UPPER_CASE); operationCodes.put(SELECT_BY_KIND_NAME, SELECT_BY_KIND); operationCodes.put(SELECT_BY_TYPE_NAME, SELECT_BY_TYPE); operationCodes.put(OCL_AS_SET_NAME, OCL_AS_SET); 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); oclAnyOperationCodes.put(TO_STRING_NAME, TO_STRING); oclAnyOperationCodes.put(OCL_AS_SET_NAME, OCL_AS_SET); } // 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 <code>0</code> 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 <tt>OclAny</tt> operaiton. * * @param operName * the operation name * @return the corresponding code (as defined by the {@link PredefinedType} * interface), or <code>0</code> if the operation name is not an * operation of the <tt>OclAny</tt> 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 <code>null</code> 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; case TO_BOOLEAN : return TO_BOOLEAN_NAME; case TO_STRING : return TO_STRING_NAME; case CHARACTERS : return CHARACTERS_NAME; case ENDS_WITH : return ENDS_WITH_NAME; case EQUALS_IGNORE_CASE : return EQUALS_IGNORE_CASE_NAME; case LAST_INDEX_OF : return LAST_INDEX_OF_NAME; case MATCHES : return MATCHES_NAME; case REPLACE_ALL : return REPLACE_ALL_NAME; case REPLACE_FIRST : return REPLACE_FIRST_NAME; case STARTS_WITH : return STARTS_WITH_NAME; case SUBSTITUTE_ALL : return SUBSTITUTE_ALL_NAME; case SUBSTITUTE_FIRST : return SUBSTITUTE_FIRST_NAME; case TOKENIZE : return TOKENIZE_NAME; case TRIM : return TRIM_NAME; case TO_LOWER_CASE : return TO_LOWER_CASE_NAME; case TO_UPPER_CASE : return TO_UPPER_CASE_NAME; case SELECT_BY_KIND : return SELECT_BY_KIND_NAME; case SELECT_BY_TYPE : return SELECT_BY_TYPE_NAME; case OCL_AS_SET : return OCL_AS_SET_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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getResultTypeOf( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, C sourceType, int opcode, List<? extends TypedElement<C>> 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, C sourceType, int opcode, List<? extends TypedElement<C>> args) { if (sourceType instanceof PrimitiveType<?>) { return getPrimitiveTypeResultTypeOf(problemObject, env, sourceType, opcode, args); } else if (sourceType instanceof CollectionType<?, ?>) { if (sourceType instanceof BagType<?, ?>) { @SuppressWarnings("unchecked") BagType<C, O> bagType = (BagType<C, O>) sourceType; return getBagTypeResultTypeOf(problemObject, env, bagType, opcode, args); } else if (sourceType instanceof SetType<?, ?>) { @SuppressWarnings("unchecked") SetType<C, O> setType = (SetType<C, O>) sourceType; return getSetTypeResultTypeOf(problemObject, env, setType, opcode, args); } else if (sourceType instanceof OrderedSetType<?, ?>) { @SuppressWarnings("unchecked") OrderedSetType<C, O> orderedSetType = (OrderedSetType<C, O>) sourceType; return getOrderedSetTypeResultTypeOf(problemObject, env, orderedSetType, opcode, args); } else if (sourceType instanceof SequenceType<?, ?>) { @SuppressWarnings("unchecked") SequenceType<C, O> seqType = (SequenceType<C, O>) sourceType; return getSequenceTypeResultTypeOf(problemObject, env, seqType, opcode, args); } @SuppressWarnings("unchecked") CollectionType<C, O> collType = (CollectionType<C, O>) sourceType; return getCollectionTypeResultTypeOf(problemObject, env, collType, opcode, args); } else if (sourceType instanceof TypeType<?, ?>) { @SuppressWarnings("unchecked") TypeType<C, O> typeType = (TypeType<C, O>) sourceType; return getTypeTypeResultTypeOf(problemObject, env, typeType, opcode, args); } else if (sourceType instanceof MessageType<?, ?, ?>) { @SuppressWarnings("unchecked") MessageType<C, O, P> messageType = (MessageType<C, O, P>) 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getAnyTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, C sourceType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> uml = env .getUMLReflection(); TypedElement<C> 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<C> typeExp = (TypeExp<C>) 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(); case OCL_AS_SET : return getSetType(env, env.getOCLFactory(), sourceType); } // 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getPrimitiveTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, C sourceType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> 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 : case ENDS_WITH : case EQUALS_IGNORE_CASE : case MATCHES : case STARTS_WITH : case TO_BOOLEAN : 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 : case INDEX_OF : case LAST_INDEX_OF : return stdlib.getInteger(); case TO_REAL : return stdlib.getReal(); case AT : case REPLACE_ALL : case REPLACE_FIRST : case SUBSTITUTE_ALL : case SUBSTITUTE_FIRST : case TO_LOWER : case TO_LOWER_CASE : case TO_STRING : case TO_UPPER : case TO_UPPER_CASE : case TRIM : return stdlib.getString(); case CHARACTERS : case TOKENIZE : return getSequenceType(env, env.getOCLFactory(), 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getBagTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, BagType<C, O> bagType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> 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 SELECT_BY_KIND : case SELECT_BY_TYPE : TypedElement<C> arg = args.get(0); if (arg instanceof TypeExp<?>) { TypeExp<C> typeExp = (TypeExp<C>) arg; argType = typeExp.getReferredType(); } else { argType = arg.getType(); } return getBagType(env, env.getOCLFactory(), argType); 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getSetTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, SetType<C, O> setType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> 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 SELECT_BY_KIND : case SELECT_BY_TYPE : TypedElement<C> arg = args.get(0); if (arg instanceof TypeExp<?>) { TypeExp<C> typeExp = (TypeExp<C>) arg; argType = typeExp.getReferredType(); } else { argType = arg.getType(); } return getSetType(env, env.getOCLFactory(), argType); 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, O> C getElementType(C type) { if (type instanceof CollectionType<?, ?>) { @SuppressWarnings("unchecked") CollectionType<C, ?> castType = (CollectionType<C, ?>) type; return castType.getElementType(); } else { return null; } } /** * Helper for the {@link #getResultTypeOf(Environment, Object, int, List)} * dealing with the {@link OrderedSetType}s. */ private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getOrderedSetTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OrderedSetType<C, O> orderedSetType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> 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 SELECT_BY_KIND : case SELECT_BY_TYPE : TypedElement<C> arg = args.get(0); if (arg instanceof TypeExp<?>) { TypeExp<C> typeExp = (TypeExp<C>) arg; argType = typeExp.getReferredType(); } else { argType = arg.getType(); } return getOrderedSetType(env, env.getOCLFactory(), argType); 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<C, O> setType = (SetType<C, O>) 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getSequenceTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, SequenceType<C, O> seqType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> 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 SELECT_BY_KIND : case SELECT_BY_TYPE : TypedElement<C> arg = args.get(0); if (arg instanceof TypeExp<?>) { TypeExp<C> typeExp = (TypeExp<C>) arg; argType = typeExp.getReferredType(); } else { argType = arg.getType(); } return getSequenceType(env, env.getOCLFactory(), argType); 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getCollectionTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, CollectionType<C, O> collType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> 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 : case OCL_IS_UNDEFINED : case OCL_IS_INVALID : return stdlib.getBoolean(); case MAX : { C type = collType.getElementType(); if (type != stdlib.getReal() && type != stdlib.getInteger()) { String message = OCLMessages.MaxOperator_ERROR_; error(env, message, "collectionTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } return type; } case MIN : { C type = collType.getElementType(); if (type != stdlib.getReal() && type != stdlib.getInteger()) { String message = OCLMessages.MinOperator_ERROR_; error(env, message, "collectionTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } return type; } case SUM : { C type = collType.getElementType(); if (type != stdlib.getReal() && type != stdlib.getInteger() && type != stdlib.getUnlimitedNatural()) { 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()); case SELECT_BY_KIND : case SELECT_BY_TYPE : TypedElement<C> arg = args.get(0); if (arg instanceof TypeExp<?>) { TypeExp<C> typeExp = (TypeExp<C>) arg; argType = typeExp.getReferredType(); } else { argType = arg.getType(); } return getCollectionType(env, env.getOCLFactory(), argType); case OCL_AS_SET : @SuppressWarnings("unchecked") C collType2 = (C)collType; return getSetType(env, env.getOCLFactory(), collType2); } String message = OCLMessages.bind(OCLMessages.CollectionType_ERROR_, collType.getName(), getOperationName(opcode)); error(env, message, "collectionTypeResultTypeOf", problemObject); //$NON-NLS-1$ return null; } private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> EList<Variable<C, PM>> createTupleParts( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, C firstType, C secondType) { EList<Variable<C, PM>> result = new BasicEList<Variable<C, PM>>(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> uml = env .getUMLReflection(); OCLFactory oclFactory = env.getOCLFactory(); Variable<C, PM> 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getTypeTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, TypeType<C, O> typeType, int opcode, List<? extends TypedElement<C>> 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getMessageTypeResultTypeOf( Object problemObject, Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, MessageType<C, O, P> messageType, int opcode, List<? extends TypedElement<C>> args) { OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createAnyOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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$ result.add(createUnaryOperation(uml, stdlib.getString(), TO_STRING_NAME)); OCLFactory oclFactory = env.getOCLFactory(); result.add(createUnaryOperation(uml, getSetType(env, oclFactory, stdlib.getT()), OCL_AS_SET_NAME)); return result; } /** * Utility method creating the operations of the <code>OclAny</code> type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>OclAny</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>OclAny</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createAnyTypeOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 4); result.addAll(createAnyOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>OclType</code> type * of the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>OclType</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>OclType</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createTypeTypeOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 1); result.addAll(createAnyOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); result.add(createUnaryOperation(env.getUMLReflection(), stdlib.getSet(), ALL_INSTANCES_NAME)); return result; } /** * Utility method creating the operations of the <code>OclMessage</code> * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the <code>OclMessage</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>OclMessage</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createMessageTypeOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 4); result.addAll(createAnyOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>String</code> type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>String</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>String</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createStringOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 11); result.addAll(createAnyOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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)); result.add(createBinaryOperation(uml, stdlib.getString(), PLUS_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result .add(createUnaryOperation(uml, stdlib.getString(), TO_LOWER_CASE_NAME)); result .add(createUnaryOperation(uml, stdlib.getString(), TO_UPPER_CASE_NAME)); result.add(createBinaryOperation(uml, stdlib.getString(), AT_NAME, stdlib.getInteger(), "index"));//$NON-NLS-1$ result .add(createUnaryOperation(uml, stdlib.getSequence(), CHARACTERS_NAME)); result.add(createBinaryOperation(uml, stdlib.getBoolean(), ENDS_WITH_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), EQUALS_IGNORE_CASE_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), INDEX_OF_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getInteger(), LAST_INDEX_OF_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), MATCHES_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getString(), REPLACE_ALL_NAME, stdlib.getString(), "regex", stdlib.getString(), "replacement"));//$NON-NLS-1$ //$NON-NLS-2$ result.add(createTernaryOperation(uml, stdlib.getString(), REPLACE_FIRST_NAME, stdlib.getString(), "regex", stdlib.getString(), "replacement"));//$NON-NLS-1$ //$NON-NLS-2$ result.add(createBinaryOperation(uml, stdlib.getBoolean(), STARTS_WITH_NAME, stdlib.getString(), "s"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getString(), SUBSTITUTE_ALL_NAME, stdlib.getString(), "regex", stdlib.getString(), "replacement"));//$NON-NLS-1$ //$NON-NLS-2$ result.add(createTernaryOperation(uml, stdlib.getString(), SUBSTITUTE_FIRST_NAME, stdlib.getString(), "regex", stdlib.getString(), "replacement"));//$NON-NLS-1$ //$NON-NLS-2$ result .add(createUnaryOperation(uml, stdlib.getBoolean(), TO_BOOLEAN_NAME)); result .add(createUnaryOperation(uml, stdlib.getSequence(), TOKENIZE_NAME)); result.add(createBinaryOperation(uml, stdlib.getSequence(), TOKENIZE_NAME, stdlib.getString(), "delimiters"));//$NON-NLS-1$ result.add(createTernaryOperation(uml, stdlib.getSequence(), TOKENIZE_NAME, stdlib.getString(), "delimiters", stdlib.getBoolean(), "returnDelimiters"));//$NON-NLS-1$ //$NON-NLS-2$ result .add(createUnaryOperation(uml, stdlib.getString(), TRIM_NAME)); return result; } /** * Utility method creating the operations of the <code>Real</code> type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>Real</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Real</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createRealOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 14); result.addAll(createAnyOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>Integer</code> type * of the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>Integer</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Integer</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createIntegerOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 20); result.addAll(createRealOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 * <code>UnlimitedNatural</code> type of the OCL Standard library. This is * useful for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the <code>Integer</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>UnlimitedNatural</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createUnlimitedNaturalOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 20); result.addAll(createRealOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>Boolean</code> type * of the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>Boolean</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Boolean</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createBooleanOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(ANY_OPERATION_COUNT + 5); result.addAll(createAnyOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>Collection(T)</code> * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the <code>Collection(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Collection(T)</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createCollectionOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(COLLECTION_OPERATION_COUNT); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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)); result.add(createUnaryOperation(uml, stdlib.getReal(), MAX_NAME)); result.add(createUnaryOperation(uml, stdlib.getReal(), MIN_NAME)); result.add(createBinaryOperation(uml, getCollectionType(env, oclFactory, stdlib.getT2()), SELECT_BY_KIND_NAME, stdlib.getOclType(), "typespec")); //$NON-NLS-1$ result.add(createBinaryOperation(uml, getCollectionType(env, oclFactory, stdlib.getT2()), SELECT_BY_TYPE_NAME, stdlib.getOclType(), "typespec")); //$NON-NLS-1$ result.add(createUnaryOperation(uml, getSetType(env, oclFactory, stdlib.getT()), OCL_AS_SET_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), OCL_IS_UNDEFINED_NAME)); result.add(createUnaryOperation(uml, stdlib.getBoolean(), OCL_IS_INVALID_NAME)); return result; } private static final int SET_OPERATION_COUNT = COLLECTION_OPERATION_COUNT + 15; /** * Utility method creating the operations of the <code>Set(T)</code> type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>Set(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Set(T)</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createSetOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(SET_OPERATION_COUNT); result.addAll(createCollectionOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>OrderedSet(T)</code> * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the <code>OrderedSet(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>OrderedSet(T)</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createOrderedSetOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(SET_OPERATION_COUNT + 10); result.addAll(createSetOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>Bag(T)</code> type of * the OCL Standard library. This is useful for implementors of metamodel * bindings ({@link Environment}s) to initialize their implementations of * the <code>Bag(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Bag(T)</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createBagOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>( COLLECTION_OPERATION_COUNT + 13); result.addAll(createCollectionOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <code>Sequence(T)</code> * type of the OCL Standard library. This is useful for implementors of * metamodel bindings ({@link Environment}s) to initialize their * implementations of the <code>Sequence(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the standard * <code>Sequence(T)</code> operations */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createSequenceOperations( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>( COLLECTION_OPERATION_COUNT + 18); result.addAll(createCollectionOperations(env)); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 * <code>Collection(T)</code> type of the OCL Standard library. This is * useful for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the <code>Collection(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the <code>Collection(T)</code> type */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createCollectionIterators( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(COLLECTION_ITERATOR_COUNT); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 * <code>Set(T)</code> type of the OCL Standard library. This is useful for * implementors of metamodel bindings ({@link Environment}s) to initialize * their implementations of the <code>Set(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the <code>Set(T)</code> type */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createSetIterators( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(SET_ITERATOR_COUNT); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); result.addAll(createCollectionIterators(env)); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 * <code>OrderedSet(T)</code> type of the OCL Standard library. This is * useful for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the <code>OrderedSet(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the <code>OrderedSet(T)</code> type */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createOrderedSetIterators( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>(SET_ITERATOR_COUNT); result.addAll(createSetIterators(env)); return result; } /** * Utility method creating the pre-defined iterators of the * <code>Bag(T)</code> type of the OCL Standard library. This is useful for * implementors of metamodel bindings ({@link Environment}s) to initialize * their implementations of the <code>Bag(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the <code>Bag(T)</code> type */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createBagIterators( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>( COLLECTION_ITERATOR_COUNT + 4); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); result.addAll(createCollectionIterators(env)); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 * <code>Sequence(T)</code> type of the OCL Standard library. This is useful * for implementors of metamodel bindings ({@link Environment}s) to * initialize their implementations of the <code>Sequence(T)</code>. * * @param env * an OCL environment * @return a list of new operations representing the pre-defined iterators * of the <code>Sequence(T)</code> type */ public static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> List<O> createSequenceIterators( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env) { List<O> result = new java.util.ArrayList<O>( COLLECTION_ITERATOR_COUNT + 4); OCLStandardLibrary<C> stdlib = env.getOCLStandardLibrary(); UMLReflection<PK, C, O, P, EL, PM, ?, COA, SSA, CT> 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 <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> O createUnaryOperation( UMLReflection<PK, C, O, P, EL, PM, ST, COA, SSA, CT> uml, C resultType, String name) { List<String> paramNames = Collections.emptyList(); List<C> paramTypes = Collections.emptyList(); return uml.createOperation(name, resultType, paramNames, paramTypes); } private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> O createBinaryOperation( UMLReflection<PK, C, O, P, EL, PM, ST, COA, SSA, CT> uml, C resultType, String name, C paramType, String paramName) { List<String> paramNames = Collections.singletonList(paramName); List<C> paramTypes = Collections.singletonList(paramType); return uml.createOperation(name, resultType, paramNames, paramTypes); } private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> O createTernaryOperation( UMLReflection<PK, C, O, P, EL, PM, ST, COA, SSA, CT> uml, C resultType, String name, C param1Type, String param1Name, C param2Type, String param2Name) { List<String> paramNames = new java.util.ArrayList<String>(2); List<C> paramTypes = new java.util.ArrayList<C>(2); paramNames.add(param1Name); paramTypes.add(param1Type); paramNames.add(param2Name); paramTypes.add(param2Type); return uml.createOperation(name, resultType, paramNames, paramTypes); } @SuppressWarnings("unchecked") private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getBagType( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OCLFactory factory, C elementType) { return TypeUtil .resolveType(env, (C) factory.createBagType(elementType)); } @SuppressWarnings("unchecked") private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getSetType( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OCLFactory factory, C elementType) { return TypeUtil .resolveType(env, (C) factory.createSetType(elementType)); } @SuppressWarnings("unchecked") private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getOrderedSetType( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OCLFactory factory, C elementType) { return TypeUtil.resolveType(env, (C) factory .createOrderedSetType(elementType)); } @SuppressWarnings("unchecked") private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getSequenceType( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OCLFactory factory, C elementType) { return TypeUtil.resolveType(env, (C) factory .createSequenceType(elementType)); } @SuppressWarnings("unchecked") private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getCollectionType( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OCLFactory factory, C elementType) { return TypeUtil.resolveType(env, (C) factory .createCollectionType(elementType)); } @SuppressWarnings("unchecked") private static <PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> C getTupleType( Environment<PK, C, O, P, EL, PM, ST, COA, SSA, CT, CLS, E> env, OCLFactory factory, List<? extends TypedElement<C>> parts) { return TypeUtil.resolveType(env, (C) factory.createTupleType(parts)); } /** * Convenience method invoking * <code>getProblemHandler().utilityProblem</code> 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 * <code>getProblemHandler().utilityProblem</code> 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, * <tt>OclMessage</tt>, and the like. Thus, it helps to find inherited * operations and attributes, etc., but not actual type conformance. For * example, <tt>{@literal Set<Fruit>}</tt> is not returned as a supertype of * <tt>{@literal Set<Apple>}</tt>. Rather, only * <tt>{@literal Collection<T>}</tt> 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 <C> Collection<C> getAllSupertypes( Environment<?, C, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?> env, PredefinedType<?> type) { Collection<C> result; OCLStandardLibrary<C> 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; } }