// checks (3) and (1)
  private Expression genObjOperation(Context ctx, MClass srcClass, Expression srcExpr)
      throws SemanticException {
    Expression res = null;

    // find operation
    String opname = fOp.getText();
    MOperation op = srcClass.operation(opname, true);
    if (op != null) {
      // check for isQuery operation with OCL body
      if (!op.hasExpression())
        throw new SemanticException(
            fOp,
            "Operation `"
                + srcClass.name()
                + "::"
                + op.signature()
                + "' cannot be used in OCL expression "
                + "(only side effect-free operations with a return type and an OCL expression as body may be used).");

      try {
        // constructor performs additional checks
        res = new ExpObjOp(op, fArgExprs);
      } catch (ExpInvalidException ex) {
        throw new SemanticException(
            fOp, "In operation call `" + srcClass.name() + "::" + opname + "': " + ex.getMessage());
      }
    } else {
      // try standard operation
      res = genStdOperation(ctx, fOp, opname, fArgExprs);
    }
    return res;
  }
  /** Handles shorthand notation for collect and expands to an explicit collect expression. */
  private Expression collectShorthandWithArgs(String opname, Expression srcExpr)
      throws SemanticException {
    Expression res = null;
    // c.op()  201 (5) with implicit (3,1)
    CollectionType cType = (CollectionType) srcExpr.type();
    Type elemType = cType.elemType();
    if (elemType.isObjectType()) {
      MClass srcClass = ((ObjectType) elemType).cls();
      MOperation op = srcClass.operation(opname, true);
      if (op != null) {
        // check for isQuery operation with OCL body
        if (!op.hasExpression())
          throw new SemanticException(
              fOp,
              "Operation `"
                  + srcClass.name()
                  + "::"
                  + op.signature()
                  + "' cannot be used in OCL expression "
                  + "(only side effect-free operations with a return type and an OCL expression as body may be used).");

        // transform c.op(...) into c->collect($e | $e.op(...))
        ExpVariable eVar = new ExpVariable("$e", elemType);
        fArgExprs[0] = eVar;
        try {
          // constructor performs additional checks
          res = new ExpObjOp(op, fArgExprs);
        } catch (ExpInvalidException ex) {
          throw new SemanticException(
              fOp,
              "In operation call `" + srcClass.name() + "::" + opname + "': " + ex.getMessage());
        }
        res = genImplicitCollect(srcExpr, res, elemType);
      }
    }
    if (res == null) {
      // try (1) predefined OCL operation
      res = collectShorthandStdOp(opname, srcExpr, cType, elemType);
    }
    return res;
  }
  /** Handles shorthand notation for collect and expands to an explicit collect expression. */
  private Expression collectShorthandWithOutArgs(String opname, Expression srcExpr)
      throws SemanticException {
    Expression res = null;
    // c.op    200 (5) with implicit (2,4,1)
    CollectionType cType = (CollectionType) srcExpr.type();
    Type elemType = cType.elemType();
    if (elemType.isObjectType()) {
      MClass srcClass = ((ObjectType) elemType).cls();
      MAttribute attr = srcClass.attribute(opname, true);
      if (attr != null) {
        // (2) attribute operation on object type (no arguments)

        // transform c.a into c->collect($e | $e.a)
        ExpVariable eVar = new ExpVariable("$e", elemType);
        ExpAttrOp eAttr = new ExpAttrOp(attr, eVar);
        res = genImplicitCollect(srcExpr, eAttr, elemType);
      } else {
        MAssociationEnd dstEnd = srcClass.navigableEnd(opname);
        if (dstEnd != null) {
          // (4) navigation operation on object type must be
          // a role name

          // transform c.r into c->collect($e | $e.r)
          ExpVariable eVar = new ExpVariable("$e", elemType);
          Expression eNav = genNavigation(fOp, srcClass, eVar, dstEnd);
          res = genImplicitCollect(srcExpr, eNav, elemType);
        }
      }
    }
    if (res == null) {
      // ! objectType || ! (attr ||  navigation)
      // try (1) predefined OCL operation
      res = collectShorthandStdOp(opname, srcExpr, cType, elemType);
    }
    return res;
  }
  private Expression gen1(Context ctx, Expression srcExpr) throws SemanticException {
    Expression res = null;
    String opname = fOp.getText();
    Type srcType = srcExpr.type();

    // generate argument expressions
    fArgExprs = new Expression[fArgs.size() + 1];
    fArgExprs[0] = srcExpr;
    Iterator it = fArgs.iterator();
    int i = 1;
    while (it.hasNext()) {
      ASTExpression astExpr = (ASTExpression) it.next();
      fArgExprs[i++] = astExpr.gen(ctx);
    }

    // flags for various cases
    final int SRC_SIMPLE_TYPE = 0x100;
    final int SRC_OBJECT_TYPE = 0x200;
    final int SRC_COLLECTION_TYPE = 0x400;

    final int DOT = 0x010;
    final int ARROW = 0x020;

    final int NO_PARENTHESES = 0x000;
    final int PARENTHESES = 0x001;

    int opcase;
    if (srcType.isObjectType()) opcase = SRC_OBJECT_TYPE;
    else if (srcType.isCollection()) opcase = SRC_COLLECTION_TYPE;
    else opcase = SRC_SIMPLE_TYPE;

    opcase += fFollowsArrow ? ARROW : DOT;
    opcase += fHasParentheses ? PARENTHESES : NO_PARENTHESES;

    switch (opcase) {
      case SRC_SIMPLE_TYPE + DOT + NO_PARENTHESES:
      case SRC_SIMPLE_TYPE + DOT + PARENTHESES:
      case SRC_COLLECTION_TYPE + ARROW + PARENTHESES:
      case SRC_COLLECTION_TYPE + ARROW + NO_PARENTHESES:
        // (1) predefined OCL operation
        res = genStdOperation(ctx, fOp, opname, fArgExprs);
        break;

      case SRC_SIMPLE_TYPE + ARROW + NO_PARENTHESES:
      case SRC_SIMPLE_TYPE + ARROW + PARENTHESES:
        ctx.reportWarning(
            fOp,
            "application of `"
                + opname
                + "' to a single value should be done with `.' "
                + "instead of `->'.");
        // (1) predefined OCL operation
        res = genStdOperation(ctx, fOp, opname, fArgExprs);
        break;

      case SRC_OBJECT_TYPE + DOT + NO_PARENTHESES:
        MClass srcClass = ((ObjectType) srcType).cls();
        MAttribute attr = srcClass.attribute(opname, true);
        if (attr != null) {
          // (2) attribute operation on object type (no arguments)
          res = new ExpAttrOp(attr, srcExpr);
        } else {
          // (4) navigation operation on object type
          // must be a role name
          MAssociationEnd dstEnd = srcClass.navigableEnd(opname);
          if (dstEnd != null) res = genNavigation(fOp, srcClass, srcExpr, dstEnd);
          else {
            // (1) predefined OCL operation
            res = genStdOperation(ctx, fOp, opname, fArgExprs);
          }
        }
        break;

      case SRC_OBJECT_TYPE + DOT + PARENTHESES:
        // (3) "isQuery" operation on object type (possibly with
        // arguments) or (1)
        MClass srcClass2 = ((ObjectType) srcType).cls();
        res = genObjOperation(ctx, srcClass2, srcExpr);
        break;

      case SRC_OBJECT_TYPE + ARROW + NO_PARENTHESES:
      case SRC_OBJECT_TYPE + ARROW + PARENTHESES:
        // (6) set operation on single object resulting from
        // navigation over associations with multiplicity zero
        // or one (p. 7-13 of OMG UML 1.3)
        if (srcExpr instanceof ExpNavigation) {
          // first map object to set with internal operation
          Expression mappedSrcExpr = new ExpObjAsSet(srcExpr);
          // replace receiver in arg list
          fArgExprs[0] = mappedSrcExpr;
          try {
            // lookup collection operation
            res = ExpStdOp.create(opname, fArgExprs);
          } catch (ExpInvalidException ex) {
            throw new SemanticException(fOp, ex);
          }
        } else {
          throw new SemanticException(
              fOp,
              "An arrow operation treating a single object as a "
                  + "set may only be applied, if the object results "
                  + "from a navigation to an association end with "
                  + "multiplicity 0..1.");
        }
        break;

      case SRC_COLLECTION_TYPE + DOT + NO_PARENTHESES:
        // c.op    200 (5) with implicit (2,4,1)
        if (Options.disableCollectShorthand)
          throw new SemanticException(fOp, MSG_DISABLE_COLLECT_SHORTHAND);
        res = collectShorthandWithOutArgs(opname, srcExpr);
        break;

      case SRC_COLLECTION_TYPE + DOT + PARENTHESES:
        // c.op()  201 (5) with implicit (3,1)
        if (Options.disableCollectShorthand)
          throw new SemanticException(fOp, MSG_DISABLE_COLLECT_SHORTHAND);
        res = collectShorthandWithArgs(opname, srcExpr);
        break;

        //  	    throw new SemanticException(fOp,
        //  		"If you want to apply an operation to a collection, please use an `->' instead of a
        // `.'. If you are trying to apply the shorthand notation for `collect' - sorry, this is not
        // yet supported. Please use the explicit notation.");

      default:
        throw new RuntimeException("case " + Integer.toHexString(opcase) + " not handled");
    }

    if (fIsPre) res.setIsPre();
    return res;
  }
