// 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 collectShorthandStdOp( String opname, Expression srcExpr, Type cType, Type elemType) throws SemanticException { Expression res = null; // (1) predefined OCL operation // find operation on element type Type[] params = new Type[fArgExprs.length]; params[0] = elemType; for (int i = 1; i < fArgExprs.length; i++) params[i] = fArgExprs[i].type(); if (!ExpStdOp.exists(opname, params)) { String msg = "Undefined operation `" + elemType + "." + opname + "' in shorthand notation for collect."; // maybe the user just confused . with ->, check for // operation on collection and give a hint. params[0] = cType; if (ExpStdOp.exists(opname, params)) msg += " However, there is an operation `" + cType + "->" + opname + "'. Maybe you wanted to use `->' instead of `.'?"; throw new SemanticException(fOp, msg); } // transform c.op(...) into c->collect($e | $e.op(...)) fArgExprs[0] = new ExpVariable("$e", elemType); try { Expression eOp = ExpStdOp.create(opname, fArgExprs); res = genImplicitCollect(srcExpr, eOp, elemType); } catch (ExpInvalidException ex) { // shouldn't fail because we already checked the // existence above throw new RuntimeException("collectShorthand failed: " + ex.getMessage()); } return res; }