/**
   * Constructs new operation call for the given operation and execution context.
   *
   * @param operation a valid AST operation to be called. <code>Note:</code> This must be an
   *     operation owned by a valid QVT Library module
   * @param context non-QVT transformation context in which this operation will be called
   * @exception IllegalArgumentException If the passed <code>operation</code> or <code>context
   *     </code> are <code>null</code>; or the operation is not valid AST element for construction
   *     of the call
   */
  HelperOperationCall(Helper operation, NonTransformationExecutionContext context) {
    if (operation == null || context == null) {
      throw new IllegalArgumentException();
    }

    fOwningModule = QvtOperationalParserUtil.getOwningModule(operation);
    if (fOwningModule == null) {
      throw new IllegalArgumentException("Not a library query or helper"); // $NON-NLS-1$
    }

    fOperation = operation;
    fContextType = QvtOperationalParserUtil.getContextualType(fOperation);

    fArgumentTypes = new ArrayList<EClassifier>(fOperation.getEParameters().size());
    for (EParameter eParam : fOperation.getEParameters()) {
      EClassifier paramType = eParam.getEType();
      if (paramType == null) {
        throw new IllegalArgumentException("Parameter with no type"); // $NON-NLS-1$
      }

      fArgumentTypes.add(paramType);
    }

    fContext = context;
  }
  @Override
  public String toString() {
    StringBuilder buf = new StringBuilder();
    if (fContext != null) {
      buf.append(fContextType).append("::"); // $NON-NLS-1$
    }

    buf.append(fOperation.getName()).append(" - ").append(fOwningModule.getName()); // $NON-NLS-1$
    return buf.toString();
  }
  public QvtOperationalModuleEnv defineLibrary(
      Library lib, Map<String, List<EOperation>> definedOperations)
      throws LibraryCreationException {
    org.eclipse.m2m.internal.qvt.oml.expressions.Library libModule =
        QvtOperationalStdLibrary.createLibrary(lib.getId());
    // FIXME - set isBlackBox=TRUE, as soon is it gets into the AST metamodel

    QvtOperationalModuleEnv libEnv = initLibEnvironment(lib, libModule);
    URI libUri =
        URI.createHierarchicalURI(
            BlackboxUnitDescriptor.URI_QVTO_SCHEME,
            BlackboxUnitDescriptor.URI_BLACKBOX_AUTHORITY,
            null,
            new String[] {lib.getId()},
            null,
            null);
    libModule.eResource().setURI(libUri);

    org.eclipse.m2m.internal.qvt.oml.expressions.Library opModule =
        QvtOperationalStdLibrary.createLibrary(lib.getId());
    QvtOperationalModuleEnv opEnv = initLibEnvironment(lib, opModule);

    for (LibraryOperation libOp : lib.getLibraryOperations()) {
      Helper helper = defineOperation(opModule, opEnv, libOp);

      libEnv.defineImperativeOperation(helper, false, true);

      List<EOperation> listOp = definedOperations.get(helper.getName());
      if (listOp == null) {
        listOp = new LinkedList<EOperation>();
        definedOperations.put(helper.getName(), listOp);
      }
      listOp.add(helper);
    }

    // FIXME - workaround to make Environment available with the module
    ASTBindingHelper.createCST2ASTBinding(
        CSTFactory.eINSTANCE.createLibraryCS(), libEnv.getModuleContextType(), libEnv);
    return libEnv;
  }
  private Helper defineOperation(
      org.eclipse.m2m.internal.qvt.oml.expressions.Library opModule,
      QvtOperationalModuleEnv opEnv,
      LibraryOperation libOp)
      throws LibraryCreationException {
    QvtLibraryOperation qvtLibOp = new QvtLibraryOperation(opEnv, libOp);

    Helper helper =
        org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsFactory.eINSTANCE.createHelper();
    helper.setName(libOp.getName());
    helper.setEType(qvtLibOp.getReturnType());
    int index = 1;
    for (EClassifier type : qvtLibOp.getParamTypes()) {
      VarParameter varParam =
          org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsFactory.eINSTANCE
              .createVarParameter();
      varParam.setKind(DirectionKind.IN);
      varParam.setEType(type);
      varParam.setName("arg" + index); // $NON-NLS-1$;
      ++index;
      helper.getEParameters().add(varParam);
    }
    if (qvtLibOp.getContextType() != opModule) {
      VarParameter varParam =
          org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsFactory.eINSTANCE
              .createVarParameter();
      varParam.setKind(DirectionKind.IN);
      varParam.setEType(qvtLibOp.getContextType());
      varParam.setName(Environment.SELF_VARIABLE_NAME);
      helper.setContext(varParam);
    }

    Class<?> returnClass =
        (helper.getEType() != null) ? helper.getEType().getInstanceClass() : null;
    CallHandlerAdapter.attach(helper, new Handler(libOp, returnClass));
    return helper;
  }