Пример #5
0
  /**
   * Create a new link between the (source or target) domain and the corr object
   *
   * @throws org.tzi.use.uml.sys.MSystemException
   */
  public MLink createMLink(
      Context ctx, MObject corrObject, MClass domainClass, MObject domainObject)
      throws MSystemException {
    MLink link = null;
    MAssociation assoc = null;
    String roleName = "";
    MClass corrClass = ctx.model().getClass(corrObject.cls().name());
    Set tmpClasses = new HashSet();
    if (domainObject.name().equals(fSourceObject.getText()))
      if (fSourceRole != null) roleName = fSourceRole.getText();
      else roleName = fSourceObject.getClass().getName().toLowerCase();
    else if (fTargetRole != null) roleName = fTargetRole.getText();
    else roleName = fTargetObject.getClass().getName().toLowerCase();
    tmpClasses.add(corrClass);
    tmpClasses.add(domainClass);
    Set<MAssociation> assocs = ctx.model().getAssociationsBetweenClasses(tmpClasses);
    if (assocs.size() == 0) {
      ModelFactory mf = new ModelFactory();
      List<VarDecl> emptyQualifiers = Collections.emptyList();

      try {
        assoc = mf.createAssociation(domainClass.name() + "_" + corrClass.name());
        assoc.addAssociationEnd(
            mf.createAssociationEnd(
                domainClass,
                roleName,
                new MMultiplicity(1, 1),
                MAggregationKind.NONE,
                false,
                emptyQualifiers));
        assoc.addAssociationEnd(
            mf.createAssociationEnd(
                corrClass,
                "cp" + "_" + assoc.name(),
                MMultiplicity.ZERO_MANY,
                MAggregationKind.NONE,
                false,
                emptyQualifiers));
        ctx.model().addAssociation(assoc);
        MSystem system = new MSystem(ctx.model());
        MSystemState temp = system.state();
        // copy object, link from ctx.systemState -> temp
        // Objects
        for (Iterator iter = ctx.systemState().allObjects().iterator(); iter.hasNext(); ) {
          MObject obj = (MObject) iter.next();
          temp.createObject(obj.cls(), obj.name());
        }
        // Links
        for (Iterator iter = ctx.systemState().allLinks().iterator(); iter.hasNext(); ) {
          MLink obj = (MLink) iter.next();
          temp.insertLink(obj);
        }
        ctx.setfCurrentSystemState(system.state());

      } catch (MInvalidModelException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

    } else {
      Iterator it = assocs.iterator();
      if (!it.hasNext()) throw new MSystemException();
      assoc = (MAssociation) it.next();
    }
    List tmpList = new ArrayList<MObject>();

    tmpList.add(domainObject);
    tmpList.add(corrObject);
    if (!ctx.systemState().hasLink(assoc, tmpList, null)) {
      link = ctx.systemState().createLink(assoc, tmpList, null);
    } else {
      link = ctx.systemState().linkBetweenObjects(assoc, tmpList).iterator().next();
    }
    return link;
  }