// 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; }
/** * 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; }