From c84573bad66efcf1fe3d061bcf0c5f9c60adff17 Mon Sep 17 00:00:00 2001 From: Kevin Lano Date: Wed, 18 Dec 2024 14:29:36 +0000 Subject: [PATCH] Add files via upload --- version24/BAnyStatement.class | Bin 0 -> 2446 bytes version24/BAnyStatement.java | 85 + version24/BApplyExpression.class | Bin 0 -> 3020 bytes version24/BApplyExpression.java | 114 + version24/BApplySetExpression.class | Bin 0 -> 2253 bytes version24/BApplySetExpression.java | 79 + version24/BAssignStatement.class | Bin 0 -> 2243 bytes version24/BAssignStatement.java | 96 + version24/BBasicExpression.class | Bin 0 -> 1683 bytes version24/BBasicExpression.java | 65 + version24/BBasicStatement.class | Bin 0 -> 804 bytes version24/BBasicStatement.java | 32 + version24/BBinaryExpression.class | Bin 0 -> 7652 bytes version24/BBinaryExpression.java | 398 + version24/BChoiceStatement.class | Bin 0 -> 1466 bytes version24/BChoiceStatement.java | 59 + version24/BComponent.class | Bin 0 -> 25172 bytes version24/BComponent.java | 1217 + version24/BExpression.class | Bin 0 -> 2287 bytes version24/BExpression.java | 93 + version24/BIfStatement.class | Bin 0 -> 2796 bytes version24/BIfStatement.java | 133 + version24/BLoopStatement.class | Bin 0 -> 1911 bytes version24/BLoopStatement.java | 80 + version24/BOp.class | Bin 0 -> 19184 bytes version24/BOp.java | 1159 + version24/BOperation.class | Bin 0 -> 3400 bytes version24/BOperation.java | 148 + version24/BOperationCall.class | Bin 0 -> 4530 bytes version24/BOperationCall.java | 273 + version24/BParallelStatement.class | Bin 0 -> 2974 bytes version24/BParallelStatement.java | 121 + version24/BPiExpression.class | Bin 0 -> 1437 bytes version24/BPiExpression.java | 58 + version24/BPostfixExpression.class | Bin 0 -> 1256 bytes version24/BPostfixExpression.java | 50 + version24/BQuantifierExpression.class | Bin 0 -> 2178 bytes version24/BQuantifierExpression.java | 88 + version24/BSetComprehension.class | Bin 0 -> 2487 bytes version24/BSetComprehension.java | 95 + version24/BSetExpression.class | Bin 0 -> 2921 bytes version24/BSetExpression.java | 127 + version24/BSigmaExpression.class | Bin 0 -> 1446 bytes version24/BSigmaExpression.java | 59 + version24/BStatement.class | Bin 0 -> 6044 bytes version24/BStatement.java | 290 + version24/BSystemTypes.class | Bin 0 -> 267890 bytes version24/BSystemTypes.java | 11807 +++++++++ version24/BTypeDef.class | Bin 0 -> 1351 bytes version24/BTypeDef.java | 51 + version24/BUnaryExpression.class | Bin 0 -> 1660 bytes version24/BUnaryExpression.java | 63 + version24/BVarStatement.class | Bin 0 -> 1514 bytes version24/BVarStatement.java | 65 + ...BacktrackDialog$BacktrackDialogPanel.class | Bin 0 -> 2426 bytes version24/BacktrackDialog$ButtonHandler.class | Bin 0 -> 1541 bytes version24/BacktrackDialog.class | Bin 0 -> 2791 bytes version24/BacktrackDialog.java | 189 + version24/BacktrackingSpecification.class | Bin 0 -> 10273 bytes version24/BacktrackingSpecification.java | 501 + version24/BasicExpression.class | Bin 0 -> 295604 bytes version24/BasicExpression.java | 18130 +++++++++++++ version24/BasicState.class | Bin 0 -> 708 bytes version24/Behaviour.class | Bin 0 -> 2232 bytes version24/Behaviour.java | 92 + version24/BehaviouralFeature.class | Bin 0 -> 195508 bytes version24/BehaviouralFeature.java | 11764 +++++++++ version24/BidirectionalAssociation.class | Bin 0 -> 1051 bytes version24/BidirectionalAssociation.java | 39 + version24/BinaryExpression.class | Bin 0 -> 343626 bytes version24/BinaryExpression.java | 21143 ++++++++++++++++ version24/Binding.class | Bin 0 -> 3248 bytes version24/Binding.java | 96 + version24/BreakStatement.class | Bin 0 -> 5529 bytes version24/build.bat | 3 + 75 files changed, 68862 insertions(+) create mode 100644 version24/BAnyStatement.class create mode 100644 version24/BAnyStatement.java create mode 100644 version24/BApplyExpression.class create mode 100644 version24/BApplyExpression.java create mode 100644 version24/BApplySetExpression.class create mode 100644 version24/BApplySetExpression.java create mode 100644 version24/BAssignStatement.class create mode 100644 version24/BAssignStatement.java create mode 100644 version24/BBasicExpression.class create mode 100644 version24/BBasicExpression.java create mode 100644 version24/BBasicStatement.class create mode 100644 version24/BBasicStatement.java create mode 100644 version24/BBinaryExpression.class create mode 100644 version24/BBinaryExpression.java create mode 100644 version24/BChoiceStatement.class create mode 100644 version24/BChoiceStatement.java create mode 100644 version24/BComponent.class create mode 100644 version24/BComponent.java create mode 100644 version24/BExpression.class create mode 100644 version24/BExpression.java create mode 100644 version24/BIfStatement.class create mode 100644 version24/BIfStatement.java create mode 100644 version24/BLoopStatement.class create mode 100644 version24/BLoopStatement.java create mode 100644 version24/BOp.class create mode 100644 version24/BOp.java create mode 100644 version24/BOperation.class create mode 100644 version24/BOperation.java create mode 100644 version24/BOperationCall.class create mode 100644 version24/BOperationCall.java create mode 100644 version24/BParallelStatement.class create mode 100644 version24/BParallelStatement.java create mode 100644 version24/BPiExpression.class create mode 100644 version24/BPiExpression.java create mode 100644 version24/BPostfixExpression.class create mode 100644 version24/BPostfixExpression.java create mode 100644 version24/BQuantifierExpression.class create mode 100644 version24/BQuantifierExpression.java create mode 100644 version24/BSetComprehension.class create mode 100644 version24/BSetComprehension.java create mode 100644 version24/BSetExpression.class create mode 100644 version24/BSetExpression.java create mode 100644 version24/BSigmaExpression.class create mode 100644 version24/BSigmaExpression.java create mode 100644 version24/BStatement.class create mode 100644 version24/BStatement.java create mode 100644 version24/BSystemTypes.class create mode 100644 version24/BSystemTypes.java create mode 100644 version24/BTypeDef.class create mode 100644 version24/BTypeDef.java create mode 100644 version24/BUnaryExpression.class create mode 100644 version24/BUnaryExpression.java create mode 100644 version24/BVarStatement.class create mode 100644 version24/BVarStatement.java create mode 100644 version24/BacktrackDialog$BacktrackDialogPanel.class create mode 100644 version24/BacktrackDialog$ButtonHandler.class create mode 100644 version24/BacktrackDialog.class create mode 100644 version24/BacktrackDialog.java create mode 100644 version24/BacktrackingSpecification.class create mode 100644 version24/BacktrackingSpecification.java create mode 100644 version24/BasicExpression.class create mode 100644 version24/BasicExpression.java create mode 100644 version24/BasicState.class create mode 100644 version24/Behaviour.class create mode 100644 version24/Behaviour.java create mode 100644 version24/BehaviouralFeature.class create mode 100644 version24/BehaviouralFeature.java create mode 100644 version24/BidirectionalAssociation.class create mode 100644 version24/BidirectionalAssociation.java create mode 100644 version24/BinaryExpression.class create mode 100644 version24/BinaryExpression.java create mode 100644 version24/Binding.class create mode 100644 version24/Binding.java create mode 100644 version24/BreakStatement.class create mode 100644 version24/build.bat diff --git a/version24/BAnyStatement.class b/version24/BAnyStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..e9de6449900764ea57adc8136d11f743022545e3 GIT binary patch literal 2446 zcmaJ@TT@e47+pIT65;_gMQJQ*yi~~rP^+zi+7gT<5~3A^Vq4pg9N}O%iOC6yy<7i; zufF(dJ2iC5OvgU9Z~Z&%Si8QHgPcUBO!)TB-s@ZYyR5w@fByUHZval=VF)o~0=OK4 z2boUvV^U03%#`fqLb!sfGNbtj*912m#EgvB#mojU7r@6M>_kS)yqFt7d=kW`GW{%w zn?Zao&@Y55FI)=&6hb_rC@Z?G+!C`WW=Wui>@EjzJBX4@S3)=fQ)cA=Dhj^Ue6^+! z&MxOy^TTz^C=Ji*1*=>g6%5tGx)D^UBYTC+M`igE^T3q<2GMU)-d&4ePuzf&g2(LJRz{CTeEg}y#uk=Nfm+w%q{6v zVta^a4O6^lmUL60TlU2sWEfyRUSjqF%8GT5O%hAPeU9D4M_}Y7{aiI5u6U7s$o>d zng$DX4Xe1z@{i@_qZ;mEO~ZYBxk={AMxoEV`FUdQo+hBG+J!?${_;2jXD?QltifTq%~Q}hb{x=DE} zoY_vk?d2WaR*s!jeWkprkCjLlanp>K+24XC*C%#^g{T?#*-nO(p`}a}b`NA6O1sEc z7M6*ZTa~X=bdy5ePGoM6re2-4(6I&Y(ET4iSSXuT-Z1$V>~`yU)0JUwUTl{PM%#71 z)e<}SV$m+fu$$4jSuLI|Ut+U3$oDD6ch$=mj6&wjBU-jc%9-O1D3J>7Nq(Co(#P>Y zd>tyj0nhw8ywBi^C&VP5!5<%dhK?TzQFw=TFFI(u=@di{$6ne9AKCrbMFdsm5bxut zi1f#QhVSVs_YQlpmzJ8Nl^EPme>=2~Ac}GuXh%DAFG0Mm4m8S90thmIjs^nlXgQU4 z+Ch)AP9CBU5bbXum`ya@I)6dPp8FcuF_+jP3EO3hvI+-TgF{T>FsXQ-9m2ny!afXZ zS?~FNsX_x?kCBmCe*@jm(UaT2PS$%@qJi)r{~LHCyNUD_AEVE;AMSMk4?XJ1%b(mk zySdX0dr!EpIcLIq!f!ercGMobdq>g9B#$w+0ro6LvBW8g1mjNPD%WQD<~^W1E)dlN z?+f??cwha4%YVbq#Q5$w>D}aaKS3uX9mXGd#7;kzC=$sA_U1V2kl9-!z76!x3u-Xp zTgN`BU^A9x1y7-iP3WT>4p9(tt{19{r|=PT&bq*pyxiC?^bPFK3V8zurZ$-qNr$*8 z(QX?(%GR7?lF|^qg$~zga!H>fO^#@GlS8-@Ej02Y08BW@P?Wr+4#gj&kUOy4q&PU0 z{2l#|FqwRges)$&jrisGh%X`w13W$Z z1ikKvB(bcke?z>!z=w=!g8j)*d6%iYNp>{LD?P<1bC}@|nmPVZTEaEEo)LIna3O&7 TOP0eMz$N>WCXphQv}58wX`TE1 literal 0 HcmV?d00001 diff --git a/version24/BAnyStatement.java b/version24/BAnyStatement.java new file mode 100644 index 00000000..dfd55694 --- /dev/null +++ b/version24/BAnyStatement.java @@ -0,0 +1,85 @@ +import java.util.Vector; + +/* Copyright K. Lano 2003-2013 + Package: B AMN +*/ + +public class BAnyStatement extends BStatement +{ private Vector vars = new Vector(); // of String + private BExpression pred; + private BStatement code; + + public BAnyStatement(Vector vs, BExpression qual, + BStatement body) + { vars = vs; + pred = qual; + code = body; + } + + public Vector getVars() + { return vars; } + + public BExpression getWhere() + { return pred; } + + public BStatement getThen() + { return code; } + + public Vector wr() + { return code.wr(); } + + public Vector rd() + { Vector res = pred.rd(); + res = VectorUtil.union(res,code.rd()); + res.removeAll(vars); + return res; + } + + public String toString() + { String res = "ANY "; + for (int i = 0; i < vars.size(); i++) + { String var = (String) vars.get(i); + res = res + var; + if (i < vars.size() - 1) + { res = res + ", "; } + } + res = res + " WHERE " + pred + "\n" + " THEN " + + code + " END"; + return res; + } + + public BStatement substituteEq(String oldE, BExpression newE) + { if (vars.contains(oldE)) { return this; } + BExpression npred = pred.substituteEq(oldE,newE); + BStatement ncode = code.substituteEq(oldE,newE); + return new BAnyStatement(vars,npred,ncode); + } + + public BStatement simplify() + { BExpression npred = pred.simplify(); + BStatement ncode = code.simplify(); + return new BAnyStatement(vars,npred,ncode); + } + + public BStatement seq2parallel() + { BStatement ncode = code.seq2parallel(); + return new BAnyStatement(vars,pred,ncode); + } + + public BStatement normalise() + { BAnyStatement res; + BStatement stat = code.normalise(); + if (stat instanceof BAnyStatement) + { BAnyStatement inner = (BAnyStatement) stat; + Vector newvars = new Vector(); + newvars.addAll(vars); + newvars.addAll(inner.getVars()); + BExpression newpred = new BBinaryExpression("&",pred,inner.getWhere()); + res = new BAnyStatement(newvars,newpred,inner.getThen()); + } + else + { res = new BAnyStatement(vars,pred,stat); } + return res; + } +} + diff --git a/version24/BApplyExpression.class b/version24/BApplyExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..1db128cfed3da2c1ed189cf4d0a13c972d072336 GIT binary patch literal 3020 zcma)8NmLYP5dNB3dKeniK_q|zYQSNJB{6CY5Y$mgR2CIQ!7L8YK+7-;Gd(IUS&iAu zzLL#6FJ3%oo{o9(CDDs{FS+HEQ;xajy&SWduew`lkeB2z)qnqgRsB_8eN{c*|NYfB z0M_91AR4hNA2rymq9+Is_Q=a#5xpw*1)*Y>i2VWd$+KU?0Xcpwh{y4Sh$jO$D1PEW z3}8^shE(XXGn|hRj0Ru?a43i|BvgzCQI2E)6G5afDKBXinINiQ29TBa!(w?vc8;o; z3ew#%5ywRwkh2paPKr1lz*7M{t>PI4f#Ga&&@?8J3PK%+;)ml+iFk6PsmDwk$&nTX zUO87#*b&=$G?msf8LD#I6HkxukTP?}Fl!o#re1x}oJdo{-)bZcvrWN@@ZElAd8_NC zr_B>Xx`G8AMpEy}jt}VRJ@J7Acb0``>CSo)Lwa{dW?$uwM3f49%=q9~XFO#&B|J=B z#j`4&Q;?S)Qm{B&ceka2f)U+pzk|;mrP&CH(x&uCc3e-I%z&QU0dXgzo1NK&X`~Xy zpkYoi+3+@rDxU|v@kCZ<0G@DNKZ}tu#;G+-9W9d`$e4ziHTA8N3L5_t#5uPH%n7@O z3W7Zo+4P{^ZU~+wu}!H|Vrr(CjZ$+rmWCfuiBVJsHU7=tq!a(GI^{aCHx0jyR~ zI+rK0tdSVf(;8mDX$6qyiyFGHMPsw9CDIyR!pj<7!K(_CdJUTpQ*lPaYj|D58+eoX zc9H;ztqEOV)UXZPRlKF)ZM?$-Zr7l>T0wF35yKpZr-sjPmYIe5t0Qe(1fa2nmWz_Nw_G%`2tZ1d%u{Beia(x8=}GdW!L86e zaERU3;!xM+&Z!5xaF)K))c>aM%^1hX64G%SC7CTTZF5^Vm$E8$tM6skEAVBL)(lzi z#OF%4NFa!oz1pk0O*{0lyFn zEoaS+v+Z;x&T1`Z*P!-YMIf3(ekhnjK@OU@=NvJeNhmB4c4UC|^#GAtc#=}s$Yz6PoIh49oLJRFkyH0tP^S8dX zz-X|*uyDw;aA+imKpEpLXS@}RcPYYH#=%s{)~&)m?vC+&5-V^LE73~ra(Heb3ZIIH zRkW$tpkgEE+J@hmnIgl>$#oqImq-02k<0Mqu&5)-g`bNr`7w=N2u=NON6z169))mDP1r zb=G@wsP1aGiQWdwth<3W&E7I{r6RQ4vTAkilptJmc6LQ`g=^a~$(P+q35FIcJEGQ| zO;PK@9PXXQO8eexsOgh9NwQkGl!2yc9&R{tNd<$i*DS+PW*sf_>r1FVGn-6Ui^yv_zedv^fh=Q zf8flYXeLEj0Dgw-GVpung`fBCh(>YmI?v$`(Hz*aJe@vy_WPF|5ms?5}keUu+!oI)3?eliR=0|>D-qQpR0G@r^H;BC5&6Zj-S QpRl4KT_e1`+fv&352Lh|m;e9( literal 0 HcmV?d00001 diff --git a/version24/BApplyExpression.java b/version24/BApplyExpression.java new file mode 100644 index 00000000..1620e8f7 --- /dev/null +++ b/version24/BApplyExpression.java @@ -0,0 +1,114 @@ +import java.util.Vector; + +/* Copyright K. Lano 2003-2013 + Package: B AMN */ + +public class BApplyExpression extends BExpression +{ private String function; + private BExpression func; // function = func.toString() + private BExpression arg; // may be list + private Vector args; + + public BApplyExpression(String f, BExpression a) + { function = f; + func = new BBasicExpression(f); + arg = a; + } + + public BApplyExpression(BExpression f, BExpression a) + { function = f + ""; + func = f; + arg = a; + } + + public BApplyExpression(BExpression f, Vector arglist) + { function = f + ""; + func = f; + args = arglist; + String argstring = ""; + for (int i = 0; i < arglist.size(); i++) + { argstring = argstring + arglist.get(i); + if (i < arglist.size() - 1) + { argstring = argstring + ","; } + } + arg = new BBasicExpression(argstring); + } + + public Vector rd() + { Vector res = func.rd(); + res = VectorUtil.union(res,arg.rd()); + return res; + } + + public String getFunction() + { return function; } + + public BExpression getArgument() + { return arg; } + + public void setMultiplicity(int m) + { multiplicity = m; } + + public boolean setValued() + { if (multiplicity != ModelElement.ONE) + { return true; } + else + { return arg.setValued(); } + } + + public BExpression simplify() + { if (arg == null) + { System.err.println("Function: " + function + " with null argument"); + return null; + } + + if (func instanceof BBinaryExpression) // (f <+ {x |-> b})(x) is b + { BBinaryExpression bbe = (BBinaryExpression) func; + if (bbe.getOperator().equals("<+") && (bbe.getRight() instanceof BSetExpression)) + { BSetExpression update = (BSetExpression) bbe.getRight(); + BExpression elem0 = update.getElement(0); + if (elem0 != null && (elem0 instanceof BBinaryExpression)) + { BBinaryExpression belem0 = (BBinaryExpression) elem0; + if (belem0.getOperator().equals("|->") && (arg + "").equals(belem0.getLeft() + "")) + { return belem0.getRight(); } + } + } + } + + BExpression sarg = arg.simplify(); + if (sarg instanceof BSetExpression) + { BSetExpression se = (BSetExpression) sarg; + if (se.isSingleton()) + { BExpression argp = se.getElement(0); + // Vector vv = new Vector(); + BApplyExpression newapp = new BApplyExpression(func,argp); + newapp.setMultiplicity(multiplicity); + // vv.add(newapp); + // return new BSetExpression(vv); + return newapp; + } // f(set) is never meant for real in UML-RSDS + } + return + new BApplyExpression(func,sarg); + } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (oldE.equals(toString())) + { return newE; } + BExpression argE = arg.substituteEq(oldE,newE); + BExpression funcE = func.substituteEq(oldE,newE); + if (funcE instanceof BBasicExpression) {} + else + { funcE.setBrackets(true); } + BExpression res = new BApplyExpression(funcE,argE); + res.setMultiplicity(multiplicity); + return res; + } + + public String toString() + { if (function == null) + { return func + "(" + arg + ")"; } + return function + "(" + arg + ")"; + } +} + diff --git a/version24/BApplySetExpression.class b/version24/BApplySetExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..b623cbc13648bb0e6b5eb9e695f6df05996c6d11 GIT binary patch literal 2253 zcmai0U2_v<6n@@(ZMxmk5?UZF-ybDSQVNQQEouoAXh{JL6bmA5(`{YYe2{FA`hnjw z-Z|r4ZyfLSqK-Co?2Mzg{v)|ipR?JLq;$sV^z6Iud(Lyt`<&U{y>gd9hM9;|TmX5bDD^a&)?~aDI zb@bw{n0I97o`!dI9-Ct3G~_kRM`7vMg9QzXI`+%ae#{BldlF`gxgW)YC>#m8p`(DJ zV3p)`K~@ARD?}G+#k^~miVCspee;ny;+Vz7k(^txi;H6lAvss*%4Q}Wmn&AaN>^?N z&B~%e`k=!w!KJTpfaz} zn;2^3sJXT?GGpc4QiX+dR4sSLbZQn|f{CHq#OKa*&2jCrW9MymiHQ@F0u!y;1@0|y zr<-8y7wXEnX8ysnS@voo;be!6V6zzLmKuDtRMF0oQLW8YUE8g>*2F`F-cxYf4#}#@q8MA8Vn;vplF))G?22SFH!miET z%+zdW-l{0TKozc-nt=7@Crs1c5HD2sqeIbF`QK}rl|yH!m$cg(UrU0ESi<2=3NxRwIYQkF)zxwM@aMB zz$f@r4nH&Sxg=C~_)!&^B#CvKlg z>aWfJ+T4BWa?BTMi$t3K5p#b2oZ~3O{X`z==Sz;mNSQ5>u-=gOO)6dCOsk`>`{yTN z%i%BzZF8U|Ns3*~ak3rDm66vMDY9p6;FxUEWsucwB5mW2EOUd*7Tt^qnVMalD3oRL z8oFvBf=pWvYo=4hL4JqQ{Eh|@5Jhtp5b=6X>X*+bl=PqW6yIJ)h`zu;at$h(T16na zj^J!+4WU(plj&7Ne&VshOSCaM10DR+(T7g-Q}P0K+6S8=lz!?Fd z)zMjpAvw0f?Ivyy4q!WuGLw=~@o~p_i2!jAtfPx)+p?+TF9_GsT}RI?Sx313728+n z)2MWtS4ST&yOW>nUEJja`Dp!oa#|4x{rJp3;_VF3a*}9;ntguONOE8mu_g-*-+lDr z)HZz8B{CCX%xa^U9of{M=v~IQsXx#=ovx#A8Rc}aj-6NiD~yJQ>)5r7lk3<$E4LY5 zLwqzG4|5%>qhB7O?-7ZISJts-Hnuk&Uc)}F_iuO~XnG%vhvKB;(5-d!&c;J)IK0A~ zN0t$j4L_soZX{!SIBHuLlA4AUPU}hZ@AB;-Mxp{a$-7QS_JjYhaR+nj$Y(c>k<- PyC75-vt4GE04DzfU;yck literal 0 HcmV?d00001 diff --git a/version24/BApplySetExpression.java b/version24/BApplySetExpression.java new file mode 100644 index 00000000..8573874c --- /dev/null +++ b/version24/BApplySetExpression.java @@ -0,0 +1,79 @@ +import java.util.Vector; + +public class BApplySetExpression extends BExpression +{ private String function; + private BExpression func; + private BExpression arg; + + public BApplySetExpression(String f, BExpression a) + { function = f; + func = new BBasicExpression(f); + arg = a; + } + + public BApplySetExpression(BExpression f, BExpression a) + { func = f; + function = "" + f; + arg = a; + } + + public Vector rd() + { Vector res = new Vector(); + res.addAll(func.rd()); + return VectorUtil.union(res,arg.rd()); + } + + public boolean setValued() + { return true; } + + public void setMultiplicity(int m) + { multiplicity = m; } + + public BExpression simplify() + { BExpression sa = arg.simplify(); + if (sa instanceof BSetExpression) + { BSetExpression se = (BSetExpression) sa; + if (se.isSingleton()) + { BExpression arg1 = se.getElement(0); + Vector rr = new Vector(); + if (arg1.setValued()) + { // f[{arg1}] is f[arg] + BApplySetExpression newaps = new BApplySetExpression(func,arg1); + newaps.setMultiplicity(multiplicity); + if (multiplicity == ModelElement.ONE) + { return newaps; } + else + { return new BUnaryExpression("union",newaps); } + } // else, its {f(arg1)} + BApplyExpression ap = + new BApplyExpression(func,arg1); + ap.setMultiplicity(multiplicity); + // if (multiplicity == ModelElement.ONE) + // { + rr.add(ap); + return new BSetExpression(rr); + // } // or just ap if setValued anyway + // else + // { return ap; } + } + else if (se.isEmpty()) + { return new BSetExpression(new Vector()); } + } + BApplySetExpression res = new BApplySetExpression(func,sa); + res.setMultiplicity(multiplicity); + return res; + } + + public String toString() + { return function + "[" + arg + "]"; } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (oldE.equals(toString())) + { return newE; } + BExpression argE = arg.substituteEq(oldE,newE); + BExpression res = new BApplySetExpression(function,argE); + res.setMultiplicity(multiplicity); + return res; + } +} // and in func + diff --git a/version24/BAssignStatement.class b/version24/BAssignStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..11fce55f77b7dc793327b0e3568eb2f71d93825b GIT binary patch literal 2243 zcma)7Yj4|B7=D~4aq7D1eO=ZI=@^j4O+&ZQZM|(x*Ro5Rm0n31Ft_zGcdnB;4ls%T zz~_lSu}LgNR6_6-iC+XlJjY2Br=1XrbbQWxectzd&dDGD{PHV+>u?lY##}o(FfWz` z8MhS#F(;Ng5iE*tMl4GT?qXTSibAtb#o?Ze`wF6%lkp&ehhm$Rv8tdCIiY_fBx~aM znSym}$k>cvOF<0VGIkUUi!8(VTtPST5$p<|FJwHH&}Ka=OX$pImcJ`GM!9Sj?O944 zAq~%&w&^ZN7)i9~TMpyf5`s&`14BYr*0haW}8{*9itbi0tQNr^@+SN6)T=~i50`Gtg3;=EByaHiUDb=NpDY?tnl zvUyap%%?9UL5gt$ zh9#lhE;>iLWtLg5vQex!`^JhXiXX@*9OAizo=nEHb;oB<#(bYz5CGVaXlBE3{jrW< z3ssT*o6}U3z#%HlG0-_7SQOSvCBr71mH|K7JLEuS&l98GCJw5_zRsHevhVPbUBcx5 zpi{FNrfbs=2y(#hb_#M=LI)|oQnB}4-Xu}e!NH=%ro`&z-bj{;q>g7XJ6?BLbP5&0 zS9YdGz%6o7La1VUac=tE>kO^k0^f{Jo8%WsNc(}-yVG)AS`K0m3PCSh-t{3jTJOHl zx0HU`Z^}E$hMRGCXAGD3I+)lU-^Li9u*-b@0{oHl-j1~ASAir5%QeAMn))_=yOPI{ zlGCAp0J1O#5+v`XHENQ z$~(qYK$<2b5q0zg!ThloJWxfrSFR!=5^-Ne``H+S^hx96dW>s)&V!6GC>*qjDwNy_ zI`TXPQpZr6&I*$OL+r{hU8iuh9$<>@LNidy*qJ?b*WTeih6tN2;Tr#KYBl`Gu8I6> zCy26!uB^!XJGx&XuAM2Xhh?#zDtdRc*EO@gSGXv4zoBoH*!y!@s;1Ti@PId$Bq4)? zjId|Dl%zP9G#h@4yG8bLg{Lh0kz+}p(6SwYzmb+PJxYjtVCq1BU^oHv?kP~MR`5U- z7j_z;Lq23fK4gO)vVos*F{`~k2X30+ZlIr#Mlpjp<_K|~a26=NjXV5h_-lZR6WkbK z-E0iu5>J8&fn;-FHFB*`eyd^kCqhgGRGNU3%~n3C1I}t}W_Ue-`y9*z zzVHumfdd%DD(_#8Lt0~D>m1D{?qQ3&9q7oTfL)aF*y}",arg,rhs); + BSetExpression bse = + new BSetExpression(); + bse.addElement(maplet); + BExpression newlhs = + new BBasicExpression(f); + BExpression newrhs = + new BBinaryExpression("<+",newlhs,bse); + newrhs.setBrackets(true); + return new BAssignStatement(newlhs,newrhs); + } + return this; + } + +} + diff --git a/version24/BBasicExpression.class b/version24/BBasicExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..ecbc8655601d97e42283b5cac8d57968193ed6a2 GIT binary patch literal 1683 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 p")) + { return simplifyImp(l,r,brack); } + if (op.equals("or")) + { return simplifyOr(l,r,brack); } + if (op.equals("+") || op.equals("/") || op.equals("*") || op.equals("-")) + { return simplifyMath(op,l,r,brack); } + return new BBinaryExpression(op,l,r); + } + + private static BExpression simplifyEq(BExpression bl, BExpression br) + { if (("" + bl).equals("" + br)) + { return new BBasicExpression("true"); } + if (bl instanceof BSetExpression && + br instanceof BSetExpression) + { BSetExpression bs1 = (BSetExpression) bl; + BSetExpression bs2 = (BSetExpression) br; + if (bs1.isSingleton() && bs2.isSingleton()) + { return new BBinaryExpression("=", + bs1.getElement(0), + bs2.getElement(0)); + } + } + return new BBinaryExpression("=",bl,br); + } // Also if different VALUEs return false. + + public static BExpression simplifyIn(BExpression bl, BExpression br) + { // BExpression newleft = bl; + String newop = ":"; + + if (bl instanceof BSetExpression) + { BSetExpression bls = (BSetExpression) bl; + if (bls.isEmpty()) { return new BBasicExpression("true"); } + if (bls.isSingleton()) + { BExpression elem = (BExpression) bls.getElement(0); + return simplifyIn(elem,br); + } + else + { newop = "<:"; } // : being used to mean subset + } + + if (br instanceof BSetExpression) + { BSetExpression bs = (BSetExpression) br; + if (bs.isEmpty()) + { if (bl instanceof BSetExpression) + { BSetExpression bls = (BSetExpression) bl; + if (bls.isSingleton()) + { return new BBasicExpression("false"); } + else + { return new BBinaryExpression("=",bl,br); } + } + return new BBinaryExpression("=",bl,br); + } + if (bs.isSingleton()) + { if (bl instanceof BSetExpression) + { BSetExpression bls = (BSetExpression) bl; + if (bls.isSingleton()) + { return new BBinaryExpression("=",bls.getElement(0),bs.getElement(0)); } + return new BBinaryExpression("<:",bl,br); + } + return new BBinaryExpression(":",bl,br); + } + if (bl instanceof BSetExpression) + { BSetExpression bls = (BSetExpression) bl; + if (bls.isSubsetOf(bs)) + { return new BBasicExpression("true"); } + } + if (bs.hasElement(bl)) + { return new BBasicExpression("true"); } + } + return new BBinaryExpression(newop,bl,br); + } + + public static BExpression simplifyNin(BExpression bl, BExpression br) + { BExpression e = simplifyIn(bl,br); + return simplifyNot(e); + } + + /* if (br instanceof BSetExpression) + { BSetExpression bs = (BSetExpression) br; + if (bs.isEmpty()) { return new BBasicExpression("true"); } + if (bs.isSingleton()) + { if (bl instanceof BSetExpression) // must be singleton + { BSetExpression bls = (BSetExpression) bl; + return new BBinaryExpression("/=",bls.getElement(0), + bs.getElement(0)); + } + return new BBinaryExpression("/=",bl, + bs.getElement(0)); + } + } + return new BBinaryExpression("/:",bl,br); + } */ + + + public static BExpression simplifyNeq(BExpression bl, BExpression br) + { if ((""+bl).equals(""+br)) + { return new BBasicExpression("false"); } + if (bl instanceof BBinaryExpression && + br instanceof BSetExpression) + { BBinaryExpression blbe = (BBinaryExpression) bl; + BSetExpression bsetr = (BSetExpression) br; + if (blbe.operator.equals("/\\") && bsetr.isEmpty()) + { BExpression bll = blbe.left; + if (bll instanceof BSetExpression) + { BSetExpression bllse = (BSetExpression) bll; + if (bllse.isSingleton()) + { BExpression belem = bllse.getElement(0); + return new BBinaryExpression(":",belem,blbe.right); + } + } + } + } + BExpression e = simplifyEq(bl,br); + return simplifyNot(e); + } + + public static BExpression simplifySub(BExpression bl, BExpression br) + { if (("" + bl).equals("" + br)) + { return new BBasicExpression("true"); } + if (br instanceof BSetExpression) + { BSetExpression bs = (BSetExpression) br; + if (bl instanceof BSetExpression) + { BSetExpression bsl = (BSetExpression) bl; + if (bsl.isSubsetOf(bs)) + { return new BBasicExpression("true"); } + } + if (bs.isEmpty()) + { return new BBinaryExpression("=",bl,new BSetExpression()); } + } + if (bl instanceof BSetExpression) + { BSetExpression bsl = (BSetExpression) bl; + if (bsl.isEmpty()) { return new BBasicExpression("true"); } + if (bsl.isSingleton()) + { return new BBinaryExpression(":",bsl.getElement(0),br); } + // if both singletons, it is = + } + return new BBinaryExpression("<:",bl,br); + } + + + private static BExpression simplifyAnd(BExpression l, BExpression r) + { if (l.equals(r)) { return l; } + if (l.conflictsWith(r)) { return new BBasicExpression("false"); } + // if (l.implies(r)) { return l; } + // if (r.implies(l)) { return r; } + if ("TRUE".equals("" + l)) { return r; } + if ("true".equals("" + l)) { return r; } + if ("TRUE".equals("" + r)) { return l; } + if ("true".equals("" + r)) { return l; } // etc + if ("FALSE".equals("" + l)) { return l; } + if ("false".equals("" + l)) { return l; } + if ("FALSE".equals("" + r)) { return r; } + if ("false".equals("" + r)) { return r; } + return new BBinaryExpression("&",l,r); + } + + private static BExpression simplifyImp(BExpression l, BExpression r, + boolean bracket) + { if (l.equals(r)) { return new BBasicExpression("true"); } + // and if (l.implies(r)) + if ("TRUE".equals("" + l)) { return r; } + if ("true".equals("" + l)) { return r; } + if ("TRUE".equals("" + r)) { return new BBasicExpression("true"); } + if ("true".equals("" + r)) { return r; } + if ("FALSE".equals("" + l)) { return new BBasicExpression("true"); } + if ("false".equals("" + l)) { return new BBasicExpression("true"); } + if ("FALSE".equals("" + r)) { return simplifyNot(l); } + if ("false".equals("" + r)) { return simplifyNot(l); } + BExpression res = new BBinaryExpression("=>",l,r); + res.setBrackets(bracket); + return res; + } + + private static BExpression simplifyOr(BExpression l, BExpression r, + boolean bracket) + { if (l.equals(r)) { return l; } + // if (l.implies(r)) { return r; } + // if (r.implies(l)) { return l; } + if ("TRUE".equals("" + l)) { return new BBasicExpression("true"); } + if ("true".equals("" + l)) { return new BBasicExpression("true"); } + if ("TRUE".equals("" + r)) { return new BBasicExpression("true"); } + if ("true".equals("" + r)) { return new BBasicExpression("true"); } // etc + if ("FALSE".equals("" + l)) { return r; } + if ("false".equals("" + l)) { return r; } + if ("FALSE".equals("" + r)) { return l; } + if ("false".equals("" + r)) { return l; } + BExpression res = new BBinaryExpression("or",l,r); + res.setBrackets(bracket); + return res; + } + + private static BExpression simplifyMath(String op, BExpression l, + BExpression r, boolean brack) + { BExpression res; + BExpression ls = unmakeSet(l); + BExpression rs = unmakeSet(r); + if (op.equals("-")) + { if (l.setValued() || r.setValued()) // ls, rs? + { res = new BBinaryExpression(op,l,r); + res.setBrackets(brack); + return res; + } + } + res = new BBinaryExpression(op,ls,rs); + res.setBrackets(brack); + return res; + } // could also evaluate them. + + public static BExpression simplifyNot(BExpression e) + { // turn < into >= etc + if ("FALSE".equals("" + e)) { return new BBasicExpression("true"); } + if ("false".equals("" + e)) { return new BBasicExpression("true"); } + if ("TRUE".equals("" + e)) { return new BBasicExpression("false"); } + if ("true".equals("" + e)) { return new BBasicExpression("false"); } + if (e instanceof BBinaryExpression) + { BBinaryExpression be = (BBinaryExpression) e; + String beop = be.operator; + String newop = null; + if (beop.equals("=")) { newop = "/="; } + if (beop.equals("<=")) { newop = ">"; } + if (beop.equals("<")) { newop = ">="; } + if (beop.equals(">=")) { newop = "<"; } + if (beop.equals("/=")) { newop = "="; } + if (beop.equals("!=")) { newop = "="; } + if (beop.equals(">")) { newop = "<="; } + if (beop.equals(":")) { newop = "/:"; } + if (beop.equals("/:")) { newop = ":"; } + if (beop.equals("<:")) { newop = "/<:"; } + if (beop.equals("/<:")) { newop = "<:"; } + // for &, or, =>, not also + if (newop != null) + { return new BBinaryExpression(newop,be.left,be.right); } + } + return new BUnaryExpression("not",e); + } + + public String toString() + { String res = left + " " + operator + " " + right; + if (needsBracket) + { return "( " + res + " )"; } // eg, for or inside & + else + { return res; } + } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (oldE.equals(toString())) + { return newE; } + BExpression le = left.substituteEq(oldE,newE); + BExpression re = right.substituteEq(oldE,newE); + BExpression res = new BBinaryExpression(operator,le,re); + res.setBrackets(needsBracket); + return res; + } // copy kind also + + public boolean conflictsWith(BExpression e) + { if (e instanceof BBinaryExpression) + { BBinaryExpression be = (BBinaryExpression) e; + if (be.operator.equals("&")) + { return conflictsWith(be.left) || + conflictsWith(be.right); + } + if (be.operator.equals("or")) + { return conflictsWith(be.left) && + conflictsWith(be.right); + } + else + { return conflictsWith(be.operator, + be.left,be.right); + } + } + return false; + } + + public boolean conflictsWith(String op, BExpression el, + BExpression er) + { if (left.toString().equals(el.toString()) && + right.toString().equals(er.toString())) + { return Expression.conflictsOp(operator,op); } + if (left.toString().equals(er.toString()) && + right.toString().equals(el.toString())) + { return Expression.conflictsReverseOp(operator,op); } + if (operator.equals("=")) + { return conflictsWithEq(op,el,er); } +// if (comparitors.contains(operator)) +// { return conflictsWithComp(op,el,er); } + if (operator.equals("&")) // shouldn't occur + { return left.conflictsWith(op,el,er) || + right.conflictsWith(op,el,er); + } + if (operator.equals("or")) + { return left.conflictsWith(op,el,er) && + right.conflictsWith(op,el,er); + } + return false; + } + + public boolean conflictsWithEq(String op, BExpression el, + BExpression er) + { if (op.equals("=")) + { if (left.toString().equals(el.toString()) && + right.getKind() == Expression.VALUE && + er.getKind() == Expression.VALUE && + !right.toString().equals(er.toString())) + { return true; } + } + return false; + } +} + diff --git a/version24/BChoiceStatement.class b/version24/BChoiceStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..6bbc53878210d4574b2451d4756ccd2636770dcc GIT binary patch literal 1466 zcmai!`%V*45XQe#N^h>*%T=YQXs=W*%2kEdB4~j`6odb5+Xa?vw`IHa@>ZHiF_QQI zK9uo0ZG{C&Op`gYbI$qgd^5BC{paT|05jMKU=RsEdNCnQ(u+p{xRLN-Qm#|dO#3k7 z!(-__@nSXr1qpd=PI~hJEMQSSE=lv$i)R6Xp38@2X;!33d65=y8`_>Npk!0qwrXod z&9oN<+AV$mfML&)ZtC_kfswHDfYXoc5RxtxG=a{nZfcv=VotN(syTxZpIzFvE#2G~ z=nF@(hw4W)X{hFYvJvH*T%Rn*Ue(r()8C3LQ+0ggC2y`%m3o89)$ttRbUSXz6MLU`*tCngQnjsL_E>*3( zwyH}N!BqO7r02D>3Qb5M3U1+rf*}km7{Rc>z-4)hq@8w${^`kb(?WrFqGk zg|^;=f3(42_IiyZa&_ikqhV;uECen>9<*qpk@{&4j{$O_Tk z;Zu_PZCpE}ClJxtFqpUFVcW zZbOtbj6RN^kaO`LTDODN-GVksT8K2Mkpp%{bE946CR2*VYv|dO3Dvy?_bGaJ6GQG3 z^j*$v904+doJJuhvPoOuAC@foa6@1)+YlGrkf2z+1t-R=;^;zx1P*m;PJffre?4cC foGEgqN#J+UnlsSk3|!BdC1;MDc@kn&;zIl{fuSK~ literal 0 HcmV?d00001 diff --git a/version24/BChoiceStatement.java b/version24/BChoiceStatement.java new file mode 100644 index 00000000..e3966582 --- /dev/null +++ b/version24/BChoiceStatement.java @@ -0,0 +1,59 @@ +import java.util.Vector; + +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BChoiceStatement extends BStatement +{ private BStatement left; + private BStatement right; + + public BChoiceStatement(BStatement l, BStatement r) + { left = l; + right = r; + } + + public String toString() + { return "CHOICE " + left + " OR " + right + " END"; } + + public Vector wr() + { Vector res = new Vector(); + res.addAll(left.wr()); + return VectorUtil.union(res,right.wr()); + } + + public Vector rd() + { Vector res = new Vector(); + res.addAll(left.rd()); + return VectorUtil.union(res,right.rd()); + } + + public BStatement substituteEq(String oldE, BExpression newE) + { BStatement nl = left.substituteEq(oldE,newE); + BStatement nr = right.substituteEq(oldE,newE); + return new BChoiceStatement(nl,nr); + } + + public BStatement simplify() + { BStatement nl = left.simplify(); + BStatement nr = right.simplify(); + return new BChoiceStatement(nl,nr); + } + + public BStatement normalise() + { BStatement ln = left.normalise(); + BStatement rn = right.normalise(); + return new BChoiceStatement(ln,rn); + } + + public BStatement seq2parallel() + { BStatement ln = left.seq2parallel(); + BStatement rn = right.seq2parallel(); + return new BChoiceStatement(ln,rn); + } +} \ No newline at end of file diff --git a/version24/BComponent.class b/version24/BComponent.class new file mode 100644 index 0000000000000000000000000000000000000000..e1e23712feb5e58a9f3250eb1f95cb97e98f3b6d GIT binary patch literal 25172 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 0) + { for (int k = 0; k < subs.size(); k++) + { Entity sb = (Entity) subs.get(k); + BComponent bs = new BComponent(sb,entities,types,sb.getInvariants()); + union(bs,e,sb); + addSubclassAxiom(sb); + usesList.remove(sb.getName()); + } + } + + for (int p = 0; p < invs.size(); p++) + { Constraint inv = (Constraint) invs.get(p); + if (inv.getEvent() != null) { continue; } + BExpression binv = inv.binvariant(); + binv.setCategory(BExpression.LOGICAL); + invariants.add(binv); + } + + if (e.hasStereotype("target")) { } + else if (e.getSuperclass() == null) + { buildConstructor(e); } + + usesList.remove(getName()); + } // if e abstract, no constructor, and union + // of subclass sets equals it. + + public BComponent(String nme,Vector interfaces) // for an interface + { super(nme); + cobj = new BBasicExpression(nme + "_OBJ"); + for (int i = 0; i < interfaces.size(); i++) + { Entity intf = (Entity) interfaces.get(i); + BExpression iobj = new BBasicExpression(intf.getName() + "_OBJ"); + BExpression inv0 = + new BBinaryExpression("<:",cobj,iobj); + inv0.setCategory(BExpression.ROOT); + invariants.add(inv0); // C_OBJ <: I_OBJ + addSees(intf.getName()); + } + } // probably addSees("Bool_TYPE"), INT, STRING + + // For interfaces: + public BComponent(Vector entities, Vector types, Vector cons, Entity e) + { this(e.getName(),e.getInterfaces()); + addSees("SystemTypes"); + Vector atts = e.getAttributes(); + Vector invs = e.getInvariants(); + constraints = invs; + Vector ops = e.getOperations(); + + for (int i = 0; i < atts.size(); i++) + { Attribute att = (Attribute) atts.get(i); + if (att.isClassScope() && att.isFrozen()) + { addInterfaceAttribute(att,e,new Vector(),types,cons); } + } + + for (int p = 0; p < invs.size(); p++) + { Constraint inv = (Constraint) invs.get(p); + if (inv.getEvent() != null) { continue; } + BExpression binv = inv.binvariant(); + binv.setCategory(BExpression.LOGICAL); + invariants.add(binv); + } + + for (int q = 0; q < ops.size(); q++) + { BehaviouralFeature op = (BehaviouralFeature) ops.get(q); + BOp bop = op.getBOperationCode(e,entities,types); + if (bop != null) + { operations.add(bop); } + if (op.isQuery()) + { constants.add(op.getName() + "_" + e); + properties.add(op.buildBConstantDefinition(e,entities,types)); + } + } + + usesList.remove(getName()); + } // if e abstract, no constructor, and union + // of subclass sets equals it. + + + public void clearVariables() + { variables = new Vector(); + invariants = new Vector(); + initialisation = new Vector(); + } + + public Vector getSees() + { return seesList; } + + public Vector getIncludes() + { return includesList; } + + public Vector getUses() + { return usesList; } + + public Vector getParameters() + { return new Vector(); } + + public void addParameter(Attribute att) + { } + + public Type getType() + { return new Type("void", null); } + + public void setType(Type t) + { } + + public void removeSees(List names) + { seesList.removeAll(names); } + + public void addSees(String s) + { seesList.add(s); } // just strings at present + + public void unionSees(List l) + { seesList.addAll(l); } + + public void addIncludes(String i) + { includesList.add(i); } + + public void removeUses(List names) + { usesList.removeAll(names); } + + public void addInvariant(BExpression inv) + { invariants.add(inv); } + + public void addInvariants(Vector invs) + { invariants.addAll(invs); } + + public void addOperation(BOp op) + { operations.add(op); } + + public void addAttribute(Attribute att, Entity ent, + Vector entities,Vector types, Vector invs) + { attributes.add(att); + String attnme = att.getName(); + variables.add(attnme); + // add invariant att: cs --> T + Type t = att.getType(); + Type elemT = att.getElementType(); + + String bt = t.generateB(); + String belemType = "void"; + if (elemT != null) + { belemType = elemT.generateB(); } + + String newSeen = null; + if (bt.equals("INT") || belemType.equals("INT") ) + { newSeen = "Int_TYPE"; } + else if (bt.equals("BOOL") || belemType.equals("BOOL") ) + { newSeen = "Bool_TYPE"; } + else if (bt.equals("STRING") || + belemType.equals("STRING") ) + { newSeen = "String_TYPE"; } + if (newSeen != null & !seesList.contains(newSeen)) + { seesList.add(newSeen); } + + BExpression ran = new BBasicExpression(bt); + BExpression attbe = + new BBasicExpression(attnme); + BExpression attxbe = + new BBasicExpression(attnme + "xx"); + BExpression fun; + if (att.isUnique()) + { fun = new BBinaryExpression(">->",objs,ran); } + else if (att.isClassScope()) + { fun = ran; } // also modify Set and Get + else + { fun = new BBinaryExpression("-->",objs,ran); } + BExpression atttyping = new BBinaryExpression(":",attbe,fun); + atttyping.setCategory(BExpression.FEATURE); + invariants.add(atttyping); + + // add att := {} to init: + BExpression empty = + new BSetExpression(new Vector()); + if (att.isInstanceScope()) + { initialisation.add( + new BAssignStatement(attbe,empty)); + } // else get default value of type + else + { String defval = att.getDefaultValue(); + BExpression bdef = new BBasicExpression(defval); + initialisation.add( + new BAssignStatement(attbe,bdef)); + } + + // add setatt and getatt operations: + String cx = getName().toLowerCase() + "x"; + BOp getatt; + if (att.isInstanceScope()) + { getatt = + BOp.buildGetOperation(attnme,cx,objs); + } + else + { getatt = BOp.buildStaticGetOperation(attnme); } + + operations.add(getatt); + + if (ent.hasStereotype("target")) { return; } + + if (att.isUpdatable()) + { BOp setatt; + BOp updatt; + BOp setAllatt; + if (att.isInstanceScope()) + { setatt = + BOp.buildSetOperation(attnme,cx,objs,ran,att.isUnique(),null,0,ModelElement.ONE, + ent,entities,types,invs); + setatt.setSignature("set" + attnme); // ??? + /* BExpression possiblePre = Constraint.conjoinAllSelected(attnme, + getName(), + constraints); + BExpression preset = + possiblePre.substituteEq(attnme + "(" + cx + ")",attxbe); + System.out.println("POSIBLE PRE: " + preset); + setatt.addPre(preset); + */ + + updatt = + BOp.buildUpdateOperation(attnme,objs,null,ran,att.isUnique()); + setAllatt = + BOp.buildSetAllOperation(attnme,cx,objs,ran); + operations.add(setatt); + operations.add(updatt); + operations.add(setAllatt); + } + else + { setatt = BOp.buildStaticSetOperation(attnme,cx,objs,ran,att.isUnique(), ModelElement.ONE,ent, + entities,types,invs); + if (setatt != null) + { operations.add(setatt); } + } + } + } + + public void addsetOperation(Attribute att, Entity ent, + Vector entities,Vector types, Vector invs) + { String attnme = att.getName(); + Type t = att.getType(); + String bt = t.generateB(); + + BExpression ran = new BBasicExpression(bt); + BExpression attbe = + new BBasicExpression(attnme); + BExpression attxbe = + new BBasicExpression(attnme + "xx"); + + String cx = getName().toLowerCase() + "x"; // e.getName()... + + if (att.isUpdatable()) + { BOp setatt; + BOp updatt; + BOp setAllatt; + if (att.isInstanceScope()) + { setatt = + BOp.buildSetOperation(attnme,cx,objs,ran,att.isUnique(),null,0,ModelElement.ONE, + ent,entities,types,invs); + System.out.println("Invs are: " + invs); + System.out.println("For " + attnme + " " + cx + " " + ent); + System.out.println(setatt); + setatt.setSignature("set" + attnme); + // updatt = + // BOp.buildUpdateOperation(attnme,objs,ran,att.isUnique()); + // setAllatt = + // BOp.buildSetAllOperation(attnme,cx,objs,ran); + operations.add(setatt); + // operations.add(updatt); + // operations.add(setAllatt); + } + } + } + + public void addsetOperation(Association ast, Entity ent, + Vector entities,Vector types, Vector invs) + { String attnme = ast.getRole2(); + String role1 = ast.getRole1(); + boolean isseq = ast.isOrdered(); + Entity ent2 = ast.getEntity2(); // must USE unless in same inherit family + String e2name = ent2.getName(); + String e2s = e2name.toLowerCase() + "s"; + // role: objs --> ent2s or FIN(ent2s) + int card1 = ast.getCard1(); + int card2 = ast.getCard2(); + BExpression targ; + BExpression elemtype; + if (card2 == ONE) + { targ = new BBasicExpression(e2s); + elemtype = targ; + } + else + { elemtype = new BBasicExpression(e2s); + if (isseq) + { targ = new BUnaryExpression("seq",elemtype); } + else + { targ = new BUnaryExpression("FIN",elemtype); } + } + + BExpression attbe = + new BBasicExpression(attnme); + BExpression attxbe = + new BBasicExpression(attnme + "xx"); + + + String cx = getName().toLowerCase() + "x"; // e.getName()... + BExpression cxbe = new BBasicExpression(cx); + + BExpression possiblePre = Constraint.conjoinAllSelected(attnme,getName(), + invs); + + if (!ast.isFrozen()) + { BOp setrole = + BOp.buildSetOperation(attnme,cx,objs,targ,ast.isInjective(),role1,card1,card2, + ent,entities,types,invs); + System.out.println("Invs are: " + invs); + System.out.println("For " + attnme + " " + cx + " " + ent); + System.out.println(setrole); + setrole.setSignature("set" + attnme); + // updatt = + // BOp.buildUpdateOperation(attnme,objs,ran,att.isUnique()); + // setAllatt = + // BOp.buildSetAllOperation(attnme,cx,objs,ran); + operations.add(setrole); + // operations.add(updatt); + // operations.add(setAllatt); + } + if (card2 != ONE) + { if (!ast.isFrozen()) + { BOp addop = BOp.buildAddOperation(attnme,cx,objs,elemtype,role1,card1,card2,isseq, + ent,entities,types,invs); + BExpression rolecx = new BApplyExpression(attnme,cxbe); + BSetExpression setrolexbe = new BSetExpression(); + setrolexbe.addElement(attxbe); + setrolexbe.setOrdered(isseq); + BExpression sub; + if (isseq) + { sub = new BBinaryExpression("^",rolecx,setrolexbe); } + else + { sub = new BBinaryExpression("\\/",rolecx,setrolexbe); } + BExpression preset2 = possiblePre.substituteEq(attnme + "(" + cx + ")",sub); + System.out.println("POSIBLE PRE: " + preset2); + addop.addPre(preset2); + + addop.setSignature("add" + attnme); + operations.add(addop); + + if (isseq) + { BOp setindop = BOp.buildSetIndOp(attnme,cx,objs,elemtype,ent); + operations.add(setindop); + } + + if (!ast.isAddOnly()) + { BOp delop = BOp.buildDelOperation(attnme,cx,objs,elemtype, + role1,card1,ent,entities,types,invs); + BExpression sub2 = new BBinaryExpression("-",rolecx,setrolexbe); + BExpression preset3 = + possiblePre.substituteEq(attnme + "(" + cx + ")",sub); + System.out.println("POSIBLE PRE: " + preset3); + delop.addPre(preset3); + delop.setSignature("remove" + attnme); + operations.add(delop); + } + } + } // also use contraints, and these ops for the Controller + } // plus cardinality preconditions + + + public void addInterfaceAttribute(Attribute att, Entity ent, + Vector entities,Vector types, Vector invs) + { attributes.add(att); + String attnme = att.getName(); + variables.add(attnme); + // add invariant att: cs --> T + Type t = att.getType(); + String bt = t.generateB(); + + String newSeen = null; + if (bt.equals("INT")) + { newSeen = "Int_TYPE"; } + else if (bt.equals("BOOL")) + { newSeen = "Bool_TYPE"; } + else if (bt.equals("STRING")) + { newSeen = "String_TYPE"; } + if (newSeen != null & !seesList.contains(newSeen)) + { seesList.add(newSeen); } + + + BExpression ran = new BBasicExpression(bt); + BExpression attbe = + new BBasicExpression(attnme); + BExpression attxbe = + new BBasicExpression(attnme + "xx"); + BExpression fun; + if (att.isUnique()) + { fun = new BBinaryExpression(">->",objs,ran); } + else if (att.isClassScope()) + { fun = ran; } // also modify Set and Get + else + { fun = new BBinaryExpression("-->",objs,ran); } + BExpression atttyping = new BBinaryExpression(":",attbe,fun); + atttyping.setCategory(BExpression.FEATURE); + invariants.add(atttyping); + + // add att := {} to init: + BExpression empty = + new BSetExpression(new Vector()); + if (att.isInstanceScope()) + { initialisation.add( + new BAssignStatement(attbe,empty)); + } // else get default value of type + else + { String defval = att.getDefaultValue(); + BExpression bdef = new BBasicExpression(defval); + initialisation.add( + new BAssignStatement(attbe,bdef)); + } + + // add setatt and getatt operations: + BOp getatt = BOp.buildStaticGetOperation(attnme); + + operations.add(getatt); + } + + public void addRole(String role, Association ast, Entity ent, + Vector entities,Vector types, Vector invs) + { variables.add(role); + roles.add(ast); + String role1 = ast.getRole1(); + int card1 = ast.getCard1(); + int card2 = ast.getCard2(); + boolean isseq = ast.isOrdered(); + boolean isqual = ast.isQualified(); + + Entity ent2 = ast.getEntity2(); // must USE unless in same inherit family + String e2name = ent2.getName(); + String e2top = ent2.getTopSuperclass() + ""; + if (usesList.contains(e2top)) { } + else { usesList.add(e2top); } // Beware of cycles + String e2s = e2name.toLowerCase() + "s"; + // role: objs --> ent2s or FIN(ent2s) + BExpression targ; + BExpression elemtype; + if (card2 == ONE) + { targ = new BBasicExpression(e2s); + elemtype = targ; + if (isqual) + { BExpression stype = new BBasicExpression("STRING"); + targ = new BBinaryExpression("+->",stype,targ); + targ.setBrackets(true); + } + } + else + { elemtype = new BBasicExpression(e2s); + if (isseq) + { targ = new BUnaryExpression("seq",elemtype); } + else if (isqual) + { BExpression stype = new BBasicExpression("STRING"); + targ = new BBinaryExpression("+->",stype, + new BUnaryExpression("FIN",elemtype)); + targ.setBrackets(true); + } + else + { targ = new BUnaryExpression("FIN",elemtype); } + } + + BExpression rolebe = + new BBasicExpression(role); + BExpression rolexbe = + new BBasicExpression(role + "xx"); + + BExpression fun; + if (ast.isInjective() && !isqual) + { fun = new BBinaryExpression(">->",objs,targ); } + else + { fun = new BBinaryExpression("-->",objs,targ); } + BExpression roletyping = new BBinaryExpression(":",rolebe,fun); + roletyping.setCategory(BExpression.FEATURE); + invariants.add(roletyping); + + // add role := {} to init: + BExpression empty = + new BSetExpression(new Vector()); + initialisation.add( + new BAssignStatement(rolebe,empty)); + + String cx = getName().toLowerCase() + "x"; + BExpression cxbe = new BBasicExpression(cx); + + if (card2 == ZEROONE && !isqual) + { BExpression rhs = new BApplyExpression(role,cxbe); + BExpression cardleq = + new BBinaryExpression("<=", + new BUnaryExpression("card",rhs), + new BBasicExpression("1")); + BExpression lhs = new BBinaryExpression(":",cxbe,objs); + BExpression cardinv = + new BQuantifierExpression("forall",cx, + new BBinaryExpression("=>",lhs,cardleq)); + cardinv.setCategory(BExpression.LOGICAL); + invariants.add(cardinv); + } + + if (role1 != null && role1.length() > 0) + { // add appropriate inverse constraint to invariants + // !(ax,bx).(ax : as & bx : bs => (bx : br(ax) <=> ax : ar(bx)) ) + BExpression e2objs = new BBasicExpression(e2s); + String e2x = e2name.toLowerCase() + "x"; + BExpression e2xbe = new BBasicExpression(e2x); + + BExpression role1app = new BApplyExpression(role1,e2xbe); + BExpression role2app = new BApplyExpression(role,cxbe); + BExpression end1exp; + BExpression end2exp; + if (card1 == ONE) + { end1exp = new BBinaryExpression("=",cxbe,role1app); } + else + { end1exp = new BBinaryExpression(":",cxbe,role1app); } + if (card2 == ONE) + { end2exp = new BBinaryExpression("=",e2xbe,role2app); } + else + { end2exp = new BBinaryExpression(":",e2xbe,role2app); } + + BExpression equivends = + new BBinaryExpression("=>",end1exp,end2exp); + equivends.setBrackets(true); + + BExpression lhs2 = new BBinaryExpression(":",e2xbe,e2objs); + BExpression invinv1 = + new BQuantifierExpression("forall",e2x, + new BBinaryExpression("=>",lhs2,equivends)); + BExpression lhs1 = new BBinaryExpression(":",cxbe,objs); + BExpression invinv2 = + new BQuantifierExpression("forall",cx, + new BBinaryExpression("=>",lhs1,invinv1)); + invinv2.setCategory(BExpression.LOGICAL); + invariants.add(invinv2); + } + + + BOp getrole = + BOp.buildGetOperation(role,cx,objs); + operations.add(getrole); + + if (ent.hasStereotype("target")) { return; } + + if (isqual) + { operations.add(BOp.buildGetQualOperation(role,cx,objs)); + BOp setqop = BOp.buildSetQualOp(role,cx,objs,elemtype,ent); + operations.add(setqop); + if (card2 != ONE) + { BOp qadd = BOp.buildAddQualOperation(role,cx,objs,elemtype,card2,isseq, + ent,entities,types,invs); + operations.add(qadd); + BOp qrem = BOp.buildDelQualOperation(role,cx,objs,elemtype, + ent,entities,types,invs); + operations.add(qrem); + } + return; + } + + BExpression possiblePre = Constraint.conjoinAllSelected(role,getName(), + constraints); + + if (!ast.isFrozen()) + { BOp setrole = + BOp.buildSetOperation(role,cx,objs,targ,ast.isInjective(),role1,card1,card2, + ent,entities,types,invs); + // BExpression preset = + // possiblePre.substituteEq(role + "(" + cx + ")",rolexbe); + // System.out.println("POSIBLE PRE: " + preset); + // setrole.addPre(preset); + setrole.setSignature("set" + role); + + BOp updrole = + BOp.buildUpdateOperation(role,objs,ast,targ,ast.isInjective()); + operations.add(setrole); + operations.add(updrole); + } + + if (card2 != ONE) + { if (!ast.isFrozen()) + { BOp addop = BOp.buildAddOperation(role,cx,objs,elemtype,role1,card1,card2,isseq, + ent,entities,types,invs); + BExpression rolecx = new BApplyExpression(role,cxbe); + BSetExpression setrolexbe = new BSetExpression(); + setrolexbe.addElement(rolexbe); + setrolexbe.setOrdered(isseq); + BExpression sub; + if (isseq) + { sub = new BBinaryExpression("^",rolecx,setrolexbe); } + else + { sub = new BBinaryExpression("\\/",rolecx,setrolexbe); } + BExpression preset2 = possiblePre.substituteEq(role + "(" + cx + ")",sub); + System.out.println("POSIBLE PRE: " + preset2); + addop.addPre(preset2); + + addop.setSignature("add" + role); + operations.add(addop); + + if (isseq) + { BOp setindop = BOp.buildSetIndOp(role,cx,objs,elemtype,ent); + operations.add(setindop); + } + + if (!ast.isAddOnly()) + { BOp delop = + BOp.buildDelOperation(role,cx,objs,elemtype,role1,card1,ent,entities,types,invs); + BExpression sub2 = new BBinaryExpression("-",rolecx,setrolexbe); + BExpression preset3 = possiblePre.substituteEq(role + "(" + cx + ")",sub); + System.out.println("POSIBLE PRE: " + preset3); + delop.addPre(preset3); + delop.setSignature("remove" + role); + operations.add(delop); + } + } + } // also use contraints, and these ops for the Controller + } // plus cardinality preconditions + // if (card2 == ZEROONE) + // { card(role2x) <= 1 } etc + + public void addSetDefinition(String nme, Vector vals) + { if (basicTypes.contains(nme)) + { return; } + BTypeDef td = new BTypeDef(nme,vals); + types.add(td); + } + + public void buildConstructor(Entity e) + { buildConstructor(e,"oo",null,new Vector(),new Vector()); } + + private void buildConstructor(Entity e, String res, BExpression pre0, + Vector params0, Vector assigns) + { System.out.println("Building constructor for " + e + + " with invariants " + e.getInvariants()); + Vector eatts = e.getAttributes(); + String nme = e.getName(); + String objset = nme.toLowerCase() + "s"; + BExpression eobjs = new BBasicExpression(objset); + java.util.Map env = new java.util.HashMap(); + + BExpression localInvPre = Constraint.conjoinAll(e.getInvariants()); + // constraints? + Vector oldatts = e.allInheritedAttributes(); + Vector oldasts = e.allInheritedAssociations(); + for (int i = 0; i < oldatts.size(); i++) + { Attribute oldatt = (Attribute) oldatts.get(i); + String oldattnme = oldatt.getName(); + // localInvPre = localInvPre.substituteEq(oldattnme, + // new BBasicExpression(oldattnme + "x")); + } + for (int i = 0; i < oldasts.size(); i++) + { Association oldast = (Association) oldasts.get(i); + String oldastnme = oldast.getRole2(); + // localInvPre = localInvPre.substituteEq(oldastnme, + // new BSetExpression()); + } // unless the association is initialised ... + + + int natts = eatts.size(); + String[] attparams = new String[natts]; + Vector params = (Vector) params0.clone(); + BExpression[] attbes = new BExpression[natts]; + BExpression[] attpres = new BExpression[natts]; + BExpression pre = + new BBinaryExpression("/=",eobjs,cobj); + if (pre0 != null) + { pre = pre0; } + + Vector attassigns = (Vector) assigns.clone(); + String oox = getName().toLowerCase() + "x"; + BExpression ooxbe = new BBasicExpression(oox); + // objs := objs \/ { ooxbe } + Vector newelem = new Vector(); + newelem.add(ooxbe); + BAssignStatement create = + new BAssignStatement(eobjs, + new BBinaryExpression("\\/",eobjs, + new BSetExpression(newelem))); + attassigns.add(create); + BExpression resbe = new BBasicExpression(res); + + for (int i = 0; i < natts; i++) + { Attribute att = (Attribute) eatts.get(i); + String attini = att.getInitialValue(); + Expression attiniexp = att.getInitialExpression(); + + if (att.isInstanceScope()) + { Type typ = att.getType(); + String attname = att.getName(); + String attx = attname + "x"; + attparams[i] = attx; + params.add(attparams[i]); + attbes[i] = new BBasicExpression(attparams[i]); + attpres[i] = + new BBinaryExpression(":",attbes[i], + new BBasicExpression(typ.generateB())); + pre = new BBinaryExpression("&",pre,attpres[i]); + BExpression lhs = + new BApplyExpression(attname,ooxbe); + if (attiniexp == null || attini.equals("")) + { attassigns.add( + new BAssignStatement(lhs,attbes[i])); + // localInvPre = localInvPre.substituteEq(attname,attbes[i]); + } + else + { BExpression attinibe = attiniexp.binvariantForm(env,true); + attassigns.add(new BAssignStatement(lhs,attinibe)); + // localInvPre = localInvPre.substituteEq(attname,attinibe); + } + + if (att.isUnique()) // attx /: ran(att) + { BExpression uniqpre = + new BBinaryExpression("/:",attbes[i], + new BUnaryExpression("ran",new BBasicExpression(attname))); + pre = new BBinaryExpression("&",pre,uniqpre); + } + } + } + + Vector eroles = e.getAssociations(); + for (int j = 0; j < eroles.size(); j++) + { Association ast = (Association) eroles.get(j); + String role = ast.getRole2(); + BExpression lhs2 = + new BApplyExpression(role,ooxbe); + int card2 = ast.getCard2(); + if (card2 >= 1) + { String rlex = role + "x"; // input param + params.add(rlex); + BExpression rlexbe = new BBasicExpression(rlex); + String e2name = ast.getEntity2().getName(); + String e2s = e2name.toLowerCase() + "s"; + BExpression e2be = new BBasicExpression(e2s); + BExpression rlepre; + if (card2 == ONE) + { rlepre = + new BBinaryExpression(":",rlexbe,e2be); + rlexbe.setMultiplicity(ModelElement.ONE); + } + else // {n} + { BExpression carde = + new BBinaryExpression("=", + new BUnaryExpression("card",rlexbe), + new BBasicExpression("" + card2)); + rlepre = + new BBinaryExpression("&",carde, + new BBinaryExpression("<:",rlexbe,e2be)); + rlexbe.setMultiplicity(ModelElement.MANY); + } + pre = new BBinaryExpression("&",pre,rlepre); + attassigns.add( + new BAssignStatement(lhs2,rlexbe)); + String role1 = ast.getRole1(); + if (role1 != null && role1.length() > 0) + { int card1 = ast.getCard1(); + BExpression invrhs = + BasicExpression.computeInverseBExpressionSet(ast,role1,role,card1,card2,ooxbe,rlexbe); + BExpression invlhs = new BBasicExpression(role1); + BStatement invstat = new BAssignStatement(invlhs,invrhs); + attassigns.add(invstat); + } + // localInvPre = localInvPre.substituteEq(role,rlexbe); + } + else if (ast.isFrozen()) + { String rlex = role + "x"; // input param + params.add(rlex); + BExpression rlexbe = new BBasicExpression(rlex); + rlexbe.setMultiplicity(ModelElement.ONE); + String e2name = ast.getEntity2().getName(); + String e2s = e2name.toLowerCase() + "s"; + BExpression e2be = new BBasicExpression(e2s); + BExpression rlepre; + rlepre = new BBinaryExpression("<:",rlexbe,e2be); + pre = new BBinaryExpression("&",pre,rlepre); + attassigns.add( + new BAssignStatement(lhs2,rlexbe)); + // localInvPre = localInvPre.substituteEq(role,rlexbe); + } + else // MANY, not frozen + { BExpression rhs = new BSetExpression(new Vector(),ast.isOrdered()); + attassigns.add( + new BAssignStatement(lhs2,rhs)); + // localInvPre = localInvPre.substituteEq(role,rhs); + } + } + Vector allassigns = new Vector(); + allassigns.addAll(attassigns); + allassigns.add( + new BAssignStatement(resbe,ooxbe)); + // The WHERE clause: + BExpression where = + new BBinaryExpression(":",ooxbe, + new BBinaryExpression("-",cobj,eobjs)); + Vector anyvars = new Vector(); + anyvars.add(oox); + BStatement anystat = + new BAnyStatement(anyvars,where, + new BParallelStatement(allassigns)); + // System.out.println("Local invariant precondition: " + localInvPre); + // BExpression simpre = localInvPre.simplify(); + /* if (simpre == null || simpre.toString().equals("true")) { } + else + { simpre.setBrackets(true); + pre = new BBinaryExpression("&",pre,simpre); + } */ + BOp newC = + new BOp("new_" + nme,res, + params,pre, + anystat); + + Vector subs = e.getSubclasses(); + for (int h = 0; h < subs.size(); h++) + { Entity esub = (Entity) subs.get(h); + buildConstructor(esub,res,pre,params,attassigns); + } + + operations.add(0,newC); // at position 0 + } + + public void generateJava(java.io.PrintWriter out) // not used + { out.println("public abstract class " + getName() + " { }"); } + + public String toString() + { String res = "MACHINE " + getName() + "\n"; + int sc = seesList.size(); + int uc = usesList.size(); + int ic = includesList.size(); + int pc = promotes.size(); + int tc = types.size(); + int conssize = constants.size(); + int propsize = properties.size(); + int vc = variables.size(); + int invc = invariants.size(); + int initc = initialisation.size(); + int opc = operations.size(); + if (sc > 0) + { res = res + "SEES "; + for (int i = 0; i < sc; i++) + { res = res + seesList.get(i); + if (i < sc - 1) + { res = res + ", "; } + else + { res = res + "\n"; } + } + } + if (uc > 0) + { res = res + "USES "; + for (int i = 0; i < uc; i++) + { res = res + usesList.get(i); + if (i < uc - 1) + { res = res + ", "; } + else + { res = res + "\n"; } + } + } + if (ic > 0) + { res = res + "INCLUDES "; + for (int i = 0; i < ic; i++) + { res = res + includesList.get(i); + if (i < ic - 1) + { res = res + ", "; } + else + { res = res + "\n"; } + } + } + if (pc > 0) + { res = res + "PROMOTES "; + for (int i = 0; i < pc; i++) + { res = res + promotes.get(i); + if (i < pc - 1) + { res = res + ", "; } + else + { res = res + "\n"; } + } + } + if (tc > 0) + { res = res + "SETS "; + for (int i = 0; i < tc; i++) + { res = res + types.get(i); + if (i < tc - 1) + { res = res + "; "; } + else + { res = res + "\n"; } + } + } + if (conssize > 0) + { res = res + "CONSTANTS "; + for (int i = 0; i < conssize; i++) + { res = res + constants.get(i); + if (i < conssize - 1) + { res = res + ", "; } + else + { res = res + "\n"; } + } + } + if (propsize > 0) + { res = res + "PROPERTIES "; + for (int i = 0; i < propsize; i++) + { res = res + properties.get(i); + if (i < propsize - 1) + { res = res + " &\n "; } + else + { res = res + "\n"; } + } + } + if (vc > 0) + { res = res + "VARIABLES "; + for (int i = 0; i < vc; i++) + { res = res + variables.get(i); + if (i < vc - 1) + { res = res + ", "; } + else + { res = res + "\n"; } + } + } + if (invc > 0) + { res = res + "INVARIANT "; + for (int i = 0; i < invc; i++) + { res = res + "(" + invariants.get(i) + ")"; + if (i < invc - 1) + { res = res + " & \n "; } + else + { res = res + "\n"; } + } + } + if (initc > 0) + { res = res + "INITIALISATION "; + for (int i = 0; i < initc; i++) + { res = res + initialisation.get(i); + if (i < initc - 1) + { res = res + " || \n "; } + else + { res = res + "\n"; } + } + } + if (opc > 0) + { res = res + "OPERATIONS\n "; + for (int i = 0; i < opc; i++) + { res = res + operations.get(i); + if (i < opc - 1) + { res = res + "; \n\n "; } + else + { res = res + "\n"; } + } + } + return res + "END"; + } + + public void display(PrintWriter out) + { out.println(toString()); } + + public void union(BComponent b,Entity sup,Entity sub) + { seesList = VectorUtil.union(seesList,b.getSees()); + usesList = VectorUtil.union(usesList,b.usesList); + includesList = VectorUtil.union(includesList, + b.includesList); + promotes = VectorUtil.union(promotes,b.promotes); + types = VectorUtil.union(types,b.types); + constants = VectorUtil.union(constants,b.constants); + properties = VectorUtil.union(properties,b.properties); + variables = VectorUtil.union(variables,b.variables); + attributes = VectorUtil.union(attributes,b.attributes); + roles = VectorUtil.union(roles,b.roles); + Vector rootinvs = new Vector(); + Vector subclassinvs = new Vector(); + Vector featureinvs = new Vector(); + Vector logicalinvs = new Vector(); + Vector otherinvs = new Vector(); + for (int i = 0; i < invariants.size(); i++) + { BExpression be = (BExpression) invariants.get(i); + int categ = be.getCategory(); + if (categ == BExpression.ROOT) { rootinvs.add(be); } + else if (categ == BExpression.SUBCLASS) { subclassinvs.add(be); } + else if (categ == BExpression.FEATURE) { featureinvs.add(be); } + else if (categ == BExpression.LOGICAL) { logicalinvs.add(be); } + else { otherinvs.add(be); } + } + for (int i = 0; i < b.invariants.size(); i++) + { BExpression be = (BExpression) b.invariants.get(i); + int categ = be.getCategory(); + if (categ == BExpression.ROOT) { rootinvs.add(be); } + else if (categ == BExpression.SUBCLASS) { subclassinvs.add(be); } + else if (categ == BExpression.FEATURE) { featureinvs.add(be); } + else if (categ == BExpression.LOGICAL) { logicalinvs.add(be); } + else { otherinvs.add(be); } + } + invariants.clear(); + invariants.addAll(rootinvs); invariants.addAll(subclassinvs); + invariants.addAll(featureinvs); invariants.addAll(logicalinvs); + invariants.addAll(otherinvs); + + // invariants = VectorUtil.union(invariants,b.invariants); + initialisation = VectorUtil.union(initialisation, + b.initialisation); + for (int i = 0; i < b.operations.size(); i++) + { BOp op = (BOp) b.operations.get(i); + String sig = op.getSignature(); + BOp supop = getBySignature(sig); + if (supop == null || sup == null) + { operations.add(op); } + else + { BOp newop = mergeOperations(supop,op,sup,sub); + operations.remove(supop); + operations.add(newop); + } + } + Vector unuseduses = new Vector(); + unuseduses.add(b.getName()); + unuseduses.add(sub + ""); + removeUses(unuseduses); // surely? + removeSees(unuseduses); + } + + private BOp getBySignature(String sig) + { for (int i = 0; i < operations.size(); i++) + { BOp op = (BOp) operations.get(i); + if (sig != null && sig.equals(op.getSignature())) + { return op; } + } + return null; + } + + private BOp mergeOperations(BOp superop, BOp subop,Entity sup, Entity sub) + { // two operations with same signature. merge is: + // PRE superop.pre + // THEN IF cx : ds THEN subop.code[cx/dx] ELSE superop.code END END + BOp res; + String cx = sup.getName().toLowerCase() + "x"; + String dx = sub.getName().toLowerCase() + "x"; + String ds = sub.getName().toLowerCase() + "s"; + + BExpression cxbe = new BBasicExpression(cx); + BExpression dsbe = new BBasicExpression(ds); + BExpression insubclass = new BBinaryExpression(":",cxbe,dsbe); + + BStatement supercode = superop.getCode(); + BStatement subcode = subop.getCode(); + System.out.println("Substituting in " + subop + " " + dx + " " + cxbe); + BStatement sc = subcode.substituteEq(dx,cxbe); + BStatement bif = new BIfStatement(insubclass,sc,supercode); + res = new BOp(superop.getName(),superop.getResult(), + superop.getParameters(),superop.getPre(),bif); + res.setSignature(superop.getSignature()); + return res; + } + + + private void addSubclassAxiom(Entity e) + { // Adds es <: sups AFTER sups definition + + Entity sup = e.getSuperclass(); + if (sup == null) { return; } + String sups = sup.getName().toLowerCase() + "s"; + String es = e.getName().toLowerCase() + "s"; + usesList.remove(e.getName()); // no need to USE it as available anyway + BBasicExpression bsups = + new BBasicExpression(sups); + BBasicExpression bes = + new BBasicExpression(es); + BBinaryExpression inv = + new BBinaryExpression("<:",bes,bsups); + inv.setCategory(BExpression.SUBCLASS); + for (int i = 0; i < invariants.size(); i++) + { BExpression inve = (BExpression) invariants.get(i); + if (inve instanceof BBinaryExpression) + { BBinaryExpression binv = (BBinaryExpression) inve; + if (sups.equals(binv.getLeft() + "")) + { invariants.add(i+1,inv); + return; + } + } + } + invariants.add(inv); + } +} + diff --git a/version24/BExpression.class b/version24/BExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..8214b260676b41997b359c650933fdacd40cb3d9 GIT binary patch literal 2287 zcmah~ZBrX%6g``SY+g1%p%hCgQqdZgmuR)x0#Zo`G&CtK8$v;=E@7by$tKNi9Q!By z&VT3!bV`_!8Am@k<6m;d@jROVo0O?v?z8vVd(S=h+`Gx&|NiznfX`8nUTV2gdh@~o) z?dXj%r5Ez+YiZ&7=w?@!GpU8FaQ%!f>W;BjsS!Uo zXIiE+FTo!lFR(_cvSUc-$(ok&xL)2iYI%LT#2eW*oJUO>@r;O+_s%YuNs>_pq|RZZ ze0$-A`Oam_E*Q-&L$+CFkGo{h6Ccke(?3;fhHaY_YnBq&^=;cRow{SBUrLycXZQ6V z^+ZXx_7a*?Gp)VZwv5jF9+u0ssVJBA149!M569n`8q*xkBBxhdZHMdDd1_bPav?;g zt&!POEWRb=h!rc=E{EpW8>aI@LT^VM_MG^?KH8Zv!&jqVSE-NNf88-liGopdDm97} z(JJ*?(O5FYbb37kPK#g#Dkc=%z%b>^ai*no$tW9^qu?e+n0+C*g7?Ku)B~Yl93u)p zio1mFtgWC3(&|o93@?fbL%}ZYD%isd8K#1L97q`KoL#bRmUfJqf)dJvAI)f^S~@>f zSjeuY7iUJry(LUVK@~4$FwzDm*CgUD!Rq!tW#BI9J7hB8)wTI*R_xf>y;nCes;Fse z+@X@;R4gjNO>Jqz8r zKrBh1t0$0D|1o@O;1~hbcZ{GKJVxjjzNCz_*U&{9BTzTO=%MXJKL+`B z8i^L%2;qE;3aU2LG=&BvJ(yT93nd5Z=g3fdF1xfL?7Xzft?3&kF&hbzs?!1$}E4c z=D1o9+)4rXfY~Z~H zt_z1Ev@yEPN*JLl`1##6>7 miGDF*F%6&pHLZ8y@^0LsCr(V^?YL*$oHRL!>}3&whyMW;i^6CC literal 0 HcmV?d00001 diff --git a/version24/BExpression.java b/version24/BExpression.java new file mode 100644 index 00000000..7513624e --- /dev/null +++ b/version24/BExpression.java @@ -0,0 +1,93 @@ +import java.util.Vector; + +/* Package: B */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public abstract class BExpression +{ protected boolean needsBracket = false; + protected int multiplicity = ModelElement.ONE; + protected int kind = Expression.UNKNOWN; + + public final static int ROOT = 0; + public final static int SUBCLASS = 1; + public final static int FEATURE = 2; + public final static int LOGICAL = 3; + + protected int category = LOGICAL; + + public void setKind(int k) + { kind = k; } + + public int getKind() + { return kind; } + + public void setCategory(int c) + { category = c; } + + public int getCategory() + { return category; } + + public abstract boolean setValued(); + + public abstract BExpression simplify(); + + public BExpression substituteEq(String oldE, BExpression newE) + { return this; } // default + + public void setMultiplicity(int m) + { multiplicity = m; } + + public static BExpression makeSet(BExpression e) + { if (e.setValued()) { return e; } + Vector elems = new Vector(); + elems.add(e); + return new BSetExpression(elems); + } + + public static BExpression unmakeSet(BExpression e) + { if (e == null) { return e; } // should not occur + if (e instanceof BSetExpression) + { BSetExpression bset = (BSetExpression) e; + if (bset.isSingleton()) + { BExpression res = bset.getElement(0); + return res; + } + } + return e; + } + + public static BExpression unSet(BExpression e) + { if (e == null) { return e; } + if (e instanceof BSetExpression) + { BSetExpression se = (BSetExpression) e; + if (se.isSingleton()) + { BExpression res = se.getElement(0); + System.out.println(res + " IS SET-VALUED: " + res.setValued()); + if (res.setValued()) + { return res; } + } + } + return e; + } + + public void setBrackets(boolean brack) + { needsBracket = brack; } + + public boolean conflictsWith(final BExpression e) + { return false; } // default + + public boolean conflictsWith(String op, BExpression el, + BExpression er) + { return false; } + + public abstract Vector rd(); +} + + diff --git a/version24/BIfStatement.class b/version24/BIfStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..a3f77cb677efbd75e0861032c8c98030be44e964 GIT binary patch literal 2796 zcmai0TT@e46#jM+azZ==xi^RiY6~P>ytWEngF&$nw4jLhkR0$pNJ4U=c6$E@eeJaG zzS@}zoifvDU+heOQ|t6w=N!lhqII0L_g;IQ^?mEISNQwQZ@&XLg-RHQakU;%ToW-V z;<|=ULzoJq4$~S^VT5osgc(_Hh`1TTXCchWb}oclA>7t5A4W5-inBYiTL|MW?uBt5 z4@CDs!^1E=KN8Jj(WK?LD94N(vmy);OB$9Hg62{&U9uGPsl=?6wv06+Z;dI0j9l4p zZUUJ?KC93$l}J7>mW*=QEaYhsJZI)j>w-dmf6a~8k9R+CTOlxB$QlZbQ)b>sRn``b z(p-8mM@`qeeaLrp%Z4?%q!8&J@VZpcc#$MiXE$yWZ4{##s#5*JIzdYh-8E^wX%&bnQi#BHsPZWI5N*?oyW#&e18yTxm8e^e& zU1HuM#&gTaXXj1p$#`0r>gCE}*)pw)WhB=XhWg(ItKnZ0vIf(xTc~WV6?5j&=L+@t zLTN3XGacW?`U#dToy!?Hh45^lQpy+;rsTLOF}bu8`>+J4qaQ0ej^L<{4@G>0K2|4@ zNSDpbjw#DlUNwtiysFT#J2Q!jnadi?gMV_OM@J58BJzwg+++WnyOvD#D5$WG)A(3n zpQBDr%_ga?cTcG+3j1x}o;2z>i%}f~6g8~tD51>wb)3T}-Fw5)aULgiT!1CwqHrD1 zk-%{g!#c)AT){9?Qmy|spr_1a=V=|r)Gs~KwnvFXA50gEEbZPke7lF-OtF<}YCf~L z!k!s>pM5Z$&0fy2pi!5JoulyrtDLdqIS$-qWKQedVi)qoRPxj-obi6(_NLQso-}V` zdsPaZ=HMo@cX>NNZ(a0t z5C_mrKSLOHy&dGL=&dgH3w$qkNCa(VFXhOdrvBZgM`?Nt$0;RJuh+nC(>@xVz)9D% zn@REUlc1!*UrmF|>CD4d~4c&fX{c z2=^PD(7f}%#u3*%PHppk$IS0F^WHbPpT;FbpIyCn{8PfWM+7Q$~ zn9JSvnp?E5=ydb8Nfw zRj@vdS|#Jd1uM8 z2b^=t1^?OwzbMiC#cD{!U*Los|3vf$G|BD{M49}~7wC-J%9c1aPW+uaJ>n$$FbM$H z!M`f_)Ta3yQ=~D&j=jMI-{fGNv+2~q-`LSk7MzqWm!DWCiQ&3RsnLKMmHrRBMuRNz z!3`Wpap!xDh%BP$8VzvE4iSyt(bR1rx-b+CMC&$ju-XGLgz0&n(cU4-0!iK_y?dm0 zpP72VK6%LQc*H_Iw(0GM{|%xVE@`;T|4mKg$RX}B{hmH#YFtoLYFY^`@^m}7Tk1rX za%9UKnig)(k?nFQCH&%pLwm5xlAS@nOU%MD8t{bE#^j7x;rv=9!yK!&R%O?=!!8mb zFaEl?>`G)O)99G6t0B|l_K60&1J=o>L_THggT-JbYKGWKEOKa~m^a{vGU literal 0 HcmV?d00001 diff --git a/version24/BIfStatement.java b/version24/BIfStatement.java new file mode 100644 index 00000000..476d00e2 --- /dev/null +++ b/version24/BIfStatement.java @@ -0,0 +1,133 @@ +import java.util.Vector; + +/* Package: B AMN */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BIfStatement extends BStatement +{ private BStatement ifpart; + private BStatement elsepart; + private BExpression cond; + + public BIfStatement(BExpression cnd, + BStatement ip, BStatement ep) + { ifpart = ip; + elsepart = ep; + cond = cnd; + } + + public BIfStatement(BExpression cnd, + BStatement ip) + { ifpart = ip; + elsepart = new BBasicStatement("skip"); + cond = cnd; + } + + public BStatement getIf() + { return ifpart; } + + public BStatement getElse() + { return elsepart; } + + public BExpression getCond() + { return cond; } + + public void setElse(BStatement stat) + { elsepart = stat; } + + public void setIf(BStatement stat) + { ifpart = stat; } + + public String toString() + { String res = "IF " + cond + "\n" + + " THEN " + ifpart + "\n"; + if (elsepart != null) + { res = res + " ELSE " + elsepart + "\n"; } + res = res + " END"; + return res; + } + + public Vector wr() + { Vector res = new Vector(); + res.addAll(ifpart.wr()); + if (elsepart != null) + { return VectorUtil.union(res,elsepart.wr()); } + return res; + } + + public Vector rd() + { Vector res = new Vector(); + res.addAll(cond.rd()); + res = VectorUtil.union(res,ifpart.rd()); + if (elsepart != null) + { return VectorUtil.union(res,elsepart.rd()); } + return res; + } + + public void extendWithCase(BStatement stat) + { if (elsepart == null) + { elsepart = stat; } + else + { if (elsepart instanceof BIfStatement) + { ((BIfStatement) elsepart).extendWithCase(stat); } + else if (stat instanceof BIfStatement) + { ((BIfStatement) stat).extendWithCase(elsepart); + elsepart = stat; + } + } + } + + public BStatement substituteEq(String oldE, BExpression newE) + { BExpression ncond = null; + BStatement nif = null; + BStatement nelse = null; + if (cond != null) + { ncond = cond.substituteEq(oldE,newE); } + if (ifpart != null) + { nif = ifpart.substituteEq(oldE,newE); } + if (elsepart != null) + { nelse = elsepart.substituteEq(oldE,newE); } + return new BIfStatement(ncond,nif,nelse); + } + + public BStatement simplify() + { BExpression ncond = null; + BStatement nif = null; + BStatement nelse = null; + if (cond != null) + { ncond = cond.simplify(); } + if (ifpart != null) + { nif = ifpart.simplify(); } + if (elsepart != null) + { nelse = elsepart.simplify(); } + return new BIfStatement(ncond,nif,nelse); + } + + public BStatement normalise() + { BStatement nif = null; + BStatement nelse = null; + if (ifpart != null) + { nif = ifpart.normalise(); } + if (elsepart != null) + { nelse = elsepart.normalise(); } + return new BIfStatement(cond,nif,nelse); + } + + public BStatement seq2parallel() + { BStatement nif = null; + BStatement nelse = null; + if (ifpart != null) + { nif = ifpart.seq2parallel(); } + if (elsepart != null) + { nelse = elsepart.seq2parallel(); } + return new BIfStatement(cond,nif,nelse); + } + +} + diff --git a/version24/BLoopStatement.class b/version24/BLoopStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..d05f39a9fa7f21b89c83e91b766620464e57ab6e GIT binary patch literal 1911 zcma)6Yg5}+5IwTx2SNdAAjG7k&ZDidF|?FYFe#1ABe+pa8;A*g%UETUF_I(8Y5T9* znPNI&raz!Rs?)QUgKffO`ayg5?%liR?BnX6e_#C#URpPV+9ku_}qMHF4Rrucp)~-Ts-?7!hXuXQ5xbKG>FT*B2_*k?(qh4S6-ewq7hYOwX*>tvYM%xZa6b zx0_5@+jCpqk+p40_TxpvbsHC<=Oqmt@8dwndr0ZHE#i)dySS%d>T;UJmR+w|BojT@ zDH&Vzdxk?1-_WF`Qk%OecAiS9Tq!&$70UbE4|Ct!soGX~Q%4T-F?_3I0pE%Eh*=ME z6IvhW_!t=xi#k5Rl7g`gqrM90_!LVzzQ+$S{HWt6FrUw`$h>%NjGke<7e6R#4jOZqBu0uTS-u%X-c1*;LOf~Hyx_Gl zVF()6#{$Jw(3#a_UKNz=9C5C|SVo+WYYZ!F+A7B*&**%XU5pf0sa!mWb-l+h=-xU{ z`B=N&+pKel-gnM1#X8?Gvb;uW$u_1BL?@k_f8kvt+l!Oncmf5oC}IK|%yg5{mM^lL z=1v%dGQB$i_73g*El^62S6L0go(W)P3`ttx`GxtZ*@5J>j`JhJ8Vs-^09gGGpN)I5 literal 0 HcmV?d00001 diff --git a/version24/BLoopStatement.java b/version24/BLoopStatement.java new file mode 100644 index 00000000..e01c12b9 --- /dev/null +++ b/version24/BLoopStatement.java @@ -0,0 +1,80 @@ +import java.util.Vector; + +/* Package: B AMN */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BLoopStatement extends BStatement +{ private BExpression test; + private BExpression invariant; + private BExpression variant; + private BStatement body; + + public BLoopStatement(BExpression tst, BExpression inv, BExpression var, BStatement bdy) + { test = tst; + invariant = inv; + variant = var; + body = bdy; + } + + public BExpression getTest() + { return test; } + + public BExpression getInvariant() + { return invariant; } + + public BExpression getVariant() + { return variant; } + + public String toString() + { return "WHILE " + test + "\n" + + " DO " + body + "\n" + + " INVARIANT " + invariant + "\n" + + " VARIANT " + variant + "\n" + + "END"; + } + + public BStatement substituteEq(String oldE, BExpression newE) + { // BExpression nlhs = lhs.substituteEq(oldE,newE); + BExpression ntest = test.substituteEq(oldE,newE); + BExpression ninvariant = invariant.substituteEq(oldE,newE); + BExpression nvariant = variant.substituteEq(oldE,newE); + BStatement nbody = body.substituteEq(oldE,newE); + return new BLoopStatement(ntest,ninvariant,nvariant,nbody); + } + + public BStatement simplify() + { // BExpression nlhs = lhs.substituteEq(oldE,newE); + BExpression ntest = test.simplify(); + BExpression ninvariant = invariant.simplify(); + BExpression nvariant = variant.simplify(); + BStatement nbody = body.simplify(); + return new BLoopStatement(ntest,ninvariant,nvariant,nbody); + } + + public Vector wr() + { return body.wr(); } + + public Vector rd() + { Vector res = new Vector(); + res.addAll(test.rd()); + res = VectorUtil.union(res,body.rd()); + return res; + } + + public BStatement seq2parallel() + { return this; } + + public BStatement normalise() + { BStatement nbody = body.normalise(); + return new BLoopStatement(test,invariant,variant,nbody); + } + +} + diff --git a/version24/BOp.class b/version24/BOp.class new file mode 100644 index 0000000000000000000000000000000000000000..2bdb1347b4711b27aae68f70003560fd62b72f03 GIT binary patch literal 19184 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 RzCkOlVwnC9RH5kg{|gdD8)g6i literal 0 HcmV?d00001 diff --git a/version24/BOp.java b/version24/BOp.java new file mode 100644 index 00000000..8e8084af --- /dev/null +++ b/version24/BOp.java @@ -0,0 +1,1159 @@ +import java.util.Vector; +import java.util.List; + +/* package: B */ +/****************************** +* Copyright (c) 2003--2024 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BOp extends ModelElement +{ private String result = null; + private Vector params = new Vector(); // of String + private BExpression pre; + private BStatement code; + private String signature; + + public BOp(String nme, String res, Vector pars, + BExpression p, BStatement s) + { super(nme); + result = res; + params = pars; + pre = p; + code = s; + } + + public void setSignature(String sig) + { signature = sig; } + + public String getSignature() + { return signature; } + + public String getResult() + { return result; } + + public Vector getParameters() + { return params; } + + public void addParameter(Attribute att) + { params.add(att.getName()); } + + public BExpression getPre() + { return pre; } + + public void addPre(BExpression p) + { pre = BBinaryExpression.simplify("&",pre,p,false); } + + public BStatement getCode() + { return code; } + + public Type getType() + { return null; } + + public void setType(Type t) + { } + + public void generateJava(java.io.PrintWriter out) // not used + { out.println(" public void " + getName() + "()"); } + + public static BOp buildGetOperation( + String nme, String cx, + BExpression cs) + // nmex <-- getnme(cx) = + // PRE cx: cs THEN nmex := nme(cx) END + { Vector pars = new Vector(); + String opname = "get" + nme; + String attx = nme + "x"; + pars.add(cx); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression attxbe = + new BBasicExpression(attx); + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BExpression rhs = new BApplyExpression(nme,cxbe); + BStatement code = new BAssignStatement(attxbe,rhs); + return new BOp(opname,attx,pars,pre1,code); + } + + public static BOp buildGetQualOperation( + String nme, String cx, + BExpression cs) + // nmex <-- getnme(cx,ind) = + // PRE cx: cs THEN nmex := nme(cx)(ind) END + { Vector pars = new Vector(); + String opname = "get" + nme; + String attx = nme + "x"; + + pars.add(cx); + pars.add("ind"); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression indbe = new BBasicExpression("ind"); + + BBasicExpression attxbe = + new BBasicExpression(attx); + + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",indbe,new BBasicExpression("STRING")); + BBinaryExpression oppre = + new BBinaryExpression("&",pre1,pre2); + + BExpression rhs = new BApplyExpression(nme,cxbe); + BStatement code = new BAssignStatement(attxbe, + new BApplyExpression(rhs,indbe)); + return new BOp(opname,attx,pars,oppre,code); + } + + public static BOp buildStaticGetOperation(String nme) + // nmex <-- getnme = + // nmex := nme; + { Vector pars = new Vector(); + String opname = "get" + nme; + String attx = nme + "x"; + + BBasicExpression attxbe = + new BBasicExpression(attx); + BExpression rhs = new BBasicExpression(nme); + BStatement code = new BAssignStatement(attxbe,rhs); + return new BOp(opname,attx,pars,null,code); + } + + public static BOp buildUpdateOperation(String nme, BExpression cs, + Association ast, BExpression btbe, boolean inj) + // updatenme(nmex) = + // PRE nmex: cs +-> T THEN nme := nme <+ nmex END + { Vector pars = new Vector(); + String opname = "update" + nme; + String attx = nme + "x"; + pars.add(attx); + BBasicExpression nmebe = new BBasicExpression(nme); + BBasicExpression attxbe = + new BBasicExpression(attx); + BExpression pfun = new BBinaryExpression("+->",cs,btbe); + BBinaryExpression pre = + new BBinaryExpression(":",attxbe,pfun); + + BExpression rhs = new BBinaryExpression("<+",nmebe,attxbe); + BStatement code = new BAssignStatement(nmebe,rhs); + + if (inj) + { // rhs: cs >-> btbe + BExpression inje = new BBinaryExpression(">->",cs,btbe); + BExpression injpre = new BBinaryExpression(":",rhs,inje); + pre = new BBinaryExpression("&",pre,injpre); + } + + /* if (ast != null) + { String role1 = ast.getRole1(); + if (role1 != null && role1.length() > 0) + { int card1 = ast.getCard1(); + int card2 = ast.getCard2(); + Entity ent1 = ast.getEntity1(); + Entity ent2 = ast.getEntity2(); + BParallelStatement body = new BParallelStatement(); + code.setWriteFrame(nme); + body.addStatement(code); + + if (card2 != ONE) + { // role1 := { bxx,axx | axx : dom(attxbe) & bxx : attxbe(axx) }, ... + BExpression role1be = new BBasicExpression(role1); + String e1name = ent1.getName(); + String e2name = ent2.getName(); // should be different + String e1var = e1name.toLowerCase() + "_xx"; + String e2var = e2name.toLowerCase() + "_xx"; + String e1s = e1name.toLowerCase() + "s"; + BExpression e1sbe = new BBasicExpression(e1s); + Vector scompvars = new Vector(); + scompvars.add(e2var); + scompvars.add(e1var); + BExpression e2varbe = new BBasicExpression(e2var); + BExpression e1varbe = new BBasicExpression(e1var); + BExpression attxapp = new BApplyExpression(attx,e1varbe); + BExpression domattx = new BUnaryExpression("dom",attxbe); + + BExpression pred11 = new BBinaryExpression(":",e1varbe,domattx); + BExpression pred12 = new BBinaryExpression(":",e2varbe,attxapp); + BExpression pred1 = new BBinaryExpression("&",pred11,pred12); + BExpression comp1 = new BSetComprehension(scompvars,pred1); + BExpression role2app = new BApplyExpression(nme, e1varbe); + BExpression role1sub = new BBinaryExpression(":",e1varbe,e1sbe); + BExpression pred21 = new BBinaryExpression("/:",e1varbe,domattx); + BExpression pred22 = new BBinaryExpression(":",e2varbe,role2app); + BExpression pred2 = new BBinaryExpression("&",pred22,pred21); + BExpression comp2 = new BSetComprehension(scompvars, + new BBinaryExpression("&",role1sub,pred2)); + BExpression invrhs = new BBinaryExpression("\\/", comp1, comp2); + BStatement invcode = new BAssignStatement(role1be,invrhs); + invcode.setWriteFrame(role1); + body.addStatement(invcode); + return new BOp(opname,null,pars,pre,body); + } + } + } */ + + + /* if (card2 == ModelElement.ZEROONE) + { String cname = cs.substring(0,cs.length()-1); + BExpression zpre = zeroOneConstraint(nme,cname,"update",attx); + pre = new BBinaryExpression("&",pre,zpre); + } */ + return new BOp(opname,null,pars,pre,code); + } + + public static BOp buildSetOperation( + String nme, String cx, + BExpression cs, + BExpression btbe, boolean inj, String role1, int card1, int card2, + Entity ent, Vector entities, Vector types, Vector invs) + // setnme(cx,nmex) = + // PRE cx: cs & nmex: T THEN nme(cx) := attx END + { Vector pars = new Vector(); + String opname = "set" + nme; + String attx = nme + "xx"; + String e2name = ""; + + Type t; + Attribute att = ent.getDefinedAttribute(nme); + if (att != null) + { t = att.getType(); } + else + { Association ast = ent.getRole(nme); + Entity ent2 = ast.getEntity2(); + e2name = ent2 + ""; + + if (ast != null && card2 == ModelElement.ONE) + { t = new Type(ent2); } + else + { t = new Type("Set",null); } + } // and element type is Entity2 in 2nd case? + pars.add(cx); + pars.add(attx); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression attxbe = + new BBasicExpression(attx); + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",attxbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); // and card(attxbe) = card2 for n + if (inj) + { String cname = cx.substring(0,cx.length()-1); + BExpression inje = injConstraint(nme,cname,attx); + pre = new BBinaryExpression("&",pre,inje); + } + if (card2 == ModelElement.ZEROONE) + { String cname = cx.substring(0,cx.length()-1); + BExpression zpre = zeroOneConstraint(nme,cname,"set",attx); + pre = new BBinaryExpression("&",pre,zpre); + } + + BExpression lhs = new BApplyExpression(nme,cxbe); + BStatement code = new BAssignStatement(lhs,attxbe); + code.setWriteFrame(nme); + BParallelStatement body = new BParallelStatement(); + body.addStatement(code); + + if (role1 != null && role1.length() > 0) + { BExpression role1be = new BBasicExpression(role1); + String e1name = ent.getName(); + String e1var = e1name.toLowerCase() + "_xx"; + String e2var = e2name.toLowerCase() + "_xx"; + String e2s = e2name.toLowerCase() + "s"; + BExpression e2sbe = new BBasicExpression(e2s); + + Vector cxset = new Vector(); + cxset.add(cxbe); + BExpression cxsetbe = new BSetExpression(cxset,false); + + if (card2 == MANY) + { if (card1 == ONE) + { // role1 := (attxbe <<| role1) \\/ attxbe*{cxbe} + BExpression rhs1 = new BBinaryExpression("<<|",attxbe,role1be); + rhs1.setBrackets(true); + BExpression rhs2 = new BBinaryExpression("*",attxbe,cxsetbe); + BExpression invrhs = new BBinaryExpression("\\/",rhs1,rhs2); + BStatement invcode = new BAssignStatement(role1be,invrhs); + invcode.setWriteFrame(role1); + body.addStatement(invcode); + } + else + { Vector scompvars = new Vector(); + scompvars.add(e2var); + scompvars.add(e1var); + BExpression e2varbe = new BBasicExpression(e2var); + BExpression e1varbe = new BBasicExpression(e1var); + BExpression pred11 = new BBinaryExpression(":",e2varbe,attxbe); + BExpression role1app = new BApplyExpression(role1,e2varbe); + BExpression role1add = new BBinaryExpression("\\/",role1app,cxsetbe); + BExpression pred12 = new BBinaryExpression("=",e1varbe,role1add); + BExpression pred1 = new BBinaryExpression("&",pred11,pred12); + BExpression comp1 = new BSetComprehension(scompvars,pred1); + BExpression role1sub = new BBinaryExpression("-",role1app,cxsetbe); + BExpression pred21 = new BBinaryExpression("/:",e2varbe,attxbe); + BExpression pred22 = new BBinaryExpression(":",e2varbe,e2sbe); + BExpression pred2 = new BBinaryExpression("&",pred22,pred21); + BExpression pred23 = new BBinaryExpression("=",e1varbe,role1sub); + BExpression comp2 = new BSetComprehension(scompvars, + new BBinaryExpression("&",pred2,pred23)); + BExpression invrhs = new BBinaryExpression("\\/", comp1, comp2); + BStatement invcode = new BAssignStatement(role1be,invrhs); + invcode.setWriteFrame(role1); + body.addStatement(invcode); + } // role1 := { bxx,axx | bxx : brx & axx = ar(bxx) \\/ { ax } } \\/ ... + } + else if (card2 == ONE && card1 != ONE) + { // role1 := { bx |-> ar(bx) \\/ {ax} } \\/ { bb,aa | bb : bs & bb /= bx & aa : ar(bx) - { ax } } + Vector scompvars = new Vector(); + scompvars.add(e2var); + scompvars.add(e1var); + BExpression e2varbe = new BBasicExpression(e2var); + BExpression e1varbe = new BBasicExpression(e1var); + BExpression pred11 = new BBinaryExpression("=",e2varbe,attxbe); + BExpression role1app = new BApplyExpression(role1,e2varbe); + BExpression role1add = new BBinaryExpression("\\/",role1app,cxsetbe); + BExpression pred12 = new BBinaryExpression("=",e1varbe,role1add); + BExpression pred1 = new BBinaryExpression("&",pred11,pred12); + BExpression comp1 = new BSetComprehension(scompvars,pred1); + BExpression role1sub = new BBinaryExpression("-",role1app,cxsetbe); + BExpression pred21 = new BBinaryExpression("/=",e2varbe,attxbe); + BExpression pred22 = new BBinaryExpression(":",e2varbe,e2sbe); + BExpression pred2 = new BBinaryExpression("&",pred22,pred21); + BExpression pred23 = new BBinaryExpression("=",e1varbe,role1sub); + BExpression comp2 = new BSetComprehension(scompvars, + new BBinaryExpression("&",pred2,pred23)); + BExpression invrhs = new BBinaryExpression("\\/", comp1, comp2); + BStatement invcode = new BAssignStatement(role1be,invrhs); + invcode.setWriteFrame(role1); + body.addStatement(invcode); + } + + } + + + Vector vpars = new Vector(); + // and the attx parameter + Attribute p1 = new Attribute(attx,t,ModelElement.INTERNAL); + vpars.add(p1); + BehaviouralFeature event = + new BehaviouralFeature("set" + nme,vpars,false,null); + + String ename = ent.getName(); + java.util.Map env = new java.util.HashMap(); + env.put(ename, new BBasicExpression(cx)); + + Vector contexts = new Vector(); + if (ent != null) + { contexts.add(ent); } + + for (int i = 0; i < invs.size(); i++) + { Constraint con = (Constraint) invs.get(i); + Constraint ccnew = con.bmatches("set",nme,ent,attx,event); + if (ccnew != null) + { boolean typed = ccnew.typeCheck(types,entities,contexts); + BStatement stat; + if (typed) + { stat = ccnew.synthesiseBCode(ent,nme,true); + body.addStatement(stat); + } + } + else if (con.getEvent() == null && con.involvesFeature(nme)) + { BExpression inv = con.binvariantForm(env,false); + inv.setBrackets(true); + BExpression inv1 = inv.substituteEq(nme + "(" + cx + ")", attxbe); + pre = new BBinaryExpression("&",pre,inv1); + } // must ensure that not both an invariant and its contrapositive are used! + } + BStatement newbody = BStatement.separateUpdates(body.getStatements()); + return new BOp(opname,null,pars,pre,newbody); + } + + + public static BOp buildStaticSetOperation( + String nme, String cx, BExpression cs, + BExpression btbe, + boolean inj, int card2, + Entity ent, Vector entities, + Vector types, Vector invs) + // setnme(nmex) = + // PRE nmex: T THEN nme := nmex END + { Vector pars = new Vector(); + String opname = "set" + nme; + String attx = nme + "x"; + + pars.add(attx); + BBasicExpression attxbe = + new BBasicExpression(attx); + BExpression pre = new BBinaryExpression(":",attxbe,btbe); + BExpression lhs = new BBasicExpression(nme); + BStatement code = new BAssignStatement(lhs,attxbe); + BParallelStatement body = new BParallelStatement(); + body.addStatement(code); + + Type t; + Attribute att = ent.getAttribute(nme); + if (att != null) + { t = att.getType(); } + else + { return null; } + + Vector vpars = new Vector(); + // and the attx parameter + Attribute p1 = new Attribute(attx,t,ModelElement.INTERNAL); + vpars.add(p1); + BehaviouralFeature event = new BehaviouralFeature("set" + nme,vpars,false,null); + + Vector contexts = new Vector(); + if (ent != null) + { contexts.add(ent); } + + for (int i = 0; i < invs.size(); i++) + { Constraint con = (Constraint) invs.get(i); + Constraint ccnew = con.bmatches("set",nme,ent,attx,event); + if (ccnew != null) + { boolean typed = ccnew.typeCheck(types,entities,contexts); + BStatement stat; + if (typed) + { stat = ccnew.staticSynthesiseBCode(ent,nme,true); + body.addStatement(stat); + } + } + } + BStatement newbody = BStatement.separateUpdates(body.getStatements()); + return new BOp(opname,null,pars,pre,newbody); + } + + // Not valid for {unique} attributes: + public static BOp buildSetAllOperation(String nme, + String cx, BExpression cs, + BExpression btbe) + // setAllnme(cx,nmex) = + // PRE cx <: cs & nmex: T + // THEN nme := nme <+ (cx*{nmex}) END + { Vector pars = new Vector(); + String opname = "setAll" + nme; + String nmex = nme + "x"; + pars.add(cx); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBasicExpression nmebe = new BBasicExpression(nme); + BBinaryExpression pre1 = + new BBinaryExpression("<:",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",nmexbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + Vector nvals = new Vector(); + nvals.add(nmexbe); + BExpression nmeset = new BSetExpression(nvals); + + BExpression update = + new BBinaryExpression("*",cxbe,nmeset); + BExpression rhs = + new BBinaryExpression("<+",nmebe,update); + BStatement code = + new BAssignStatement(nmebe,rhs); + return new BOp(opname,null,pars,pre,code); + } + + public static BOp buildSetIndOp( + String nme, String cx, + BExpression cs, + BExpression btbe, Entity ent) + // setnme(cx,ind,e2x) = + // PRE cx: cs & ind: dom(nme(cx)) & e2x: btbe + // THEN nme(cx)(ind) := e2x END + { Vector pars = new Vector(); + String opname = "set" + nme; + Type t; + Association ast = ent.getRole(nme); + t = new Type(ast.getEntity2()); + + String e2x = ast.getEntity2().getName().toLowerCase() + "xx"; + + pars.add(cx); + pars.add("ind"); + pars.add(e2x); + + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression e2xbe = + new BBasicExpression(e2x); + BBasicExpression indbe = new BBasicExpression("ind"); + + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",e2xbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + + BExpression lhs = new BApplyExpression(nme,cxbe); + BExpression indom = new BBinaryExpression(":",indbe, + new BUnaryExpression("dom",lhs)); + BExpression lhs1 = new BApplyExpression(lhs,indbe); + + BStatement code = new BAssignStatement(lhs1,e2xbe); + code.setWriteFrame(nme); + pre = new BBinaryExpression("&",pre,indom); + + return new BOp(opname,null,pars,pre,code); + } + + public static BOp buildSetQualOp( + String nme, String cx, + BExpression cs, + BExpression btbe, Entity ent) + // setnme(cx,ind,e2x) = + // PRE cx: cs & ind: STRING & e2x: btbe + // THEN nme(cx)(ind) := e2x END + { Vector pars = new Vector(); + String opname = "set" + nme; + Type t; + Association ast = ent.getRole(nme); + t = new Type(ast.getEntity2()); + + String e2x = ast.getEntity2().getName().toLowerCase() + "xx"; + + pars.add(cx); + pars.add("ind"); + pars.add(e2x); + + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression e2xbe = + new BBasicExpression(e2x); + BBasicExpression indbe = new BBasicExpression("ind"); + + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",e2xbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + + BExpression lhs = new BApplyExpression(nme,cxbe); + BExpression indom = new BBinaryExpression(":",indbe, + new BBasicExpression("STRING")); + BExpression lhs1 = new BApplyExpression(lhs,indbe); + + BStatement code = new BAssignStatement(lhs1,e2xbe); + code.setWriteFrame(nme); + pre = new BBinaryExpression("&",pre,indom); + + return new BOp(opname,null,pars,pre,code); + } + + + + + public static BOp buildDelOperation( + String nme, String cx, + BExpression cs, + BExpression btbe, String role1, int card1, + Entity ent, Vector entities, Vector types, Vector invs) + // removenme(cx,nmex) = + // PRE cx: cs & nmex: T + // THEN nme(cx) := nme(cx) - { nmex } END, or more complex if nme is ordered + { Vector pars = new Vector(); + String opname = "remove" + nme; + String nmex = nme + "xx"; + pars.add(cx); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",nmexbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + BExpression lhs = new BApplyExpression(nme,cxbe); + Vector vals = new Vector(); + vals.add(nmexbe); + BSetExpression nmese = new BSetExpression(vals); + BExpression rhs = + new BBinaryExpression("-",lhs,nmese); + rhs.setBrackets(true); + if (ent.getRole(nme).isOrdered()) + { BBasicExpression nmebe = new BBasicExpression(nme); + BBinaryExpression rresf = new BBinaryExpression("|>>",nmebe,nmese); + Vector subparams = new Vector(); + subparams.add("_ii_"); + subparams.add("_yy_"); + BUnaryExpression domf = new BUnaryExpression("dom", rresf); + BBasicExpression jjbe = new BBasicExpression("_jj_"); + BBinaryExpression rge = new BBinaryExpression("..", new BBasicExpression("1"), jjbe); + BBinaryExpression intrsec = new BBinaryExpression("/\\", domf, rge); + BUnaryExpression cardintrsec = new BUnaryExpression("card", intrsec); + BBasicExpression iibe = new BBasicExpression("_ii_"); + BBinaryExpression iieq = new BBinaryExpression("=", iibe, cardintrsec); + BBinaryExpression jjindom = new BBinaryExpression(":", jjbe, domf); + BApplyExpression appf = new BApplyExpression(nmebe, jjbe); + BBasicExpression yybe = new BBasicExpression("_yy_"); + BBinaryExpression yyeq = new BBinaryExpression("=", yybe, appf); + BBinaryExpression and1 = new BBinaryExpression("&", jjindom, yyeq); + BBinaryExpression and2 = new BBinaryExpression("&", and1, iieq); + BQuantifierExpression exists1 = new BQuantifierExpression("#", "_jj_", and2); + rhs = new BSetComprehension(subparams, exists1); + lhs = nmebe; + } + java.util.Map env = new java.util.HashMap(); + env.put(ent.getName(), new BBasicExpression(cx)); + + BStatement code = new BAssignStatement(lhs,rhs); + code.setWriteFrame(nme); + BParallelStatement body = new BParallelStatement(); + body.addStatement(code); + + if (role1 != null && role1.length() > 0) + { if (card1 != ONE) + { BExpression invlhs = new BApplyExpression(role1,nmexbe); + Vector invvals = new Vector(); + invvals.add(cxbe); + BSetExpression role1se = new BSetExpression(invvals,false); + BExpression invrhs = new BBinaryExpression("-",invlhs,role1se); + invrhs.setBrackets(true); + BStatement inversecode = new BAssignStatement(invlhs,invrhs); + inversecode.setWriteFrame(role1); + body.addStatement(inversecode); + } + else // role1 := role1 domain anti-restriction { nmexbe } + { BExpression role1be = new BBasicExpression(role1); + Vector invvals = new Vector(); + invvals.add(nmexbe); + BSetExpression role1se = new BSetExpression(invvals,false); + + BExpression invrhs = new BBinaryExpression("<<|",role1se,role1be); + BStatement inversecode = new BAssignStatement(role1be,invrhs); + inversecode.setWriteFrame(role1); + body.addStatement(inversecode); + } + } + + + Vector vpars = new Vector(); + // and the attx parameter + Association ast = ent.getDefinedRole(nme); + Type t = new Type(ast.getEntity2()); + + Attribute p1 = new Attribute(nmex,t,ModelElement.INTERNAL); + vpars.add(p1); + BehaviouralFeature event = new BehaviouralFeature("remove" + + nme,vpars,false,null); + Vector contexts = new Vector(); + if (ent != null) + { contexts.add(ent); } + + for (int i = 0; i < invs.size(); i++) + { Constraint con = (Constraint) invs.get(i); + Constraint ccnew = con.bmatches("remove",nme,ent,nmex,event); + if (ccnew != null) + { boolean typed = ccnew.typeCheck(types,entities,contexts); + if (typed) + { BStatement stat = ccnew.bupdateOperation(ent,true); + body.addStatement(stat); + } + } + else if (con.getEvent() == null && con.involvesFeature(nme)) + { BExpression inv = con.binvariantForm(env,false); + inv.setBrackets(true); + + BExpression inv1 = inv.substituteEq(nme + "(" + cx + ")", rhs); + pre = new BBinaryExpression("&",pre,inv1); + } // must ensure that not both an invariant and its contrapositive are used! + + } + BStatement newbody = BStatement.separateUpdates(body.getStatements()); + return new BOp(opname,null,pars,pre,newbody); + } + + public static BOp buildDelQualOperation( + String nme, String cx, + BExpression cs, + BExpression btbe, + Entity ent, Vector entities, Vector types, Vector invs) + // removenme(cx,ind,nmex) = + // PRE cx: cs & ind : STRING & nmex: T + // THEN nme(cx)(ind) := nme(cx)(ind) - { nmex } END + { Vector pars = new Vector(); + String opname = "remove" + nme; + String nmex = nme + "xx"; + pars.add(cx); + pars.add("ind"); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBasicExpression indbe = new BBasicExpression("ind"); + + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",nmexbe,btbe); + BBinaryExpression pre3 = + new BBinaryExpression(":",indbe,new BBasicExpression("STRING")); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + pre = new BBinaryExpression("&",pre,pre3); + + BExpression lhs = new BApplyExpression(nme,cxbe); + lhs = new BApplyExpression(lhs,indbe); + + Vector vals = new Vector(); + vals.add(nmexbe); + BSetExpression nmese = new BSetExpression(vals); + BExpression rhs = + new BBinaryExpression("-",lhs,nmese); + rhs.setBrackets(true); + + java.util.Map env = new java.util.HashMap(); + env.put(ent.getName(), new BBasicExpression(cx)); + + BStatement code = new BAssignStatement(lhs,rhs); + code.setWriteFrame(nme); + BParallelStatement body = new BParallelStatement(); + body.addStatement(code); + + Vector vpars = new Vector(); + // and the attx parameter + Association ast = ent.getDefinedRole(nme); + Type t = new Type(ast.getEntity2()); + + Attribute p1 = new Attribute(nmex,t,ModelElement.INTERNAL); + vpars.add(p1); + BehaviouralFeature event = new BehaviouralFeature("remove" + + nme,vpars,false,null); + Vector contexts = new Vector(); + if (ent != null) + { contexts.add(ent); } + + for (int i = 0; i < invs.size(); i++) + { Constraint con = (Constraint) invs.get(i); + Constraint ccnew = con.bmatches("remove",nme,ent,nmex,event); + if (ccnew != null) + { boolean typed = ccnew.typeCheck(types,entities,contexts); + if (typed) + { BStatement stat = ccnew.bupdateOperation(ent,true); + body.addStatement(stat); + } + } + else if (con.getEvent() == null && con.involvesFeature(nme)) + { BExpression inv = con.binvariantForm(env,false); + inv.setBrackets(true); + + BExpression inv1 = inv.substituteEq(nme + "(" + cx + ")", rhs); + pre = new BBinaryExpression("&",pre,inv1); + } // must ensure that not both an invariant and its contrapositive are used! + + } + BStatement newbody = BStatement.separateUpdates(body.getStatements()); + return new BOp(opname,null,pars,pre,newbody); + } + + public static BOp buildAddOperation( + String nme, String cx, + BExpression cs, + BExpression btbe, + String role1, int card1, int card2, boolean isseq, + Entity ent, Vector entities, Vector types, Vector invs) + // addnme(cx,nmex) = + // PRE cx: cs & nmex: T & + // card(nme(cx) \/ {nmex}) <= 1 (for ZEROONE) + // THEN nme(cx) := nme(cx) \/ { nmex } END or ^ [nmex] for a sequence + // inverse: role1(nmex) := role1(nmex) \/ { cx } + { Vector pars = new Vector(); + String opname = "add" + nme; + String nmex = nme + "xx"; + pars.add(cx); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",nmexbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + BExpression lhs = new BApplyExpression(nme,cxbe); + Vector vals = new Vector(); + vals.add(nmexbe); + BSetExpression nmese = new BSetExpression(vals,isseq); + BExpression rhs; + if (isseq) + { rhs = new BBinaryExpression("^",lhs,nmese); } + else + { rhs = new BBinaryExpression("\\/",lhs,nmese); } + rhs.setBrackets(true); + + java.util.Map env = new java.util.HashMap(); + env.put(ent.getName(), new BBasicExpression(cx)); + + if (card2 == ZEROONE) + { BExpression cardleq = + new BBinaryExpression("<=", + new BUnaryExpression("card",rhs), + new BBasicExpression("1")); + pre = new BBinaryExpression("&",pre,cardleq); + } + BStatement code = new BAssignStatement(lhs,rhs); + code.setWriteFrame(nme); + BParallelStatement body = new BParallelStatement(); + body.addStatement(code); + + if (role1 != null && role1.length() > 0) + { if (card1 != ONE) + { BExpression invlhs = new BApplyExpression(role1,nmexbe); + Vector invvals = new Vector(); + invvals.add(cxbe); + BSetExpression role1se = new BSetExpression(invvals,false); + BExpression invrhs = new BBinaryExpression("\\/",invlhs,role1se); + invrhs.setBrackets(true); + BStatement inversecode = new BAssignStatement(invlhs,invrhs); + inversecode.setWriteFrame(role1); + body.addStatement(inversecode); + } + else // role1(nmexbe) := cx + { BExpression invlhs = new BApplyExpression(role1,nmexbe); + BStatement inversecode = new BAssignStatement(invlhs,cxbe); + inversecode.setWriteFrame(role1); + body.addStatement(inversecode); + } + } + + Vector vpars = new Vector(); + // and the attx parameter + Association ast = ent.getDefinedRole(nme); + Type t = new Type(ast.getEntity2()); + + Attribute p1 = new Attribute(nmex,t,ModelElement.INTERNAL); + vpars.add(p1); + BehaviouralFeature event = new BehaviouralFeature("add" + nme,vpars,false,null); + + if (isseq) + { event.setOrdered(true); } + + Vector contexts = new Vector(); + if (ent != null) + { contexts.add(ent); } + + for (int i = 0; i < invs.size(); i++) + { Constraint con = (Constraint) invs.get(i); + Constraint ccnew = con.bmatches("add",nme,ent,nmex,event); + if (ccnew != null) + { boolean typed = ccnew.typeCheck(types,entities,contexts); + if (typed) + { BStatement stat = ccnew.bupdateOperation(ent,true); + body.addStatement(stat); + } + } + else if (con.getEvent() == null && con.involvesFeature(nme)) + { BExpression inv = con.binvariantForm(env,false); + inv.setBrackets(true); + + BExpression inv1 = inv.substituteEq(nme + "(" + cx + ")", rhs); + pre = new BBinaryExpression("&",pre,inv1); + } // must ensure that not both an invariant and its contrapositive are used! + + } + BStatement newbody = BStatement.separateUpdates(body.getStatements()); + return new BOp(opname,null,pars,pre,newbody); + } + + public static BOp buildAddQualOperation( + String nme, String cx, + BExpression cs, + BExpression btbe, + int card2, boolean isseq, + Entity ent, Vector entities, Vector types, Vector invs) + // addnme(cx,ind,nmex) = + // PRE cx: cs & ind : STRING & nmex: T & + // card(nme(cx)(ind) \/ {nmex}) <= 1 (for ZEROONE) + // THEN nme(cx)(ind) := nme(cx)(ind) \/ { nmex } END or ^ [nmex] for a sequence + { Vector pars = new Vector(); + String opname = "add" + nme; + String nmex = nme + "xx"; + pars.add(cx); + pars.add("ind"); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBasicExpression indbe = new BBasicExpression("ind"); + BBinaryExpression pre1 = + new BBinaryExpression(":",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",nmexbe,btbe); + BBinaryExpression pre3 = + new BBinaryExpression(":",indbe,new BBasicExpression("STRING")); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + pre = new BBinaryExpression("&",pre,pre3); + BExpression lhs = new BApplyExpression(nme,cxbe); + lhs = new BApplyExpression(lhs,indbe); + + Vector vals = new Vector(); + vals.add(nmexbe); + BSetExpression nmese = new BSetExpression(vals,isseq); + BExpression rhs; + if (isseq) + { rhs = new BBinaryExpression("^",lhs,nmese); } + else + { rhs = new BBinaryExpression("\\/",lhs,nmese); } + rhs.setBrackets(true); + + java.util.Map env = new java.util.HashMap(); + env.put(ent.getName(), new BBasicExpression(cx)); + + if (card2 == ZEROONE) + { BExpression cardleq = + new BBinaryExpression("<=", + new BUnaryExpression("card",rhs), + new BBasicExpression("1")); + pre = new BBinaryExpression("&",pre,cardleq); + } + BStatement code = new BAssignStatement(lhs,rhs); + code.setWriteFrame(nme); + BParallelStatement body = new BParallelStatement(); + body.addStatement(code); + + Vector vpars = new Vector(); + // and the attx parameter + Association ast = ent.getDefinedRole(nme); + Type t = new Type(ast.getEntity2()); + + Attribute p1 = new Attribute(nmex,t,ModelElement.INTERNAL); + vpars.add(p1); + BehaviouralFeature event = new BehaviouralFeature("add" + nme,vpars,false,null); + + if (isseq) + { event.setOrdered(true); } + + Vector contexts = new Vector(); + if (ent != null) + { contexts.add(ent); } + + for (int i = 0; i < invs.size(); i++) + { Constraint con = (Constraint) invs.get(i); + Constraint ccnew = con.bmatches("add",nme,ent,nmex,event); + if (ccnew != null) + { boolean typed = ccnew.typeCheck(types,entities,contexts); + if (typed) + { BStatement stat = ccnew.bupdateOperation(ent,true); + body.addStatement(stat); + } + } + else if (con.getEvent() == null && con.involvesFeature(nme)) + { BExpression inv = con.binvariantForm(env,false); + inv.setBrackets(true); + + BExpression inv1 = inv.substituteEq(nme + "(" + cx + ")", rhs); + pre = new BBinaryExpression("&",pre,inv1); + } // must ensure that not both an invariant and its contrapositive are used! + + } + BStatement newbody = BStatement.separateUpdates(body.getStatements()); + return new BOp(opname,null,pars,pre,newbody); + } + + public static BOp buildAddAllOperation(String nme, + String cx, BExpression cs, + BExpression btbe) + // addAllnme(cx,nmex) = + // PRE cx <: cs & nmex: T + // THEN + // nme := nme <+ { x:cx | x |-> nme(x) \/ {nmex}} + // END + { Vector pars = new Vector(); + String opname = "addAll" + nme; + String nmex = nme + "x"; + pars.add(cx); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBasicExpression nmebe = new BBasicExpression(nme); + BBinaryExpression pre1 = + new BBinaryExpression("<:",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression(":",nmexbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + Vector nvals = new Vector(); + nvals.add(nmexbe); + BExpression nmeset = new BSetExpression(nvals); + + String xxvar = "xx"; + BExpression xxbe = new BBasicExpression(xxvar); + BExpression xapp = + new BApplyExpression(nme,xxbe); + BExpression pred = + new BBinaryExpression("|->",xxbe, + new BBinaryExpression("\\/",xapp,nmeset)); + BExpression update = + new BSetComprehension(xxvar,cxbe,pred); + BExpression rhs = + new BBinaryExpression("<+",nmebe,update); + BStatement code = + new BAssignStatement(nmebe,rhs); + return new BOp(opname,null,pars,pre,code); + } + + + public static BOp buildUnionAllOperation(String nme, + String cx, BExpression cs, + BExpression btbe) + // unionAllnme(cx,nmex) = + // PRE cx <: cs & nmex <: T + // THEN + // nme := nme <+ { x:cx | x |-> nme(x) \/ nmex} + // END + { Vector pars = new Vector(); + String opname = "unionAll" + nme; + String nmex = nme + "x"; + pars.add(cx); + pars.add(nmex); + BBasicExpression cxbe = new BBasicExpression(cx); + BBasicExpression nmexbe = + new BBasicExpression(nmex); + BBasicExpression nmebe = new BBasicExpression(nme); + BBinaryExpression pre1 = + new BBinaryExpression("<:",cxbe,cs); + BBinaryExpression pre2 = + new BBinaryExpression("<:",nmexbe,btbe); + BExpression pre = + new BBinaryExpression("&",pre1,pre2); + String xxvar = "xx"; + BExpression xxbe = new BBasicExpression(xxvar); + BExpression xapp = + new BApplyExpression(nme,xxbe); + BExpression pred = + new BBinaryExpression("|->",xxbe, + new BBinaryExpression("\\/",xapp,nmexbe)); + BExpression update = + new BSetComprehension(xxvar,cxbe,pred); + BExpression rhs = + new BBinaryExpression("<+",nmebe,update); + BStatement code = + new BAssignStatement(nmebe,rhs); + return new BOp(opname,null,pars,pre,code); + } + + public String toString() + { String res = " "; + if (result != null) + { res = res + result + " <-- "; } + res = res + getName(); + int numbParams = params.size(); + if (numbParams > 0) + { res = res + "("; + for (int i = 0; i < numbParams; i++) + { res = res + params.get(i); + if (i < numbParams - 1) + { res = res + ","; } + } + res = res + ")"; + } + + res = res + " = \n"; + if (pre == null) + { res = res + " " + code; } + else + { res = res + " PRE " + pre + "\n"; + res = res + " THEN " + code + "\n"; + res = res + " END"; + } + return res; + } + + private static BExpression injConstraint(String role, + String cname, String val) + { // val /: role[cs - {cx}] + String cs = cname.toLowerCase() + "s"; + String cx = cname.toLowerCase() + "x"; + BExpression cxbe = new BBasicExpression(cx); + BExpression csbe = new BBasicExpression(cs); + BExpression valbe = new BBasicExpression(val); + Vector s = new Vector(); + s.add(cxbe); + BExpression newset = new BSetExpression(s); + BExpression mins = + new BBinaryExpression("-",csbe,newset); + BExpression app = + new BApplySetExpression(role,mins); + return new BBinaryExpression("/:",valbe,app); + } + + private static BExpression zeroOneConstraint(String role, + String cname, String op, + String val) + { // card(role') <= 1 where role' is new value of role + String cs = cname.toLowerCase() + "s"; + String cx = cname.toLowerCase() + "x"; + BExpression cxbe = new BBasicExpression(cx); + BExpression valbe = new BBasicExpression(val); + BExpression newset; + if (op.equals("set")) + { newset = valbe; } + else + { BExpression app = new BApplyExpression(role,cxbe); + if (op.equals("add")) + { Vector singset = new Vector(); + singset.add(valbe); + BExpression sing = new BSetExpression(singset); + newset = + new BBinaryExpression("\\/",app,sing); + } + else // op is "union" + { newset = + new BBinaryExpression("\\/",app,valbe); + } + } + return new BBinaryExpression("<=", + new BUnaryExpression("card",newset), + new BBasicExpression("1")); + } + + private static BExpression zeroOneQualConstraint(String role, + String cname, String op, + String val) + { // card(role') <= 1 where role' is new value of role + String cs = cname.toLowerCase() + "s"; + String cx = cname.toLowerCase() + "x"; + BExpression cxbe = new BBasicExpression(cx); + BExpression valbe = new BBasicExpression(val); + BExpression indbe = new BBasicExpression("ind"); + + BExpression newset; + if (op.equals("set")) + { newset = valbe; } + else + { BExpression app = new BApplyExpression(role,cxbe); + app = new BApplyExpression(app,indbe); + + if (op.equals("add")) + { Vector singset = new Vector(); + singset.add(valbe); + BExpression sing = new BSetExpression(singset); + newset = + new BBinaryExpression("\\/",app,sing); + } + else // op is "union" + { newset = + new BBinaryExpression("\\/",app,valbe); + } + } + return new BBinaryExpression("<=", + new BUnaryExpression("card",newset), + new BBasicExpression("1")); + } + +} + diff --git a/version24/BOperation.class b/version24/BOperation.class new file mode 100644 index 0000000000000000000000000000000000000000..208a7fb07e95ae951eccdce3f45a6549a310e011 GIT binary patch literal 3400 zcmb7GTT@e47+oh^atKG!2r617Xj>r(#0yphK>@J_xe16>6dIBP9?8w*1VP11>%AB4 zU9I(@(@r1y(AsL8sWY9vwbPmU*#3*Y_odUdPfkK0v9-)(?|t_E_TJxG-}=7IuYdpW zBY+0nw_z*xmvGc2nr_kbl%N-VRvfUQ82e@Pi+(`Hpy&_UFoZ)kyoSRvj);$88AnBb zOvZ?qAC>XC44;fK8Gac78LEtND<*7MjpM>Xv*83LZ3v2kf*2OfF)k#K-kW0Am&ghgH6@d4eZt06V4)1Y{#7S{9@2@N&5`}53X z@2(xNlCrsL78vHj7uVPZ zB8iw^-KzIL6}*CN3bu=82O6z-Q^6%%mat-BgxV5XFrdaH zSR4)oS8$bVIhr}VhU-?`Q1BMot$16(J9t+@kt05-MHSq{ZV9r3e|`NOG`@*;^Lub# zM~{MCV%;j%J9_qrvzyK3q1Jwf1Zmn__4e?qc-pbEu8xC}(V^BZ{`#qkvNm5_^LI>B zJ@GiP30Un4Zs9#E-dE5jy!t@&d#w0S!AJO5!6&$_;0~@!SZbWKx2Juyx2>}#5~*!c za2KCiaZkZ#!gLq*3TY7mPK6uc@> zO0yCm#>8ct<6gp&Icj^yPN;r;-qgTMoQmgZkpvei=1YjlqWVH27ktsEDsrVRkL+r5 z)L;gW8)ZF`$~Xz-HMxegSZ27F)>rCA0*?v_ODN6CDiWi`J3>)Cl{rTQQNk)1CO7fK zSX|figsyg+l;FzaX4hQMnrgeUGrc79vCy4V4$UXbC?KRHsD>x><3WT=2%eT+G!OIR_Cp(+XehF znb<<)lhHG!*q1<}D0i}LHr6aCWMA%l49V$w1dG%C2nEi%M<{&2c?m6S?S_q=dzWD` z%Gp+Mh3R6R@;&dPz7YNnMNd$C_%W<@If)YILs;0^ZETV#O+w*JVG@h(K%uF9F=rld zkVIM5&Lydx1?f#og{eJ>rK!!!#AmtK$r~+(e@@sqUWsZ{!i81X!gr(rYl*jt&yE8l zTv4$OA*@F$E$M9o9cDV30RG~;B`Etg%Z+RR6=`3d3&3((yZE!ONN*Dm(!{JxuU4i9 zt1@N+q3a1&A2yA%PkD?Nl33I2mXcVTOF=zK>Hh`-tsw=qq`*lE>PSI7-#ib_V_=c3mG|%MGo|29iL0oGj&qO-S(INhfW#`D+}{0 zrI9HNz690SN2PeFg-$ZnP0o7BRUZ!G07lV|SqzY^LHxp*r%a>YaVX84NS+Rus*%={ zxndsqG!x~#yyaJo;H)JtXKON?H5O)0&ZX=b+Nvb|S&Ti0xEhNpi}K1VMc6Rqb(Hct zMtO};UOtlMr`Q6dO~nz6V+s?vhvWDO8h+;gs=r|}O_-1xA8#|wzGkhlkg##4dTz1I z)Ea}ZhuDxr&0W}BsZ1kZj?A`&m9p9;>SPLQ61A=cd6FuVVFHQ3jVLR@Nk(7i^N?W7 zrx@Q;jQlj=%%mOPLYMgugz5M#)A2x-h@IrwC{vf<6zoP(+BWff?)6z^sOu~X+AQ|t9A$YP!?-~9FB;zMGrhY(??e$F$?zk56Rz0v y`c|E>%j+4*q+bS^_RTzCi%a-bz0j{qEV!4+(G{l9RZ@733b{^?y!6C^&VK;o3*QU? literal 0 HcmV?d00001 diff --git a/version24/BOperation.java b/version24/BOperation.java new file mode 100644 index 00000000..8a559f72 --- /dev/null +++ b/version24/BOperation.java @@ -0,0 +1,148 @@ +import java.io.*; + +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +class BOperation +{ String name; + String precond; + IfStatement body; + + public BOperation(String n, String p, IfStatement b) + { name = n; + precond = p; + body = b; + } + + public void display() + { System.out.print(" " + name + " = "); + if (body.isEmpty()) + { System.out.print(" skip"); + return; + } + else + { System.out.println(); } + System.out.println(" PRE " + precond); + System.out.println(" THEN"); + body.display(); + System.out.print(" END"); + } + + public void displayImp(String var) + /* var is statemachine name */ + { System.out.print(" " + name + " ="); + if (body.isEmpty()) + { System.out.print(" skip"); + return; + } + else + { System.out.println(); } + System.out.println(" VAR " + var + "x"); + System.out.println(" IN " + var + "x <-- " + var + "_VAL_VAR;"); + Statement newBody = body.substituteEq(var, new BasicExpression(var + "x")); + newBody.displayImp(null); + System.out.print(" END"); + } // VAL_NVAR if Attribute + + public void displayImp(String var, PrintWriter out) + /* var is statemachine name */ + { out.print(" " + name + " ="); + if (body.isEmpty()) + { out.print(" skip"); + return; + } + else + { out.println(); } + out.println(" VAR " + var + "x"); + out.println(" IN " + var + "x <-- " + var + "_VAL_VAR;"); + Statement newBody = body.substituteEq(var, new BasicExpression(var + "x")); + newBody.displayImp(null,out); + out.print(" END"); + } // VAL_NVAR if Attribute + + public void displayMultImp(String var) + /* var is statemachine name */ + { System.out.print(" " + name + " ="); + if (body.isEmpty()) + { System.out.print(" skip"); + return; + } + else + { System.out.println(); } + + int n = var.length(); + String lib = var.substring(0,1).toUpperCase() + + var.substring(1,n); + System.out.println(" VAR " + var + "x"); + System.out.println(" IN " + var + "x <-- " + lib + "_VAL_FNC_OBJ(oo);"); + Statement newBody = body.substituteEq(var, new BasicExpression(var + "x")); + newBody.displayImp(null); + System.out.print(" END"); + } + + public void displayMultImp(String var, PrintWriter out) + /* var is statemachine name */ + { out.print(" " + name + " ="); + if (body.isEmpty()) + { out.print(" skip"); + return; + } + else + { out.println(); } + + int n = var.length(); + String lib = var.substring(0,1).toUpperCase() + + var.substring(1,n); + out.println(" VAR " + var + "x"); + out.println(" IN " + var + "x <-- " + lib + "_VAL_FNC_OBJ(oo);"); + Statement newBody = body.substituteEq(var, new BasicExpression(var + "x")); + newBody.displayImp(null,out); + out.print(" END"); + } + + public void display(PrintWriter out) + { out.print(" " + name + " ="); + if (body.cases.size() == 0) + { out.print(" skip"); + return; + } + else + { out.println(); } + out.println(" PRE " + precond); + out.println(" THEN"); + body.display(out); + out.print(" END"); + } + + public void displayJava(String stat) + { System.out.println("public " + stat + "void " + name + "()"); + System.out.println("/* Assumes: " + precond + " */"); + System.out.println("{"); + body.displayJava(null); /* Or ""? */ + System.out.println("}"); + } + + public void displayJava(PrintWriter out, String stat) + { out.println("public " + stat + "void " + name + "()"); + out.println("/* Assumes: " + precond + " */"); + out.println("{"); + body.displayJava("", out); + out.println("}"); + } + // Should display java forms of precond. +} + + + + + + + + + diff --git a/version24/BOperationCall.class b/version24/BOperationCall.class new file mode 100644 index 0000000000000000000000000000000000000000..bf9efe7a9f7d1f0a900fafc0b337e49ec6abf9ee GIT binary patch literal 4530 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 literal 0 HcmV?d00001 diff --git a/version24/BOperationCall.java b/version24/BOperationCall.java new file mode 100644 index 00000000..4deb7587 --- /dev/null +++ b/version24/BOperationCall.java @@ -0,0 +1,273 @@ +import java.util.Vector; + +/* Package: B */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BOperationCall extends BStatement +{ private String opName; + private Vector arguments = new Vector(); // BExpression + + public BOperationCall(String op, Vector args) + { opName = op; + arguments = args; + } + + public String toString() + { String res = opName; + int pc = arguments.size(); + if (pc > 0) + { res = res + "("; + for (int i = 0; i < pc; i++) + { res = res + arguments.get(i); + if (i < pc - 1) + { res = res + ","; } + } + res = res + ")"; + } + return res; + } + + public BStatement substituteEq(String oldE, BExpression newE) + { // if (oldE.equals(toString())) + // { return newE; } + Vector nargs = new Vector(); + for (int i = 0; i < nargs.size(); i++) + { BExpression be = (BExpression) nargs.get(i); + BExpression nbe = be.substituteEq(oldE,newE); + nargs.add(nbe); + } + return new BOperationCall(opName,nargs); + } + + public BExpression updateExpression(String var) + { // if it is setAllvar(S,v), return S*{v}, etc + if (opName.equals("setAll" + var)) + { BExpression set = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + BSetExpression valset = new BSetExpression(); + valset.addElement(val); + return new BBinaryExpression("*",set,valset); + } + if (opName.equals("set" + var)) + { BExpression set = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + BSetExpression valset = new BSetExpression(); + valset.addElement(new BBinaryExpression("|->",set,val)); + return valset; + } + if (opName.equals("update" + var)) + { return (BExpression) arguments.get(0); } + if (opName.equals("add" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { ex |-> var(ex) \/ { val }} + BSetExpression valset = new BSetExpression(); + valset.addElement(val); + BApplyExpression fex = + new BApplyExpression(var,ex); + BBinaryExpression union = + new BBinaryExpression("\\/",fex,valset); + BBinaryExpression mapsto = + new BBinaryExpression("|->",ex,union); + BSetExpression maplet = new BSetExpression(); + maplet.addElement(mapsto); + return maplet; + } + else if (opName.equals("remove" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { ex |-> var(ex) - { val }} + BSetExpression valset = new BSetExpression(); + valset.addElement(val); + BApplyExpression fex = + new BApplyExpression(var,ex); + BBinaryExpression minus = + new BBinaryExpression("-",fex,valset); + BBinaryExpression mapsto = + new BBinaryExpression("|->",ex,minus); + BSetExpression maplet = new BSetExpression(); + maplet.addElement(mapsto); + return maplet; + } + else if (opName.equals("union" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { ex |-> var(ex) \/ val } + BApplyExpression fex = + new BApplyExpression(var,ex); + BBinaryExpression union = + new BBinaryExpression("\\/",fex,val); + BBinaryExpression mapsto = + new BBinaryExpression("|->",ex,union); + BSetExpression maplet = new BSetExpression(); + maplet.addElement(mapsto); + return maplet; + } + else if (opName.equals("subtract" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { ex |-> var(ex) - val } + BApplyExpression fex = + new BApplyExpression(var,ex); + BBinaryExpression minus = + new BBinaryExpression("-",fex,val); + BBinaryExpression mapsto = + new BBinaryExpression("|->",ex,minus); + BSetExpression maplet = new BSetExpression(); + maplet.addElement(mapsto); + return maplet; + } + else if (opName.equals("addAll" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { exx,varx | exx : ex & + // varx = var(exx) \/ { val } } + String exx = "e_xx"; + String varx = var + "_x"; + Vector args = new Vector(); + args.add(exx); + args.add(varx); + BBasicExpression exxbe = + new BBasicExpression(exx); + BApplyExpression fex = + new BApplyExpression(var,exxbe); + BBasicExpression varxbe = + new BBasicExpression(varx); + BSetExpression valset = new BSetExpression(); + valset.addElement(val); + + BBinaryExpression union = + new BBinaryExpression("\\/",fex,valset); + BBinaryExpression eq = + new BBinaryExpression("=",varxbe,union); + BBinaryExpression range = + new BBinaryExpression(":",exxbe,ex); + BExpression pred = + new BBinaryExpression("&",range,eq); + BSetComprehension res = + new BSetComprehension(args,pred); + return res; + } + else if (opName.equals("removeAll" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { exx,varx | exx : ex & + // varx = var(exx) - { val } } + String exx = "e_xx"; + String varx = var + "_x"; + Vector args = new Vector(); + args.add(exx); + args.add(varx); + BBasicExpression exxbe = + new BBasicExpression(exx); + BApplyExpression fex = + new BApplyExpression(var,exxbe); + BBasicExpression varxbe = + new BBasicExpression(varx); + BSetExpression valset = new BSetExpression(); + valset.addElement(val); + + BBinaryExpression minus = + new BBinaryExpression("-",fex,valset); + BBinaryExpression eq = + new BBinaryExpression("=",varxbe,minus); + BBinaryExpression range = + new BBinaryExpression(":",exxbe,ex); + BExpression pred = + new BBinaryExpression("&",range,eq); + BSetComprehension res = + new BSetComprehension(args,pred); + return res; + } + else if (opName.equals("unionAll" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { exx,varx | exx : ex & + // varx = var(exx) \/ val } + String exx = "e_xx"; + String varx = var + "_x"; + Vector args = new Vector(); + args.add(exx); + args.add(varx); + BBasicExpression exxbe = + new BBasicExpression(exx); + BApplyExpression fex = + new BApplyExpression(var,exxbe); + BBasicExpression varxbe = + new BBasicExpression(varx); + + BBinaryExpression union = + new BBinaryExpression("\\/",fex,val); + BBinaryExpression eq = + new BBinaryExpression("=",varxbe,union); + BBinaryExpression range = + new BBinaryExpression(":",exxbe,ex); + BExpression pred = + new BBinaryExpression("&",range,eq); + BSetComprehension res = + new BSetComprehension(args,pred); + return res; + } + else if (opName.equals("subtractAll" + var)) + { BExpression ex = (BExpression) arguments.get(0); + BExpression val = (BExpression) arguments.get(1); + // var := var <+ { exx,varx | exx : ex & + // varx = var(exx) - val } + String exx = "e_xx"; + String varx = var + "_x"; + Vector args = new Vector(); + args.add(exx); + args.add(varx); + BBasicExpression exxbe = + new BBasicExpression(exx); + BApplyExpression fex = + new BApplyExpression(var,exxbe); + BBasicExpression varxbe = + new BBasicExpression(varx); + + BBinaryExpression minus = + new BBinaryExpression("-",fex,val); + BBinaryExpression eq = + new BBinaryExpression("=",varxbe,minus); + BBinaryExpression range = + new BBinaryExpression(":",exxbe,ex); + BExpression pred = + new BBinaryExpression("&",range,eq); + BSetComprehension res = + new BSetComprehension(args,pred); + return res; + } + return null; + } + + public BStatement simplify() + { return this; } + + public BStatement seq2parallel() + { return this; } + + public BStatement normalise() + { return this; } + + public Vector rd() + { Vector res = new Vector(); + for (int i = 0; i < arguments.size(); i++) + { BExpression arg = (BExpression) arguments.get(i); + res = VectorUtil.union(res,arg.rd()); + } + return res; + } + + public Vector wr() + { Vector res = new Vector(); + return res; + } + +} diff --git a/version24/BParallelStatement.class b/version24/BParallelStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..e963ba27fc9e37312bfe827c98bed2a2f79f07b0 GIT binary patch literal 2974 zcmbVO-%}H36g``4e!3t;0tP`4wT6U1wbp8)R6(rTfL0U)tr}p(g^-2Ha0Di}}=tv>(%c%=mG|kE=d>7DPLy#9R|I>&JCJZpd;@ z5a)fk86?hv+$@T@6~t|PE~`88f?ET)E311FAS0_KG4$&emjIR(1WRVd)Hn2;SyB*6 zuVo%(#>%FV9h=ja&3rLM52JK7Q_N(udRBq5sK9&L$QkCi0(W$HPJud^U(prpP8&IW zro6GF7q4fQvV0PbHp5vPqKk6rjxM%-uVq$NW^1en98FKuZ&R|f&FMheZG64FKAkDp zf!kJfv%Z7xyQ0I*krepN{H$3ta;pxHY$mrlR(+cCVMT#fDle5x!z`Qn)I$XcJ13`K zdSdE}LQyZ3jC?LN>?F&kGfc_YC}fTMUn*!P5l1cxT#t)1MaBu_^2Loz)+p)htAy1b z9xK>or!?4x*?hUUtY0vsv^^8GmelhcmDXv9Vpu`P&NgZ|gu@!%!x0TS?rT`Z0}Te& zh}$5f0A%yz3ERxR`vwO~>qa5SXcn9!<%zP9UD1mg){zyn!5xF#5gfFBG<=8?8cyOA zCDqJSNRDbq;k1S`IPODELmmYU<2bJ2V|hG=_cc5OBSbNxp#-y*l!FBYNFg+IX1%(y zv_|2khN)AvWPHV1QKgq?sR?ntWJ|&6Oi5=71wBWsR{eGEs7k}mpGDf{UyEH8n}cb? zKUf{B8=No&o^pG7QA{K zSUncjsEsvAUT*RlXvs^kVk0fc^*R813B_r!0f(%L0>Rk#P~#PN=NpN6=>zoB9<3K< zk^WM;gYGkZboXsyU%amZ|IY}_2t-04p1PE8-~K5;F00zz@NhkdAltYHL+Imrh;2N^ zrvbQL!=?O<0mk`&-)_}DN>qvN5zyycRQpz?bcA<25NM_4uSiJnABTeJ(5`82@H~Sz zq{&Jp#qoZ*ZF}xMp@!9db!8LBUZS14*v$kw#3@WSe+8YP5Fd>2FSLiIg0A#am6`my z!<`safANS5xoVoD*u`~>4T{6dinSqu4%T`vt3ALP#+dLduM5nx%uFTyZm4h2;loG# zeT{adS_?^yhn=0^H%!n+-;1`KXRJ)@>^5~;#UZ~yQj;v$#Rj2Zm5_`*PkftD z!4@a`Yt8*OLi?SB;$#&00ljHUs=qs$*vr-d(_}D123N@7DjPS$7G7(LewcCj74yHM z@B5GFbBsRE=rdyk({7zAJqhs)d#pjDW;}AD2s#BkC?c=mK+-Fhp`>qQB;tvv5pTp-!NG>Q zlRVsk2V`dO*jeKYt}~|%PGyb?&r`_-T;@LoH+j8-B0WodYT^;6Q)Y7r?${ny&c9KmF0I;Q5A?6wv1gP zS2Rj*bE|gMD!rW%2v(}*ra-KaUwBVgt6Aj|k3+jg(J=*DX04KC&k5v`r>mQ4nl`C5 zGS8Pc$#AA%mCR*ld)=%)H`a?hiPlVeP0~|0kW9T6h}dQCLIR0o>a>u6Qf2a=-yGX2 z=GM#&yIkd6BQXp%?cxTtJtGZuDrlh#rB?latRoR&mp$DS?&6q=pB0NSMmH zaFKA}qSJI97I_EI&s%eyqAqp_ExyYX>(H4U$xHRg_E6l=J|&!m%IVgQPCj7X8Dxskpx zwm`_4a_#4CioXXL6Z!#!p5BL|XZ8`$hxQTt!gGNEu5mY~15unu8~M+XTTtt=&(h5( zn5P6j|EZBWprVk5bCqfZs>#!_Lxf%(pd}uzBcgwW!Vr&oI8cWgZ}o6cVvV?t*xm_d z*#TdX&pc0Ng&F;1BSTvuO~CTDZ~R;(rbPS8^f8Io(jX$dT!KWsE)`#(PdLYar2q;0 zJi@aDkMHc#A>ywjUpjMubH{vbZnjRoG}@6N3*V~GWs@sJt~s}^j>IQ~^u4rRM~An` z>`9e$rjGN=QpZKp!6T`muAr}_xOQ~YL|_;(jL?Wt8a&P}CXmA<)j_kAm`3dkv4WxB DV$&=a literal 0 HcmV?d00001 diff --git a/version24/BPiExpression.java b/version24/BPiExpression.java new file mode 100644 index 00000000..ba737f19 --- /dev/null +++ b/version24/BPiExpression.java @@ -0,0 +1,58 @@ +import java.util.Vector; + +/* Package: B AMN */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BPiExpression extends BExpression +{ private String var; + private BExpression pred; + private BExpression value; + // PI(var).(pred | value) + + public BPiExpression(String v, BExpression p, + BExpression val) + { var = v; + pred = p; + value = val; + } + + public boolean setValued() + { return false; } + + public String toString() + { return "PI(" + var + ").(" + pred + " | " + + value + ")"; + } + + public Vector rd() + { Vector res = pred.rd(); + res = VectorUtil.union(res,value.rd()); + res.remove(var); + return res; + } + + public BExpression simplify() + { BExpression p2 = pred.simplify(); + BExpression v2 = value.simplify(); + return new BPiExpression(var,p2,v2); + } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (var.equals(oldE)) { return this; } + // also variable capture ... + if (oldE.equals(toString())) + { return newE; } + + BExpression npred = pred.substituteEq(oldE,newE); + BExpression nval = value.substituteEq(oldE,newE); + return new BPiExpression(var,npred,nval); + } +} + diff --git a/version24/BPostfixExpression.class b/version24/BPostfixExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..5bd2dd926e2fafab88c1a7f09bb0500a64525191 GIT binary patch literal 1256 zcmah}+fEZv6kTUp+G&}#P;LTVxQO-!Rm2N|s3rJR)TD+4-=;8-!J#d4G5F$t@DDs- zA|;W;=&RpkjO%m;Y0HCYviF&@_g;JLwNLu%&$sUY7O)z}0CF*?$V*dDF&oDmit_rN zH20&Jk2CThiiJ4h$f9yTr z#kI}au8iyUuD5U0T!BQnw079A4aYI-HHIR~X3cb01g0`qD?4(t8v^0g`nDmEDw{Rq zwYOh2?00(A;!Vsk+zs9GjBSBXCi|X^Dz3iuVO?(o8H&x&U?%H#@m$j?ZWvqSEcrR+ ze#0_%J`tK3?F{|-+`2zY8$#!Vn&VX+*K|GCSUV7y`|mIvO$6eVx@T`0uS_}2Na=0e zad*taOQq(dsv53gS;HWPGz?=zKzxqknT8cS*Ki9H8YVHt67tz;^#7!Cpo^Ck;L+!)AsqRtbCApD^-e?## zZeg}PA$TOgUfNU*xN$ul`4@m!Udu&3MNs)N0fj$m)jClw`Ur#+f_98wMaDz)soWVv zE`JIoS2#uJ3$FymX_KvRKVnGpJiy!QxDgaDvRE*uFZUHnI^0Ch5qiSMp<~`DZPmlj z*gDC!HyH^*Bw5B?1u)V}7?m)gCL$+1`^_a+u%VDkrIm~=gjAwr&P&0# z)8~k9o}o9bHIeXHB-1JXtk5;l*F8d(5PU}gP=)QK=u`Pz6aBtyg@05fV!qHsx`XmC cdRS3FFJ_V8ztuQbH%T8TnjmzB2@0}*0jF~Mp8x;= literal 0 HcmV?d00001 diff --git a/version24/BPostfixExpression.java b/version24/BPostfixExpression.java new file mode 100644 index 00000000..8bfeff7c --- /dev/null +++ b/version24/BPostfixExpression.java @@ -0,0 +1,50 @@ +import java.util.Vector; + +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BPostfixExpression extends BExpression +{ private String operator; + private BExpression argument; + + public BPostfixExpression(String op, BExpression arg) + { operator = op; + argument = arg; + } + + public boolean setValued() + { if (operator.equals("~")) + { return true; } + return false; // + } + + public Vector rd() + { return argument.rd(); } + + public BExpression simplify() + { BExpression b1 = argument.simplify(); + if (b1 instanceof BPostfixExpression) + { BPostfixExpression pf = (BPostfixExpression) b1; + if (pf.operator.equals("~")) + { return pf.argument; } + } + return new BPostfixExpression(operator,b1); + } + + public String toString() + { return "(" + argument + ")" + operator; } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (oldE.equals(toString())) + { return newE; } + return new BPostfixExpression(operator, + argument.substituteEq(oldE,newE)); + } +} + diff --git a/version24/BQuantifierExpression.class b/version24/BQuantifierExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..1d6964c80ed513cc527e8af7c324129f9ba9bb9d GIT binary patch literal 2178 zcmZ`(Npl-j5dKE%SRTh_BH4~tya2M~4KM++IElAlkhj>_aahOJ*i15(m4xY~eT zToW-RVp_zEC}!iBOCXM`BCd;gPsO~7_Y?R4ITZ^k7UNh-phZktu&iQ5)*C8TWnEM8 zq1;**v7zFoicRr*OT|YjK91v)1Veo);xiFzqWnA#LqTG{Via6!$1)uSdhWJyV2s&D zVRvlRb*#efMFrslgQ`f$aLP|DDz0UZt()6!(V>NEIJ=cSv*0Rd%1zCFS#r#B*(w&O zie0h_mOH6nBK@N8Iw!%~L+cDXUCf&bnsZjcT&(PEna-NAW%K0!{RMM7m5uldIe7)i z^pGDqXv#9&qF;2t;xrUZtFEzqXTd0WNyM?GprLHK>xNx1={KAnxA+D7xTV>aBE3P@auVAzuFu_ZwU68TWV#V1u=PZGtV`}9of6ss)6&f`RV_U;( zcvV9hLmFO@T?SbVuj35`Egsha2sGqjYS_W90+70$qGQ-LtJLrX7)$Bne?URo^Gz~U zvFyC*Xs~db5Ray1cZbFd`X(m0;faks4FweWHB6|6#OhsKAjPgzq4(&HVVAk4>Q*Gh zjEET5a0!a6ZCPO2l>WC5E6#D3km1mO4_}Zq;rjvRH8^Z%CAM*MY#54j-X_eLxe$0Nwocpr3^*(z>-E^9&N^jlRq;h*lBHJw|-<2qSLjsS{;4lSxXBKczI|k0d6<)negZy7>j-uH| zyianHkI}oyZA3n^M|k;B;2_L{KIsV`3BRweu_vaO_B19jgR7XubSZ|ce1<#-WatmZ0vb89 iO<3ZrEpx6{$lMLGw91^ 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 literal 0 HcmV?d00001 diff --git a/version24/BSetExpression.java b/version24/BSetExpression.java new file mode 100644 index 00000000..8e440cca --- /dev/null +++ b/version24/BSetExpression.java @@ -0,0 +1,127 @@ +import java.util.Vector; + +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BSetExpression extends BExpression +{ private Vector elements = new Vector(); + private boolean ordered = false; + + public BSetExpression() { } + + public BSetExpression(Vector vals) + { elements = vals; } + + public BSetExpression(Vector vals,boolean ord) + { this(vals); + ordered = ord; + } + + public boolean isSingleton() + { return elements.size() == 1; } + + public boolean isEmpty() + { return elements.size() == 0; } + + public boolean isOrdered() + { return ordered; } + + public void setOrdered(boolean ord) + { ordered = ord; } + + public BExpression getElement(int i) + { return (BExpression) elements.get(i); } + + public void addElement(BExpression b) + { elements.add(b); } + + public boolean hasElement(BExpression b) + { boolean res = false; + for (int i = 0; i < elements.size(); i++) + { if (("" + elements.get(i)).equals("" + b)) + { return true; } + } + return res; + } + + public Vector rd() + { Vector res = new Vector(); + for (int i = 0; i < elements.size(); i++) + { BExpression elem = (BExpression) elements.get(i); + res = VectorUtil.union(res,elem.rd()); + } + return res; + } + + public boolean isSubsetOf(BSetExpression bset) + { boolean res = true; + for (int i = 0; i < elements.size(); i++) + { BExpression elem = (BExpression) elements.get(i); + if (bset.hasElement(elem)) { } + else + { return false; } + } + return res; + } + + public boolean setValued() + { return true; } + + public BExpression simplify() + { if (isSingleton()) + { BExpression elem = (BExpression) elements.get(0); + BExpression esimp = elem.simplify(); + if (esimp.setValued()) + { return esimp; } // cannot have sets of sets in OCL + } + Vector selemts = new Vector(); + for (int i = 0; i < elements.size(); i++) + { BExpression e = (BExpression) elements.get(i); + selemts.add(e.simplify()); + } + return new BSetExpression(selemts,ordered); + } + + public String toString() + { String res; + if (ordered && elements.size() == 0) + { return "<>"; } + if (ordered) + { res = "["; } + else + { res = "{"; } + + for (int i = 0; i < elements.size(); i++) + { res = res + elements.get(i); + if (i < elements.size() - 1) + { res = res + ", "; } + } + + if (ordered) + { res = res + "]"; } + else + { res = res + "}"; } + return res; + } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (oldE.equals(toString())) + { return newE; } + BSetExpression res = new BSetExpression(new Vector(),ordered); + for (int i = 0; i < elements.size(); i++) + { BExpression elem = (BExpression) elements.get(i); + res.addElement(elem.substituteEq(oldE,newE)); + } + return res; + } + + public boolean conflictsWith(BExpression e) + { return false; } +} + diff --git a/version24/BSigmaExpression.class b/version24/BSigmaExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..d1757417b67a3925dca9f58bc91771518310aa32 GIT binary patch literal 1446 zcmah}+fvg|6kR915>kY66A(c~?Y$xh2#5j#q6O3{4!#A5Ot7@2O&Fc=NBjpLa7KzF zGk$;{<+x4~pn#(UaIIsrU6l8<#9(IgCX2i5kMx4At{H$ zxF_XE7^7i~N%g)A8&@%bNfi$;C9e-dc%(9XTEz@zrRI1&4q;Bfx2IPGqPcB-PtO+g z;#M|qRm|engn++XF*XGvxtX~SRI639RHQkurx$EPAUJ6jO>0UZ8@m{NCg#i~zDnfT z(k2lu<;6xm|(G|JpboAIV$##``6`>=m!(OLk?$ zm^Wo7?K63EYezqwTt-eg{A43h6Oy~ zMB*7oU8LIosb4_EHQc~}hMTw*!cz^;kPBf+!!lMh+(t~G`FtI+gsUMu*YH9*#gPzb ztQ(9ocybif%Vnd;(Wd`0my1MrC3EIy{8!eu$;HIK{8g8&*CdY1Wf!?+0%Km%dOBV5 z>n$E^y@?$=)2y?xmx{4d+LNr*_i|htx6F;HTYttFyS84a;u_yeC!eGbisX%&BB^sE z*`o|X$eHr&<86%J{giEqLx@E307@ct0AC_~0RLCo1^RhL9iI*~5W9)Etwa{gb=^bh zrWEv3d|ystWFBy1gyfv3%$8#|X&pX7VC@jWXsCv8;u{o-XoIW!YEYw%uI`t*M!kl} z{yF46B5{#C&UY(yrf7bXJOy!E8bFvJZG`FN0t&f=9^e#z zPd)-(bpcy)E?&#h5u$4nFPS<->nUE7?NdyKF!4Sz9Ccz^d@hGySGs!Q0C=rdh JQ`8lt{{Z){FM9w0 literal 0 HcmV?d00001 diff --git a/version24/BSigmaExpression.java b/version24/BSigmaExpression.java new file mode 100644 index 00000000..1b0b8d79 --- /dev/null +++ b/version24/BSigmaExpression.java @@ -0,0 +1,59 @@ +import java.util.Vector; + +/* Package: B AMN */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + + +public class BSigmaExpression extends BExpression +{ private String var; + private BExpression pred; + private BExpression value; + // SIGMA(var).(pred | value) + + public BSigmaExpression(String v, BExpression p, + BExpression val) + { var = v; + pred = p; + value = val; + } + + public boolean setValued() + { return false; } + + public String toString() + { return "SIGMA(" + var + ").(" + pred + " | " + + value + ")"; + } + + public Vector rd() + { Vector res = pred.rd(); + res = VectorUtil.union(res,value.rd()); + res.remove(var); + return res; + } + + public BExpression simplify() + { BExpression p2 = pred.simplify(); + BExpression v2 = value.simplify(); + return new BSigmaExpression(var,p2,v2); + } + + public BExpression substituteEq(String oldE, BExpression newE) + { if (var.equals(oldE)) { return this; } + // also variable capture ... + if (oldE.equals(toString())) + { return newE; } + + BExpression npred = pred.substituteEq(oldE,newE); + BExpression nval = value.substituteEq(oldE,newE); + return new BSigmaExpression(var,npred,nval); + } +} + diff --git a/version24/BStatement.class b/version24/BStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..626417b67f9b3b529a670d34bcb5c89f7835eb14 GIT binary patch literal 6044 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 0) + { s1norm = (BAssignStatement) s1stat.normalise(); + s2norm = s2.normalise(); + } + BExpression lhs = s1norm.getLhs(); + BExpression rhs = s1norm.getRhs(); + + BStatement stat2 = s2norm.seq2parallel(); + BStatement s2new = stat2.substituteEq(lhs + "",rhs); + BStatement s3 = s2new.simplify(); + System.out.println("S2 simplified is: " + s3); + System.out.println(); + + if (inters1.size() == 0) // no common written data + { res.addStatement(s1norm); + res.addStatement(s3); + return res; + } + else + { return s3; } + } + + if (s1 instanceof BIfStatement) + { BExpression cond = ((BIfStatement) s1).getCond(); + BStatement ifpart = ((BIfStatement) s1).getIf(); + BStatement elsepart = ((BIfStatement) s1).getElse(); + Vector fr2 = ifpart.wr(); + BStatement s3 = sequence2parallel(ifpart,s2,fr2,wfr2,rd2); + Vector fr3 = elsepart.wr(); + BStatement s4 = sequence2parallel(elsepart,s2,fr3,wfr2,rd2); + return new BIfStatement(cond,s3,s4); + } + + if (s1 instanceof BAnyStatement) + { Vector vars = ((BAnyStatement) s1).getVars(); + BExpression cond = ((BAnyStatement) s1).getWhere(); + BStatement thenpart = ((BAnyStatement) s1).getThen(); + // Vector fr2 = thenpart.wr(); + BStatement s3 = sequence2parallel(thenpart,s2,wfr1,wfr2,rd2); + return new BAnyStatement(vars,cond,s3); + } + + if (s1 instanceof BParallelStatement) + { ((BParallelStatement) s1).addStatement(s2); + return s1.seq2parallel(); + } + + if (s1 instanceof BBasicStatement) + { return s2; } + + return this; + } + + public static BStatement separateUpdates(Vector statements) + { // for each vbl, gather updates to vbl + Map updates = new HashMap(); + Vector updated = new Vector(); + for (int i = 0; i < statements.size(); i++) + { BStatement bs = (BStatement) statements.get(i); + if (bs == null) { continue; } + String var = bs.getWriteFrame(); + System.out.println("Statement:::: " + bs + " on variable " + var); + BStatement varupd = (BStatement) updates.get(var); + if (varupd == null) + { updates.put(var,bs); + updated.add(var); + } + else + { BStatement newupd = addCase(var,varupd,bs); + updates.put(var,newupd); + } + } + BParallelStatement res = new BParallelStatement(); + for (int j = 0; j < updated.size(); j++) + { String v = (String) updated.get(j); + BStatement vs = (BStatement) updates.get(v); + vs.setWriteFrame(v); + res.addStatement(vs); + } + res.setWriteFrame(updated); + System.out.println("Complete statement:::: " + res); + return res; + } + + private static BStatement addCase(String var, + BStatement stat, + BStatement cse) + { if (stat == null) + { if (cse instanceof BAssignStatement) + { return ((BAssignStatement) cse).normalise(); } + return cse; + } + + if (cse == null) { return stat; } + + if (stat instanceof BIfStatement && cse instanceof BIfStatement) + { return combineIfStatements(var,(BIfStatement) stat, (BIfStatement) cse); } + + if (stat instanceof BIfStatement) + { BIfStatement ifstat = (BIfStatement) stat; + BStatement ifpart = ifstat.getIf(); + BStatement elsepart = ifstat.getElse(); + BStatement newif = addCase(var,ifpart,cse); + BStatement newelse = addCase(var,elsepart,cse); + ifstat.setElse(newelse); + ifstat.setIf(newif); + return ifstat; + } + + if (cse instanceof BIfStatement) + { BIfStatement if2 = (BIfStatement) cse; + BStatement ifpart2 = if2.getIf(); + BStatement else2 = if2.getElse(); + BStatement newif2 = addCase(var,stat,ifpart2); + BStatement newelse2 = addCase(var,stat,else2); + if2.setIf(newif2); + if2.setElse(newelse2); + return if2; + } + return combineUpdates(var,stat,cse); + } + + // Can optimise if both if statements, with contradictory or identical + // conditions: if e then if not(e) then c1 else c2 end else c3 == + // if e then c2 else c3 + // + + private static BStatement combineIfStatements(String var, + BIfStatement stat, BIfStatement cse) + { BExpression e1 = stat.getCond(); + BExpression e2 = cse.getCond(); + BStatement cseif = cse.getIf(); + BStatement cseelse = cse.getElse(); + BStatement ifpart = stat.getIf(); + BStatement elsepart = stat.getElse(); + + System.out.println("COMBINING If's with conditions " + e1 + " " + e2); + + if (("" + e1).equals("" + e2)) + { BStatement newif = addCase(var,ifpart,cseif); + BStatement newelse = addCase(var,elsepart,cseelse); + stat.setElse(newelse); + stat.setIf(newif); + return stat; + } + + if (e1.conflictsWith(e2)) + { BStatement newif = addCase(var,ifpart,cseelse); + BStatement newelse = addCase(var,elsepart,cse); + stat.setElse(newelse); + stat.setIf(newif); + return stat; + } + + BStatement newif = addCase(var,ifpart,cse); + BStatement newelse = addCase(var,elsepart,cse); + stat.setElse(newelse); + stat.setIf(newif); + return stat; + } + + + + private static BStatement combineUpdates(String var, + BStatement stat, + BStatement cse) + { // combine effects of statements on same var + if (stat instanceof BAssignStatement && + cse instanceof BAssignStatement) + { BAssignStatement s1 = (BAssignStatement) stat; + BAssignStatement s2 = (BAssignStatement) cse; + BAssignStatement s3 = (BAssignStatement) s2.normalise(); // makes everything var := var <+ e + BExpression rhs1 = s1.getRhs(); + BExpression rhs2 = s3.getRhs(); + BExpression newrhs = + combineUpdateExpressions(var,rhs1,rhs2); + return new BAssignStatement( + new BBasicExpression(var),newrhs); + } + if (stat instanceof BOperationCall && + cse instanceof BOperationCall) + { BOperationCall c1 = (BOperationCall) stat; + BOperationCall c2 = (BOperationCall) cse; + BExpression v1 = c1.updateExpression(var); + BExpression v2 = c2.updateExpression(var); + BExpression v; + if ((v1 + "").equals(v2 + "")) + { v = v1; } + else + { v = new BBinaryExpression("<+",v1,v2); } + Vector pars = new Vector(); + pars.add(v); + return new BOperationCall("update" + var,pars); + } + return cse; + } // case of BOperationCall + + private static BExpression combineUpdateExpressions(String v, + BExpression upd1, + BExpression upd2) + { System.out.println("WARNING ==> Possible update conflicts on: " + v + " " + + upd1 + " " + upd2); + BExpression res; + if (upd1 instanceof BBinaryExpression && + upd2 instanceof BBinaryExpression) + { BBinaryExpression be1 = (BBinaryExpression) upd1; + BBinaryExpression be2 = (BBinaryExpression) upd2; + BExpression ll = be1.leftmostArgument(); + BExpression ll2 = be2.getLeft(); + if (v.equals(ll.toString()) && + v.equals(ll2.toString()) ) + { be1.setBrackets(true); + res = new BBinaryExpression(be2.getOperator(),be1, + be2.getRight()); + return res; + } // the order matters: (a /\ b) \/ c isn't (a \/ c) /\ b + } + return upd2; + } + + public abstract BStatement substituteEq(String oldE, BExpression newE); + + public abstract BStatement simplify(); +} + diff --git a/version24/BSystemTypes.class b/version24/BSystemTypes.class new file mode 100644 index 0000000000000000000000000000000000000000..794f4dae46f72943e614b1b9084c3faee410a29d GIT binary patch literal 267890 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 String defining operation for each predicate of + // a select used in the specification + public static java.util.Map selectCodes = new java.util.HashMap(); + // stores numeric codes of the predicates + public static java.util.Map selectDecs = new java.util.HashMap(); + public static Vector selectList = new Vector(); + + private static int index = 0; + + public static Vector existsList = new Vector(); + public static java.util.Map existsOps = new java.util.HashMap(); + public static java.util.Map existsDecs = new java.util.HashMap(); + public static java.util.Map existsCodes = new java.util.HashMap(); + + public static Vector exists1List = new Vector(); + public static java.util.Map exists1Ops = new java.util.HashMap(); + public static java.util.Map exists1Decs = new java.util.HashMap(); + public static java.util.Map exists1Codes = new java.util.HashMap(); + + public static Vector rejectList = new Vector(); + public static java.util.Map rejectOps = new java.util.HashMap(); + public static java.util.Map rejectCodes = new java.util.HashMap(); + public static java.util.Map rejectDecs = new java.util.HashMap(); + + public static Vector forAllList = new Vector(); + public static java.util.Map forAllOps = new java.util.HashMap(); + public static java.util.Map forAllDecs = new java.util.HashMap(); + public static java.util.Map forAllCodes = new java.util.HashMap(); + + public static java.util.Map collectOps = new java.util.TreeMap(); + public static java.util.Map collectCodes = new java.util.TreeMap(); + public static java.util.Map collectDecs = new java.util.TreeMap(); + public static Vector collectList = new Vector(); + + public static java.util.Map anyOps = new java.util.TreeMap(); + public static java.util.Map anyCodes = new java.util.TreeMap(); + public static java.util.Map anyDecs = new java.util.TreeMap(); + public static Vector anyList = new Vector(); + + + public BSystemTypes(String nme) + { super(nme,new Vector()); + clearVariables(); + } // SystemTypes has no variables, only types. + + + public static void resetDesigns() + { selectOps.clear(); selectCodes.clear(); + selectList.clear(); selectDecs.clear(); + + existsOps.clear(); existsCodes.clear(); + existsList.clear(); + + exists1Ops.clear(); exists1Codes.clear(); + exists1List.clear(); + + exists1Decs.clear(); existsDecs.clear(); + + forAllOps.clear(); forAllCodes.clear(); + forAllDecs.clear(); forAllList.clear(); + + + rejectOps.clear(); rejectCodes.clear(); + rejectList.clear(); rejectDecs.clear(); + + collectList.clear(); collectDecs.clear(); + collectOps.clear(); collectCodes.clear(); + + anyList.clear(); anyDecs.clear(); + anyOps.clear(); anyCodes.clear(); + + index = 0; + } + + public static String getSelectDefinition(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + // Only applies to left being a collection of objects, not numerics, strings or + // collections + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "List"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + // System.out.println(left + " element type is " + e); + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) selectOps.get(pp); + // But left may be ordered in one case and not in other + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static List select_" + oldindex + "(List _l"; + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + res = res + " { // Implements: " + left + "->select(" + var + " | " + pred + ")\n" + + " List _results_" + oldindex + " = new Vector();\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res = res + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; } + + System.out.println(">>> Evaluating " + pred + " in environment " + newenv); + + String test = pred.queryForm(newenv,false); + + System.out.println(">>> Result = " + test); + + String wvar = Expression.wrap(e,var); + res = res + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + wvar + "); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }\n\n"; + + // Version for maps: + res = res + " public static HashMap select_" + oldindex + "(Map _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + res = res + " { // Implements: " + left + "->select(" + var + " | " + pred + ")\n" + + " HashMap _results_" + oldindex + " = new HashMap();\n" + + " java.util.Set _keys = _l.keySet();\n" + + " for (Object _i : _keys)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res = res + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; } + + res = res + " if (" + test + ")\n" + + " { _results_" + oldindex + ".put(_i, " + wvar + "); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }\n"; + + + selectList.add(pp); + selectOps.put(pp,res); + selectCodes.put(pp,"" + oldindex); + + return "select_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) selectCodes.get(pp); + return "select_" + ind + "(" + lqf + ")"; + } + } + + public static String getSelectDefinitionJava6(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String restype1 = "ArrayList"; + // if (left.isOrdered()) + // { restype = "ArrayList"; } + // else + // { restype = "HashSet"; } + String restype2 = "HashSet"; + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "HashSet"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + // System.out.println(left + " element type is " + e); + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) selectOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + String res1 = " public static " + restype1 + " select_" + oldindex + "(" + restype1 + " _l"; + String res2 = " public static " + restype2 + " select_" + oldindex + "(" + restype2 + " _l"; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res1 = res1 + "," + par.getType().getJava6() + " " + par.getName(); + res2 = res2 + "," + par.getType().getJava6() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res1 = res1 + ")\n"; + res1 = res1 + " { // Implements: " + left + "->select(" + var + " | " + pred + ")\n" + + " " + restype1 + " _results_" + oldindex + " = new " + restype1 + "();\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res1 = res1 + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res1 = res1 + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res1 = res1 + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res1 = res1 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res1 = res1 + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; } + + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype2 + " _results_" + oldindex + " = new " + restype2 + "();\n" + + " for (Object _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res2 = res2 + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res2 = res2 + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res2 = res2 + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res2 = res2 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res2 = res2 + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; } + + String test = pred.queryFormJava6(newenv,false); + + res1 = res1 + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + + res2 = res2 + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + // no need to wrap var in Java 6. + + selectList.add(pp); + selectOps.put(pp,res1 + "\n\n" + res2); + selectCodes.put(pp,"" + oldindex); + + return "select_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) selectCodes.get(pp); + return "select_" + ind + "(" + lqf + ")"; + } + } + + public static String getSelectDefinitionJava7( + Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "Set"; } // element type? + else if (ename.equals("Sequence")) + { tname = "ArrayList"; + if (e != null) + { tname = e.getJava7(); } + } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + String partype1 = "List<" + tname + ">"; + String restype1 = "ArrayList<" + tname + ">"; + String restype2 = "HashSet<" + tname + ">"; + String restype3 = "TreeSet<" + tname + ">"; + String restype4 = "Set<" + tname + ">"; + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) selectOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + String res1 = " public static " + restype1 + " select_" + oldindex + "(" + partype1 + " _l"; + String res2 = " public static " + restype2 + " select_" + oldindex + "(" + restype2 + " _l"; + String res3 = " public static " + restype3 + " select_" + oldindex + "(" + restype3 + " _l"; + String res4 = " public static " + restype2 + " select_" + oldindex + "(" + restype4 + " _l"; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + if (par.getType() == null) + { System.err.println("!! ERROR: no type for " + par); } + else + { Type partype = par.getType(); + String jType = + partype.getJava7(partype.getElementType()); + res1 = res1 + ", " + jType + " " + par.getName(); + res2 = res2 + ", " + jType + " " + par.getName(); + res3 = res3 + ", " + jType + " " + par.getName(); + res4 = res4 + ", " + jType + " " + par.getName(); + } + } + + res1 = res1 + ")\n"; + res1 = res1 + " { // implements: " + left + "->select( " + var + " | " + pred + " )\n" + + " " + restype1 + " _results_" + oldindex + " = new " + restype1 + "();\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res1 = res1 + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res1 = res1 + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res1 = res1 + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res1 = res1 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res1 = res1 + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; } + + res2 = res2 + ")\n"; + res2 = res2 + " { // implements: " + lqf + "->select( " + selectvar + " | " + pred + " )\n" + + " " + restype2 + " _results_" + oldindex + " = new " + restype2 + "();\n" + + " for (" + tname + " _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res2 = res2 + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res2 = res2 + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res2 = res2 + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res2 = res2 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res2 = res2 + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; } + + res3 = res3 + ")\n"; + res3 = res3 + " { " + restype3 + " _results_" + oldindex + " = new " + restype3 + "();\n" + + " for (" + tname + " _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res3 = res3 + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res3 = res3 + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res3 = res3 + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res3 = res3 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res3 = res3 + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; } + + res4 = res4 + ")\n"; + res4 = res4 + " { // implements: " + lqf + "->select( " + selectvar + " | " + pred + " )\n" + + " " + restype2 + " _results_" + oldindex + " = new " + restype2 + "();\n" + + " for (" + tname + " _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res4 = res4 + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res4 = res4 + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res4 = res4 + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res4 = res4 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res4 = res4 + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; } + + String test = pred.queryFormJava7(newenv,false); + + res1 = res1 + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + + res2 = res2 + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + res3 = res3 + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + var + "); }\n"; + res3 = res3 + " }\n"; + res3 = res3 + " return _results_" + oldindex + ";\n }"; + + res4 = res4 + " if (" + test + ")\n" + + " { _results_" + oldindex + ".add(" + var + "); }\n"; + res4 = res4 + " }\n"; + res4 = res4 + " return _results_" + oldindex + ";\n }"; + + selectList.add(pp); + selectOps.put(pp,res1 + "\n\n" + res2 + "\n\n" + res3 + "\n\n" + res4); + selectCodes.put(pp,"" + oldindex); + + return "select_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) selectCodes.get(pp); + return "select_" + ind + "(" + lqf + ")"; + } + } + + public static String getSelectDefinitionCSharp(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller.inst().get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("String")) + { tname = "string"; } + else if (ename.equals("boolean")) + { tname = "bool"; } + + // System.out.println(left + " element type is " + e); + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) selectOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static ArrayList select_" + oldindex + "(ArrayList _l"; + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getCSharp() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + res = res + " { // Implements: " + left + "->select(" + var + " | " + pred + ")\n" + + " ArrayList _results_" + oldindex + " = new ArrayList();\n" + + " for (int _iselect = 0; _iselect < _l.Count; _iselect++)\n" + + " { " + tname + " " + var + " = (" + tname + ") _l[_iselect];\n"; + + String test = pred.queryFormCSharp(newenv,false); + res = res + " if (" + test + ")\n" + + " { _results_" + oldindex + ".Add(" + var + "); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }"; + + + selectList.add(pp); + selectOps.put(pp,res); + selectCodes.put(pp,"" + oldindex); + + return "select_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) selectCodes.get(pp); + return "select_" + ind + "(" + lqf + ")"; + } + } + + public static String getSelectDefinitionCPP(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; } + else + { ename = e.getName(); } + + String tname = ename + "*"; + if (Type.isBasicType(e)) + { tname = e.getCPP("void*"); } + else if ("Sequence".equals(ename)) + { tname = e.getCPP(e.getElementType()); } // "vector*"; } + else if ("Set".equals(ename)) + { tname = e.getCPP(e.getElementType()); } // "set*"; } + + String restype1 = "std::set<" + tname + ">"; + String addop1 = "insert"; + String restype2 = "std::vector<" + tname + ">"; + String addop2 = "push_back"; + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) selectOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res1 = " static " + restype1 + "* select_" + oldindex + "(" + restype1 + "* _l"; + String res2 = " static " + restype2 + "* select_" + oldindex + "(" + restype2 + "* _l"; + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String cpppt = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + cpppt + " " + par.getName(); + res2 = res2 + ", " + cpppt + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res1 = res1 + ")\n"; + res1 = res1 + " { // implements: " + left + "->select( " + var + " | " + pred + " )\n" + + " " + restype1 + "* _results_" + oldindex + " = new " + restype1 + "();\n" + + " for (" + restype1 + "::iterator _iselect = _l->begin(); _iselect != _l->end(); ++_iselect)\n" + + " { " + tname + " " + var + " = *_iselect;\n"; + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype2 + "* _results_" + oldindex + " = new " + restype2 + "();\n" + + " for (" + restype2 + "::iterator _iselect = _l->begin(); _iselect != _l->end(); ++_iselect)\n" + + " { " + tname + " " + var + " = *_iselect;\n"; + + String test = pred.queryFormCPP(newenv,false); + res1 = res1 + " if (" + test + ")\n" + + " { _results_" + oldindex + "->" + addop1 + "(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + res2 = res2 + " if (" + test + ")\n" + + " { _results_" + oldindex + "->" + addop2 + "(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + String res = res1 + "\n\n" + res2; + + selectList.add(pp); + selectOps.put(pp,res); + selectCodes.put(pp,"" + oldindex); + + return "select_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) selectCodes.get(pp); + return "select_" + ind + "(" + lqf + ")"; + } + } + + public static String getCollectDefinition(Expression left, String lqf, + Expression exp, boolean rprim, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "List"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) collectOps.get(pp); + // But may be different left element type with same expression + + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static List collect_" + oldindex + "(List _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + } + res = res + ")\n"; + res = res + " { // implements: " + left + "->collect( " + var + " | " + exp + " )\n" + + " List _results_" + oldindex + " = new Vector();\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res = res + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + String elem = exp.queryForm(newenv,false); + Type restype = exp.getType(); + String jtype = restype.typeWrapper(); + + if (rprim) + { elem = Expression.wrap(exp.getType(),elem); } + + res = res + " " + jtype + " collect_x = " + elem + ";\n" + + " if (collect_x != null) { _results_" + oldindex + ".add(collect_x); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }\n\n"; + + // Also need a Map version: + res = res + " public static HashMap collect_" + oldindex + "(Map _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + } + res = res + ")\n"; + res = res + + " { // implements: " + left + "->collect( " + var + " | " + exp + " )\n" + + " HashMap _results_" + oldindex + " = new HashMap();\n" + + " java.util.Set _keys = _l.keySet();\n" + + " for (Object _i : _keys)\n" + + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n" + + " " + jtype + " collect_x = " + elem + ";\n" + + " if (collect_x != null) { _results_" + oldindex + ".put(_i,collect_x); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }"; + + collectList.add(pp); + collectOps.put(pp,res); + collectCodes.put(pp,"" + oldindex); + + return "collect_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) collectCodes.get(pp); + return "collect_" + ind + "(" + lqf + ")"; + } + } + + public static String getCollectDefinitionJava6(Expression left, String lqf, + Expression exp, boolean rprim, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "HashSet"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + String restype = ""; + // if (left.isOrdered()) + { restype = "ArrayList"; } + // else + // { restype = "HashSet"; } + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) collectOps.get(pp); + // But may be different left element type with same expression + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static " + restype + " collect_" + oldindex + "(Collection _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava6() + " " + par.getName(); + } + res = res + ")\n"; + res = res + " { // implements: " + left + "->collect( " + var + " | " + exp + " )\n" + + " " + restype + " _results_" + oldindex + " = new " + restype + "();\n" + + " for (Object _i : _l)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _i).intValue();\n"; + } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + String elem = exp.queryFormJava6(newenv,false); + + if (rprim) + { elem = Expression.wrap(exp.getType(),elem); } + + res = res + " _results_" + oldindex + ".add(" + elem + ");\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }"; + + collectList.add(pp); + collectOps.put(pp,res); + collectCodes.put(pp,"" + oldindex); + + return "collect_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) collectCodes.get(pp); + return "collect_" + ind + "(" + lqf + ")"; + } + } + + public static String getCollectDefinitionJava7( + Expression left, String lqf, + Expression exp, boolean rprim, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "Set"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + Type argtype = exp.getType(); + String exptype = "Object"; + if (argtype == null) + { System.err.println("!! ERROR: No type for " + exp + " in collect"); } + else + { exptype = + Type.getJava7Type(argtype, argtype.getKeyType(), + exp.getElementType()); + } + + String restype = "ArrayList<" + exptype + ">"; + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) collectOps.get(pp); + // But may be different left element type with same expression + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static " + restype + " collect_" + oldindex + "(Collection<" + tname + "> _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + "," + + partype.getJava7(partype.getElementType()) + + " " + par.getName(); + } + } + res = res + ")\n"; + res = res + " { // Implements: " + left + "->collect( " + var + " | " + exp + " )\n" + + " " + restype + " _results_" + oldindex + " = new " + restype + "();\n" + + " for (" + tname + " _i : _l)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _i).intValue();\n"; + } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + String elem = exp.queryFormJava7(newenv,false); + + if (rprim) + { elem = Expression.wrap(exp.getType(),elem); } + + res = res + " _results_" + oldindex + ".add(" + elem + ");\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }"; + + collectList.add(pp); + collectOps.put(pp,res); + collectCodes.put(pp,"" + oldindex); + + return "collect_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) collectCodes.get(pp); + return "collect_" + ind + "(" + lqf + ")"; + } + } + + public static String getCollectDefinitionCSharp(Expression left, String lqf, + Expression exp, boolean rprim, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller.inst().get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("String")) + { tname = "string"; } + else if (ename.equals("boolean")) + { tname = "bool"; } + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) collectOps.get(pp); + // But may be different left element type with same expression + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static ArrayList collect_" + oldindex + "(ArrayList _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + System.out.println(">> Collect parameter " + par + " " + par.getType()); + + res = res + ", " + par.getType().getCSharp() + " " + par.getName(); + } + res = res + ")\n"; + res = res + " { // Implements: " + left + "->collect( " + var + " | " + exp + " )\n" + + " ArrayList _results_" + oldindex + " = new ArrayList();\n" + + " for (int _icollect = 0; _icollect < _l.Count; _icollect++)\n" + + " { " + tname + " " + var + " = (" + tname + ") _l[_icollect];\n"; + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String elem = exp.queryFormCSharp(newenv,false); + + // if (rprim) + // { elem = Expression.wrap(exp.getType(),elem); } + + res = res + " _results_" + oldindex + + ".Add(" + elem + ");\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }"; + + collectList.add(pp); + collectOps.put(pp,res); + collectCodes.put(pp,"" + oldindex); + + return "collect_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) collectCodes.get(pp); + return "collect_" + ind + "(" + lqf + ")"; + } + } + + public static String getCollectDefinitionCPP(Expression left, String lqf, + Expression exp, boolean rprim, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; } + else + { ename = e.getName(); } + + String tname = ename + "*"; + if (Type.isBasicType(e)) + { tname = e.getCPP("void*"); } + else if ("Sequence".equals(ename)) + { tname = e.getCPP(e.getElementType()); } + else if ("Set".equals(ename)) + { tname = e.getCPP(e.getElementType()); } + + String argtype1 = "std::vector<" + tname + ">"; + String argtype2 = "std::set<" + tname + ">"; + + Type re = exp.getType(); + String restype = "void*"; + if (re != null) + { restype = re.getCPP(exp.getElementType()); } + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) collectOps.get(pp); + // But may be different left element type with same expression + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res1 = " static vector<" + restype + ">* collect_" + oldindex + + "(" + argtype1 + "* _l"; + String res2 = " static vector<" + restype + ">* collect_" + oldindex + + "(" + argtype2 + "* _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String partype = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + partype + " " + par.getName(); + res2 = res2 + ", " + partype + " " + par.getName(); + } + + res1 = res1 + ")\n"; + res1 = res1 + + " { // Implements: " + left + "->collect( " + var + " | " + exp + " )\n" + + " vector<" + restype + ">* _results_" + oldindex + + " = new vector<" + restype + ">();\n" + + " for (int _icollect = 0; _icollect < _l->size(); _icollect++)\n" + + " { " + tname + " " + var + " = (*_l)[_icollect];\n"; + + res2 = res2 + ")\n"; + res2 = res2 + " { vector<" + restype + ">* _results_" + oldindex + + " = new vector<" + restype + ">();\n" + + " for (" + argtype2 + "::iterator _icollect = _l->begin(); _icollect != _l->end(); ++_icollect)\n" + + " { " + tname + " " + var + " = *_icollect;\n"; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + String elem = exp.queryFormCPP(newenv,false); + + res1 = res1 + " _results_" + oldindex + "->push_back(" + elem + ");\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + + res2 = res2 + " _results_" + oldindex + "->push_back(" + elem + ");\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + collectList.add(pp); + collectOps.put(pp,res1 + "\n\n" + res2); + collectCodes.put(pp,"" + oldindex); + + return "collect_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) collectCodes.get(pp); + return "collect_" + ind + "(" + lqf + ")"; + } + } + + public static String getAnyDefinitionCPP(Expression left, String lqf, + Expression exp, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; } + else + { ename = e.getName(); } + + String tname = ename + "*"; + if (Type.isBasicType(e)) + { tname = e.getCPP("void*"); } + else if ("Sequence".equals(ename)) + { tname = e.getCPP(e.getElementType()); } + else if ("Set".equals(ename)) + { tname = e.getCPP(e.getElementType()); } + + String argtype1 = "std::vector<" + tname + ">"; + String argtype2 = "std::set<" + tname + ">"; + + Type re = left.getElementType(); + String restype = "void*"; + if (re != null) + { restype = re.getCPP(re.getElementType()); } + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + // But may be different left element type with same expression + + // System.out.println(">>> CPP Any definition " + op); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + String elem = exp.queryFormCPP(newenv,false); + + String res1 = " static " + restype + " any_" + oldindex + + "(" + argtype1 + "* _l"; + String res2 = " static " + restype + " any_" + oldindex + + "(" + argtype2 + "* _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String partype = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + partype + " " + par.getName(); + res2 = res2 + ", " + partype + " " + par.getName(); + } + + res1 = res1 + ")\n"; + + if (ename.equals("int")) // for Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCPP(env,false); + String endexpqf = endexp.queryFormCPP(env,false); + String inttest = exp.queryFormCPP(env,false); + res1 = res1 + " { // Implements: " + left + "->any(" + var + "|" + exp + ")\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return " + var + "; } }\n"; + res1 = res1 + " return 0;\n }"; + + anyList.add(pp); + anyOps.put(pp,res1); + // anyDecs.put(pp,decl1); + anyCodes.put(pp,"" + oldindex); + + System.out.println(">>> CPP Any definition " + res1); + + return "any_" + oldindex + "(NULL)"; + } + } + } + + res1 = res1 + + " { // Implements: " + left + "->any( " + var + " | " + exp + " )\n" + + " " + restype + " _result_" + oldindex + + " = NULL;\n" + + " for (int _iany = 0; _iany < _l->size(); _iany++)\n" + + " { " + tname + " " + var + " = (*_l)[_iany];\n"; + + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype + " _result_" + oldindex + + " = NULL;\n" + + " for (" + argtype2 + "::iterator _iany = _l->begin(); _iany != _l->end(); ++_iany)\n" + + " { " + tname + " " + var + " = *_iany;\n"; + + + res1 = res1 + " if (" + elem + ") { return " + var + "; }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _result_" + oldindex + ";\n }"; + + res2 = res2 + " if (" + elem + ") { return " + var + "; }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _result_" + oldindex + ";\n }"; + + anyList.add(pp); + anyOps.put(pp,res1 + "\n\n" + res2); + anyCodes.put(pp,"" + oldindex); + + System.out.println(">>> CPP Any definition " + res1 + "\n\n" + res2); + + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + + // distinguish cases where elem is an object and primitive: wrap(exp.getType(), + public static String getRejectDefinition(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "List"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) rejectOps.get(pp); + // But may be different left element type with same pred + + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + String res = " public static List reject_" + oldindex + "(List _l"; + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + res = res + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + + " List _results_" + oldindex + + " = new Vector();\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; + } + + String test = pred.queryForm(newenv,false); + String wvar = Expression.wrap(e,var); + res = res + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + wvar + "); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }\n\n"; + + /* Version for maps: */ + + res = res + " public static HashMap reject_" + oldindex + "(Map _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + res = res + " { // Implements: " + left + "->reject(" + var + " | " + pred + ")\n" + + " HashMap _results_" + oldindex + " = new HashMap();\n" + + " java.util.Set _keys = _l.keySet();\n" + + " for (Object _i : _keys)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res = res + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; } + + res = res + " if (" + test + ") { } \n" + + " else\n" + + " { _results_" + oldindex + ".put(_i, " + wvar + "); }\n"; + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }\n"; + + + rejectList.add(pp); + rejectOps.put(pp,res); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + public static String getRejectDefinitionJava6(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "HashSet"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + String restype1 = "ArrayList"; + String restype2 = "HashSet"; + // Both versions are needed. + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) rejectOps.get(pp); + // But may be different left element type with same pred + + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res1 = " public static " + restype1 + " reject_" + oldindex + "(ArrayList _l"; + String res2 = " public static " + restype2 + " reject_" + oldindex + "(HashSet _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res1 = res1 + ", " + par.getType().getJava6() + " " + par.getName(); + res2 = res2 + ", " + par.getType().getJava6() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res1 = res1 + ")\n"; + res1 = res1 + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + + " " + restype1 + " _results_" + oldindex + + " = new " + restype1 + "();\n" + + " for (int _i = 0; i < _l.size(); _i++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res1 = res1 + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; } + else if (ename.equals("double")) + { res1 = res1 + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; } + else if (ename.equals("long")) + { res1 = res1 + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; } + else if (ename.equals("boolean")) + { res1 = res1 + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; } + else + { res1 = res1 + + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; + } + String test = pred.queryFormJava6(newenv,false); + res1 = res1 + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + + res2 = res2 + ")\n"; + res2 = res2 + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + + " " + restype2 + " _results_" + oldindex + + " = new " + restype2 + "();\n" + + " for (Object _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res2 = res2 + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res2 = res2 + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res2 = res2 + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res2 = res2 + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res2 = res2 + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + res2 = res2 + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + rejectList.add(pp); + rejectOps.put(pp,res1 + "\n\n" + res2); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + public static String getRejectDefinitionJava7( + Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "Set"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; + if (e != null) + { tname = e.getJava7(); } + } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + String partype1 = "List<" + tname + ">"; + String restype1 = "ArrayList<" + tname + ">"; + String restype2 = "HashSet<" + tname + ">"; + String restype3 = "TreeSet<" + tname + ">"; + String restype4 = "Set<" + tname + ">"; + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) rejectOps.get(pp); + // But may be different left element type with same pred + + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res1 = " public static " + restype1 + " reject_" + oldindex + "(" + partype1 + " _l"; + String res2 = " public static " + restype2 + " reject_" + oldindex + "(" + restype2 + " _l"; + String res3 = " public static " + restype3 + " reject_" + oldindex + "(" + restype3 + " _l"; + String res4 = " public static " + restype2 + " reject_" + oldindex + "(" + restype4 + " _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { String jType = + partype.getJava7(partype.getElementType()); + res1 = res1 + ", " + jType + " " + par.getName(); + res2 = res2 + ", " + jType + " " + par.getName(); + res3 = res3 + ", " + jType + " " + par.getName(); + res4 = res4 + ", " + jType + " " + par.getName(); + } + } + + res1 = res1 + ")\n"; + res1 = res1 + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + + " " + restype1 + " _results_" + oldindex + + " = new " + restype1 + "();\n" + + " for (int _ireject = 0; _ireject < _l.size(); _ireject++)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res1 = res1 + " { int " + var + " = ((Integer) _l.get(_ireject)).intValue();\n"; } + else if (ename.equals("double")) + { res1 = res1 + " { double " + var + " = ((Double) _l.get(_ireject)).doubleValue();\n"; } + else if (ename.equals("long")) + { res1 = res1 + " { long " + var + " = ((Long) _l.get(_ireject)).longValue();\n"; } + else if (ename.equals("boolean")) + { res1 = res1 + " { boolean " + var + " = ((Boolean) _l.get(_ireject)).booleanValue();\n"; } + else + { res1 = res1 + + " { " + tname + " " + var + " = (" + tname + ") _l.get(_ireject);\n"; + } + + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype2 + " _results_" + oldindex + + " = new " + restype2 + "();\n" + + " for (" + tname + " _ireject : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res2 = res2 + " { int " + var + " = ((Integer) _ireject).intValue();\n"; } + else if (ename.equals("double")) + { res2 = res2 + " { double " + var + " = ((Double) _ireject).doubleValue();\n"; } + else if (ename.equals("long")) + { res2 = res2 + " { long " + var + " = ((Long) _ireject).longValue();\n"; } + else if (ename.equals("boolean")) + { res2 = res2 + " { boolean " + var + " = ((Boolean) _ireject).booleanValue();\n"; } + else + { res2 = res2 + + " { " + tname + " " + var + " = (" + tname + ") _ireject;\n"; + } + + res3 = res3 + ")\n"; + res3 = res3 + " { " + restype3 + " _results_" + oldindex + + " = new " + restype3 + "();\n" + + " for (" + tname + " _ireject : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res3 = res3 + " { int " + var + " = ((Integer) _ireject).intValue();\n"; } + else if (ename.equals("double")) + { res3 = res3 + " { double " + var + " = ((Double) _ireject).doubleValue();\n"; } + else if (ename.equals("long")) + { res3 = res3 + " { long " + var + " = ((Long) _ireject).longValue();\n"; } + else if (ename.equals("boolean")) + { res3 = res3 + " { boolean " + var + " = ((Boolean) _ireject).booleanValue();\n"; } + else + { res3 = res3 + + " { " + tname + " " + var + " = (" + tname + ") _ireject;\n"; + } + + res4 = res4 + ")\n"; + res4 = res4 + " { " + restype2 + " _results_" + oldindex + + " = new " + restype2 + "();\n" + + " for (" + tname + " _ireject : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res4 = res4 + " { int " + var + " = ((Integer) _ireject).intValue();\n"; } + else if (ename.equals("double")) + { res4 = res4 + " { double " + var + " = ((Double) _ireject).doubleValue();\n"; } + else if (ename.equals("long")) + { res4 = res4 + " { long " + var + " = ((Long) _ireject).longValue();\n"; } + else if (ename.equals("boolean")) + { res4 = res4 + " { boolean " + var + " = ((Boolean) _ireject).booleanValue();\n"; } + else + { res4 = res4 + + " { " + tname + " " + var + " = (" + tname + ") _ireject;\n"; + } + + String test = pred.queryFormJava7(newenv,false); + + res1 = res1 + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + + res2 = res2 + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + res3 = res3 + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + var + "); }\n"; + res3 = res3 + " }\n"; + res3 = res3 + " return _results_" + oldindex + ";\n }"; + + res4 = res4 + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".add(" + var + "); }\n"; + res4 = res4 + " }\n"; + res4 = res4 + " return _results_" + oldindex + ";\n }"; + + rejectList.add(pp); + rejectOps.put(pp,res1 + "\n\n" + res2 + "\n\n" + res3 + "\n\n" + res4); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + public static String getRejectDefinitionCSharp(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller.inst().get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("String")) + { tname = "string"; } + else if (ename.equals("boolean")) + { tname = "bool"; } + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) rejectOps.get(pp); + // But may be different left element type with same pred + + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static ArrayList reject_" + oldindex + "(ArrayList _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getCSharp() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + res = res + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n\n" + + " ArrayList _results_" + oldindex + + " = new ArrayList();\n" + + " for (int _ireject = 0; _ireject < _l.Count; _ireject++)\n" + + " { " + tname + " " + var + " = (" + tname + ") _l[_ireject];\n"; + + String test = ""; + if (Expression.isLambdaApplication(pred)) + { Expression subs = Expression.simplifyApply(pred); + test = subs.queryFormCSharp(newenv,false); + } + else + { test = pred.queryFormCSharp(newenv,false); } + + res = res + " if (" + test + ") { } \n" + + " else { _results_" + oldindex + ".Add(" + var + "); }\n"; + + res = res + " }\n"; + res = res + " return _results_" + oldindex + ";\n }"; + + rejectList.add(pp); + rejectOps.put(pp,res); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + public static String getRejectDefinitionCPP(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; } + else + { ename = e.getName(); } + + String tname = ename + "*"; + /* if (Type.isBasicType(e)) + { tname = e.getCPP("void*"); } + else if ("Sequence".equals(ename)) + { tname = "vector*"; } + else if ("Set".equals(ename)) + { tname = "set*"; } */ + if (e != null) + { tname = e.getCPP(e.getElementType()); } + + String restype1 = "std::set<" + tname + ">"; + String addop1 = "insert"; + String restype2 = "std::vector<" + tname + ">"; + String addop2 = "push_back"; + + // System.out.println(left + " element type is " + e); + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) rejectOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res1 = " static " + restype1 + "* reject_" + oldindex + "(" + restype1 + "* _l"; + String res2 = " static " + restype2 + "* reject_" + oldindex + "(" + restype2 + "* _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String cpppt = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + cpppt + " " + par.getName(); + res2 = res2 + ", " + cpppt + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res1 = res1 + ")\n"; + res1 = res1 + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + + " " + restype1 + "* _results_" + oldindex + " = new " + restype1 + "();\n" + + " for (" + restype1 + "::iterator _ireject = _l->begin(); _ireject != _l->end(); ++_ireject)\n" + + " { " + tname + " " + var + " = *_ireject;\n"; + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype2 + "* _results_" + oldindex + " = new " + restype2 + "();\n" + + " for (" + restype2 + "::iterator _ireject = _l->begin(); _ireject != _l->end(); ++_ireject)\n" + + " { " + tname + " " + var + " = *_ireject;\n"; + + String test = pred.queryFormCPP(newenv,false); + res1 = res1 + " if (" + test + ") { }\n" + + " else { _results_" + oldindex + "->" + addop1 + "(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + res2 = res2 + " if (" + test + ") { }\n" + + " else { _results_" + oldindex + "->" + addop2 + "(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + String res = res1 + "\n\n" + res2; + + rejectList.add(pp); + rejectOps.put(pp,res); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinition(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! ERROR: Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "List"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(List _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryForm(env,false); + String endexpqf = endexp.queryForm(env,false); + String inttest = pred.queryForm(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (int _iany = 0; _iany < _l.size(); _i++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _l.get(_iany)).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _l.get(_iany)).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _l.get(_iany)).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _l.get(_iany)).longValue();\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _l.get(_iany);\n"; + } + + + + String test = pred.queryForm(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _l.get(_iany); }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinitionJava6(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else if ("Set".equals(e.getName())) + { ename = "HashSet"; } + else if ("Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(Collection _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava6() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava6(env,false); + String endexpqf = endexp.queryFormJava6(env,false); + String inttest = pred.queryFormJava6(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (Object _iany : _l)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _iany).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _iany).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _iany).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _iany).longValue();\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _iany;\n"; + } + + + + String test = pred.queryFormJava6(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _iany; }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinitionJava7(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else if ("Set".equals(e.getName())) + { ename = "HashSet"; } + else if ("Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(Collection<" + tname + "> _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava7() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava7(env,false); + String endexpqf = endexp.queryFormJava7(env,false); + String inttest = pred.queryFormJava7(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (Object _iany : _l)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _iany).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _iany).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _iany).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _iany).longValue();\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _iany;\n"; + } + + + + String test = pred.queryFormJava7(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _iany; }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinitionCSharp(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else if ("Set".equals(e.getName())) + { ename = "ArrayList"; } + else if ("Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("String")) + { tname = "string"; } + else if (ename.equals("boolean")) + { tname = "bool"; } + + // if (ename.equals("int")) + // { tname = "Integer"; } + // else if (e != null) + // { tname = e.typeWrapperCSharp(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(ArrayList _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getCSharp() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCSharp(env,false); + String endexpqf = endexp.queryFormCSharp(env,false); + String inttest = pred.queryFormCSharp(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (int _iany = 0; _iany < _l.Count; _iany++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = (int) _l[_iany];\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = (double) _l[_iany];\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { bool " + var + " = (bool) _l[_iany];\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = (long) _l[_iany];\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _l[_iany];\n"; + } + + + + String test = pred.queryFormCSharp(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _l[_iany]; }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + // For: left->exists(pred) + public static String getExistsDefinition(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->exists(" + + exvar + "|" + pred + ")"); + return "/* error in ->exists */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "List"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + String pp = lqf + " " + pred + " " + ename + "(" + signature + ")"; + String op = (String) existsOps.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean exists_" + oldindex + "(List _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryForm(env,false); + String endexpqf = endexp.queryForm(env,false); + String inttest = pred.queryForm(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return true; } }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + return "exists_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; + } + else + { res = res + + " { " + ename + " " + var + " = (" + ename + ") _l.get(_i);\n"; + } + + + + String test = pred.queryForm(newenv,false); + res = res + " if (" + test + ") { return true; }\n"; + res = res + " }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + + return "exists_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) existsCodes.get(pp); + return "exists_" + ind + "(" + lqf + ")"; + } + } + + public static String getExistsDefinitionJava6(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + // System.out.println("Quantifier range: " + left); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "HashSet"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + String pp = lqf + " " + pred + " " + ename + "(" + signature + ")"; + String op = (String) existsOps.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean exists_" + oldindex + "(Collection _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava6() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava6(env,false); + String endexpqf = endexp.queryFormJava6(env,false); + String inttest = pred.queryFormJava6(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return true; } }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + return "exists_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (Object _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + String test = pred.queryFormJava6(newenv,false); + res = res + " if (" + test + ") { return true; }\n"; + res = res + " }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + + return "exists_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) existsCodes.get(pp); + return "exists_" + ind + "(" + lqf + ")"; + } + } + + public static String getExistsDefinitionJava7(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + // System.out.println("Quantifier range: " + left); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "Set"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + String pp = lqf + " " + pred + " " + ename + "(" + signature + ")"; + String op = (String) existsOps.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean exists_" + oldindex + "(Collection<" + tname + "> _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype == null) + { System.err.println("!! ERROR: no type for " + par); } + else + { res = res + ", " + + partype.getJava7(partype.getElementType()) + " " + par.getName(); + } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava7(env,false); + String endexpqf = endexp.queryFormJava7(env,false); + String inttest = pred.queryFormJava7(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return true; } }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + return "exists_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (" + tname + " _iexists : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _iexists).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _iexists).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _iexists).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _iexists).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _iexists;\n"; + } + + String test = pred.queryFormJava7(newenv,false); + res = res + " if (" + test + ") { return true; }\n"; + res = res + " }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + + return "exists_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) existsCodes.get(pp); + return "exists_" + ind + "(" + lqf + ")"; + } + } + + public static String getExistsDefinitionCSharp(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + // System.out.println("Quantifier range: " + left); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller.inst().get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set") || ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("String")) + { tname = "string"; } + else if (ename.equals("boolean")) + { tname = "bool"; } + + String pp = lqf + " " + pred + " " + ename + "(" + signature + ")"; + String op = (String) existsOps.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static bool exists_" + oldindex + "(ArrayList _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + ", " + par.getType().getCSharp() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCSharp(env,false); + String endexpqf = endexp.queryFormCSharp(env,false); + String inttest = pred.queryFormCSharp(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return true; } }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + return "exists_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (int _iexists = 0; _iexists < _l.Count; _iexists++)\n" + + " { " + tname + " " + var + " = (" + tname + ") _l[_iexists];\n"; + String test = pred.queryFormCSharp(newenv,false); + res = res + " if (" + test + ") { return true; }\n"; + res = res + " }\n"; + res = res + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res); + existsCodes.put(pp,"" + oldindex); + + return "exists_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) existsCodes.get(pp); + return "exists_" + ind + "(" + lqf + ")"; + } + } + + public static String getExistsDefinitionCPP(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + // System.out.println("Quantifier range: " + left); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst()->get" + instances + "()"; + } + + + String pp = lqf + " " + pred + "(" + signature + ")"; + String op = (String) existsOps.get(pp); + // System.out.println("Exists definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + String ename; + String argtype; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; + argtype = ename + "*"; + } + else if ("Set".equals(e.getName())) + { ename = "set"; + argtype = e.getCPP(e.getElementType()); + } + else if ("Sequence".equals(e.getName())) + { ename = "vector"; + argtype = e.getCPP(e.getElementType()); + } + else if (e.isEntity()) + { ename = e.getName(); + argtype = ename + "*"; + } + else if ("String".equals(e.getName())) + { ename = e.getName(); + argtype = "string"; + } + else if ("boolean".equals(e.getName())) + { ename = e.getName(); + argtype = "bool"; + } + else // primitive types, enumerations + { ename = e.getName(); + argtype = ename; + } // bool case? + + + String cet = argtype; + + + String argtype1 = "std::vector<" + argtype + ">"; + String argtype2 = "std::set<" + argtype + ">"; + + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res1 = " static bool exists_" + oldindex + "(" + argtype1 + "* _l"; + String decl1 = " static bool exists_" + oldindex + "(" + argtype1 + "* _l"; + String res2 = " static bool exists_" + oldindex + "(" + argtype2 + "* _l"; + String decl2 = " static bool exists_" + oldindex + "(" + argtype2 + "* _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String cpptype = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + cpptype + " " + par.getName(); + decl1 = decl1 + ", " + cpptype + " " + par.getName(); + res2 = res2 + ", " + cpptype + " " + par.getName(); + decl2 = decl2 + ", " + cpptype + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res1 = res1 + ")\n"; + decl1 = decl1 + ");\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCPP(env,false); + String endexpqf = endexp.queryFormCPP(env,false); + String inttest = pred.queryFormCPP(env,false); + res1 = res1 + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return true; } }\n"; + res1 = res1 + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res1); + existsDecs.put(pp,decl1); + existsCodes.put(pp,"" + oldindex); + + return "exists_" + oldindex + "(NULL)"; + } + } + } + + + res1 = res1 + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (" + argtype1 + "::iterator _iexists = _l->begin(); _iexists != _l->end(); ++_iexists)\n" + + " { " + cet + " " + var + " = *_iexists;\n"; + String test = pred.queryFormCPP(newenv,false); + res1 = res1 + " if (" + test + ") { return true; }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return false;\n }"; + + res2 = res2 + " { // Implements: " + left + "->exists(" + var + "|" + pred + ")\n" + + " for (" + argtype2 + "::iterator _iexists = _l->begin(); _iexists != _l->end(); ++_iexists)\n" + + " { " + cet + " " + var + " = *_iexists;\n"; + res2 = res2 + " if (" + test + ") { return true; }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return false;\n }"; + + existsList.add(pp); + existsOps.put(pp,res1 + "\n\n" + res2); + existsDecs.put(pp,decl1 + "\n\n" + decl2); + existsCodes.put(pp,"" + oldindex); + + return "exists_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) existsCodes.get(pp); + return "exists_" + ind + "(" + lqf + ")"; + } + } + + public static String getExists1Definition(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String pp = lqf + " " + pred + "(" + signature + ")"; + String op = (String) exists1Ops.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists1 definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "List"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean exists1_" + oldindex + "(List _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + ", " + par.getType().getJava() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryForm(env,false); + String endexpqf = endexp.queryForm(env,false); + String inttest = pred.queryForm(env,false); + res = res + + " { boolean _alreadyfound = false;\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n" + + " }\n"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + return "exists1_" + oldindex + "(null)"; + } + } + } + + + res = res + " { \n" + + " boolean _alreadyfound = false;\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; + } + else + { res = res + + " { " + ename + " " + var + " = (" + ename + ") _l.get(_i);\n"; + } + + String test = pred.queryForm(newenv,false); + res = res + " if (" + test + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n"; + res = res + " }"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + + return "exists1_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) exists1Codes.get(pp); + return "exists1_" + ind + "(" + lqf + ")"; + } + } + + public static String getExists1DefinitionJava6(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + + // System.out.println("Exists1 definition for " + pp + " is " + op); + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String pp = lqf + " " + pred + " " + ename + "(" + signature + ")"; + String op = (String) exists1Ops.get(pp); + // But may be different left element type with same pred + + String tname = ename; + if (ename.equals("Set")) + { tname = "HashSet"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean exists1_" + oldindex + "(Collection _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + ", " + par.getType().getJava6() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava6(env,false); + String endexpqf = endexp.queryFormJava6(env,false); + String inttest = pred.queryFormJava6(env,false); + res = res + " { boolean _alreadyfound = false;\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n" + + " }\n"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + return "exists1_" + oldindex + "(null)"; + } + } + } + + + res = res + " { \n" + + " boolean _alreadyfound = false;\n" + + " for (Object _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + String test = pred.queryFormJava6(newenv,false); + res = res + " if (" + test + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n"; + res = res + " }"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + + return "exists1_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) exists1Codes.get(pp); + return "exists1_" + ind + "(" + lqf + ")"; + } + } + + public static String getExists1DefinitionJava7(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left.umlkind == Expression.CLASSID && (left instanceof BasicExpression) && + ((BasicExpression) left).arrayIndex == null) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) exists1Ops.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists1 definition for " + pp + " is " + op); + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "Set"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean exists1_" + oldindex + "(Collection<" + tname + "> _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype == null) + { System.err.println("!! ERROR: no type for " + par); } + else + { res = res + "," + + partype.getJava7(partype.getElementType()) + " " + par.getName(); + } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava7(env,false); + String endexpqf = endexp.queryFormJava7(env,false); + String inttest = pred.queryFormJava7(env,false); + res = res + " { boolean _alreadyfound = false;\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n" + + " }\n"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + return "exists1_" + oldindex + "(null)"; + } + } + } + + + res = res + " { \n" + + " boolean _alreadyfound = false;\n" + + " for (" + tname + " _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + String test = pred.queryFormJava7(newenv,false); + res = res + " if (" + test + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n"; + res = res + " }"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + + return "exists1_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) exists1Codes.get(pp); + return "exists1_" + ind + "(" + lqf + ")"; + } + } + + + public static String getExists1DefinitionCSharp(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller.inst().get" + instances + "()"; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) exists1Ops.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists1 definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else if ("String".equals(e.getName())) + { ename = "string"; } + else if ("boolean".equals(e.getName())) + { ename = "bool"; } + else + { ename = e.getName(); } + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static bool exists1_" + oldindex + "(ArrayList _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + ", " + par.getType().getCSharp() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCSharp(env,false); + String endexpqf = endexp.queryFormCSharp(env,false); + String inttest = pred.queryFormCSharp(env,false); + res = res + " { bool _alreadyfound = false;\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n" + + " }\n"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + return "exists1_" + oldindex + "(null)"; + } + } + } + + + res = res + " { \n" + + " bool _alreadyfound = false;\n" + + " for (int _iexists1 = 0; _iexists1 < _l.Count; _iexists1++)\n" + + " { " + ename + " " + var + " = (" + ename + ") _l[_iexists1];\n"; + String test = pred.queryFormCSharp(newenv,false); + res = res + " if (" + test + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n"; + res = res + " }"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Codes.put(pp,"" + oldindex); + + return "exists1_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) exists1Codes.get(pp); + return "exists1_" + ind + "(" + lqf + ")"; + } + } + + public static String getExists1DefinitionCPP(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + // System.out.println("Quantifier range: " + left); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst()->get" + instances + "()"; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + // String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) exists1Ops.get(pp); + // But may be different left element type with same pred + + // System.out.println("Exists1 definition for " + pp + " is " + op); + + if (op == null) + { // add new definitions + String ename; + String argtype; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; + argtype = ename + "*"; + } + else if ("Set".equals(e.getName())) + { ename = "set"; + argtype = e.getCPP(e.getElementType()); + } + else if ("Sequence".equals(e.getName())) + { ename = "vector"; + argtype = e.getCPP(e.getElementType()); + } + else if (e.isEntity()) + { ename = e.getName(); + argtype = ename + "*"; + } + else if ("String".equals(e.getName())) + { ename = e.getName(); + argtype = "string"; + } + else if ("boolean".equals(e.getName())) + { ename = e.getName(); + argtype = "bool"; + } + else // primitive types, enumerations + { ename = e.getName(); + argtype = ename; + } // bool case? + + String cet = argtype; + + + if (left.isOrdered()) + { argtype = "std::vector<" + argtype + ">"; } + else + { argtype = "std::set<" + argtype + ">"; } + // Both are needed. + + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " static bool exists_" + oldindex + "(" + argtype + "* _l"; + String decl = " static bool exists_" + oldindex + "(" + argtype + "* _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String cpptype = par.getType().getCPP(par.getElementType()); + res = res + ", " + cpptype + " " + par.getName(); + decl = decl + ", " + cpptype + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + decl = decl + ");\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCPP(env,false); + String endexpqf = endexp.queryFormCPP(env,false); + String inttest = pred.queryFormCPP(env,false); + res = res + + " { bool _alreadyfound = false;\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n" + + " }\n"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Decs.put(pp,decl); + exists1Codes.put(pp,"" + oldindex); + return "exists1_" + oldindex + "(NULL)"; + } + } + } + + + res = res + " { bool _alreadyfound = false;\n" + + " for (" + argtype + "::iterator _iexists1 = _l->begin(); _iexists1 != _l->end(); ++_iexists1)\n" + + " { " + cet + " " + var + " = *_iexists1;\n"; + String test = pred.queryFormCPP(newenv,false); + res = res + " if (" + test + ")\n" + + " { if (_alreadyfound) { return false; }\n" + + " else { _alreadyfound = true; } \n" + + " } \n" + + " }\n" + + " return _alreadyfound; \n"; + + exists1List.add(pp); + exists1Ops.put(pp,res); + exists1Decs.put(pp,decl); + exists1Codes.put(pp,"" + oldindex); + + return "exists1_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) exists1Codes.get(pp); + return "exists1_" + ind + "(" + lqf + ")"; + } + } + + // For: left->forAll(pred) + public static String getForAllDefinition(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) forAllOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "List"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean forAll_" + oldindex + "(List _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getJava() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryForm(env,false); + String endexpqf = endexp.queryForm(env,false); + String inttest = pred.queryForm(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { }\n" + + " else { return false; }\n" + + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + return "forAll_" + oldindex + "(null)"; + } + } + } + + res = res + " { \n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; + } + else + { res = res + + " { " + ename + " " + var + " = (" + ename + ") _l.get(_i);\n"; + } + + String test = pred.queryForm(newenv,false); + res = res + " if (" + test + ") { }\n" + + " else { return false; } \n"; + res = res + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + + return "forAll_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) forAllCodes.get(pp); + return "forAll_" + ind + "(" + lqf + ")"; + } + } + + public static String getForAllDefinitionJava6(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) forAllOps.get(pp); + // But may be different left element type with same pred + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "HashSet"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean forAll_" + oldindex + "(Collection _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype == null) + { System.err.println("ERROR: no type for " + par); } + else + { res = res + ", " + partype.getJava6() + " " + par.getName(); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava6(env,false); + String endexpqf = endexp.queryFormJava6(env,false); + String inttest = pred.queryFormJava6(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { }\n" + + " else { return false; }\n" + + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + return "forAll_" + oldindex + "(null)"; + } + } + } + + res = res + " { \n" + + " for (Object _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + String test = pred.queryFormJava6(newenv,false); + res = res + " if (" + test + ") { }\n" + + " else { return false; } \n"; + res = res + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + + return "forAll_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) forAllCodes.get(pp); + return "forAll_" + ind + "(" + lqf + ")"; + } + } + + public static String getForAllDefinitionJava7(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left.umlkind == Expression.CLASSID && (left instanceof BasicExpression) && + ((BasicExpression) left).arrayIndex == null) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) forAllOps.get(pp); + // But may be different left element type with same pred + + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "Object"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("Set")) + { tname = "Set"; } + else if (ename.equals("Sequence")) + { tname = "ArrayList"; } + else if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static boolean forAll_" + oldindex + "(Collection<" + tname + "> _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype == null) + { System.err.println("!! ERROR: no type for parameter " + par); } + else + { res = res + "," + + partype.getJava7(partype.getElementType()) + " " + par.getName(); + } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava7(env,false); + String endexpqf = endexp.queryFormJava7(env,false); + String inttest = pred.queryFormJava7(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { }\n" + + " else { return false; }\n" + + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + return "forAll_" + oldindex + "(null)"; + } + } + } + + res = res + " { \n" + + " for (" + tname + " _i : _l)\n"; + if (ename.equals("int") || "Integer".equals(tname)) + { res = res + " { int " + var + " = ((Integer) _i).intValue();\n"; } + else if (ename.equals("double")) + { res = res + " { double " + var + " = ((Double) _i).doubleValue();\n"; } + else if (ename.equals("long")) + { res = res + " { long " + var + " = ((Long) _i).longValue();\n"; } + else if (ename.equals("boolean")) + { res = res + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + String test = pred.queryFormJava7(newenv,false); + res = res + " if (" + test + ") { }\n" + + " else { return false; } \n"; + res = res + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + + return "forAll_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) forAllCodes.get(pp); + return "forAll_" + ind + "(" + lqf + ")"; + } + } + + public static String getForAllDefinitionCSharp(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left.umlkind == Expression.CLASSID && (left instanceof BasicExpression) && + ((BasicExpression) left).arrayIndex == null) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller.inst().get" + instances + "()"; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) forAllOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + String ename; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else if ("String".equals(e.getName())) + { ename = "string"; } + else if ("boolean".equals(e.getName())) + { ename = "bool"; } + else // entities, primitive types, enumerations + { ename = e.getName(); } + + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static bool forAll_" + oldindex + "(ArrayList _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + res = res + "," + par.getType().getCSharp() + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCSharp(env,false); + String endexpqf = endexp.queryFormCSharp(env,false); + String inttest = pred.queryFormCSharp(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { }\n" + + " else { return false; }\n" + + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + return "forAll_" + oldindex + "(null)"; + } + } + } + + res = res + " { \n" + + " for (int _iforall = 0; _iforall < _l.Count; _iforall++)\n" + + " { " + ename + " " + var + " = (" + ename + ") _l[_iforall];\n"; + String test = pred.queryFormCSharp(newenv,false); + res = res + " if (" + test + ") { }\n" + + " else { return false; } \n"; + res = res + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllCodes.put(pp,"" + oldindex); + + return "forAll_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) forAllCodes.get(pp); + return "forAll_" + ind + "(" + lqf + ")"; + } + } + + public static String getForAllDefinitionCPP(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left.umlkind == Expression.CLASSID && (left instanceof BasicExpression) && + ((BasicExpression) left).arrayIndex == null) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + String pp = "" + pred + " " + lqf + "(" + signature + ")"; + String op = (String) forAllOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + String ename; + String argtype; + Type e = left.getElementType(); + if (e == null || "OclAny".equals(e.getName())) + { ename = "void"; + argtype = ename + "*"; + } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "void"; // actually set or vector of void* + argtype = e.getCPP(e.getElementType()); + } + else if (e.isEntity()) + { ename = e.getName(); + argtype = ename + "*"; + } + else if ("String".equals(e.getName())) + { ename = e.getName(); + argtype = "string"; + } + else if ("boolean".equals(e.getName())) + { ename = e.getName(); + argtype = "bool"; + } + else // primitive types, enumerations + { ename = e.getName(); + argtype = ename; + } + + String cet = argtype; + + + if (left.isOrdered()) + { argtype = "std::vector<" + argtype + ">"; } + else + { argtype = "std::set<" + argtype + ">"; } + + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " static bool forAll_" + oldindex + "(" + argtype + "* _l"; + String decl = " static bool forAll_" + oldindex + "(" + argtype + "* _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String cpptype = par.getType().getCPP(par.getElementType()); + res = res + ", " + cpptype + " " + par.getName(); + decl = decl + ", " + cpptype + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + decl = decl + ");\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCPP(env,false); + String endexpqf = endexp.queryFormCPP(env,false); + String inttest = pred.queryFormCPP(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { }\n" + + " else { return false; }\n" + + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllDecs.put(pp,decl); + forAllCodes.put(pp,"" + oldindex); + return "forAll_" + oldindex + "(NULL)"; + } + } + } + + res = res + " { // implements " + left + "->forAll( " + var + " | " + pred + " )\n" + + " for (" + argtype + "::iterator _iforall = _l->begin(); _iforall != _l->end(); ++_iforall)\n" + + " { " + cet + " " + var + " = *_iforall;\n"; + + String test = pred.queryFormCPP(newenv,false); + res = res + " if (" + test + ") { }\n" + + " else { return false; } \n"; + res = res + " }\n"; + res = res + " return true;\n }"; + + forAllList.add(pp); + forAllOps.put(pp,res); + forAllDecs.put(pp,decl); + forAllCodes.put(pp,"" + oldindex); + + return "forAll_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) forAllCodes.get(pp); + + return "forAll_" + ind + "(" + lqf + ")"; + } + } + + + public void addCardinalityBound(String typ, String card) + { if (card == null || + card.equals("") || + card.equals("*")) + { return; } + int num; + try + { num = Integer.parseInt(card); } + catch (Exception e) + { String nums = card.substring(3); // 0..nums + try + { num = Integer.parseInt(nums); } + catch (Exception e2) + { System.err.println("Invalid cardinality format: " + + card); + return; + } + } + BExpression btyp = new BBasicExpression(typ); + BExpression numbe = new BBasicExpression(""+num); + BExpression ce = new BUnaryExpression("card",btyp); + BExpression inv = new BBinaryExpression("=",ce,numbe); // <= + addInvariant(inv); + } + + + public static String getSelectOps() + { String res = ""; + // java.util.Iterator keys = selectOps.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < selectList.size(); i++) + { Object k = selectList.get(i); + res = res + selectOps.get(k) + "\n\n"; + } + return res; + } + + public static String getCollectOps() + { String res = ""; + // java.util.Iterator keys = collectOps.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < collectList.size(); i++) + { Object k = collectList.get(i); + res = res + collectOps.get(k) + "\n\n"; + } + return res; + } + + public static String getRejectOps() + { String res = ""; + // java.util.Iterator keys = rejectOps.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < rejectList.size(); i++) + { Object k = rejectList.get(i); + res = res + rejectOps.get(k) + "\n\n"; + } + return res; + } + + public static String getAnyOps() + { String res = ""; + System.out.println(">>> Any ops are: " + anyOps); + + for (int i = 0; i < anyList.size(); i++) + { Object k = anyList.get(i); + res = res + anyOps.get(k) + "\n\n"; + } + return res; + } + + public static String getExistsOps() + { String res = ""; + // java.util.Iterator keys = existsOps.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < existsList.size(); i++) + { Object k = existsList.get(i); + res = res + existsOps.get(k) + "\n\n"; + } + return res; + } + + public static String getExistsDecs() + { String res = ""; + // java.util.Iterator keys = existsDecs.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < existsList.size(); i++) + { Object k = existsList.get(i); + res = res + existsDecs.get(k) + "\n\n"; + } + return res; + } + + + public static String getExists1Ops() + { String res = ""; + // java.util.Iterator keys = exists1Ops.keySet().iterator(); + // while (keys.hasNext()) + for (int i = 0; i < exists1List.size(); i++) + { Object k = exists1List.get(i); + res = res + exists1Ops.get(k) + "\n\n"; + } + return res; + } + + public static String getExists1Decs() + { String res = ""; + // java.util.Iterator keys = exists1Decs.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < exists1List.size(); i++) + { Object k = exists1List.get(i); + res = res + exists1Decs.get(k) + "\n\n"; + } + return res; + } + + public static String getForAllOps() + { String res = ""; + // java.util.Iterator keys = forAllOps.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < forAllList.size(); i++) + { Object k = forAllList.get(i); + res = res + forAllOps.get(k) + "\n\n"; + } + return res; + } + + public static String getForAllDecs() + { String res = ""; + // java.util.Iterator keys = forAllDecs.keySet().iterator(); + // while (keys.hasNext()) + // { Object k = keys.next(); + for (int i = 0; i < forAllList.size(); i++) + { Object k = forAllList.get(i); + res = res + forAllDecs.get(k) + "\n\n"; + } + return res; + } + + public static String generateCopyOps() // Java4 + { String res = " public static Vector copyCollection(Vector s)\n" + + " { Vector result = new Vector();\n" + + " result.addAll(s);\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static HashMap copyMap(Map s)\n" + + " { HashMap result = new HashMap();\n" + + " result.putAll(s);\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static int[] newRefint(int x)\n" + + " { int[] res = new int[1]; \n" + + " res[0] = x; \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static long[] newReflong(long x)\n" + + " { long[] res = new long[1]; \n" + + " res[0] = x; \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static double[] newRefdouble(double x)\n" + + " { double[] res = new double[1]; \n" + + " res[0] = x; \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static boolean[] newRefboolean(boolean x)\n" + + " { boolean[] res = new boolean[1]; \n" + + " res[0] = x; \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static String[] newRefString(String x)\n" + + " { String[] res = new String[1]; \n" + + " res[0] = x; \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static Object[] newRefObject(Object x)\n" + + " { Object[] res = new Object[1]; \n" + + " res[0] = x; \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static Vector sequenceRange(Object[] arr, int n)\n" + + " { Vector res = new Vector();\n" + + " for (int i = 0; i < n; i++) \n" + + " { res.add(arr[i]); } \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static int sequenceCompare(List sq1, List sq2)\n" + + " { int res = 0;\n" + + " for (int i = 0; i < sq1.size() && i < sq2.size(); i++)\n" + + " { Object elem1 = sq1.get(i);\n" + + " if (((Comparable) elem1).compareTo(sq2.get(i)) < 0)\n" + + " { return -1; }\n" + + " else if (((Comparable) elem1).compareTo(sq2.get(i)) > 0)\n" + + " { return 1; }\n" + + " }\n" + + "\n" + + " if (sq1.size() > sq2.size())\n" + + " { return 1; }\n" + + " if (sq2.size() > sq1.size())\n" + + " { return -1; }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateCopyOpsJava6() + { String res = " public static HashSet copySet(HashSet s)\n" + + " { HashSet result = new HashSet();\n" + + " result.addAll(s);\n" + + " return result;\n" + + " }\n\n"; + res = " public static ArrayList copySequence(ArrayList s)\n" + + " { ArrayList result = new ArrayList();\n" + + " result.addAll(s);\n" + + " return result;\n" + + " }\n\n"; + res = res + + " public static HashMap copyMap(Map s)\n" + + " { HashMap result = new HashMap();\n" + + " result.putAll(s);\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static ArrayList sequenceRange(Object[] arr, int n)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n; i++) \n" + + " { res.add(arr[i]); } \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static int sequenceCompare(List sq1, List sq2)\n" + + " { int res = 0;\n" + + " for (int i = 0; i < sq1.size() && i < sq2.size(); i++)\n" + + " { Object elem1 = sq1.get(i);\n" + + " if (((Comparable) elem1).compareTo(sq2.get(i)) < 0)\n" + + " { return -1; }\n" + + " else if (((Comparable) elem1).compareTo(sq2.get(i)) > 0)\n" + + " { return 1; }\n" + + " }\n" + + "\n" + + " if (sq1.size() > sq2.size())\n" + + " { return 1; }\n" + + " if (sq2.size() > sq1.size())\n" + + " { return -1; }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateCopyOpsJava7() + { String res = " public static HashSet copySet(Collection s)\n" + + " { HashSet result = new HashSet();\n" + + " result.addAll(s);\n" + + " return result;\n" + + " }\n\n"; + res = res + " public static TreeSet copySortedSet(Collection s)\n" + + " { TreeSet result = new TreeSet();\n" + + " result.addAll(s);\n" + + " return result;\n" + + " }\n\n"; + res = res + " public static ArrayList copySequence(Collection s)\n" + + " { ArrayList result = new ArrayList();\n" + + " result.addAll(s); \n" + + " return result; \n" + + " }\n\n"; + res = res + + " public static HashMap copyMap(Map s)\n" + + " { HashMap result = new HashMap();\n" + + " result.putAll(s);\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static ArrayList sequenceRange(T[] arr, int n)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n; i++) \n" + + " { res.add(arr[i]); } \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static int sequenceCompare(List sq1, List sq2)\n" + + " { int res = 0;\n" + + " for (int i = 0; i < sq1.size() && i < sq2.size(); i++)\n" + + " { Object elem1 = sq1.get(i);\n" + + " if (((Comparable) elem1).compareTo(sq2.get(i)) < 0)\n" + + " { return -1; }\n" + + " else if (((Comparable) elem1).compareTo(sq2.get(i)) > 0)\n" + + " { return 1; }\n" + + " }\n" + + "\n" + + " if (sq1.size() > sq2.size())\n" + + " { return 1; }\n" + + " if (sq2.size() > sq1.size())\n" + + " { return -1; }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static T iterate(Collection _s, T initialValue, Function> _f)\n" + + " { T acc = initialValue; \n" + + " for (S _x : _s) \n" + + " { acc = _f.apply(_x).apply(acc); }\n" + + " return acc; \n" + + " } \n\n"; + + return res; + } + + + public static String generateCopyOpsCSharp() + { String res = " public static ArrayList copyCollection(ArrayList a)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.AddRange(a); \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static Hashtable copyMap(Hashtable m)\n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m) \n" + + " { res.Add(pair.Key, pair.Value); } \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList collectSequence(ArrayList col, Func f)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < col.Count; i++)\n" + + " { res.Add(f(col[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static object iterate(ArrayList col, object init, Func> f)\n" + + " { object res = init;\n" + + " for (int i = 0; i < col.Count; i++)\n" + + " { res = f(col[i])(res); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public unsafe static T* resizeTo(T* arr, int n) where T : unmanaged\n" + + " { T* tmp = stackalloc T[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n" + + " public unsafe static ArrayList sequenceRange(T* arr, int n) where T : unmanaged\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n; i++)\n" + + " { res.Add(arr[i]); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static int sequenceCompare(ArrayList sq1, ArrayList sq2)\n" + + " { int res = 0;\n" + + " for (int i = 0; i < sq1.Count && i < sq2.Count; i++)\n" + + " { object elem1 = sq1[i];\n" + + " if (((IComparable) elem1).CompareTo(sq2[i]) < 0)\n" + + " { return -1; }\n" + + " else if (((IComparable) elem1).CompareTo(sq2[i]) > 0)\n" + + " { return 1; }\n" + + " }\n" + + "\n" + + " if (sq1.Count > sq2.Count)\n" + + " { return 1; }\n" + + " if (sq2.Count > sq1.Count)\n" + + " { return -1; }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateCopyOpsCPP() + { String res = " static set<_T>* copySet(set<_T>* a)\n" + + " { set<_T>* res = new set<_T>(); \n" + + " res->insert(a->begin(),a->end()); \n" + + " return res; \n" + + " }\n\n" + + " static vector<_T>* copySequence(vector<_T>* a)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " res->insert(res->end(), a->begin(),a->end());\n" + + " return res; \n" + + " }\n\n" + + " static map* copyMap(map* m)\n" + + " { map* res = new map();\n" + + " map::iterator iter; \n" + + " for (iter = m->begin(); iter != m->end(); ++iter)\n" + + " { string key = iter->first;\n" + + " (*res)[key] = iter->second; \n" + + " } \n" + + " return res;\n" + + " } \n\n"; + + res = res + + " static string collectionToString(vector<_T>* c)\n" + + " { ostringstream buff;\n" + + " buff << \"Sequence{\";\n" + + " for (auto _pos = c->begin(); _pos != c->end(); ++_pos)\n" + + " { buff << *_pos;\n" + + " if (_pos + 1 < c->end())\n" + + " { buff << \", \"; }\n" + + " }\n" + + " buff << \"}\";\n" + + " return buff.str(); \n" + + " }\n\n"; + + res = res + + " static string collectionToString(std::set<_T>* c)\n" + + " { ostringstream buff;\n" + + " buff << \"Set{\"; \n" + + " auto _pos = c->begin(); \n" + + " if (_pos == c->end())\n" + + " {\n" + + " buff << \"}\";\n" + + " }\n" + + " else\n" + + " {\n" + + " buff << *_pos;\n" + + " ++_pos;\n" + + " for (; _pos != c->end(); ++_pos)\n" + + " { buff << \", \"; \n" + + " buff << *_pos;\n" + + " }\n" + + " buff << \"}\";\n" + + " }\n" + + " return buff.str(); \n" + + " }\n\n"; + + res = res + + " static string collectionToString(map* c)\n" + + " { ostringstream buff;\n" + + " buff << \"Map{\";\n" + + " int sze = c->size();\n" + + " int count = 0;\n" + + " for (auto it = c->begin(); it != c->end(); it++)\n" + + " {\n" + + " buff << (*it).first;\n" + + " buff << \" |-> \";\n" + + " buff << (*it).second;\n" + + " if (count + 1 < sze)\n" + + " { buff << \", \"; }\n" + + " count++; \n" + + " }\n" + + " buff << \"}\";\n" + + " return buff.str();\n" + + " }\n\n"; + + /* + res = res + + " static int sequenceCompare(vector* sq1, vector* sq2)\n" + + " { int res = 0;\n" + + " for (int i = 0; i < sq1->size() && i < sq2->size(); i++)\n" + + " { T elem1 = sq1->at(i);\n" + + " if (elem1 < sq2->at(i))\n" + + " { return -1; }\n" + + " else if (elem1 > sq2->at(i))\n" + + " { return 1; }\n" + + " }\n" + + "\n" + + " if (sq1->size() > sq2->size())\n" + + " { return 1; }\n" + + " if (sq2->size() > sq1->size())\n" + + " { return -1; }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " template\n" + + " static T iterate(vector* _s, T initialValue, std::function(S)> _f)\n" + + " { T acc = initialValue; \n" + + " for (vector::iterator _pos = _s->begin(); _pos != _s->end(); ++_pos) \n" + + " { S _x = *_pos;\n" + + " acc = (_f(_x))(acc); \n" + + " }\n" + + " return acc; \n" + + " } \n\n"; */ + + return res; + } + + public static String generateCPPExtendedLibrary() + { String res = + "template\n" + + "class UmlRsdsOcl {\n" + + " public:\n\n" + + + " static T iterate(vector* _s, T initialValue, std::function _f)\n" + + " { T acc = initialValue; \n" + + " for (vector::iterator _pos = _s->begin(); _pos != _s->end(); ++_pos) \n" + + " { S _x = *_pos;\n" + + " acc = _f(_x,acc); \n" + + " }\n" + + " return acc; \n" + + " } \n\n"; + + res = res + + " static map* includingMap(map* m, S src, T trg)\n" + + " { map* copy = new map();\n" + + " map::iterator iter; \n" + + " for (iter = m->begin(); iter != m->end(); ++iter)\n" + + " { S key = iter->first;\n" + + " (*copy)[key] = iter->second;\n" + + " } \n" + + " (*copy)[src] = trg;\n" + + " return copy; \n" + + " }\n\n"; + + res = res + + " static map* unionMap(map* m1, map* m2)\n" + + " { map* res = new map();\n" + + " map::iterator iter; \n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter)\n" + + " { S key = iter->first;\n" + + " if (m2->count(key) == 0) \n" + + " { (*res)[key] = iter->second; }\n" + + " } \n" + + " for (iter = m2->begin(); iter != m2->end(); ++iter)\n" + + " { S key = iter->first;\n" + + " (*res)[key] = iter->second;\n" + + " } \n" + + " return res;\n" + + " } \n\n"; + + res = res + "};\n\n"; + return res; + } + + public static String generateSubrangeOp() // for Java + { String res = " public static List integerSubrange(int i, int j)\n" + + " { List tmp = new Vector(); \n" + + " for (int k = i; k <= j; k++)\n" + + " { tmp.add(new Integer(k)); } \n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static String subrange(String s, int i, int j)\n" + + " { int len = s.length();\n" + + " if (len == 0) { return s; }\n" + + " if (j > len) { j = len; }\n" + + " if (j < i) { return \"\"; }\n" + + " if (i > len) { return \"\"; }\n" + + " if (i < 1) { i = 1; }\n" + + " return s.substring(i-1,j);\n" + + " }\n\n"; + + res = res + " public static List subrange(List l, int i, int j)\n"; + res = res + " { List tmp = new Vector(); \n" + + " if (i < 0) { i = l.size() + i; }\n" + + " if (j < 0) { j = l.size() + j; }\n" + + " for (int k = i-1; k < j; k++)\n" + + " { tmp.add(l.get(k)); } \n" + + " return tmp; \n" + + " }\n\n"; + return res; + } + + public static String generateSubrangeOpJava6() // for Java6 + { String res = " public static ArrayList integerSubrange(int i, int j)\n" + + " { ArrayList tmp = new ArrayList(); \n" + + " for (int k = i; k <= j; k++)\n" + + " { tmp.add(new Integer(k)); } \n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static String subrange(String s, int i, int j)\n" + + " { int len = s.length();\n" + + " if (len == 0) { return s; }\n" + + " if (j > len) { j = len; }\n" + + " if (j < i) { return \"\"; }\n" + + " if (i > len) { return \"\"; }\n" + + " if (i < 1) { i = 1; }\n" + + " return s.substring(i-1,j);\n" + + " }\n\n"; + + res = res + " public static ArrayList subrange(ArrayList l, int i, int j)\n"; + res = res + " { ArrayList tmp = new ArrayList(); \n" + + " if (i < 0) { i = l.size() + i; }\n" + + " if (j < 0) { j = l.size() + j; }\n" + + " for (int k = i-1; k < j; k++)\n" + + " { tmp.add(l.get(k)); } \n" + + " return tmp; \n" + + " }\n\n"; + return res; + } + + public static String generateSubrangeOpJava7() // for Java7 + { String res = " public static ArrayList integerSubrange(int i, int j)\n" + + " { ArrayList tmp = new ArrayList(); \n" + + " for (int k = i; k <= j; k++)\n" + + " { tmp.add(new Integer(k)); } \n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static String subrange(String s, int i, int j)\n" + + " { int len = s.length();\n" + + " if (len == 0) { return s; }\n" + + " if (j > len) { j = len; }\n" + + " if (j < i) { return \"\"; }\n" + + " if (i > len) { return \"\"; }\n" + + " if (i < 1) { i = 1; }\n" + + " return s.substring(i-1,j);\n" + + " }\n\n"; + + res = res + " public static String subrange(String s, long i, long j)\n" + + " { long len = s.length();\n" + + " if (len == 0) { return s; }\n" + + " if (j > len) { j = len; }\n" + + " if (j < i) { return \"\"; }\n" + + " if (i > len) { return \"\"; }\n" + + " if (i < 1) { i = 1; }\n" + + " String res = \"\"; \n" + + " for (long k = i-1; k < j; k++)\n" + + " { res = res + s.charAt((int) k); } \n" + + " return res; \n" + + " }\n\n"; + + + res = res + " public static ArrayList subrange(ArrayList l, int i, int j)\n"; + res = res + " { ArrayList tmp = new ArrayList(); \n" + + " if (i < 0) { i = l.size() + i; }\n" + + " if (j < 0) { j = l.size() + j; }\n" + + " for (int k = i-1; k < j; k++)\n" + + " { tmp.add(l.get(k)); } \n" + + " return tmp; \n" + + " }\n\n"; + return res; + } + + public static String generateSubrangeOpCSharp() // for CSharp + { String res = " public static ArrayList integerSubrange(int i, int j)\n" + + " { ArrayList tmp = new ArrayList(); \n" + + " for (int k = i; k <= j; k++)\n" + + " { tmp.Add(k); } \n" + + " return tmp;\n" + + " }\n\n" + + " public static string subrange(string s, long i, long j)\n"; + + res = res + " { if (i < 1)\n" + + " { i = 1; }\n" + + " if (j > s.Length)\n" + + " { j = s.Length; }\n" + + " if (i > s.Length || i > j)\n" + + " { return \"\"; }\n" + + " return s.Substring((int) (i-1), (int) (j-i+1));\n" + + " }\n\n"; + + res = res + " public static ArrayList subrange(ArrayList l, int i, int j)\n"; + res = res + " { ArrayList tmp = new ArrayList(); \n" + + " if (i < 0) { i = l.Count + i; }\n" + + " if (j < 0) { j = l.Count + j; }\n" + + " if (i < 1) { i = 1; }\n" + + " for (int k = i-1; k < j; k++)\n" + + " { tmp.Add(l[k]); } \n" + + " return tmp; \n" + + " }\n\n"; + res = res + + " public static int indexOfSubList(ArrayList a, ArrayList b)\n" + + " { /* Index of a subsequence a of sequence b in b */\n" + + " if (a.Count == 0 || b.Count == 0)\n" + + " { return 0; }\n" + + "\n" + + " int i = 0;\n" + + " while (i < b.Count && b[i] != a[0])\n" + + " { i++; }\n" + + "\n" + + " if (i >= b.Count)\n" + + " { return 0; }\n" + + "\n" + + " int j = 0;\n" + + " while (j < a.Count && i + j < b.Count && b[i + j] == a[j])\n" + + " { j++; }\n" + + "\n" + + " if (j >= a.Count)\n" + + " { return i + 1; }\n" + + "\n" + + " ArrayList subr = subrange(b, i + 2, b.Count);\n" + + " int res1 = indexOfSubList(a, subr);\n" + + " if (res1 == 0)\n" + + " { return 0; }\n" + + " return res1 + i + 1;\n" + + " }\n\n"; + res = res + + " public static int lastIndexOfSubList(ArrayList a, ArrayList b)\n" + + " { int res = 0;\n" + + " if (a.Count == 0 || b.Count == 0)\n" + + " { return res; }\n" + + "\n" + + " ArrayList arev = reverse(a);\n" + + " ArrayList brev = reverse(b);\n" + + " int i = indexOfSubList(arev, brev);\n" + + " if (i == 0)\n" + + " { return res; }\n" + + " res = b.Count - i - a.Count + 2;\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateIncludesAllMapOpCSharp() // for CSharp + { String res = " public static bool includesAllMap(Hashtable sup, Hashtable sub) \n" + + " { foreach (DictionaryEntry pair in sub) \n" + + " { if (sup.ContainsKey(pair.Key)) \n" + + " { if (sup[pair.Key].Equals(pair.Value)) { } \n" + + " else \n" + + " { return false; } \n" + + " } \n" + + " else \n" + + " { return false; } \n" + + " } \n" + + " return true; \n" + + " } \n"; + return res; + } + + public static String generateExcludesAllMapOpCSharp() // for CSharp + { String res = " public static bool excludesAllMap(Hashtable sup, Hashtable sub) \n" + + " { foreach (DictionaryEntry pair in sub) \n" + + " { if (sup.ContainsKey(pair.Key)) \n" + + " { if (pair.Value.Equals(sup[pair.Key])) \n" + + " { return false; } \n" + + " } \n" + + " } \n" + + " return true; \n" + + " } \n"; + return res; + } + + + public static String generateIncludingMapOpCSharp() // for CSharp + { String res = + " public static Hashtable includingMap(Hashtable m, object src, object trg) \n" + + " { Hashtable copy = new Hashtable(m); \n" + + " copy.Add(src, trg); \n" + + " return copy; \n" + + " } \n"; + return res; + } + + public static String generateExcludeAllMapOpCSharp() // for CSharp + { String res = + " public static Hashtable excludeAllMap(Hashtable m1, Hashtable m2) \n" + + " { // m1 - m2 \n" + + " Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry x in m1) \n" + + " { object key = x.Key; \n" + + " if (m2.ContainsKey(key)) { } \n" + + " else \n" + + " { res[key] = m1[key]; } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateExcludingMapKeyOpCSharp() // for CSharp + { String res = + " public static Hashtable excludingMapKey(Hashtable m, object k) \n" + + " { // m - { k |-> m(k) } \n" + + " Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m) \n" + + " { if (pair.Key.Equals(k)) { } \n" + + " else \n" + + " { res.Add(pair.Key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateExcludingMapValueOpCSharp() // for CSharp + { String res = + " public static Hashtable excludingMapValue(Hashtable m, object v) \n" + + " { // m - { k |-> v } \n" + + " Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m) \n" + + " { if (pair.Value.Equals(v)) { } \n" + + " else \n" + + " { res.Add(pair.Key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateUnionMapOpCSharp() // for CSharp + { String res = + " public static Hashtable unionMap(Hashtable m1, Hashtable m2) \n" + + " { /* Overrides m1 by m2 if they have pairs in common */ \n" + + " Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m2) \n" + + " { res.Add(pair.Key, pair.Value); } \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { if (res.ContainsKey(pair.Key)) { } \n" + + " else { res.Add(pair.Key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateIntersectionMapOpCSharp() // for CSharp + { String res = + " public static Hashtable intersectionMap(Hashtable m1, Hashtable m2) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object key = pair.Key; \n" + + " if (m2.ContainsKey(key) && pair.Value != null && pair.Value.Equals(m2[key])) \n" + + " { res.Add(key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + res = res + + " public static Hashtable restrictMap(Hashtable m1, ArrayList ks) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object key = pair.Key; \n" + + " if (ks.Contains(key)) \n" + + " { res.Add(key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static Hashtable antirestrictMap(Hashtable m1, ArrayList ks) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object key = pair.Key; \n" + + " if (ks.Contains(key)) { }\n" + + " else \n" + + " { res.Add(key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + res = res + + " public static ArrayList mapKeys(Hashtable m) \n" + + " { ArrayList res = new ArrayList(); \n" + + " res.AddRange(m.Keys);\n" + + " return res; \n" + + " } \n\n"; + res = res + + " public static ArrayList mapValues(Hashtable m) \n" + + " { ArrayList res = new ArrayList(); \n" + + " res.AddRange(m.Values);\n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static Hashtable selectMap(Hashtable m1, Func f) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object val = pair.Value; \n" + + " if (f(val))\n" + + " { res.Add(pair.Key,val); } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static Hashtable rejectMap(Hashtable m1, Func f) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object val = pair.Value; \n" + + " if (f(val)) { }\n" + + " else\n" + + " { res.Add(pair.Key,val); } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static Hashtable collectMap(Hashtable m1, Func f) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object val = pair.Value; \n" + + " res.Add(pair.Key, f(val)); \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + + return res; + } + + + + public static String generateTokeniseCSVOp() + { String res = " public static Vector tokeniseCSV(String line)\n" + + "{ StringBuffer buff = new StringBuffer();\n" + + " int x = 0;\n" + + " int len = line.length();\n" + + " boolean instring = false;\n" + + " Vector res = new Vector();\n" + + " while (x < len)\n" + + " { char chr = line.charAt(x);\n" + + " x++;\n" + + " if (chr == ',')\n" + + " { if (instring) { buff.append(chr); }\n" + + " else\n" + + " { res.add(buff.toString().trim());\n" + + " buff = new StringBuffer();\n" + + " }\n" + + " }\n" + + " else if ('\"' == chr)\n" + + " { if (instring) { instring = false; }\n" + + " else { instring = true; } \n" + + " }\n" + + " else\n" + + " { buff.append(chr); }\n" + + " }\n" + + " res.add(buff.toString().trim());\n" + + " return res;\n" + + "}\n"; + return res; + } + + + public static String generateIncludesAllMapOpCPP() + { String res = " static bool includesAllMap(map* sup, map* sub) \n" + + " { map::iterator iter; \n" + + " for (iter = sub->begin(); iter != sub->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " map::iterator f = sup->find(key); \n" + + " if (f != sup->end()) \n" + + " { if (iter->second == f->second) {} \n" + + " else \n" + + " { return false; } \n" + + " } \n" + + " else \n" + + " { return false; } \n" + + " } \n" + + " return true; \n" + + " } \n"; + return res; + } + + public static String generateExcludesAllMapOpCPP() + { String res = + " static bool excludesAllMap(map* sup, map* sub) \n" + + " { map::iterator iter; \n" + + " for (iter = sub->begin(); iter != sub->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " map::iterator f = sup->find(key); \n" + + " if (f != sup->end()) \n" + + " { if (iter->second == f->second) \n" + + " { return false; } \n" + + " } \n" + + " } \n" + + " return true; \n" + + " } \n"; + return res; + } + + public static String generateIncludingMapOpCPP() + { String res = + " static map* includingMap(map* m, string src, _T trg) \n" + + " { map* copy = new map(); \n" + + " map::iterator iter; \n" + + " for (iter = m->begin(); iter != m->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " (*copy)[key] = iter->second; \n" + + " } \n" + + " (*copy)[src] = trg; \n" + + " return copy; \n" + + " } \n"; + return res; + } + + public static String generateExcludeAllMapOpCPP() + { String res = + " static map* excludeAllMap(map* m1, map* m2) \n" + + " { map* res = new map(); \n" + + " map::iterator iter; \n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " map::iterator f = m2->find(key); \n" + + " if (f != m2->end()) \n" + + " { if (iter->second == f->second) { } \n" + + " else \n" + + " { (*res)[key] = iter->second; } \n" + + " } \n" + + " else \n" + + " { (*res)[key] = iter->second; } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateExcludingMapKeyOpCPP() + { String res = + " static map* excludingMapKey(map* m, string k) \n" + + " { // m - { k |-> m(k) } \n" + + " map* res = new map(); \n" + + " map::iterator iter; \n" + + " for (iter = m->begin(); iter != m->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " if (key == k) {} \n" + + " else \n" + + " { (*res)[key] = iter->second; } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + + public static String generateExcludingMapValueOpCPP() + { String res = + " static map* excludingMapValue(map* m, _T v) \n" + + " { // m - { k |-> v } \n" + + " map* res = new map(); \n" + + " map::iterator iter; \n" + + " for (iter = m->begin(); iter != m->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " if (iter->second == v) {} \n" + + " else \n" + + " { (*res)[key] = iter->second; } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + + + public static String generateUnionMapOpCPP() + { String res = + " static map* unionMap(map* m1, map* m2) \n" + + " { map* res = new map(); \n" + + " map::iterator iter; \n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " if (m2->count(key) == 0) \n" + + " { (*res)[key] = iter->second; } \n" + + " } \n" + + " for (iter = m2->begin(); iter != m2->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " (*res)[key] = iter->second; \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateIntersectionMapOpCPP() + { String res = + " static map* intersectionMap(map* m1, map* m2) \n" + + " { map* res = new map(); \n" + + " map::iterator iter; \n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter) \n" + + " { string key = iter->first; \n" + + " if (m2->count(key) > 0) \n" + + " { if (m2->at(key) == iter->second) \n" + + " { (*res)[key] = iter->second; } \n" + + " } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + + res = res + + " static std::map* intersectAllMap(vector*>* se)\n" + + " { std::map* res = new std::map();\n" + + " if (se->size() == 0) { return res; }\n" + + " res = (*se)[0]; \n" + + " for (int i = 1; i < se->size(); ++i)\n" + + " { res = UmlRsdsLib<_T>::intersectionMap(res, (*se)[i]); }\n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateKeysMapOpCPP() + { String res = + " static std::set* keys(map* s)\n" + + " { map::iterator iter;\n" + + " std::set* res = new std::set();\n" + + " \n" + + " for (iter = s->begin(); iter != s->end(); ++iter)\n" + + " { string key = iter->first;\n" + + " res->insert(key);\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateValuesMapOpCPP() + { String res = + " static vector<_T>* values(map* s)\n" + + " { map::iterator iter;\n" + + " vector<_T>* res = new vector<_T>();\n" + + " \n" + + " for (iter = s->begin(); iter != s->end(); ++iter)\n" + + " { _T value = iter->second;\n" + + " res->push_back(value);\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateRestrictOpCPP() + { String res = + " static map* restrict(map* m1, std::set* ks)\n" + + " { map* res = new map();\n" + + " map::iterator iter;\n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter)\n" + + " { string key = iter->first;\n" + + " if (ks->find(key) != ks->end())\n" + + " { (*res)[key] = iter->second; }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + res = res + + " static map* antirestrict(map* m1, std::set* ks)\n" + + " { map* res = new map();\n" + + " map::iterator iter;\n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter)\n" + + " { string key = iter->first;\n" + + " if (ks->find(key) == ks->end())\n" + + " { (*res)[key] = iter->second; }\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + + + public static String generateTokeniseOpCPP() + { String res = + " static vector* tokenise(vector* res, string str)\n" + + " { bool inspace = true; \n" + + " string* current = new string(\"\"); \n" + + " for (int i = 0; i < str.length(); i++)\n" + + " { if (str[i] == \'.\' || isspace(str[i]) > 0)\n" + + " { if (inspace) {}\n" + + " else \n" + + " { res->push_back(*current);\n" + + " current = new string(\"\"); \n" + + " inspace = true;\n" + + " }\n" + + " }\n" + + " else \n" + + " { if (inspace) { inspace = false; }\n" + + " current->append(str.substr(i,1)); \n" + + " }\n" + + " }\n" + + " if (current->length() > 0) { res->push_back(*current); }\n" + + " delete current;\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateGCDOp() + { String res = " public static long gcd(long xx, long yy)\n" + + " { long x = Math.abs(xx);\n" + + " long y = Math.abs(yy);\n" + + " while (x != 0 && y != 0)\n" + + " { long z = y; \n" + + " y = x % y; \n" + + " x = z;\n" + + " } \n" + + " if (y == 0)\n" + + " { return x; }\n" + + " if (x == 0)\n" + + " { return y; }\n" + + " return 0;\n" + + " } \n"; + return res; + } + + public static String generateGCDOpCSharp() + { String res = " public static long gcd(long xx, long yy)\n" + + " { long x = Math.Abs(xx);\n" + + " long y = Math.Abs(yy);\n" + + " while (x != 0 && y != 0)\n" + + " { long z = y; \n" + + " y = x % y; \n" + + " x = z;\n" + + " } \n" + + " if (y == 0)\n" + + " { return x; }\n" + + " if (x == 0)\n" + + " { return y; }\n" + + " return 0;\n" + + " } \n\n"; + res = res + + " public static bool toBoolean(object sx)\n" + + " { if (sx == null) { return false; }\n" + + " if (\"\".Equals(sx + \"\") || \"false\".Equals(sx + \"\") || \"False\".Equals(sx + \"\"))\n" + + " { return false; }\n" + + " try\n" + + " { double d = double.Parse(sx + \"\");\n" + + " if (Double.IsNaN(d) || (d <= 0.0 && d >= 0.0))\n" + + " { return false; }\n" + + " } catch { }\n" + + " return true;\n" + + " }\n\n"; + + res = res + + " public static int toInteger(string sx)\n" + + " { string tsx = sx.Trim();\n" + + " if (tsx.StartsWith(\"0x\"))\n" + + " { return Convert.ToInt32(tsx, 16); }\n" + + " if (tsx.StartsWith(\"0b\"))\n" + + " { return Convert.ToInt32(tsx, 2); }\n" + + " if (tsx.StartsWith(\"0\") && tsx.Length > 1)\n" + + " { return Convert.ToInt32(tsx, 8); }\n" + + " return toInt(tsx);\n" + + " } \n\n"; + + res = res + + " public static long toLong(string sx)\n" + + " { string sxx = sx.Trim();\n" + + " if (sxx.StartsWith(\"0x\"))\n" + + " { return Convert.ToInt64(sxx, 16); }\n" + + " if (sxx.StartsWith(\"0b\"))\n" + + " { return Convert.ToInt64(sxx, 2); }\n" + + " if (sxx.StartsWith(\"0\") && sxx.Length > 1)\n" + + " { return Convert.ToInt64(sxx, 8); }\n" + + " return long.Parse(sxx);\n" + + " } \n\n"; + + res = res + + " public static int char2byte(string qf) \n" + + " { if (qf.Length < 1) { return -1; }\n" + + " return Char.ConvertToUtf32(qf, 0);\n" + + " }\n" + + "\n" + + " public static string byte2char(int qf)\n" + + " { if (qf < 0) { return \"\"; }\n" + + " return Char.ConvertFromUtf32(qf);\n" + + " }\n\n"; + + return res; + } + + + public static String generateGCDOpCPP() + { String res = " static long gcd(long xx, long yy)\n" + + " { long x = labs(xx);\n" + + " long y = labs(yy);\n" + + " while (x != 0 && y != 0)\n" + + " { long z = y; \n" + + " y = x % y; \n" + + " x = z;\n" + + " } \n" + + " if (y == 0)\n" + + " { return x; }\n" + + " if (x == 0)\n" + + " { return y; }\n" + + " return 0;\n" + + " } \n"; + return res; + } + + + public static String generateRoundOpCPP() + { String res = + " static int oclRound(double d)\n" + + " { int f = (int) floor(d);\n" + + " if (d >= f + 0.5)\n" + + " { return f+1; }\n" + + " else \n" + + " { return f; }\n" + + " }\n\n"; + return res; + } + + public static String generateIsTypeOfOp() + { String res = " public static boolean oclIsTypeOf(Object x, String E)\n" + + " { try { \n" + + " if (x.getClass() == Class.forName(E))\n" + + " { return true; } \n" + + " else \n" + + " { return false; }\n" + + " } \n" + + " catch (Exception e) { return false; }\n" + + " } \n"; + return res; + } + + + public static String generateSubrangeOpCPP() // for C++ + { String res = " static vector* integerSubrange(int i, int j)\n" + + " { vector* tmp = new vector(); \n" + + " for (int k = i; k <= j; k++)\n" + + " { tmp->push_back(k); } \n" + + " return tmp;\n" + + " }\n\n" + + " static string subrange(string s, int i, int j)\n"; + res = res + " { if (i < 1) { i = 1; }\n" + + " return s.substr(i-1,j-i+1);\n" + + " }\n\n"; + res = res + " static vector<_T>* subrange(vector<_T>* l, int i, int j)\n"; + res = res + " { if (i < 1) { i = 1; }\n" + + " if (j > l->size()) { j = l->size(); }\n" + + " vector<_T>* tmp = new vector<_T>(); \n" + + " tmp->insert(tmp->end(), (l->begin()) + (i - 1), (l->begin()) + j);\n" + + " return tmp; \n" + + " }\n\n"; + return res; + } + + public static String generateAnyOp() + { String res = " public static Object any(List v)\n" + + " { if (v.size() == 0) { return null; }\n" + + " return v.get(0);\n" + + " }\n"; + res = res + " public static Object any(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return any(range); }\n\n"; + return res; + } + + public static String generateAnyOpJava6() + { String res = " public static Object any(Collection v)\n" + + " { for (Object o : v) { return o; }\n" + + " return null;\n" + + " }\n"; + return res; + } // map + + public static String generateAnyOpJava7() + { String res = " public static T any(Collection v)\n" + + " { for (T o : v) { return o; }\n" + + " return null;\n" + + " }\n"; + return res; + } // map + + public static String generateAnyOpCSharp() + { String res = " public static object any(ArrayList v)\n" + + " { if (v.Count == 0) { return null; }\n" + + " return v[0];\n" + + " }\n"; + return res; + } // map + + public static String generateAnyOpCPP() + { String res = " static _T any(vector<_T>* v)\n" + + " { if (v->size() == 0) { return 0; }\n" + + " return v->at(0);\n" + + " }\n\n" + + " static _T any(std::set<_T>* v)\n" + + " { if (v->size() == 0) { return 0; }\n" + + " std::set<_T>::iterator _pos = v->begin();\n" + + " return *_pos;\n" + + " }\n\n"; + return res; + } // map + + public static String generateFirstOp() + { String res = + " public static Object first(List v)\n" + + " { if (v.size() == 0) { return null; }\n" + + " return v.get(0);\n" + + " }\n"; + return res; + } + + public static String generateFirstOpJava6() + { String res = " public static Object first(Collection v)\n" + + " { for (Object o : v) { return o; }\n" + + " return null;\n" + + " }\n"; + return res; + } + + public static String generateFirstOpJava7() + { String res = " public static T first(Collection v)\n" + + " { for (T o : v) { return o; }\n" + + " return null;\n" + + " }\n"; + return res; + } + + public static String generateFirstOpCSharp() + { String res = " public static object first(ArrayList v)\n" + + " { if (v.Count == 0) { return null; }\n" + + " return v[0];\n" + + " }\n"; + return res; + } + + public static String generateFirstOpCPP() + { String res = " static _T first(vector<_T>* v)\n" + + " { if (v->size() == 0) { return 0; }\n" + + " return v->at(0);\n" + + " }\n\n" + + " static _T first(std::set<_T>* v)\n" + + " { if (v->size() == 0) { return 0; }\n" + + " std::set<_T>::iterator _pos = v->begin();\n" + + " return *_pos;\n" + + " }\n\n"; + return res; + } + + public static String generateTimeOpCSharp() + { String res = " public static long getTime()\n" + + " { DateTimeOffset d = new DateTimeOffset(DateTime.Now);\n" + + " return d.ToUnixTimeMilliseconds();\n" + + " }\n\n"; + res = res + + " public static long getTime(DateTime d)\n" + + " { DateTimeOffset doff = new DateTimeOffset(d);\n" + + " return doff.ToUnixTimeMilliseconds();\n" + + " }\n\n"; + + res = res + + " public static double roundTo(double x, int n)\n" + + " { if (n == 0) \n" + + " { return Math.Round(x); }\n" + + " double y = x*Math.Pow(10,n); \n" + + " return Math.Round(y)/Math.Pow(10,n);\n" + + " }\n\n"; + + res = res + + " public static double truncateTo(double x, int n)\n" + + " { if (n < 0) \n" + + " { return (int) x; }\n" + + " double y = x*Math.Pow(10,n); \n" + + " return ((int) y)/Math.Pow(10,n);\n" + + " }\n\n"; + + return res; + } + + public static String generateTimeOp() + { String res = " public static long getTime()\n" + + " { java.util.Date d = new java.util.Date();\n" + + " return d.getTime();\n" + + " }\n\n"; + + res = res + + " public static double roundN(double x, int n)\n" + + " { if (n == 0) \n" + + " { return Math.round(x); }\n" + + " double y = x*Math.pow(10,n); \n" + + " return Math.round(y)/Math.pow(10,n);\n" + + " }\n\n"; + + res = res + + " public static double truncateN(double x, int n)\n" + + " { if (n < 0) \n" + + " { return (int) x; }\n" + + " double y = x*Math.pow(10,n); \n" + + " return ((int) y)/Math.pow(10,n);\n" + + " }\n\n"; + + return res; + } + + public static String generateTimeOpCPP() + { String res = " static long long getTime()\n" + + " { return 1000*time(NULL); }\n\n"; + res = res + " static struct tm* getDate()\n" + + " { time_t t = time(NULL);\n" + + " struct tm* res = localtime(&t);\n" + + " return res;\n" + + " }\n"; + + res = res + + " static double roundTo(double x, int n)\n" + + " { if (n == 0) \n" + + " { return round(x); }\n" + + " double y = x*pow(10,n); \n" + + " return round(y)/pow(10,n);\n" + + " }\n\n"; + + res = res + + " static double truncateTo(double x, int n)\n" + + " { if (n < 0) \n" + + " { return (int) x; }\n" + + " double y = x*pow(10,n); \n" + + " return ((int) y)/pow(10,n);\n" + + " }\n\n"; + + return res; + } + + public static String generateSetEqualsOp() + { String res = " public static boolean equals(List a, List b)\n" + + " { return a.containsAll(b) && b.containsAll(a); }\n\n"; + return res; + } // but should disregard null elements. + + public static String generateSetEqualsOpCSharp() + { String res = " public static bool isSubset(ArrayList a, ArrayList b)\n" + + " { bool res = true; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { if (a[i] != null && b.Contains(a[i])) { }\n" + + " else { return false; }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " public static bool equalsSet(ArrayList a, ArrayList b)\n" + + " { return isSubset(a,b) && isSubset(b,a); }\n\n"; + return res; + } + + public static String generateSubcollectionsOp() + { String res = " public static List subcollections(List v)\n" + + " { Vector res = new Vector();\n" + + " if (v.size() == 0)\n" + + " { res.add(new Vector());\n" + + " return res;\n" + + " }\n" + + " if (v.size() == 1)\n" + + " { res.add(new Vector());\n" + + " res.add(v);\n" + + " return res;\n" + + " }\n" + + " Vector s = new Vector();\n" + + " Object x = v.get(0);\n" + + " s.addAll(v);\n" + + " s.remove(0);\n" + + " List scs = subcollections(s);\n" + + " res.addAll(scs);\n" + + " for (int i = 0; i < scs.size(); i++)\n" + + " { Vector sc = (Vector) scs.get(i);\n" + + " Vector scc = new Vector();\n" + + " scc.add(x);\n" + + " scc.addAll(sc);\n" + + " res.add(scc);\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateSubcollectionsOpCSharp() + { String res = " public static ArrayList subcollections(ArrayList v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (v.Count == 0)\n" + + " { res.Add(new ArrayList());\n" + + " return res;\n" + + " }\n" + + " if (v.Count == 1)\n" + + " { res.Add(new ArrayList());\n" + + " res.Add(v);\n" + + " return res;\n" + + " }\n" + + " ArrayList s = new ArrayList();\n" + + " object x = v[0];\n" + + " s.AddRange(v);\n" + + " s.RemoveAt(0);\n" + + " ArrayList scs = subcollections(s);\n" + + " res.AddRange(scs);\n" + + " for (int i = 0; i < scs.Count; i++)\n" + + " { ArrayList sc = (ArrayList) scs[i];\n" + + " ArrayList scc = new ArrayList();\n" + + " scc.Add(x);\n" + + " scc.AddRange(sc);\n" + + " res.Add(scc);\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + + + public static String generateMaxOp() // for Java + { String res = " public static Comparable max(List l)\n"; + res = res + " { Comparable res = null; \n"; + res = res + " if (l.size() == 0) { return res; }\n"; + res = res + " res = (Comparable) l.get(0); \n"; + res = res + " for (int i = 1; i < l.size(); i++)\n"; + res = res + " { Comparable e = (Comparable) l.get(i);\n"; + res = res + " if (res.compareTo(e) < 0) { res = e; } }\n"; + res = res + " return res; }\n"; + res = res + " public static Comparable max(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return max(range); }\n\n"; + + return res; + } + + public static String generateMaxOpJava6() // for Java6 + { String res = " public static Comparable max(Collection l)\n"; + res = res + " { Comparable res = null; \n"; + res = res + " if (l.size() == 0) { return res; }\n"; + res = res + " res = (Comparable) Set.any(l); \n"; + res = res + " for (Object _o : l)\n"; + res = res + " { Comparable e = (Comparable) _o;\n"; + res = res + " if (res.compareTo(e) < 0) { res = e; } }\n"; + res = res + " return res; }\n"; + return res; + } // map + + public static String generateMaxOpJava7() // for Java7 + { /* String res = " public static T max(Collection l)\n"; + res = res + " { return Collections.max(l); }\n"; + return res; + } */ + + String res = " public static T max(Collection s)\n" + + " { ArrayList slist = new ArrayList();\n" + + " slist.addAll(s); \n" + + " T result = slist.get(0);\n" + + " for (int i = 1; i < slist.size(); i++)\n" + + " { T val = slist.get(i); \n" + + " if (0 < val.compareTo(result))\n" + + " { result = val; } \n" + + " } \n" + + " return result;\n" + + " } \n"; + return res; + } + + + public static String generateMaxOpCSharp() // for CSharp + { String res = " public static object max(ArrayList l)\n"; + res = res + " { IComparable res = null; \n"; + res = res + " if (l.Count == 0) { return res; }\n"; + res = res + " res = (IComparable) l[0]; \n"; + res = res + " for (int i = 1; i < l.Count; i++)\n"; + res = res + " { IComparable e = (IComparable) l[i];\n"; + res = res + " if (res.CompareTo(e) < 0) { res = e; } }\n"; + res = res + " return res; }\n"; + return res; + } // map + + public static String generateMaxOpCPP() // for C++ + { String res = " static _T max(std::set<_T>* l)\n"; + res = res + " { return *std::max_element(l->begin(), l->end()); }\n"; + res = res + " static _T max(vector<_T>* l)\n"; + res = res + " { return *std::max_element(l->begin(), l->end()); }\n"; + return res; + } // map + + public static String generateMinOp() + { String res = " public static Comparable min(List l)\n"; + res = res + " { Comparable res = null; \n"; + res = res + " if (l.size() == 0) { return res; }\n"; + res = res + " res = (Comparable) l.get(0); \n"; + res = res + " for (int i = 1; i < l.size(); i++)\n"; + res = res + " { Comparable e = (Comparable) l.get(i);\n"; + res = res + " if (res.compareTo(e) > 0) { res = e; } }\n"; + res = res + " return res; }\n"; + res = res + " public static Comparable min(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return min(range); }\n\n"; + return res; + } + + public static String generateMinOpJava6() + { String res = " public static Comparable min(Collection l)\n"; + res = res + " { Comparable res = null; \n"; + res = res + " if (l.size() == 0) { return res; }\n"; + res = res + " res = (Comparable) Set.any(l); \n"; + res = res + " for (Object _o : l)\n"; + res = res + " { Comparable e = (Comparable) _o;\n"; + res = res + " if (res.compareTo(e) > 0) { res = e; } }\n"; + res = res + " return res; }\n"; + return res; + } // map + + public static String generateMinOpJava7() // for Java7 - not needed. + { // String res = " public static T min(Collection l)\n"; + // res = res + " { return Collections.min(l); }\n"; + // return res; + String res = " public static T min(Collection s)\n" + + " { ArrayList slist = new ArrayList();\n" + + " slist.addAll(s); \n" + + " T result = slist.get(0);\n" + + " for (int i = 1; i < slist.size(); i++)\n" + + " { T val = slist.get(i); \n" + + " if (val.compareTo(result) < 0)\n" + + " { result = val; } \n" + + " } \n" + + " return result;\n" + + " } \n"; + return res; + } // and for map + + public static String generateMinOpCSharp() + { String res = " public static object min(ArrayList l)\n"; + res = res + " { IComparable res = null; \n"; + res = res + " if (l.Count == 0) { return res; }\n"; + res = res + " res = (IComparable) l[0]; \n"; + res = res + " for (int i = 1; i < l.Count; i++)\n"; + res = res + " { IComparable e = (IComparable) l[i];\n"; + res = res + " if (res.CompareTo(e) > 0) { res = e; } }\n"; + res = res + " return res; }\n"; + return res; + } // map + + public static String generateMinOpCPP() // for C++ + { String res = " static _T min(std::set<_T>* l)\n"; + res = res + " { return *std::min_element(l->begin(), l->end()); }\n"; + res = res + " static _T min(vector<_T>* l)\n"; + res = res + " { return *std::min_element(l->begin(), l->end()); }\n"; + return res; + } // map + + public static String generateBeforeOp() + { String res = " public static String before(String s, String sep)\n" + + " { if (sep.length() == 0) { return s; }\n" + + " int ind = s.indexOf(sep);\n" + + " if (ind < 0) { return s; }\n" + + " return s.substring(0,ind); \n" + + " }\n"; + return res; + } + + public static String generateAfterOp() + { String res = " public static String after(String s, String sep)\n" + + " { int ind = s.indexOf(sep);\n" + + " int seplength = sep.length();\n" + + " if (ind < 0) { return \"\"; }\n" + + " if (seplength == 0) { return \"\"; }\n" + + " return s.substring(ind + seplength, s.length()); \n" + + " }\n"; + return res; + } + + public static String generateIsMatchOp() + { String res = " public static boolean isMatch(String str, String regex)\n" + + " { return str.matches(regex); }\n\n"; + return res; + } + + public static String generateHasMatchOp() + { String res = " public static boolean hasMatch(String str, String regex)\n" + + " { java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str); \n" + + " if (matcher.find())\n" + + " { return true; }\n" + + " return false;\n" + + " }\n\n"; + return res; + } + + public static String generateSplitOp() + { String res = " public static Vector split(String str, String delim)\n" + + " { String[] splits = str.split(delim);\n" + + " Vector res = new Vector();\n" + + " for (int j = 0; j < splits.length; j++)\n" + + " { if (splits[j].length() > 0)\n" + + " { res.add(splits[j]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateAllMatchesOp() + { String res = " public static Vector allMatches(String str, String regex)\n" + + " { java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str);\n" + + " Vector res = new Vector();\n" + + " while (matcher.find())\n" + + " { res.add(matcher.group() + \"\"); }\n" + + " return res; \n" + + " }\n"; + return res; + } + + public static String generateFirstMatchOp() + { String res = " public static String firstMatch(String str, String regex)\n" + + " { java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str);\n" + + " String res = null;\n" + + " if (matcher.find())\n" + + " { res = matcher.group() + \"\"; }\n" + + " return res; \n" + + " }\n"; + return res; + } + + public static String generateSplitOpJava6() + { String res = " public static ArrayList split(String str, String delim)\n" + + " { String[] splits = str.split(delim);\n" + + " ArrayList res = new ArrayList();\n" + + " for (int j = 0; j < splits.length; j++)\n" + + " { if (splits[j].length() > 0)\n" + + " { res.add(splits[j]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateAllMatchesOpJava6() + { String res = " public static ArrayList allMatches(String str, String regex)\n" + + " { java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str);\n" + + " ArrayList res = new ArrayList();\n" + + " while (matcher.find())\n" + + " { res.add(matcher.group() + \"\"); }\n" + + " return res; \n" + + " }\n"; + return res; + } + + public static String generateSplitOpJava7() + { String res = " public static ArrayList split(String str, String delim)\n" + + " { String[] splits = str.split(delim);\n" + + " ArrayList res = new ArrayList();\n" + + " for (int j = 0; j < splits.length; j++)\n" + + " { if (splits[j].length() > 0) \n" + + " { res.add(splits[j]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateAllMatchesOpJava7() + { String res = " public static ArrayList allMatches(String str, String regex)\n" + + " { java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str);\n" + + " ArrayList res = new ArrayList();\n" + + " while (matcher.find())\n" + + " { res.add(matcher.group() + \"\"); }\n" + + " return res; \n" + + " }\n"; + return res; + } + + public static String generateHasMatchOpCSharp() + { String res = " public static bool hasMatch(string s, string patt)\n" + + " { Regex r = new Regex(patt);\n" + + " return r.IsMatch(s);\n" + + " }\n"; + return res; + } + + public static String generateIsMatchOpCSharp() + { String res = " public static bool isMatch(string s, string patt)\n" + + " { Regex r = new Regex(patt);\n" + + " Match m = r.Match(s);\n" + + " return (m + \"\").Equals(s);\n" + + " }\n"; + return res; + } + + + public static String generateAllMatchesOpCSharp() + { String res = " public static ArrayList allMatches(string s, string patt)\n" + + " { Regex r = new Regex(patt);\n" + + " MatchCollection col = r.Matches(s);\n" + + " ArrayList res = new ArrayList();\n" + + " foreach (Match mm in col)\n" + + " { res.Add(mm.Value + \"\"); }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateFirstMatchOpCSharp() + { String res = " public static string firstMatch(string s, string patt)\n" + + " { Regex r = new Regex(patt);\n" + + " Match m = r.Match(s);\n" + + " if (m.Success)\n" + + " { return m.Value + \"\"; }\n" + + " return null;\n" + + " }\n"; + return res; + } + + public static String generateIsMatchOpCPP() + { String res = " static bool isMatch(string str, string patt)\n" + + " { std::regex rr(patt);\n" + + " return std::regex_match(str,rr);\n" + + " }\n\n"; + return res; + } + + public static String generateHasMatchOpCPP() + { String res = " static bool hasMatch(string str, string patt)\n" + + " { std::regex rr(patt);\n" + + " return std::regex_search(str,rr);\n" + + " }\n\n"; + return res; + } + + public static String generateTrimOpCPP() + { String res = " static string trim(string str)\n" + + " { int i = str.find_first_not_of(\"\\n\\t \");\n" + + " int j = str.find_last_not_of(\"\\n\\t \");\n" + + " if (i > j) \n" + + " { return \"\"; }\n" + + " return str.substr(i, j-i+1);\n" + + " } \n"; + return res; + } + + public static String generateAllMatchesOpCPP() + { String res = + " static vector* allMatches(string s, string patt)\n" + + " { int slen = s.length(); \n" + + " vector* res = new vector(); \n" + + " if (slen == 0) \n" + + " { return res; } \n" + + " std::regex patt_regex(patt);\n" + + " auto words_begin = std::sregex_iterator(s.begin(), s.end(), patt_regex);\n" + + " auto words_end = std::sregex_iterator();\n" + + " \n" + + " for (std::sregex_iterator i = words_begin; i != words_end; ++i)\n" + + " { std::smatch match = *i;\n" + + " std::string match_str = match.str();\n" + + " if (match_str.length() > 0)\n" + + " { res->push_back(match_str); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateFirstMatchOpCPP() + { String res = + " static string firstMatch(string s, string patt)\n" + + " { int slen = s.length(); \n" + + " string res = \"\"; \n" + + " if (slen == 0) \n" + + " { return res; } \n" + + " std::regex patt_regex(patt);\n" + + " auto words_begin = std::sregex_iterator(s.begin(), s.end(), patt_regex);\n" + + " auto words_end = std::sregex_iterator();\n" + + " \n" + + " for (std::sregex_iterator i = words_begin; i != words_end; ++i)\n" + + " { std::smatch match = *i;\n" + + " std::string match_str = match.str();\n" + + " if (match_str.length() > 0)\n" + + " { return match_str; }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateReplaceOpCPP() + { String res = + " static string replace(string s1, string s2, string rep)\n" + + " { int s1len = s1.length(); \n" + + " int s2len = s2.length(); \n" + + " int replen = rep.length(); \n" + + " if (s1len == 0 || s2len == 0 || replen == 0)\n" + + " { return s1; } \n" + + " string result = \"\";\n" + + " int prev = 0; \n" + + " int m1 = s1.find(s2);\n" + + " if (m1 >= 0)\n" + + " { result = result + s1.substr(prev, m1 - prev) + rep; \n" + + " string remainder = s1.substr(m1 + s2len, s1len - (m1 + s2len)); \n" + + " return result + replace(remainder, s2, rep);\n" + + " } \n" + + " return s1;\n" + + " } \n"; + return res; + } // substituteAll + + public static String generateReplaceAllOpCPP() + { String res = " static string replaceAll(string text, string patt, string rep)\n" + + " { std::regex patt_re(patt);\n" + + " std::string res = std::regex_replace(text, patt_re, rep);\n" + + " return res;\n" + + " }\n"; + return res; + } // replaceAllMatches + + public static String generateReplaceFirstOpCPP() + { String res = " static string replaceFirstMatch(string text, string patt, string rep)\n" + + " { std::regex patt_re(patt);\n" + + " std::regex_constants::match_flag_type fonly =\n" + + " std::regex_constants::format_first_only;\n" + + + " std::string res = std::regex_replace(text, patt_re, rep, fonly);\n" + + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateSplitOpCPP() + { String res = " static vector* split(string s, string patt)\n" + + " { int slen = s.length();\n" + + " vector* res = new vector();\n" + + " if (slen == 0) \n" + + " { res->push_back(s);\n" + + " return res; \n" + + " } \n" + + " std::regex patt_regex(patt);\n" + + " auto words_begin = std::sregex_iterator(s.begin(), s.end(), patt_regex);\n" + + " auto words_end = std::sregex_iterator();\n" + + " int prev = 0; \n" + + " for (std::sregex_iterator i = words_begin; i != words_end; ++i)\n" + + " { std::smatch match = *i;\n" + + " int pos = match.position(0);\n" + + " int ln = match.length(0); \n" + + " if (ln > 0)\n" + + " { string subst = s.substr(prev, pos - prev + 1);\n" + + " res->push_back(subst);\n" + + " prev = pos + ln; \n" + + " } \n" + + " }\n" + + " if (prev <= slen)\n" + + " { string lastst = s.substr(prev,slen - prev + 1);\n" + + " res->push_back(lastst);\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateReplaceOp() + { String res = " public static String replace(String str, String delim, String rep)\n" + + " { String result = \"\";\n" + + " String s = str + \"\";\n" + + " int i = (s.indexOf(delim) + 1);\n" + + " if (i == 0)\n" + + " { return s; }\n" + + " \n" + + " int sublength = delim.length();\n" + + " if (sublength == 0)\n" + + " { return s; }\n" + + " \n" + + " while (i > 0)\n" + + " { result = result + Set.subrange(s,1,i - 1) + rep;\n" + + " s = Set.subrange(s,i + delim.length(),s.length());\n" + + " i = (s.indexOf(delim) + 1);\n" + + " }\n" + + " result = result + s;\n" + + " return result;\n" + + " }\n"; + return res; + } + + public static String generateReplaceOpJava7() + { String res = " public static String replace(String str, String delim, String rep)\n" + + " { String result = \"\";\n" + + " String s = str + \"\";\n" + + " int i = (s.indexOf(delim) + 1);\n" + + " if (i == 0)\n" + + " { return s; }\n" + + " \n" + + " int sublength = delim.length();\n" + + " if (sublength == 0)\n" + + " { return s; }\n" + + " \n" + + " while (i > 0)\n" + + " { result = result + Ocl.subrange(s,1,i - 1) + rep;\n" + + " s = Ocl.subrange(s,i + delim.length(),s.length());\n" + + " i = (s.indexOf(delim) + 1);\n" + + " }\n" + + " result = result + s;\n" + + " return result;\n" + + " }\n"; + return res; + } + + public static String generateReplaceAllOp() + { String res = " public static String replaceAll(String str, String regex, String rep)\n" + + " { if (str == null) { return null; }\n" + + " java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str);\n" + + " return matcher.replaceAll(rep);\n" + + " }\n"; + return res; + } + + public static String generateReplaceFirstOp() + { String res = " public static String replaceFirstMatch(String str, String regex, String rep)\n" + + " { if (str == null) { return null; }\n" + + " java.util.regex.Pattern patt = java.util.regex.Pattern.compile(regex);\n" + + " java.util.regex.Matcher matcher = patt.matcher(str);\n" + + " return matcher.replaceFirst(rep);\n" + + " }\n"; + return res; + } + + public static String generateReplaceOpCSharp() + { String res = " public static string replace(string str, string delim, string rep)\n" + + " { if (str == null) { return null; }\n" + + " String result = \"\";\n" + + " String s = str + \"\";\n" + + " int i = (s.IndexOf(delim) + 1);\n" + + " if (i == 0)\n" + + " { return s; }\n" + + "\n" + + " int sublength = delim.Length;\n" + + " if (sublength == 0)\n" + + " { return s; }\n" + + "\n" + + " while (i > 0)\n" + + " { result = result + SystemTypes.subrange(s, 1, i - 1) + rep;\n" + + " s = SystemTypes.subrange(s, i + delim.Length, s.Length);\n" + + " i = (s.IndexOf(delim) + 1);\n" + + " }\n" + + " result = result + s;\n" + + " return result;\n" + + " }\n"; + return res; + } + + + + public static String generateReplaceAllOpCSharp() + { String res = " public static string replaceAll(string s, string patt, string rep)\n" + + " { if (s == null) { return null; }\n" + + " Regex r = new Regex(patt);\n" + + " return \"\" + r.Replace(s, rep);\n" + + " }\n"; + return res; + } + + public static String generateReplaceFirstOpCSharp() + { String res = " public static string replaceFirstMatch(string s, string patt, string rep)\n" + + " { if (s == null) { return null; }\n" + + " Regex r = new Regex(patt);\n" + + " return \"\" + r.Replace(s, rep, 1);\n" + + " }\n"; + return res; + } + + public static String generateSplitOpCSharp() + { String res = " public static ArrayList split(string s, string patt)\n" + + " { Regex r = new Regex(patt);\n" + + " ArrayList res = new ArrayList();\n" + + " string[] wds = r.Split(s);\n" + + " for (int x = 0; x < wds.Length; x++)\n" + + " { if (wds[x].Length > 0)\n" + + " { res.Add(wds[x]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateBeforeOpCSharp() + { String res = " public static string before(string s, string sep)\n" + + " { if (sep.Length == 0) { return s; }\n" + + " int ind = s.IndexOf(sep);\n" + + " if (ind < 0) { return s; }\n" + + " return s.Substring(0,ind); \n" + + " }\n"; + return res; + } + + public static String generateAfterOpCSharp() + { String res = " public static string after(string s, string sep)\n" + + " { int ind = s.IndexOf(sep);\n" + + " int seplength = sep.Length;\n" + + " if (ind < 0) { return \"\"; }\n" + + " if (seplength == 0) { return \"\"; }\n" + + " return s.Substring(ind + seplength, s.Length - (ind + seplength)); \n" + + " }\n"; + return res; + } + + public static String generateBeforeOpCPP() + { String res = " static string before(string s, string sep)\n" + + " { if (sep.length() == 0) { return s; }\n" + + " if (s.find(sep) == string::npos) { return s; }\n" + + " return s.substr(0,s.find(sep)); \n" + + " }\n"; + return res; + } + + public static String generateAfterOpCPP() + { String res = " static string after(string s, string sep)\n" + + " { int seplength = sep.length();\n" + + " if (s.find(sep) == string::npos) { return \"\"; }\n" + + " if (seplength == 0) { return \"\"; }\n" + + " return s.substr(s.find(sep) + seplength, s.length() - (s.find(sep) + seplength)); \n" + + " }\n"; + return res; + } + + public static String generateUnionOp() // Should only be used if first one is a set. + { String res = " public static List union(List a, List b)\n" + + " { List res = new Vector(); \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Object x = a.get(i); \n" + + " if (x == null || res.contains(x)) { } else { res.add(x); } \n" + + " }\n" + + " for (int j = 0; j < b.size(); j++)\n" + + " { Object y = b.get(j); \n" + + " if (y == null || res.contains(y)) { } else { res.add(y); }\n" + + " }\n" + + " return res; }\n"; + return res; + } + + public static String generateUnionOpJava6() + { String res = " public static HashSet union(HashSet a, Collection b)\n" + + " { HashSet res = new HashSet(); \n" + + " res.addAll(a); res.addAll(b);\n" + + " return res; }\n\n" + + " public static ArrayList union(ArrayList a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a); res.addAll(b);\n" + + " return res; }\n\n"; + return res; + } + + public static String generateUnionOpJava7() + { String res = " public static HashSet union(HashSet a, Collection b)\n" + + " { HashSet res = new HashSet(); \n" + + " for (Object x : a)\n" + + " { try \n" + + " { T y = (T) x; \n" + + " res.add(y); \n" + + " } catch (Exception _e) { }\n" + + " }\n" + + " res.addAll(b);\n" + + " return res;\n" + + " }\n\n" + + " public static TreeSet union(TreeSet a, Collection b)\n" + + " { TreeSet res = (TreeSet) a.clone(); \n" + + " res.addAll(b);\n" + + " return res;\n" + + " }\n\n" + + " public static ArrayList union(ArrayList a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a); res.addAll(b);\n" + + " return res; }\n"; + return res; + } + + public static String generateUnionOpCSharp() + { String res = " public static ArrayList union(ArrayList a, ArrayList b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { if (a[i] == null || res.Contains(a[i])) { } else { res.Add(a[i]); } }\n" + + " for (int j = 0; j < b.Count; j++)\n" + + " { if (b[j] == null || res.Contains(b[j])) { } else { res.Add(b[j]); } }\n" + + " return res; }\n"; + return res; + } // if both are sequences, concatenate is used. + + public static String generateUnionOpCPP() + { String res = " static std::set<_T>* unionSet(std::set<_T>* a, std::set<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " res->insert(a->begin(),a->end()); \n" + + " res->insert(b->begin(),b->end()); \n" + + " return res;\n" + + " }\n\n"; + res = res + " static std::set<_T>* unionSet(vector<_T>* a, std::set<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " res->insert(a->begin(),a->end()); \n" + + " res->insert(b->begin(),b->end()); \n" + + " return res;\n" + + " }\n\n"; + res = res + " static std::set<_T>* unionSet(std::set<_T>* a, vector<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " res->insert(a->begin(),a->end()); \n" + + " res->insert(b->begin(),b->end()); \n" + + " return res;\n" + + " }\n\n"; + res = res + " static std::set<_T>* unionSet(std::vector<_T>* a, vector<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " res->insert(a->begin(),a->end()); \n" + + " res->insert(b->begin(),b->end()); \n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateConcatOp() + { String res = " public static List concatenate(List a, List b)\n" + + " { List res = new Vector(); \n" + + " res.addAll(a); \n" + + " res.addAll(b); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static Vector singleValueMatrix(Vector sh, Object x)\n" + + " { Vector result;\n" + + " if ((sh).size() == 0)\n" + + " { return (new Vector()); }\n" + + " int n = (int) sh.get(0);\n" + + " \n" + + " if ((sh).size() == 1)\n" + + " { Vector _results_0 = new Vector();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_0.add(x); }\n" + + " return _results_0;\n" + + " }\n" + + "\n" + + " Vector tl = (Vector) Set.tail(sh);\n" + + " Vector res = (new Vector());\n" + + " Vector _results_1 = new Vector();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_1.add(Set.singleValueMatrix(tl,x)); }\n" + + " res = (Vector) Set.concatenate(res, _results_1);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateConcatOpJava6() + { String res = " public static ArrayList concatenate(Collection a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a); \n" + + " res.addAll(b); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList singleValueMatrix(ArrayList sh, Object x)\n" + + " { ArrayList result;\n" + + " if (sh.size() == 0)\n" + + " { return new ArrayList(); }\n" + + " int n = (int) sh.get(0);\n" + + " \n" + + " if (sh.size() == 1)\n" + + " { ArrayList _results_0 = new ArrayList();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_0.add(x); }\n" + + " return _results_0;\n" + + " }\n" + + "\n" + + " ArrayList tl = (ArrayList) Set.tail(sh);\n" + + " ArrayList res = new ArrayList();\n" + + " ArrayList _results_1 = new ArrayList();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_1.add(Set.singleValueMatrix(tl,x)); }\n" + + " res = (ArrayList) Set.concatenate(res, _results_1);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateConcatOpJava7() + { String res = " public static ArrayList concatenate(Collection a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a); \n" + + " res.addAll(b); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList singleValueMatrix(ArrayList sh,Object x)\n" + + " { ArrayList result;\n" + + " if ((sh).size() == 0)\n" + + " { return (new ArrayList()); }\n" + + " int n = (int) sh.get(0);\n" + + " \n" + + " if ((sh).size() == 1)\n" + + " { ArrayList _results_0 = new ArrayList();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_0.add(x); }\n" + + " return _results_0;\n" + + " }\n" + + "\n" + + " ArrayList tl = Ocl.tail(sh);\n" + + " ArrayList res = (new ArrayList());\n" + + " ArrayList> _results_1 = new ArrayList>();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_1.add(Ocl.singleValueMatrix(tl,x)); }\n" + + " res = Ocl.concatenate(res, _results_1);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateConcatOpCSharp() + { String res = " public static ArrayList concatenate(ArrayList a, ArrayList b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.AddRange(a); \n" + + " res.AddRange(b); \n" + + " return res;\n" + + " }\n"; + res = res + + " public static ArrayList prepend(ArrayList a, object x)\n" + + " {\n" + + " ArrayList res = new ArrayList();\n" + + " res.Add(x);\n" + + " res.AddRange(a);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList append(ArrayList a, object x)\n" + + " {\n" + + " ArrayList res = new ArrayList();\n" + + " res.AddRange(a);\n" + + " res.Add(x); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList singleValueMatrix(ArrayList sh, object x)\n" + + " { ArrayList result;\n" + + " if (sh.Count == 0)\n" + + " { return new ArrayList(); }\n" + + " int n = (int) sh[0];\n" + + " \n" + + " if (sh.Count == 1)\n" + + " { ArrayList _results_0 = new ArrayList();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_0.Add(x); }\n" + + " return _results_0;\n" + + " }\n" + + "\n" + + " ArrayList tl = (ArrayList) SystemTypes.tail(sh);\n" + + " ArrayList res = new ArrayList();\n" + + " ArrayList _results_1 = new ArrayList();\n" + + " for (int _i = 0; _i < n; _i++)\n" + + " { _results_1.Add(SystemTypes.singleValueMatrix(tl,x)); }\n" + + " res = (ArrayList) SystemTypes.concatenate(res, _results_1);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateConcatOpCPP() + { String res = " static vector<_T>* concatenate(vector<_T>* a, vector<_T>* b)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " res->insert(res->end(), a->begin(),a->end()); \n" + + " res->insert(res->end(), b->begin(),b->end()); \n" + + " return res;\n" + + " }\n\n"; + res = res + " static vector<_T>* concatenate(vector<_T>* a, std::set<_T>* b)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " res->insert(res->end(), a->begin(),a->end()); \n" + + " res->insert(res->end(), b->begin(),b->end()); \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateSubtractOp() + { String res = " public static List subtract(List a, List b)\n" + + " { List res = new Vector(); \n" + + " res.addAll(a);\n" + + " res.removeAll(b);\n" + + " return res;\n" + + " }\n\n" + + " public static String subtract(String a, String b)\n" + + " { String res = \"\"; \n" + + " for (int i = 0; i < a.length(); i++)\n" + + " { if (b.indexOf(a.charAt(i)) < 0)\n" + + " { res = res + a.charAt(i); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateSubtractOpJava6() + { String res = " public static HashSet subtract(HashSet a, Collection b)\n" + + " { HashSet res = new HashSet(); \n" + + " res.addAll(a);\n" + + " res.removeAll(b);\n" + + " return res;\n" + + " }\n\n" + + " public static ArrayList subtract(ArrayList a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a);\n" + + " res.removeAll(b);\n" + + " return res;\n" + + " }\n\n" + + " public static String subtract(String a, String b)\n" + + " { String res = \"\"; \n" + + " for (int i = 0; i < a.length(); i++)\n" + + " { if (b.indexOf(a.charAt(i)) < 0) { res = res + a.charAt(i); } }\n" + + " return res; }\n\n"; + return res; + } + + public static String generateSubtractOpJava7() + { String res = " public static HashSet subtract(HashSet a, Collection b)\n" + + " { HashSet res = new HashSet(); \n" + + " res.addAll(a);\n" + + " res.removeAll(b);\n" + + " return res; }\n\n" + + " public static TreeSet subtract(TreeSet a, Collection b)\n" + + " { TreeSet res = new TreeSet(); \n" + + " res.addAll(a);\n" + + " res.removeAll(b);\n" + + " return res; }\n\n" + + " public static ArrayList subtract(ArrayList a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a);\n" + + " res.removeAll(b);\n" + + " return res; }\n\n" + + " public static String subtract(String a, String b)\n" + + " { String res = \"\"; \n" + + " for (int i = 0; i < a.length(); i++)\n" + + " { if (b.indexOf(a.charAt(i)) < 0) { res = res + a.charAt(i); } }\n" + + " return res; }\n\n"; + return res; + } + + public static String generateSubtractOpCSharp() + { String res = " public static ArrayList subtract(ArrayList a, ArrayList b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { if (a[i] == null || b.Contains(a[i])) {}\n" + + " else { res.Add(a[i]); }\n" + + " }\n" + + " return res; }\n\n" + + " public static ArrayList subtract(ArrayList a, object b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { if (a[i] == null || b == a[i]) {}\n" + + " else { res.Add(a[i]); }\n" + + " }\n" + + " return res; }\n\n" + + " public static string subtract(string a, string b)\n" + + " { string res = \"\"; \n" + + " for (int i = 0; i < a.Length; i++)\n" + + " { if (b.IndexOf(a[i]) < 0) { res = res + a[i]; } }\n" + + " return res; }\n\n"; + return res; + } + + public static String generateSubtractOpCPP() + { String res = " static vector<_T>* subtract(vector<_T>* a, vector<_T>* b)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*a)[i],b)) { }\n" + + " else { res->push_back((*a)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* subtract(vector<_T>* a, std::set<_T>* b)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*a)[i],b)) { }\n" + + " else\n" + + " { res->push_back((*a)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* subtract(std::set<_T>* a, std::set<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " for (std::set<_T>::iterator _pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos,b)) { }\n" + + " else\n" + + " { res->insert(*_pos); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* subtract(std::set<_T>* a, vector<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " for (std::set<_T>::iterator _pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos,b)) { }\n" + + " else\n" + + " { res->insert(*_pos); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static string subtract(string a, string b)\n" + + " { string res = \"\"; \n" + + " for (int i = 0; i < a.length(); i++)\n" + + " { if (b.find(a[i]) == string::npos) { res = res + a[i]; } }\n" + + " return res; }\n\n"; + return res; + } + + public static String generateIntersectionOp() + { String res = " public static List intersection(List a, List b)\n" + + " { List res = new Vector(); \n" + + " res.addAll(a);\n" + + " res.retainAll(b);\n" + + " return res; }\n\n"; + return res; + } + + public static String generateIntersectionOpJava6() + { String res = " public static HashSet intersection(HashSet a, Collection b)\n" + + " { HashSet res = new HashSet(); \n" + + " res.addAll(a);\n" + + " res.retainAll(b);\n" + + " return res; }\n\n" + + " public static ArrayList intersection(ArrayList a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a);\n" + + " res.retainAll(b);\n" + + " return res; }\n\n"; + return res; // shouldn't it always be a set? + } + + public static String generateIntersectionOpJava7() + { String res = " public static HashSet intersection(HashSet a, Collection b)\n" + + " { HashSet res = new HashSet(); \n" + + " res.addAll(a);\n" + + " res.retainAll(b);\n" + + " return res; }\n\n" + + " public static TreeSet intersection(TreeSet a, Collection b)\n" + + " { TreeSet res = new TreeSet(); \n" + + " res.addAll(a);\n" + + " res.retainAll(b);\n" + + " return res; }\n\n" + + " public static ArrayList intersection(ArrayList a, Collection b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a);\n" + + " res.retainAll(b);\n" + + " return res; }\n\n"; + return res; // shouldn't it always be a set? + } // TreeSet version is valid? + + public static String generateIntersectionOpCSharp() + { String res = " public static ArrayList intersection(ArrayList a, ArrayList b)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { if (a[i] != null && b.Contains(a[i])) { res.Add(a[i]); } }\n" + + " return res; }\n\n"; + return res; + } + + public static String generateIntersectionOpCPP() + { String res = " static std::set<_T>* intersection(std::set<_T>* a, std::set<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " for (std::set<_T>::iterator _pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos, b))\n" + + " { res->insert(*_pos); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* intersection(std::set<_T>* a, vector<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " for (std::set<_T>::iterator _pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos, b))\n" + + " { res->insert(*_pos); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* intersection(vector<_T>* a, std::set<_T>* b)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*a)[i], b))\n" + + " { res->push_back((*a)[i]); }\n" + + " } \n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* intersection(vector<_T>* a, vector<_T>* b)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*a)[i], b))\n" + + " { res->push_back((*a)[i]); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + return res; + } // use the standard library op for sets. + + public static String generateIntersectAllOp() // for s->intersectAll(e) + { String res = " public static List intersectAll(List se)\n" + + " { List res = new Vector(); \n" + + " if (se.size() == 0) { return res; }\n" + + " res.addAll((List) se.get(0));\n" + + " for (int i = 1; i < se.size(); i++)\n" + + " { res.retainAll((List) se.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateIntersectAllOpJava6() // for s->intersectAll(e) + { String res = " public static HashSet intersectAll(Collection se)\n" + + " { HashSet res = new HashSet(); \n" + + " if (se.size() == 0) { return res; }\n" + + " res.addAll((Collection) Set.any(se));\n" + + " for (Object _o : se)\n" + + " { res.retainAll((Collection) _o); }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateIntersectAllOpJava7() // for s->intersectAll(e) + { String res = " public static HashSet intersectAll(Collection> se)\n" + + " { HashSet res = new HashSet(); \n" + + " if (se.size() == 0) { return res; }\n" + + " res.addAll((Collection) Ocl.any(se));\n" + + " for (Collection _o : se)\n" + + " { res.retainAll(_o); }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateIntersectAllOpCSharp() // for s->intersectAll(e) + { String res = " public static ArrayList intersectAll(ArrayList se)\n" + + " { ArrayList res = new ArrayList(); \n" + + " if (se.Count == 0) { return res; }\n" + + " res.AddRange((ArrayList) se[0]);\n" + + " for (int i = 1; i < se.Count; i++)\n" + + " { res = SystemTypes.intersection(res,(ArrayList) se[i]); }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateIntersectAllOpCPP() // for s->intersectAll(e) + { String res = " static std::set<_T>* intersectAll(std::set*>* se)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " std::set*>::iterator _pos = se->begin();\n" + + " std::set<_T>* frst = *_pos;\n" + + " res->insert(frst->begin(), frst->end());\n" + + " ++_pos; \n" + + " for (; _pos != se->end(); ++_pos)\n" + + " { res = UmlRsdsLib<_T>::intersection(res, *_pos); }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* intersectAll(std::set*>* se)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " std::set*>::iterator _pos = se->begin();\n" + + " vector<_T>* frst = *_pos;\n" + + " res->insert(frst->begin(), frst->end());\n" + + " ++_pos; \n" + + " for (; _pos != se->end(); ++_pos)\n" + + " { res = UmlRsdsLib<_T>::intersection(res, *_pos); }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* intersectAll(vector*>* se)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " std::set<_T>* frst = (*se)[0];\n" + + " res->insert(frst->begin(), frst->end());\n" + + " for (int i = 1; i < se->size(); ++i)\n" + + " { res = UmlRsdsLib<_T>::intersection(res, (*se)[i]); }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* intersectAll(vector*>* se)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " vector<_T>* frst = (*se)[0];\n" + + " res->insert(res->end(), frst->begin(), frst->end());\n" + + " for (int i = 1; i < se->size(); ++i)\n" + + " { res = UmlRsdsLib<_T>::intersection(res, (*se)[i]); }\n" + + " return res;\n" + + " }\n\n"; + return res; + } // and other possibilities + + public static String generateUnionAllOp() // for s->unionAll(e) + { String res = " public static List unionAll(List se)\n" + + " { List res = new Vector(); \n" + + " for (int i = 0; i < se.size(); i++)\n" + + " { List b = (List) se.get(i); \n" + + " for (int j = 0; j < b.size(); j++)\n" + + " { Object y = b.get(j); \n" + + " if (y == null || res.contains(y)) { } else { res.add(y); } \n" + + " }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static HashMap unionAllMap(List se)\n" + + " { HashMap res = new HashMap(); \n" + + " for (int i = 0; i < se.size(); i++)\n" + + " { Map b = (Map) se.get(i); \n" + + " res.putAll(b);\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } // and eliminate duplicates + + public static String generateUnionAllOpJava6() // for s->unionAll(e) + { String res = " public static HashSet unionAll(Collection se)\n" + + " { HashSet res = new HashSet(); \n" + + " for (Object _o : se)\n" + + " { Collection b = (Collection) _o; \n" + + " res.addAll(b);\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static HashMap unionAllMap(Collection se)\n" + + " { HashMap res = new HashMap(); \n" + + " for (Object _o : se)\n" + + " { res.putAll((Map) _o); }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } // and eliminate duplicates + + public static String generateUnionAllOpJava7() // for s->unionAll(e) + { String res = " public static HashSet unionAll(Collection se)\n" + + " { HashSet res = new HashSet(); \n" + + " for (Object _o : se)\n" + + " { res.addAll((Collection) _o); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static HashMap unionAllMap(Collection se)\n" + + " { HashMap res = new HashMap(); \n" + + " for (Object _o : se)\n" + + " { res.putAll((Map) _o); }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } // Should be typed. Need to cast result to correct type. + + public static String generateUnionAllOpCSharp() // for s->unionAll(e) + { String res = " public static ArrayList unionAll(ArrayList se)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < se.Count; i++)\n" + + " { ArrayList b = (ArrayList) se[i]; \n" + + " for (int j = 0; j < b.Count; j++)\n" + + " { if (b[j] == null || res.Contains(b[j])) { } else { res.Add(b[j]); } }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static Hashtable unionAllMap(ArrayList se)\n" + + " { Hashtable res = new Hashtable(); \n" + + " for (int i = 0; i < se.Count; i++)\n" + + " { Hashtable b = (Hashtable) se[i]; \n" + + " res = SystemTypes.unionMap(res,b); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static Hashtable intersectionAllMap(ArrayList se)\n" + + " { Hashtable res = (Hashtable) se[0]; \n" + + " for (int i = 1; i < se.Count; i++)\n" + + " { Hashtable b = (Hashtable) se[i]; \n" + + " res = SystemTypes.intersectionMap(res,b); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } // and eliminate duplicates + + public static String generateUnionAllOpCPP() // for s->unionAll(e) + { String res = " static std::set<_T>* unionAll(std::set*>* se)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " std::set*>::iterator _pos;\n" + + " for (_pos = se->begin(); _pos != se->end(); ++_pos)\n" + + " { res = UmlRsdsLib<_T>::unionSet(res, *_pos); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " static std::set<_T>* unionAll(std::set*>* se)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " std::set*>::iterator _pos;\n" + + " for (_pos = se->begin(); _pos != se->end(); ++_pos)\n" + + " { res = UmlRsdsLib<_T>::unionSet(res, *_pos); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " static std::set<_T>* unionAll(vector*>* se)\n" + + " { std::set<_T>* res = new std::set<_T>(); \n" + + " if (se->size() == 0) { return res; }\n" + + " for (int i = 0; i < se->size(); ++i)\n" + + " { res = UmlRsdsLib<_T>::unionSet(res, (*se)[i]); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " static std::map* unionAllMap(vector*>* se)\n" + + " { std::map* res = new std::map();\n" + + " if (se->size() == 0) { return res; }\n" + + " for (int i = 0; i < se->size(); ++i)\n" + + " { res = UmlRsdsLib<_T>::unionMap(res, (*se)[i]); }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } // vector is concatenateAll + + public static String generateReverseOp() + { String res = " public static List reverse(List a)\n" + + " { List res = new Vector(); \n" + + " for (int i = a.size() - 1; i >= 0; i--)\n" + + " { res.add(a.get(i)); } \n" + + " return res;\n" + + " }\n\n" + + " public static String reverse(String a)\n" + + " { String res = \"\"; \n" + + " for (int i = a.length() - 1; i >= 0; i--)\n" + + " { res = res + a.charAt(i); } \n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateReverseOpJava6() + { String res = " public static ArrayList reverse(Collection a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a); \n" + + " Collections.reverse(res); \n" + + " return res;\n" + + " }\n\n" + + " public static String reverse(String a)\n" + + " { String res = \"\"; \n" + + " for (int i = a.length() - 1; i >= 0; i--)\n" + + " { res = res + a.charAt(i); } \n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateReverseOpJava7() + { String res = " public static ArrayList reverse(Collection a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(a); Collections.reverse(res); \n" + + " return res;\n" + + " }\n\n" + + " public static String reverse(String a)\n" + + " { String res = \"\"; \n" + + " for (int i = a.length() - 1; i >= 0; i--)\n" + + " { res = res + a.charAt(i); } \n" + + " return res;\n" + + " }\n\n"; + return res; + } // cast to correct type. + + public static String generateReverseOpCSharp() + { String res = " public static ArrayList reverse(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.AddRange(a); \n" + + " res.Reverse(); \n" + + " return res;\n" + + " }\n\n" + + " public static string reverse(string a)\n" + + " { string res = \"\"; \n" + + " for (int i = a.Length - 1; i >= 0; i--)\n" + + " { res = res + a[i]; } \n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateReverseOpCPP() + { String res = " static vector<_T>* reverse(vector<_T>* a)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " res->insert(res->end(), a->begin(), a->end()); \n" + + " std::reverse(res->begin(), res->end()); \n" + + " return res;\n" + + " }\n\n" + + " static string reverse(string a)\n" + + " { string res(\"\"); \n" + + " for (int i = a.length() - 1; i >= 0; i--)\n" + + " { res = res + a[i]; } \n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateFrontOp() + { String res = " public static List front(List a)\n" + + " { List res = new Vector(); \n" + + " for (int i = 0; i < a.size() - 1; i++)\n" + + " { res.add(a.get(i)); } \n" + + " return res; }\n"; + return res; + } + + public static String generateFrontOpJava6() + { String res = " public static ArrayList front(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.size() - 1; i++)\n" + + " { res.add(a.get(i)); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashSet front(HashSet a)\n" + + " { HashSet res = new HashSet(); \n" + + " Object lst = null; \n" + + " for (Object x : a)\n" + + " { res.add(x); \n" + + " lst = x; \n" + + " } \n" + + " res.remove(lst);\n" + + " return res; \n" + + " }\n\n"; + + return res; + } + + public static String generateFrontOpJava7() + { String res = " public static ArrayList front(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.size() - 1; i++)\n" + + " { res.add(a.get(i)); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashSet front(HashSet a)\n" + + " { HashSet res = new HashSet();\n" + + " T lst = null;\n" + + " for (T x : a)\n" + + " { res.add(x); \n" + + " lst = x; \n" + + " } \n" + + " res.remove(lst);\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static TreeSet front(TreeSet a)\n" + + " { TreeSet res = new TreeSet();\n" + + " T lst = null;\n" + + " for (T x : a)\n" + + " { res.add(x); \n" + + " lst = x; \n" + + " } \n" + + " res.remove(lst);\n" + + " return res; \n" + + " }\n\n"; + + return res; + } + + public static String generateFrontOpCSharp() + { String res = " public static ArrayList front(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count - 1; i++)\n" + + " { res.Add(a[i]); } \n" + + " return res; }\n"; + return res; + } + + public static String generateFrontOpCPP() + { String res = + " static vector<_T>* front(vector<_T>* a)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " if (a->size() == 0) { return res; } \n" + + " auto _pos = a->end(); \n" + + " _pos--; \n" + + " res->insert(res->end(), a->begin(), _pos); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " static std::set<_T>* front(std::set<_T>* a)\n" + + " {\n" + + " std::set<_T>* res = new std::set<_T>();\n" + + " if (a->size() == 0) { return res; }\n" + + " auto _pos = a->end();\n" + + " _pos--;\n" + + " res->insert(a->begin(), _pos);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateTailOp() + { String res = " public static List tail(List a)\n" + + " { List res = new Vector(); \n" + + " for (int i = 1; i < a.size(); i++)\n" + + " { res.add(a.get(i)); } \n" + + " return res; }\n"; + return res; + } + + public static String generateTailOpJava6() + { String res = " public static ArrayList tail(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 1; i < a.size(); i++)\n" + + " { res.add(a.get(i)); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashSet tail(HashSet a)\n" + + " { HashSet res = new HashSet(); \n" + + " Object fst = null; \n" + + " for (Object x : a)\n" + + " { res.add(x); \n" + + " if (fst == null) { fst = x; }\n" + + " } \n" + + " res.remove(fst);\n" + + " return res; \n" + + " }\n\n"; + + return res; + } + + public static String generateTailOpJava7() + { String res = " public static ArrayList tail(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 1; i < a.size(); i++)\n" + + " { res.add(a.get(i)); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashSet tail(HashSet a)\n" + + " { HashSet res = new HashSet(); \n" + + " T fst = null; \n" + + " for (T x : a)\n" + + " { res.add(x); \n" + + " if (fst == null) { fst = x; }\n" + + " } \n" + + " res.remove(fst);\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static TreeSet tail(TreeSet a)\n" + + " { TreeSet res = new TreeSet(); \n" + + " T fst = null; \n" + + " for (T x : a)\n" + + " { res.add(x); \n" + + " if (fst == null) { fst = x; }\n" + + " } \n" + + " res.remove(fst);\n" + + " return res; \n" + + " }\n\n"; + + return res; + } // more efficient just to remove the first element + + public static String generateTailOpCSharp() + { String res = " public static ArrayList tail(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 1; i < a.Count; i++)\n" + + " { res.Add(a[i]); } \n" + + " return res; }\n"; + return res; + } + + public static String generateTailOpCPP() + { String res = + " static vector<_T>* tail(vector<_T>* a)\n" + + " { vector<_T>* res = new vector<_T>(); \n" + + " if (a->size() == 0) { return res; } \n" + + " auto _pos = a->begin(); \n" + + " _pos++; \n" + + " res->insert(res->end(), _pos, a->end()); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " static std::set<_T>* tail(std::set<_T>* a)\n" + + " {\n" + + " std::set<_T>* res = new std::set<_T>();\n" + + " if (a->size() == 0) { return res; }\n" + + " auto _pos = a->begin();\n" + + " _pos++;\n" + + " res->insert(_pos, a->end());\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateSumOps() + { String res = " public static int sumint(List a)\n" + + " { int sum = 0; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Integer x = (Integer) a.get(i); \n" + + " if (x != null) { sum += x.intValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static double sumdouble(List a)\n" + + " { double sum = 0.0; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Double x = (Double) a.get(i); \n" + + " if (x != null) { sum += x.doubleValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static long sumlong(List a)\n" + + " { long sum = 0; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Long x = (Long) a.get(i); \n" + + " if (x != null) { sum += x.longValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static String sumString(List a)\n" + + " { String sum = \"\"; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Object x = a.get(i); \n" + + " sum = sum + x; }\n" + + " return sum; }\n\n"; + res = res + " public static int sumint(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumint(range); }\n\n"; + res = res + " public static double sumdouble(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumdouble(range); }\n\n"; + res = res + " public static long sumlong(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumlong(range); }\n\n"; + res = res + " public static String sumString(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumString(range); }\n\n"; + return res; + } + + + public static String generatePrdOps() + { String res = " public static int prdint(List a)\n" + + " { int res = 1; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Integer x = (Integer) a.get(i); \n" + + " if (x != null) { res *= x.intValue(); }\n" + + " } \n" + + " return res; }\n\n"; + res = res + " public static double prddouble(List a)\n" + + " { double res = 1; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Double x = (Double) a.get(i); \n" + + " if (x != null) { res *= x.doubleValue(); }\n" + + " } \n" + + " return res; }\n\n"; + res = res + " public static long prdlong(List a)\n" + + " { long res = 1; \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Long x = (Long) a.get(i); \n" + + " if (x != null) { res *= x.longValue(); }\n" + + " }\n" + + " return res; }\n\n"; + res = res + " public static int prdint(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return prdint(range); }\n\n"; + res = res + " public static double prddouble(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return prddouble(range); }\n\n"; + res = res + " public static long prdlong(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return prdlong(range); }\n\n"; + return res; + } + + + public static String generateSumOpsJava6() + { String res = " public static int sumint(Collection a)\n" + + " { int sum = 0; \n" + + " for (Object _o : a)\n" + + " { Integer x = (Integer) _o; \n" + + " if (x != null) { sum += x.intValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static double sumdouble(Collection a)\n" + + " { double sum = 0.0; \n" + + " for (Object _o : a)\n" + + " { Double x = (Double) _o; \n" + + " if (x != null) { sum += x.doubleValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static long sumlong(Collection a)\n" + + " { long sum = 0; \n" + + " for (Object _o : a)\n" + + " { Long x = (Long) _o; \n" + + " if (x != null) { sum += x.longValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static String sumString(Collection a)\n" + + " { String sum = \"\"; \n" + + " for (Object x : a)\n" + + " { sum = sum + x; }\n" + + " return sum; }\n\n"; + return res; + } // and for maps + + public static String generatePrdOpsJava6() + { String res = " public static int prdint(Collection a)\n" + + " { int prd = 1; \n" + + " for (Object _o : a)\n" + + " { Integer x = (Integer) _o; \n" + + " if (x != null) { prd *= x.intValue(); }\n" + + " } \n" + + " return prd; }\n\n"; + res = res + " public static double prddouble(Collection a)\n" + + " { double prd = 1; \n" + + " for (Object _o : a)\n" + + " { Double x = (Double) _o; \n" + + " if (x != null) { prd *= x.doubleValue(); }\n" + + " } \n" + + " return prd; }\n\n"; + res = res + " public static long prdlong(Collection a)\n" + + " { long prd = 1; \n" + + " for (Object _o : a)\n" + + " { Long x = (Long) _o; \n" + + " if (x != null) { prd *= x.longValue(); }\n" + + " } \n" + + " return prd; }\n\n"; + return res; + } // maps + + + public static String generateSumOpsJava7() + { String res = " public static int sumint(Collection a)\n" + + " { int sum = 0; \n" + + " for (Integer x : a)\n" + + " { if (x != null) { sum += x.intValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static double sumdouble(Collection a)\n" + + " { double sum = 0.0; \n" + + " for (Double x : a)\n" + + " { if (x != null) { sum += x.doubleValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static long sumlong(Collection a)\n" + + " { long sum = 0; \n" + + " for (Long x : a)\n" + + " { if (x != null) { sum += x.longValue(); }\n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static String sumString(Collection a)\n" + + " { String sum = \"\"; \n" + + " for (String x : a)\n" + + " { sum = sum + x; }\n" + + " return sum; }\n\n"; + return res; + } // maps + + public static String generatePrdOpsJava7() + { String res = " public static int prdint(Collection a)\n" + + " { int prd = 1; \n" + + " for (Integer x : a)\n" + + " { if (x != null) { prd *= x.intValue(); }\n" + + " } \n" + + " return prd; }\n\n"; + res = res + " public static double prddouble(Collection a)\n" + + " { double prd = 1; \n" + + " for (Double x : a)\n" + + " { if (x != null) { prd *= x.doubleValue(); }\n" + + " } \n" + + " return prd; }\n\n"; + res = res + " public static long prdlong(Collection a)\n" + + " { long prd = 1; \n" + + " for (Long x : a)\n" + + " { if (x != null) { prd *= x.longValue(); }\n" + + " } \n" + + " return prd; }\n\n"; + return res; + } // maps + + + public static String generateSumOpsCSharp() + { String res = " public static int sumint(ArrayList a)\n" + + " { int sum = 0; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { int x = (int) a[i]; \n" + + " sum += x; \n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static double sumdouble(ArrayList a)\n" + + " { double sum = 0.0; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { double x = double.Parse(\"\" + a[i]); \n" + + " sum += x; \n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static long sumlong(ArrayList a)\n" + + " { long sum = 0; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { long x = (long) a[i]; \n" + + " sum += x; \n" + + " } \n" + + " return sum; }\n\n"; + res = res + " public static string sumString(ArrayList a)\n" + + " { string sum = \"\"; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { object x = a[i]; \n" + + " sum = sum + x; }\n" + + " return sum; }\n\n"; + return res; + } // maps + + public static String generatePrdOpsCSharp() + { String res = " public static int prdint(ArrayList a)\n" + + " { int _prd = 1; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { int x = (int) a[i]; \n" + + " _prd *= x; \n" + + " } \n" + + " return _prd; }\n\n"; + res = res + " public static double prddouble(ArrayList a)\n" + + " { double _prd = 1; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { double x = (double) a[i]; \n" + + " _prd *= x; \n" + + " } \n" + + " return _prd; }\n\n"; + res = res + " public static long prdlong(ArrayList a)\n" + + " { long _prd = 1; \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { long x = (long) a[i]; \n" + + " _prd *= x;\n" + + " } \n" + + " return _prd; }\n\n"; + return res; + } // maps + + public static String generateSumOpsCPP() + { String res = " static string sumString(vector* a)\n" + + " { string _sum(\"\"); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { _sum.append( (*a)[i] ); }\n" + + " return _sum; }\n\n"; + res = res + " static string sumString(std::set* a)\n" + + " { string _sum(\"\"); \n" + + " std::set::iterator _pos;\n" + + " for (_pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { _sum.append( *_pos ); }\n" + + " return _sum; }\n\n"; + res = res + " static _T sum(vector<_T>* a)\n" + + " { _T _sum(0); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { _sum += (*a)[i]; }\n" + + " return _sum; }\n\n"; + res = res + " static _T sum(std::set<_T>* a)\n" + + " { _T _sum(0); \n" + + " std::set<_T>::iterator _pos;\n" + + " for (_pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { _sum += *_pos; }\n" + + " return _sum; }\n\n"; + return res; + } // maps + + public static String generatePrdOpsCPP() + { String res = " static _T prd(vector<_T>* a)\n" + + " { _T _prd(1); \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { _prd *= (*a)[i]; }\n" + + " return _prd; }\n\n"; + res = res + " static _T prd(std::set<_T>* a)\n" + + " { _T _prd(1); \n" + + " std::set<_T>::iterator _pos;\n" + + " for (_pos = a->begin(); _pos != a->end(); ++_pos)\n" + + " { _prd *= *_pos; }\n" + + " return _prd; }\n\n"; + return res; + } // maps + + public static String generateClosureOps(Vector assocs) + { String res = ""; + for (int i = 0; i < assocs.size(); i++) + { Association ast = (Association) assocs.get(i); + String closureops = ast.generateClosureOperation(); + res = res + closureops; + } + return res; + } + + public static String generateClosureOpsJava6(Vector assocs) + { String res = ""; + for (int i = 0; i < assocs.size(); i++) + { Association ast = (Association) assocs.get(i); + String closureops = ast.generateClosureOperationJava6(); + res = res + closureops; + } + return res; + } + + public static String generateClosureOpsJava7(Vector assocs) + { String res = ""; + for (int i = 0; i < assocs.size(); i++) + { Association ast = (Association) assocs.get(i); + String closureops = ast.generateClosureOperationJava7(); + res = res + closureops; + } + return res; + } + + public static String generateClosureOpsCSharp(Vector assocs) + { String res = ""; + for (int i = 0; i < assocs.size(); i++) + { Association ast = (Association) assocs.get(i); + String closureops = ast.generateClosureOperationCSharp(); + res = res + closureops; + } + return res; + } + + public static String generateClosureOpsCPP(Vector assocs) + { String res = ""; + for (int i = 0; i < assocs.size(); i++) + { Association ast = (Association) assocs.get(i); + String closureops = ast.generateClosureOperationCPP(); + res = res + closureops; + } + return res; + } + + + public static String generateAsSetOp() + { String res = " public static List asSet(List a)\n" + + " { Vector res = new Vector(); \n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Object obj = a.get(i);\n" + + " if (res.contains(obj)) { } \n" + + " else { res.add(obj); }\n" + + " } \n" + + " return res; \n" + + " }\n\n"; + res = res + " public static List asOrderedSet(List a)\n" + + " { return asSet(a); }\n\n"; + res = res + " public static List asSet(Map m)\n" + + " { Vector range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return asSet(range);\n" + + " }\n\n"; + + res = res + + " public static Vector mapAsSequence(Map m)\n" + + " { Vector range = new Vector();\n" + + " java.util.Set ss = m.entrySet();\n" + + " for (Object x : ss)\n" + + " { Map.Entry ee = (Map.Entry) x;\n" + + " HashMap mx = new HashMap(); \n" + + " mx.put(ee.getKey(), ee.getValue());\n" + + " range.add(mx); \n" + + " } \n" + + " return range;\n" + + " }\n\n"; + + res = res + + " public static Vector mapAsSet(Map m)\n" + + " { Vector range = mapAsSequence(m); \n" + + " return (Vector) asSet(range); \n" + + " }\n\n"; + + return res; + } + + public static String generateAsSetOpCSharp() + { String res = " public static ArrayList asSet(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { object obj = a[i];\n" + + " if (res.Contains(obj)) { } \n" + + " else { res.Add(obj); }\n" + + " } \n" + + " return res; \n" + + " }\n\n"; + res = res + " public static ArrayList asOrderedSet(ArrayList a)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { object obj = a[i];\n" + + " if (res.Contains(obj)) { } \n" + + " else { res.Add(obj); }\n" + + " } \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static T[] asReference(ArrayList sq, T[] r)\n" + + " {\n" + + " for (int i = 0; i < sq.Count && i < r.Length; i++)\n" + + " { r[i] = (T) sq[i]; }\n" + + " return r;\n" + + " }\n\n"; + + res = res + + " public static ArrayList asSequence(T[] r)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < r.Length; i++)\n" + + " { res.Add(r[i]); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList asSequence(Hashtable m)\n" + + " { ArrayList res = new ArrayList();\n" + + " foreach (DictionaryEntry pair in m)\n" + + " { object key = pair.Key;\n" + + " Hashtable maplet = new Hashtable();\n" + + " maplet[key] = pair.Value;\n" + + " res.Add(maplet);\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } // and map as a set + + public static String refOps() + { String res = ""; + res = " public static T[] asReference(Vector sq, T[] r)\n" + + " {\n" + + " for (int i = 0; i < sq.size() && i < r.length; i++)\n" + + " { r[i] = (T) sq.get(i); }\n" + + " return r;\n" + + " }\n\n"; + + res = res + " public static int[] resizeTo(int[] arr, int n)\n" + + " { int[] tmp = new int[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static long[] resizeTo(long[] arr, int n)\n" + + " { long[] tmp = new long[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static double[] resizeTo(double[] arr, int n)\n" + + " { double[] tmp = new double[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static boolean[] resizeTo(boolean[] arr, int n)\n" + + " { boolean[] tmp = new boolean[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static Object[] resizeTo(Object[] arr, int n)\n" + + " { Object[] tmp = new Object[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + + " public static Vector sequenceRange(int[] arr, int n)\n" + + " { Vector res = new Vector();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Integer(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static Vector sequenceRange(long[] arr, int n)\n" + + " { Vector res = new Vector();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Long(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static Vector sequenceRange(double[] arr, int n)\n" + + " { Vector res = new Vector();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Double(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static Vector sequenceRange(boolean[] arr, int n)\n" + + " { Vector res = new Vector();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Boolean(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static Vector asSequence(T[] r)\n" + + " { Vector res = new Vector(); \n" + + " for (int i = 0; i < r.length; i++)\n" + + " { res.add(r[i]); }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + + public static String refOpsJava6() + { String res = ""; + res = " public static T[] asReference(ArrayList sq, T[] r)\n" + + " {\n" + + " for (int i = 0; i < sq.size() && i < r.length; i++)\n" + + " { r[i] = (T) sq.get(i); }\n" + + " return r;\n" + + " }\n\n"; + + res = res + " public static int[] resizeTo(int[] arr, int n)\n" + + " { int[] tmp = new int[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static long[] resizeTo(long[] arr, int n)\n" + + " { long[] tmp = new long[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static double[] resizeTo(double[] arr, int n)\n" + + " { double[] tmp = new double[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static boolean[] resizeTo(boolean[] arr, int n)\n" + + " { boolean[] tmp = new boolean[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + " public static Object[] resizeTo(Object[] arr, int n)\n" + + " { Object[] tmp = new Object[n];\n" + + " for (int i = 0; i < n; i++)\n" + + " { tmp[i] = arr[i]; }\n" + + " return tmp;\n" + + " }\n\n"; + + res = res + + " public static ArrayList sequenceRange(int[] arr, int n)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Integer(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList sequenceRange(long[] arr, int n)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Long(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList sequenceRange(double[] arr, int n)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Double(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList sequenceRange(boolean[] arr, int n)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < n && i < arr.length; i++)\n" + + " { res.add(new Boolean(arr[i])); }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList asSequence(T[] r)\n" + + " { ArrayList res = new ArrayList(); \n" + + " for (int i = 0; i < r.length; i++)\n" + + " { res.add(r[i]); }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + + public static String generateSortOp() + { String res = " public static List sort(final List a)\n" + + " { int i = a.size()-1;\n" + + " return mergeSort(a,0,i);\n" + + " }\n\n"; + res = res + + " public static List asSequence(final List a)\n" + + " { return a; }\n\n"; + res = res + + " public static List asBag(final List a)\n" + + " { int i = a.size()-1;\n" + + " return mergeSort(a,0,i);\n" + + " }\n\n"; + res = res + + " static List mergeSort(final List a, int ind1, int ind2)\n" + + " { List res = new Vector();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.add(a.get(ind1));\n" + + " return res;\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " List a1;\n" + + " List a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new Vector();\n" + + " a1.add(a.get(ind1));\n" + + " a2 = mergeSort(a,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSort(a,ind1,mid-1);\n" + + " a2 = mergeSort(a,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.size() && j < a2.size())\n" + + " { Comparable e1 = (Comparable) a1.get(i); \n" + + " Comparable e2 = (Comparable) a2.get(j);\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(e1);\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.add(e2);\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.size())\n" + + " { for (int k = j; k < a2.size(); k++)\n" + + " { res.add(a2.get(k)); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.size(); k++) \n" + + " { res.add(a1.get(k)); } \n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + /* public static String generateSortOpJava6() // Not needed -- uses Collections.sort instead. + { String res = " public static ArrayList sort(final ArrayList a)\n" + + " { int i = a.size()-1;\n" + + " return mergeSort(a,0,i);\n" + + " }\n\n" + + " public static ArrayList sort(final HashSet a)\n" + + " { ArrayList b = new ArrayList(); \n" + + " b.addAll(a); \n" + + " int i = b.size()-1;\n" + + " return mergeSort(b,0,i);\n" + + " }\n\n" + + " static ArrayList mergeSort(final ArrayList a, int ind1, int ind2)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.add(a.get(ind1));\n" + + " return res;\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " ArrayList a1;\n" + + " ArrayList a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new ArrayList();\n" + + " a1.add(a.get(ind1));\n" + + " a2 = mergeSort(a,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSort(a,ind1,mid-1);\n" + + " a2 = mergeSort(a,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.size() && j < a2.size())\n" + + " { Comparable e1 = (Comparable) a1.get(i); \n" + + " Comparable e2 = (Comparable) a2.get(j);\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(e1);\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.add(e2);\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.size())\n" + + " { for (int k = j; k < a2.size(); k++)\n" + + " { res.add(a2.get(k)); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.size(); k++) \n" + + " { res.add(a1.get(k)); } \n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } */ + + + public static String generateSortOpJava6() + { String res = " public static ArrayList sort(Collection a)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(a);\n" + + " Collections.sort(res);\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateSortOpJava7() + { String res = + " public static TreeSet sortSet(HashSet col)\n" + + " { TreeSet res = new TreeSet();\n" + + " res.addAll(col); \n" + + " return res; \n" + + " }\n\n" + + " public static ArrayList sort(Collection a)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(a);\n" + + " Collections.sort(res);\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateSortOpCSharp() + { String res = " public static ArrayList sort(ArrayList a)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.AddRange(a);\n" + + " res.Sort();\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateAsBagOpCSharp() + { String res = " public static ArrayList asBag(ArrayList a)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.AddRange(a);\n" + + " res.Sort();\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateSortOpCPP() + { String res = " static vector<_T>* sort(vector<_T>* a)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), a->begin(), a->end());\n" + + " std::sort(res->begin(), res->end());\n" + + " return res;\n" + + " }\n\n"; + res = res + " static vector<_T>* sort(std::set<_T>* a)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), a->begin(), a->end());\n" + + " std::sort(res->begin(), res->end());\n" + + " return res;\n" + + " }\n\n"; + + res = res + " static vector<_T>* sort(vector<_T>* a, std::function f)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), a->begin(), a->end());\n" + + " std::sort(res->begin(), res->end(), f);\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* sort(std::set<_T>* a, std::function f)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), a->begin(), a->end());\n" + + " std::sort(res->begin(), res->end(), f);\n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateSortByOp() + { String res = " public static List sortedBy(final List a, List f)\n" + + " { int i = a.size()-1;\n" + + " java.util.Map f_map = new java.util.HashMap();\n" + + " for (int j = 0; j < a.size(); j++)\n" + + " { f_map.put(a.get(j), f.get(j)); }\n" + + " return mergeSort(a,f_map,0,i);\n" + + " }\n\n" + + " static List mergeSort(final List a, java.util.Map f, int ind1, int ind2)\n" + + " { List res = new Vector();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.add(a.get(ind1));\n" + + " return res;\n" + + " }\n" + + " if (ind2 == ind1 + 1)\n" + + " { Comparable e1 = (Comparable) f.get(a.get(ind1)); \n" + + " Comparable e2 = (Comparable) f.get(a.get(ind2));\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(a.get(ind1)); res.add(a.get(ind2)); return res; }\n" + + " else \n" + + " { res.add(a.get(ind2)); res.add(a.get(ind1)); return res; }\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " List a1;\n" + + " List a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new Vector();\n" + + " a1.add(a.get(ind1));\n" + + " a2 = mergeSort(a,f,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSort(a,f,ind1,mid-1);\n" + + " a2 = mergeSort(a,f,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.size() && j < a2.size())\n" + + " { Comparable e1 = (Comparable) f.get(a1.get(i)); \n" + + " Comparable e2 = (Comparable) f.get(a2.get(j));\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(a1.get(i));\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.add(a2.get(j));\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.size())\n" + + " { for (int k = j; k < a2.size(); k++)\n" + + " { res.add(a2.get(k)); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.size(); k++) \n" + + " { res.add(a1.get(k)); } \n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateSortByOpJava6() + { String res = " public static ArrayList sortedBy(final ArrayList a, ArrayList f)\n" + + " { int i = a.size()-1;\n" + + " java.util.Map f_map = new java.util.HashMap();\n" + + " for (int j = 0; j < a.size(); j++)\n" + + " { f_map.put(a.get(j), f.get(j)); }\n" + + " return mergeSort(a,f_map,0,i);\n" + + " }\n\n" + + " static ArrayList mergeSort(final ArrayList a, java.util.Map f, int ind1, int ind2)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.add(a.get(ind1));\n" + + " return res;\n" + + " }\n" + + " if (ind2 == ind1 + 1)\n" + + " { Comparable e1 = (Comparable) f.get(a.get(ind1)); \n" + + " Comparable e2 = (Comparable) f.get(a.get(ind2));\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(a.get(ind1)); res.add(a.get(ind2)); return res; }\n" + + " else \n" + + " { res.add(a.get(ind2)); res.add(a.get(ind1)); return res; }\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " ArrayList a1;\n" + + " ArrayList a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new ArrayList();\n" + + " a1.add(a.get(ind1));\n" + + " a2 = mergeSort(a,f,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSort(a,f,ind1,mid-1);\n" + + " a2 = mergeSort(a,f,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.size() && j < a2.size())\n" + + " { Comparable e1 = (Comparable) f.get(a1.get(i)); \n" + + " Comparable e2 = (Comparable) f.get(a2.get(j));\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(a1.get(i));\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.add(a2.get(j));\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.size())\n" + + " { for (int k = j; k < a2.size(); k++)\n" + + " { res.add(a2.get(k)); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.size(); k++) \n" + + " { res.add(a1.get(k)); } \n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateSortByOpJava7() + { String res = " public static ArrayList sortedBy(final ArrayList a, ArrayList f)\n" + + " { int i = a.size()-1;\n" + + " if (i < 0) { return a; } \n\n" + + " if (f.get(i) instanceof Comparable)\n" + + " { java.util.Map f_map = new java.util.HashMap();\n" + + " for (int j = 0; j < a.size(); j++)\n" + + " { f_map.put(a.get(j), (Comparable) f.get(j)); }\n" + + " return mergeSort(a,f_map,0,i);\n" + + " } \n\n" + + " if (f.get(i) instanceof List)\n" + + " { java.util.Map list_map = new java.util.HashMap();\n" + + " for (int j = 0; j < a.size(); j++)\n" + + " { list_map.put(a.get(j), (List) f.get(j)); }\n" + + " return mergeSortSequence(a, list_map, 0, i);\n" + + " } \n\n" + + " return a;\n" + + " }\n\n" + + " static ArrayList mergeSort(final ArrayList a, java.util.Map f, int ind1, int ind2)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.add(a.get(ind1));\n" + + " return res;\n" + + " }\n" + + " if (ind2 == ind1 + 1)\n" + + " { Comparable e1 = (Comparable) f.get(a.get(ind1)); \n" + + " Comparable e2 = (Comparable) f.get(a.get(ind2));\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(a.get(ind1)); res.add(a.get(ind2)); return res; }\n" + + " else \n" + + " { res.add(a.get(ind2)); res.add(a.get(ind1)); return res; }\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " ArrayList a1;\n" + + " ArrayList a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new ArrayList();\n" + + " a1.add(a.get(ind1));\n" + + " a2 = mergeSort(a,f,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSort(a,f,ind1,mid-1);\n" + + " a2 = mergeSort(a,f,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.size() && j < a2.size())\n" + + " { Comparable e1 = (Comparable) f.get(a1.get(i)); \n" + + " Comparable e2 = (Comparable) f.get(a2.get(j));\n" + + " if (e1.compareTo(e2) < 0) // e1 < e2\n" + + " { res.add(a1.get(i));\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.add(a2.get(j));\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.size())\n" + + " { for (int k = j; k < a2.size(); k++)\n" + + " { res.add(a2.get(k)); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.size(); k++) \n" + + " { res.add(a1.get(k)); } \n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " static ArrayList mergeSortSequence(final ArrayList a, java.util.Map f, int ind1, int ind2)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.add(a.get(ind1));\n" + + " return res;\n" + + " }\n" + + " if (ind2 == ind1 + 1)\n" + + " { List e1 = (List) f.get(a.get(ind1)); \n" + + " List e2 = (List) f.get(a.get(ind2));\n" + + " if (Ocl.sequenceCompare(e1,e2) < 0) // e1 < e2\n" + + " { res.add(a.get(ind1)); res.add(a.get(ind2)); return res; }\n" + + " else \n" + + " { res.add(a.get(ind2)); res.add(a.get(ind1)); return res; }\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " ArrayList a1;\n" + + " ArrayList a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new ArrayList();\n" + + " a1.add(a.get(ind1));\n" + + " a2 = mergeSortSequence(a,f,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSortSequence(a,f,ind1,mid-1);\n" + + " a2 = mergeSortSequence(a,f,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.size() && j < a2.size())\n" + + " { List e1 = (List) f.get(a1.get(i)); \n" + + " List e2 = (List) f.get(a2.get(j));\n" + + " if (Ocl.sequenceCompare(e1,e2) < 0) // e1 < e2\n" + + " { res.add(a1.get(i));\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.add(a2.get(j));\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.size())\n" + + " { for (int k = j; k < a2.size(); k++)\n" + + " { res.add(a2.get(k)); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.size(); k++) \n" + + " { res.add(a1.get(k)); } \n" + + " } \n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateSortByOpCSharp() + { String res = " public static ArrayList sortedBy(ArrayList a, ArrayList f)\n" + + " { int i = a.Count - 1;\n" + + " if (i < 0) { return a; }\n" + + " if (f[i] is IComparable)\n" + + " { Hashtable f_map = new Hashtable();\n" + + " for (int j = 0; j < a.Count; j++)\n" + + " { f_map[a[j]] = f[j]; }\n" + + " return mergeSort(a, f_map, 0, i);\n" + + " } \n" + + " else if (f[i] is ArrayList)\n" + + " { Hashtable f_map = new Hashtable();\n" + + " for (int j = 0; j < a.Count; j++)\n" + + " { f_map[a[j]] = f[j]; }\n" + + " return mergeSortSequence(a, f_map, 0, i);\n" + + " } \n" + + " return a;\n" + + " }\n\n" + + " static ArrayList mergeSort(ArrayList a, Hashtable f, int ind1, int ind2)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " { res.Add(a[ind1]);\n" + + " return res;\n" + + " }\n" + + " if (ind2 == ind1 + 1)\n" + + " { IComparable e1 = (IComparable) f[a[ind1]]; \n" + + " IComparable e2 = (IComparable) f[a[ind2]];\n" + + " if (e1.CompareTo(e2) < 0) // e1 < e2\n" + + " { res.Add(a[ind1]); res.Add(a[ind2]); return res; }\n" + + " else \n" + + " { res.Add(a[ind2]); res.Add(a[ind1]); return res; }\n" + + " }\n" + + " int mid = (ind1 + ind2)/2;\n" + + " ArrayList a1;\n" + + " ArrayList a2;\n" + + " if (mid == ind1)\n" + + " { a1 = new ArrayList();\n" + + " a1.Add(a[ind1]);\n" + + " a2 = mergeSort(a,f,mid+1,ind2);\n" + + " }\n" + + " else\n" + + " { a1 = mergeSort(a,f,ind1,mid-1);\n" + + " a2 = mergeSort(a,f,mid,ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.Count && j < a2.Count)\n" + + " { IComparable e1 = (IComparable) f[a1[i]]; \n" + + " IComparable e2 = (IComparable) f[a2[j]];\n" + + " if (e1.CompareTo(e2) < 0) // e1 < e2\n" + + " { res.Add(a1[i]);\n" + + " i++; // get next e1\n" + + " } \n" + + " else \n" + + " { res.Add(a2[j]);\n" + + " j++; \n" + + " } \n" + + " } \n" + + " if (i == a1.Count)\n" + + " { for (int k = j; k < a2.Count; k++)\n" + + " { res.Add(a2[k]); } \n" + + " } \n" + + " else \n" + + " { for (int k = i; k < a1.Count; k++) \n" + + " { res.Add(a1[k]); } \n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " static ArrayList mergeSortSequence(ArrayList a, Hashtable f, int ind1, int ind2)\n" + + " {\n" + + " ArrayList res = new ArrayList();\n" + + " if (ind1 > ind2)\n" + + " { return res; }\n" + + " if (ind1 == ind2)\n" + + " {\n" + + " res.Add(a[ind1]);\n" + + " return res;\n" + + " }\n" + + " if (ind2 == ind1 + 1)\n" + + " {\n" + + " ArrayList e1 = (ArrayList) f[a[ind1]];\n" + + " ArrayList e2 = (ArrayList) f[a[ind2]];\n" + + " if (SystemTypes.sequenceCompare(e1, e2) < 0) // e1 < e2\n" + + " { res.Add(a[ind1]); res.Add(a[ind2]); return res; }\n" + + " else\n" + + " { res.Add(a[ind2]); res.Add(a[ind1]); return res; }\n" + + " }\n" + + " int mid = (ind1 + ind2) / 2;\n" + + " ArrayList a1;\n" + + " ArrayList a2;\n" + + " if (mid == ind1)\n" + + " {\n" + + " a1 = new ArrayList();\n" + + " a1.Add(a[ind1]);\n" + + " a2 = mergeSortSequence(a, f, mid + 1, ind2);\n" + + " }\n" + + " else\n" + + " {\n" + + " a1 = mergeSortSequence(a, f, ind1, mid - 1);\n" + + " a2 = mergeSortSequence(a, f, mid, ind2);\n" + + " }\n" + + " int i = 0;\n" + + " int j = 0;\n" + + " while (i < a1.Count && j < a2.Count)\n" + + " {\n" + + " ArrayList e1 = (ArrayList) f[a1[i]];\n" + + " ArrayList e2 = (ArrayList) f[a2[j]];\n" + + " if (SystemTypes.sequenceCompare(e1, e2) < 0) // e1 < e2\n" + + " {\n" + + " res.Add(a1[i]);\n" + + " i++; // get next e1\n" + + " }\n" + + " else\n" + + " {\n" + + " res.Add(a2[j]);\n" + + " j++;\n" + + " }\n" + + " }\n" + + " if (i == a1.Count)\n" + + " {\n" + + " for (int k = j; k < a2.Count; k++)\n" + + " { res.Add(a2[k]); }\n" + + " }\n" + + " else\n" + + " {\n" + + " for (int k = i; k < a1.Count; k++)\n" + + " { res.Add(a1[k]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + + public static String symmetricDifferenceOp() + { String res = + " public static List symmetricDifference(List a, List b)\n" + + " { List res = new Vector();\n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Object _a = a.get(i);\n" + + " if (b.contains(_a) || res.contains(_a)) { }\n" + + " else { res.add(_a); }\n" + + " }\n" + + " for (int j = 0; j < b.size(); j++)\n" + + " { Object _b = b.get(j);\n" + + " if (a.contains(_b) || res.contains(_b)) { }\n" + + " else { res.add(_b); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String symmetricDifferenceOpJava6() + { String res = + " public static HashSet symmetricDifference(Collection a, Collection b)\n" + + " { HashSet res = new HashSet();\n" + + " for (Object _a : a)\n" + + " { if (b.contains(_a)) { }\n" + + " else { res.add(_a); }\n" + + " }\n" + + " for (Object _b : b)\n" + + " { if (a.contains(_b)) { }\n" + + " else { res.add(_b); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String symmetricDifferenceOpJava7() + { String res = + " public static Set symmetricDifference(Collection a, Collection b)\n" + + " { Set res = new HashSet();\n" + + " for (T _a : a)\n" + + " { if (b.contains(_a)) { }\n" + + " else { res.add(_a); }\n" + + " }\n" + + " for (T _b : b)\n" + + " { if (a.contains(_b)) { }\n" + + " else { res.add(_b); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String symmetricDifferenceOpCSharp() + { String res = + " public static ArrayList symmetricDifference(ArrayList a, ArrayList b)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { object _a = a[i];\n" + + " if (b.Contains(_a) || res.Contains(_a)) { }\n" + + " else { res.Add(_a); }\n" + + " }\n" + + " for (int j = 0; j < b.Count; j++)\n" + + " { object _b = b[j];\n" + + " if (a.Contains(_b) || res.Contains(_b)) { }\n" + + " else { res.Add(_b); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String maximalElementsOp() + { String res = + " public static Vector maximalElements(List s, List v)\n" + + " { Vector res = new Vector();\n" + + " if (s.size() == 0) { return res; }\n" + + " Comparable largest = (Comparable) v.get(0);\n" + + " res.add(s.get(0));\n" + + " \n" + + " for (int i = 1; i < s.size(); i++)\n" + + " { Comparable next = (Comparable) v.get(i);\n" + + " if (largest.compareTo(next) < 0)\n" + + " { largest = next;\n" + + " res.clear();\n" + + " res.add(s.get(i));\n" + + " }\n" + + " else if (largest.compareTo(next) == 0)\n" + + " { res.add(s.get(i)); }\n" + + " }\n" + + " return res;\n" + + " }"; + return res; + } + + public static String maximalElementsOpJava6() + { String res = + " public static ArrayList maximalElements(ArrayList s, ArrayList v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (s.size() == 0) { return res; }\n" + + " Comparable largest = (Comparable) v.get(0);\n" + + " res.add(s.get(0));\n" + + " \n" + + " for (int i = 1; i < s.size(); i++)\n" + + " { Comparable next = (Comparable) v.get(i);\n" + + " if (largest.compareTo(next) < 0)\n" + + " { largest = next;\n" + + " res.clear();\n" + + " res.add(s.get(i));\n" + + " }\n" + + " else if (largest.compareTo(next) == 0)\n" + + " { res.add(s.get(i)); }\n" + + " }\n" + + " return res;\n" + + " }"; + return res; + } + + public static String maximalElementsOpJava7() + { String res = + " public static ArrayList maximalElements(List s, List v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (s.size() == 0) { return res; }\n" + + " Comparable largest = (Comparable) v.get(0);\n" + + " res.add(s.get(0));\n" + + " \n" + + " for (int i = 1; i < s.size(); i++)\n" + + " { Comparable next = (Comparable) v.get(i);\n" + + " if (largest.compareTo(next) < 0)\n" + + " { largest = next;\n" + + " res.clear();\n" + + " res.add(s.get(i));\n" + + " }\n" + + " else if (largest.compareTo(next) == 0)\n" + + " { res.add(s.get(i)); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeSet maximalElements(TreeSet s, List v)\n" + + " { ArrayList lst = new ArrayList();\n" + + " lst.addAll(s); \n" + + " ArrayList lres = maximalElements(lst, v);\n" + + " TreeSet res = new TreeSet(); \n" + + " res.addAll(lres); \n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String maximalElementsOpCSharp() + { String res = + " public static ArrayList maximalElements(ArrayList s, ArrayList v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (s.Count == 0) { return res; }\n" + + " IComparable largest = (IComparable) v[0];\n" + + " res.Add(s[0]);\n" + + " \n" + + " for (int i = 1; i < s.Count; i++)\n" + + " { IComparable next = (IComparable) v[i];\n" + + " if (largest.CompareTo(next) < 0)\n" + + " { largest = next;\n" + + " res.Clear();\n" + + " res.Add(s[i]);\n" + + " }\n" + + " else if (largest.CompareTo(next) == 0)\n" + + " { res.Add(s[i]); }\n" + + " }\n" + + " return res;\n" + + " }"; + return res; + } + + public static String maximalElementsOpCPP() + { String res = + " static vector<_T>* maximalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " int largest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { int next = (*v)[i];\n" + + " if (next > largest)\n" + + " { largest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (largest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* maximalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " long largest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { long next = (*v)[i];\n" + + " if (next > largest)\n" + + " { largest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (largest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* maximalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " string largest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { string next = (*v)[i];\n" + + " if (next > largest)\n" + + " { largest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (largest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* maximalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " double largest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { double next = (*v)[i];\n" + + " if (next > largest)\n" + + " { largest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (largest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + + public static String minimalElementsOp() + { String res = + " public static Vector minimalElements(List s, List v)\n" + + " { Vector res = new Vector();\n" + + " if (s.size() == 0) { return res; }\n" + + " Comparable smallest = (Comparable) v.get(0);\n" + + " res.add(s.get(0));\n" + + " \n" + + " for (int i = 1; i < s.size(); i++)\n" + + " { Comparable next = (Comparable) v.get(i);\n" + + " if (next.compareTo(smallest) < 0)\n" + + " { smallest = next;\n" + + " res.clear();\n" + + " res.add(s.get(i));\n" + + " }\n" + + " else if (smallest.compareTo(next) == 0)\n" + + " { res.add(s.get(i)); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String minimalElementsOpJava6() + { String res = + " public static ArrayList minimalElements(ArrayList s, ArrayList v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (s.size() == 0) { return res; }\n" + + " Comparable smallest = (Comparable) v.get(0);\n" + + " res.add(s.get(0));\n" + + " \n" + + " for (int i = 1; i < s.size(); i++)\n" + + " { Comparable next = (Comparable) v.get(i);\n" + + " if (next.compareTo(smallest) < 0)\n" + + " { smallest = next;\n" + + " res.clear();\n" + + " res.add(s.get(i));\n" + + " }\n" + + " else if (smallest.compareTo(next) == 0)\n" + + " { res.add(s.get(i)); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String minimalElementsOpJava7() + { String res = + " public static ArrayList minimalElements(List s, List v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (s.size() == 0) { return res; }\n" + + " Comparable smallest = (Comparable) v.get(0);\n" + + " res.add(s.get(0));\n" + + " \n" + + " for (int i = 1; i < s.size(); i++)\n" + + " { Comparable next = (Comparable) v.get(i);\n" + + " if (next.compareTo(smallest) < 0)\n" + + " { smallest = next;\n" + + " res.clear();\n" + + " res.add(s.get(i));\n" + + " }\n" + + " else if (smallest.compareTo(next) == 0)\n" + + " { res.add(s.get(i)); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeSet minimalElements(TreeSet s, List v)\n" + + " { ArrayList lst = new ArrayList();\n" + + " lst.addAll(s); \n" + + " ArrayList lres = minimalElements(lst, v);\n" + + " TreeSet res = new TreeSet(); \n" + + " res.addAll(lres); \n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String minimalElementsOpCSharp() + { String res = + " public static ArrayList minimalElements(ArrayList s, ArrayList v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (s.Count == 0) { return res; }\n" + + " IComparable smallest = (IComparable) v[0];\n" + + " res.Add(s[0]);\n" + + " \n" + + " for (int i = 1; i < s.Count; i++)\n" + + " { IComparable next = (IComparable) v[i];\n" + + " if (next.CompareTo(smallest) < 0)\n" + + " { smallest = next;\n" + + " res.Clear();\n" + + " res.Add(s[i]);\n" + + " }\n" + + " else if (smallest.CompareTo(next) == 0)\n" + + " { res.Add(s[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String minimalElementsOpCPP() + { String res = + " static vector<_T>* minimalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " int smallest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { int next = (*v)[i];\n" + + " if (next < smallest)\n" + + " { smallest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (smallest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* minimalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " long smallest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { long next = (*v)[i];\n" + + " if (next < smallest)\n" + + " { smallest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (smallest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* minimalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " string smallest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { string next = (*v)[i];\n" + + " if (next < smallest)\n" + + " { smallest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (smallest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* minimalElements(vector<_T>* s, vector* v)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (s->size() == 0) { return res; }\n" + + " double smallest = (*v)[0];\n" + + " res->push_back((*s)[0]);\n" + + " \n" + + " for (int i = 1; i < s->size(); i++)\n" + + " { double next = (*v)[i];\n" + + " if (next < smallest)\n" + + " { smallest = next;\n" + + " res->clear();\n" + + " res->push_back((*s)[i]);\n" + + " }\n" + + " else if (smallest == next)\n" + + " { res->push_back((*s)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String countOp() + { String res = + " public static int count(List l, Object obj)\n" + + " { int res = 0; \n" + + " for (int _i = 0; _i < l.size(); _i++)\n" + + " { if (obj == l.get(_i)) { res++; } \n" + + " else if (obj != null && obj.equals(l.get(_i))) { res++; } \n" + + " }\n" + + " return res; \n" + + " }\n\n"; + res = res + " public static int count(Map m, Object obj)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return count(range,obj); }\n\n"; + res = res + " public static int count(String s, String x)\n" + + " { int res = 0; \n" + + " if (\"\".equals(s)) { return res; }\n" + + " int ind = s.indexOf(x); \n" + + " if (ind == -1) { return res; }\n" + + " String ss = s.substring(ind+1,s.length());\n" + + " res++; \n" + + " while (ind >= 0)\n" + + " { ind = ss.indexOf(x); \n" + + " if (ind == -1 || ss.equals(\"\")) { return res; }\n" + + " res++; \n" + + " ss = ss.substring(ind+1,ss.length());\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String countOpJava6() + { String res = + " public static int count(Collection l, Object obj)\n" + + " { int res = 0; \n" + + " for (Object _o : l)\n" + + " { if (obj == _o) { res++; } \n" + + " else if (obj != null && obj.equals(_o)) { res++; } \n" + + " }\n" + + " return res; \n" + + " }\n\n" + + " public static int count(String s, String x)\n" + + " { int res = 0; \n" + + " if (\"\".equals(s)) { return res; }\n" + + " int ind = s.indexOf(x); \n" + + " if (ind == -1) { return res; }\n" + + " String ss = s.substring(ind+1,s.length());\n" + + " res++; \n" + + " while (ind >= 0)\n" + + " { ind = ss.indexOf(x); \n" + + " if (ind == -1 || ss.equals(\"\")) { return res; }\n" + + " res++; \n" + + " ss = ss.substring(ind+1,ss.length());\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + return res; + } // map case + + public static String countOpJava7() + { String res = + " public static int count(Collection l, T obj)\n" + + " { return Collections.frequency(l,obj); }\n\n" + + " public static int count(String s, String x)\n" + + " { int res = 0; \n" + + " if (\"\".equals(s)) { return res; }\n" + + " int ind = s.indexOf(x); \n" + + " if (ind == -1) { return res; }\n" + + " String ss = s.substring(ind+1,s.length());\n" + + " res++; \n" + + " while (ind >= 0)\n" + + " { ind = ss.indexOf(x); \n" + + " if (ind == -1 || ss.equals(\"\")) { return res; }\n" + + " res++; \n" + + " ss = ss.substring(ind+1,ss.length());\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + return res; + } // map case + + public static String countOpCSharp() + { String res = + " public static int count(ArrayList l, object obj)\n" + + " { int res = 0; \n" + + " for (int _i = 0; _i < l.Count; _i++)\n" + + " { if (obj == l[_i]) { res++; } \n" + + " else if (obj != null && obj.Equals(l[_i])) { res++; } \n" + + " }\n" + + " return res; \n" + + " }\n\n" + + " public static int count(string s, string x)\n" + + " { int res = 0; \n" + + " if (\"\".Equals(s)) { return res; }\n" + + " int ind = s.IndexOf(x); \n" + + " if (ind == -1) { return res; }\n" + + " string ss = s.Substring(ind+1,s.Length-ind-1);\n" + + " res++; \n" + + " while (ind >= 0)\n" + + " { ind = ss.IndexOf(x); \n" + + " if (ind == -1 || ss.Equals(\"\")) { return res; }\n" + + " res++; \n" + + " ss = ss.Substring(ind+1,ss.Length-ind-1);\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + return res; + } // maps + + public static String countOpCPP() + { String res = + " static int count(std::set<_T>* l, _T obj)\n" + + " { if (l->find(obj) != l->end()) { return 1; } else { return 0; } \n" + + " }\n\n" + + " static int count(vector<_T>* l, _T obj)\n" + + " { return std::count(l->begin(), l->end(), obj); }\n\n" + + " static int count(string s, string x)\n" + + " { int res = 0; \n" + + " if (s.length() == 0) { return res; }\n" + + " int ind = s.find(x); \n" + + " if (ind == string::npos) { return res; }\n" + + " string ss = s.substr(ind+1, s.length() - ind - 1);\n" + + " res++; \n" + + " while (ind != string::npos)\n" + + " { ind = ss.find(x); \n" + + " if (ind == string::npos || ss.length() == 0) { return res; }\n" + + " res++; \n" + + " ss = ss.substr(ind+1, ss.length() - ind - 1);\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + return res; + } // maps + + public static String charactersOp() + { String res = + " public static List characters(String str)\n" + + " { char[] _chars = str.toCharArray();\n" + + " Vector _res = new Vector();\n" + + " for (int i = 0; i < _chars.length; i++)\n" + + " { _res.add(\"\" + _chars[i]); }\n" + + " return _res;\n" + + " }\n\n"; + return res; + } + + public static String charactersOpJava6() + { String res = + " public static ArrayList characters(String str)\n" + + " { char[] _chars = str.toCharArray();\n" + + " ArrayList _res = new ArrayList();\n" + + " for (int i = 0; i < _chars.length; i++)\n" + + " { _res.add(\"\" + _chars[i]); }\n" + + " return _res;\n" + + " }\n\n"; + return res; + } + + public static String charactersOpJava7() + { String res = + " public static ArrayList characters(String str)\n" + + " { char[] _chars = str.toCharArray();\n" + + " ArrayList _res = new ArrayList();\n" + + " for (int i = 0; i < _chars.length; i++)\n" + + " { _res.add(\"\" + _chars[i]); }\n" + + " return _res;\n" + + " }\n\n"; + return res; + } + + public static String charactersOpCSharp() + { String res = + " public static ArrayList characters(string str)\n" + + " { ArrayList _res = new ArrayList();\n" + + " for (int i = 0; i < str.Length; i++)\n" + + " { _res.Add(\"\" + str[i]); }\n" + + " return _res;\n" + + " }\n\n"; + return res; + } + + public static String charactersOpCPP() + { String res = + " static vector* characters(string str)\n" + + " { vector* _res = new vector();\n" + + " for (int i = 0; i < str.size(); i++)\n" + + " { _res->push_back(str.substr(i,1)); }\n" + + " return _res;\n" + + " }\n\n"; + return res; + } + + public static String prependOp() + { String res = + " public static List prepend(List l, Object ob)\n" + + " { List res = new Vector();\n" + + " res.add(ob);\n" + + " res.addAll(l);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String prependOpJava6() + { String res = + " public static ArrayList prepend(ArrayList l, Object ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.add(ob);\n" + + " res.addAll(l);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String prependOpJava7() + { String res = + " public static ArrayList prepend(List l, T ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.add(ob);\n" + + " res.addAll(l);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String prependOpCSharp() + { String res = + " public static ArrayList prepend(ArrayList l, object ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.Add(ob);\n" + + " res.AddRange(l);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String prependOpCPP() + { String res = + " static vector<_T>* prepend(vector<_T>* l, _T ob)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->push_back(ob);\n" + + " res->insert(res->end(), l->begin(), l->end());\n" + + " return res;\n" + + " }\n"; + return res; + } + + + public static String appendOp() // also used for l->including(ob) + { String res = + " public static List append(List l, Object ob)\n" + + " { List res = new Vector();\n" + + " res.addAll(l);\n" + + " res.add(ob);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String appendOpJava6() // also used for l->including(ob) + { String res = + " public static ArrayList append(ArrayList l, Object ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l);\n" + + " res.add(ob);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String appendOpJava7() // also used for l->including(ob) + { String res = + " public static ArrayList append(List l, T ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l);\n" + + " res.add(ob);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String appendOpCSharp() // also used for l->including(ob) + { String res = + " public static ArrayList append(ArrayList l, object ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.AddRange(l);\n" + + " res.Add(ob);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String appendOpCPP() + { String res = + " static vector<_T>* append(vector<_T>* l, _T ob)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), l->begin(), l->end());\n" + + " res->push_back(ob);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateInsertAtOp() // also used for l->including(ob) + { String res = + " public static List insertAt(List l, int ind, Object ob)\n" + + " { List res = new Vector();\n" + + " for (int i = 0; i < ind-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " if (ind <= l.size() + 1) { res.add(ob); }\n" + + " for (int i = ind-1; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n"; + res = res + " public static String insertAt(String l, int ind, Object ob)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " if (ind <= l.length() + 1) { res = res + ob; }\n" + + " for (int i = ind-1; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateInsertIntoOp() + { String res = + " public static List insertInto(List l, int ind, List ob)\n" + + " { List res = new Vector();\n" + + " for (int i = 0; i < ind-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " for (int j = 0; j < ob.size(); j++)\n" + + " { res.add(ob.get(j)); }\n" + + " for (int i = ind-1; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static List excludingSubrange(List l, int startIndex, int endIndex)\n" + + " { List res = new Vector();\n" + + " for (int i = 0; i < startIndex-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " for (int i = endIndex; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String setSubrange(String ss, int startIndex, int endIndex, String v)\n" + + " { String res = ss;\n" + + " if (ss.length() < endIndex)\n" + + " { for (int i = ss.length()-1; i < endIndex; i++)\n" + + " { res = res + \" \"; }\n" + + " }\n" + + " return res.substring(0,startIndex-1) + v +\n" + + " res.substring(endIndex); \n" + + " }\n\n"; + + res = res + " public static String insertInto(String l, int ind, Object ob)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " res = res + ob; \n" + + " for (int i = ind-1; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n"; + + res = res + + " public static String excludingSubrange(String l, int startIndex, int endIndex)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < startIndex-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " for (int i = endIndex; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateRemoveSetAtOps() + { String res = + " public static List removeAt(List l, int ind)\n" + + " { List res = new Vector();\n" + + " res.addAll(l); \n" + + " if (ind <= res.size() && ind >= 1)\n" + + " { res.remove(ind - 1); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String removeAt(String ss, int ind)\n" + + " { StringBuffer sb = new StringBuffer(ss); \n" + + " if (ind <= ss.length() && ind >= 1)\n" + + " { sb.deleteCharAt(ind - 1); } \n" + + " return sb.toString();\n" + + " }\n\n"; + + res = res + + " public static List removeFirst(List l, Object x)\n" + + " { List res = new Vector();\n" + + " res.addAll(l); \n" + + " res.remove(x);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static List setAt(List l, int ind, Object val)\n" + + " { List res = new Vector();\n" + + " res.addAll(l); \n" + + " if (ind <= res.size() && ind >= 1)\n" + + " { res.set(ind - 1,val); } \n" + + " return res;\n" + + " }\n"; + res = res + " public static String setAt(String ss, int ind, Object val)\n" + + " { String res = ss;\n" + + " if (ind <= res.length() && ind >= 1)\n" + + " { res = ss.substring(0,ind-1); \n" + + " res = res + val + ss.substring(ind);\n" + + " } \n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateInsertAtOpJava6() // also used for l->including(ob) + { String res = + " public static ArrayList insertAt(ArrayList l, int ind, Object ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < ind-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " if (ind <= l.size() + 1) { res.add(ob); }\n" + + " for (int i = ind-1; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n"; + res = res + " public static String insertAt(String l, int ind, Object ob)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " if (ind <= l.length() + 1) { res = res + ob; }\n" + + " for (int i = ind-1; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateInsertIntoOpJava6() + { String res = + " public static ArrayList insertInto(ArrayList l, int ind, ArrayList ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < ind-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " for (int j = 0; j < ob.size(); j++)\n" + + " { res.add(ob.get(j)); }\n" + + " for (int i = ind-1; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList excludingSubrange(ArrayList l, int startIndex, int endIndex)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < startIndex-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " for (int i = endIndex; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static String insertInto(String l, int ind, Object ob)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " res = res + ob;\n" + + " for (int i = ind-1; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String excludingSubrange(String l, int startIndex, int endIndex)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < startIndex-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " for (int i = endIndex; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String setSubrange(String ss, int startIndex, int endIndex, String v)\n" + + " { String res = ss;\n" + + " if (ss.length() < endIndex)\n" + + " { for (int i = ss.length()-1; i < endIndex; i++)\n" + + " { res = res + \" \"; }\n" + + " }\n" + + " return res.substring(0,startIndex-1) + v +\n" + + " res.substring(endIndex); \n" + + " }\n\n"; + + + return res; + } + + + public static String generateRemoveSetAtOpsJava6() + { String res = + " public static ArrayList removeAt(ArrayList l, int ind)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l); \n" + + " if (ind <= res.size() && ind >= 1)\n" + + " { res.remove(ind - 1); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String removeAt(String ss, int ind)\n" + + " { StringBuffer sb = new StringBuffer(ss); \n" + + " if (ind <= ss.length() && ind >= 1)\n" + + " { sb.deleteCharAt(ind - 1); } \n" + + " return sb.toString();\n" + + " }\n\n"; + + res = res + + " public static ArrayList removeFirst(ArrayList l, Object x)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l); \n" + + " res.remove(x);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList setAt(ArrayList l, int ind, Object val)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l); \n" + + " if (ind <= res.size() && ind >= 1)\n" + + " { res.set(ind - 1,val); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static String setAt(String ss, int ind, Object val)\n" + + " { String res = ss;\n" + + " if (ind <= res.length() && ind >= 1)\n" + + " { res = ss.substring(0,ind-1); \n" + + " res = res + val + ss.substring(ind);\n" + + " } \n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateInsertAtOpJava7() + { String res = + " public static ArrayList insertAt(List l, int ind, T ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < ind-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " if (ind <= l.size() + 1) { res.add(ob); }\n" + + " for (int i = ind-1; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n"; + res = res + " public static String insertAt(String l, int ind, Object ob)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " if (ind <= l.length() + 1) { res = res + ob; }\n" + + " for (int i = ind-1; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateInsertIntoOpJava7() + { String res = + " public static ArrayList insertInto(List l, int ind, List ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < ind-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " for (int j = 0; j < ob.size(); j++)\n" + + " { res.add(ob.get(j)); }\n" + + " for (int i = ind-1; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList excludingSubrange(List l, int startIndex, int endIndex)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < startIndex-1 && i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " for (int i = endIndex; i < l.size(); i++)\n" + + " { res.add(l.get(i)); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static String insertInto(String l, int ind, Object ob)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " res = res + ob;\n" + + " for (int i = ind-1; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String excludingSubrange(String l, int startIndex, int endIndex)\n" + + " { String res = \"\";\n" + + " for (int i = 0; i < startIndex-1 && i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " for (int i = endIndex; i < l.length(); i++)\n" + + " { res = res + l.charAt(i); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String setSubrange(String ss, int startIndex, int endIndex, String v)\n" + + " { String res = ss;\n" + + " if (ss.length() < endIndex)\n" + + " { for (int i = ss.length()-1; i < endIndex; i++)\n" + + " { res = res + \" \"; }\n" + + " }\n" + + " return res.substring(0,startIndex-1) + v +\n" + + " res.substring(endIndex); \n" + + " }\n\n"; + + return res; + } + + + public static String generateRemoveSetAtOpsJava7() + { String res = + " public static ArrayList removeAt(List l, int ind)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l); \n" + + " if (ind <= res.size() && ind >= 1)\n" + + " { res.remove(ind - 1); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static String removeAt(String ss, int ind)\n" + + " { StringBuffer sb = new StringBuffer(ss); \n" + + " if (ind <= ss.length() && ind >= 1)\n" + + " { sb.deleteCharAt(ind - 1); } \n" + + " return sb.toString();\n" + + " }\n\n"; + + res = res + + " public static ArrayList removeFirst(List l, T x)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l); \n" + + " res.remove(x);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList setAt(List l, int ind, T val)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(l); \n" + + " if (ind <= res.size() && ind >= 1)\n" + + " { res.set(ind - 1,val); } \n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static String setAt(String ss, int ind, Object val)\n" + + " { String res = ss;\n" + + " if (ind <= res.length() && ind >= 1)\n" + + " { res = ss.substring(0,ind-1); \n" + + " res = res + val + ss.substring(ind);\n" + + " } \n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateInsertAtOpCSharp() + { String res = + " public static ArrayList insertAt(ArrayList l, int ind, object ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < ind-1 && i < l.Count; i++)\n" + + " { res.Add(l[i]); }\n" + + " if (ind <= l.Count + 1) { res.Add(ob); }\n" + + " for (int i = ind-1; i < l.Count; i++)\n" + + " { res.Add(l[i]); }\n" + + " return res;\n" + + " }\n"; + res = res + " public static string insertAt(string l, int ind, object ob)\n" + + " { string res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.Length; i++)\n" + + " { res = res + l[i]; }\n" + + " if (ind <= l.Length + 1) { res = res + ob; }\n" + + " for (int i = ind-1; i < l.Length; i++)\n" + + " { res = res + l[i]; }\n" + + " return res;\n" + + " }\n"; + return res; + } + + /* These are also needed for C++ */ + + public static String generateInsertIntoOpCSharp() + { String res = + " public static ArrayList insertInto(ArrayList l, int ind, ArrayList ob)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < ind-1 && i < l.Count; i++)\n" + + " { res.Add(l[i]); }\n" + + " for (int j = 0; j < ob.Count; j++) \n" + + " { res.Add(ob[j]); }\n" + + " for (int i = ind-1; i < l.Count; i++)\n" + + " { res.Add(l[i]); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList excludingSubrange(ArrayList l, int startIndex, int endIndex)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < startIndex-1 && i < l.Count; i++)\n" + + " { res.Add(l[i]); }\n" + + " for (int i = endIndex; i < l.Count; i++)\n" + + " { res.Add(l[i]); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static string insertInto(string l, int ind, object ob)\n" + + " { string res = \"\";\n" + + " for (int i = 0; i < ind-1 && i < l.Length; i++)\n" + + " { res = res + l[i]; }\n" + + " res = res + ob; \n" + + " for (int i = ind-1; i < l.Length; i++)\n" + + " { res = res + l[i]; }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static string excludingSubrange(string l, int startIndex, int endIndex)\n" + + " { string res = \"\";\n" + + " for (int i = 0; i < startIndex-1 && i < l.Length; i++)\n" + + " { res = res + l[i]; }\n" + + " for (int i = endIndex; i < l.Length; i++)\n" + + " { res = res + l[i]; }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static string setSubrange(string ss, int startIndex, int endIndex, String v)\n" + + " { string res = ss;\n" + + " if (ss.Length < endIndex)\n" + + " { for (int i = ss.Length-1; i < endIndex; i++)\n" + + " { res = res + \" \"; }\n" + + " }\n" + + " return SystemTypes.subrange(ss,1,startIndex-1) + v +\n" + + " SystemTypes.subrange(ss,endIndex+1,ss.Length); \n" + + " }\n\n"; + + return res; + } + + public static String generateRemoveSetAtOpsCSharp() + { String res = + " public static ArrayList removeFirst(ArrayList a, object x)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.AddRange(a);\n" + + " res.Remove(x);\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList removeAt(ArrayList a, int i)\n" + + " {\n" + + " ArrayList res = new ArrayList();\n" + + " res.AddRange(a);\n" + + " if (i <= res.Count && i >= 1)\n" + + " { res.RemoveAt(i - 1); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static string removeAtString(string a, int i)\n" + + " { string res = \"\";\n" + + " for (int x = 0; x < i-1 && x < a.Length; x++)\n" + + " { res = res + a[x]; }\n" + + " for (int x = i; x >= 0 && x < a.Length; x++)\n" + + " { res = res + a[x]; }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList setAt(ArrayList a, int i, object x)\n" + + " {\n" + + " ArrayList res = new ArrayList();\n" + + " res.AddRange(a);\n" + + " if (i <= res.Count && i >= 1)\n" + + " { res[i - 1] = x; }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static string setAt(string a, int i, string x)\n" + + " { string res = \"\";\n" + + " for (int j = 0; j < i-1 && j < a.Length; j++)\n" + + " { res = res + a[j]; }\n" + + " if (i <= a.Length && i >= 1)\n" + + " { res = res + x; }\n" + + " for (int j = i; j >= 0 && j < a.Length; j++)\n" + + " { res = res + a[j]; }\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + + public static String generateInsertAtOpCPP() + { String res = + " static vector<_T>* insertAt(vector<_T>* l, int ind, _T ob)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), l->begin(), l->end());\n" + + " res->insert(res->begin() + (ind - 1), ob);\n" + + " return res; \n" + + " }\n"; + res = res + " static string insertAt(string l, int ind, string ob)\n" + + " { string res(l);\n" + + " res.insert(ind-1,ob);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateRemoveSetAtOpsCPP() + { String res = + " static vector<_T>* setAt(vector<_T>* l, int ind, _T ob)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), l->begin(), l->end());\n" + + " if (ind >= 1 && ind <= res->size())\n" + + " { (*res)[(ind - 1)] = ob; }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " static string setAt(string st, int ind, string ch)\n" + + " { string res = \"\";\n" + + " if (ind >= 1 && ind <= st.length())\n" + + " { res = st.substr(0,ind-1).append(ch).append(st.substr(ind, st.length()-ind)); }\n" + + " else\n" + + " { res = st; }\n" + + " return res; \n" + + " }\n\n"; + + res = res + + " static vector<_T>* removeAt(vector<_T>* l, int ind)\n" + + " { if (ind >= 1 && ind <= l->size())\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), l->begin(), l->begin() + (ind - 1));\n" + + " res->insert(res->end(), l->begin() + ind, l->end());\n" + + " return res;\n" + + " }\n" + + " return l;\n" + + " }\n\n"; + + res = res + + " static vector<_T>* excludingSubrange(vector<_T>* l, int ind1, int ind2)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " if (ind1 < 1) { ind1 = 1; }\n" + + " if (ind2 > l->size()) { ind2 = l->size(); }\n" + + " if (ind1 > 1 && ind1 <= l->size())\n" + + " {\n" + + " res->insert(res->end(), l->begin(), l->begin() + (ind1 - 2));\n" + + " }\n" + + " if (ind2 >= ind1 && ind2 < l->size())\n" + + " { res->insert(res->end(), l->begin() + ind2, l->end());\n" + + "\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " static string excludingSubrange(string l, int ind1, int ind2)\n" + + " { string res = \"\";\n" + + " if (ind1 < 1) { ind1 = 1; }\n" + + " if (ind2 > l.size()) { ind2 = l.size(); }\n" + + " if (ind1 > 1 && ind1 <= l.size())\n" + + " { res = l.substr(0,ind1-1); }\n" + + " if (ind2 >= ind1 && ind2 < l.size())\n" + + " { res = res + l.substr(ind2); }\n" + + " return res;\n" + + " }\n\n"; + + + res = res + " static string removeAt(string ss, int ind)\n" + + " { if (ind >= 1 && ind <= ss.length())\n" + + " { string res = ss.substr(0,ind-1);\n" + + " res = res + ss.substr(ind);\n" + + " return res;\n" + + " } \n" + + " return ss;\n" + + " }\n"; + + res = res + + " static vector<_T>* removeFirst(vector<_T>* sq, _T x)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), sq->begin(), sq->end());\n" + + " auto iter = find(res->begin(), res->end(), x);\n" + + " if (iter != res->end())\n" + + " { res->erase(iter); }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + + public static String generateIndexOfOpCPP() // also used for l->including(ob) + { String res = + " static int indexOf(_T x, vector<_T>* a)\n" + + " { int res = 0; \n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (x == (*a)[i])\n" + + " { return i+1; }\n" + + " }\n" + + " return res; \n" + + " }\n\n"; + + res = res + " static int indexOf(vector<_T>* a, vector<_T>* b)\n" + + " { /* Index of a subsequence a of sequence b in b */\n" + + "\n" + + " if (a->size() == 0 || b->size() == 0)\n" + + " { return 0; }\n" + + " int i = 0; \n" + + " while (i < b->size() && (*b)[i] != (*a)[0])\n" + + " { i++; } \n" + + "\n" + + " if (i >= b->size())\n" + + " { return 0; } \n" + + "\n" + + " int j = 0; \n" + + " while (j < a->size() && i+j < b->size() && (*b)[i+j] == (*a)[j]) \n" + + " { j++; }\n" + + "\n" + + " if (j >= a->size())\n" + + " { return i+1; }\n" + + "\n" + + " vector<_T>* subr = subrange(b, i+2, b->size());\n" + + " int res1 = indexOf(a,subr); \n" + + " if (res1 == 0) \n" + + " { return 0; } \n" + + " return res1 + i + 1;\n" + + " }\n\n"; + + res = res + " static int lastIndexOf(vector<_T>* a, vector<_T>* b)\n" + + " { int res = 0; \n" + + " if (a->size() == 0 || b->size() == 0)\n" + + " { return res; }\n" + + "\n" + + " vector<_T>* arev = reverse(a); \n" + + " vector<_T>* brev = reverse(b);\n" + + " int i = indexOf(arev,brev);\n" + + " if (i == 0) \n" + + " { return res; }\n" + + " res = b->size() - i - a->size() + 2;\n" + + " return res;\n" + + " }\n\n"; + + res = res + " static int indexOf(string x, string str)\n" + + " { int res = str.find(x); \n" + + " if (res == string::npos) { return 0; }\n" + + " return res + 1; \n" + + " } \n\n" + + " static int lastIndexOf(_T x, vector<_T>* a)\n" + + " { int res = 0; \n" + + " for (int i = a->size() - 1; i >= 0; i--)\n" + + " { if (x == (*a)[i])\n" + + " { return i+1; } }\n" + + " return res; \n" + + " }\n\n"; + + res = res + " static int lastIndexOf(string x, string str)\n" + + " { int res = str.rfind(x); \n" + + " if (res == string::npos) { return 0; }\n" + + " return res + 1; \n" + + " } \n\n"; + return res; + } + + public static String generateUCLCOpsCPP() // also used for l->including(ob) + { String res = + " static string toLowerCase(string str)\n" + + " { string res(str);\n" + + " for (int i = 0; i < str.length(); i++)\n" + + " { res[i] = tolower(str[i]); }\n" + + " return res; \n" + + " }\n\n"; + res = res + " static string toUpperCase(string str)\n" + + " { string res(str);\n" + + " for (int i = 0; i < str.length(); i++)\n" + + " { res[i] = toupper(str[i]); }\n" + + " return res;\n" + + " }\n\n"; + res = res + " static bool equalsIgnoreCase(string str1, string str2)\n" + + " { int len1 = str1.length();\n" + + " int len2 = str2.length();\n" + + " if (len1 != len2) { return false; }\n" + + " for (int i = 0; i < len1; i++)\n" + + " { if (tolower(str1[i]) == tolower(str2[i]))\n" + + " { }\n" + + " else \n" + + " { return false; }\n" + + " }\n" + + " return true;\n" + + " }\n\n"; + + return res; + } + + public static String generateSWEWOpsCPP() // also used for l->including(ob) + { String res = + " static bool startsWith(string s1, string s2)\n" + + " { int l1 = s1.length(); \n" + + " int l2 = s2.length();\n" + + " if (l1 < l2) { return false; }\n" + + " if (s1.substr(0,l2) == s2) { return true; }\n" + + " return false; \n" + + " }\n\n"; + res = res + + " static bool endsWith(string s1, string s2)\n" + + " { int l1 = s1.length(); \n" + + " int l2 = s2.length();\n" + + " if (l1 < l2) { return false; }\n" + + " if (s1.substr(l1-l2,l2) == s2) { return true; }\n" + + " return false; \n" + + " }\n\n"; + return res; + } + + /* public static int count(String s, String x) + { int res = 0; + if ("".equals(s)) { return res; } + int ind = s.indexOf(x); + if (ind == -1) { return res; } + String ss = s.substring(ind+1,s.length()); + res++; + while (ind >= 0) + { ind = ss.indexOf(x); + if (ind == -1 || ss.equals("")) { return res; } + res++; + ss = ss.substring(ind+1,ss.length()); + } + return res; + } */ + + public static String generateLastOp() + { String res = " public static Object last(List v)\n" + + " { if (v.size() == 0) { return null; }\n" + + " return v.get(v.size() - 1);\n" + + " }\n\n"; + return res; + } + + public static String generateLastOpJava6() + { String res = " public static Object last(ArrayList v)\n" + + " { if (v.size() == 0) { return null; }\n" + + " return v.get(v.size() - 1);\n" + + " }\n\n"; + + res = res + + " public static Object last(HashSet v)\n" + + " { int n = v.size(); \n" + + " if (n == 0) { return null; }\n" + + " Object res = null; \n" + + " for (Object o : v) { res = o; }\n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateLastOpJava7() + { String res = " public static T last(List v)\n" + + " { if (v.size() == 0) { return null; }\n" + + " return v.get(v.size() - 1);\n" + + " }\n\n"; + + res = res + + " public static T last(Set v)\n" + + " { int n = v.size(); \n" + + " if (n == 0) { return null; }\n" + + " T res = null; \n" + + " for (T o : v) { res = o; }\n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateLastOpCSharp() + { String res = " public static object last(ArrayList v)\n" + + " { if (v.Count == 0) { return null; }\n" + + " return v[v.Count - 1];\n" + + " }\n\n"; + return res; + } + + public static String generateLastOpCPP() + { String res = " static _T last(vector<_T>* v)\n" + + " { if (v->size() == 0) { return 0; }\n" + + " return v->at(v->size() - 1);\n" + + " }\n\n" + + " static _T last(std::set<_T>* v)\n" + + " { if (v->size() == 0) { return 0; }\n" + + " std::set<_T>::iterator _pos = v->end();\n" + + " _pos--;\n" + + " return *_pos;\n" + + " }\n\n"; + return res; + } // and for set<_T>* + + public static String generateSubcollectionsOpJava6() + { String res = " public static ArrayList subcollections(ArrayList v)\n" + + " { ArrayList res = new ArrayList();\n" + + " if (v.size() == 0) { res.add(new ArrayList()); return res; }\n" + + " if (v.size() == 1) { res.add(new ArrayList()); res.add(v); return res;\n " + + " }\n" + + " ArrayList s = new ArrayList();\n" + + " Object x = v.get(0);\n" + + " s.addAll(v);\n" + + " s.remove(0);\n" + + " ArrayList scs = subcollections(s);\n" + + " res.addAll(scs);\n" + + " for (int i = 0; i < scs.size(); i++)\n" + + " { ArrayList sc = (ArrayList) scs.get(i);\n" + + " ArrayList scc = new ArrayList();\n" + + " scc.add(x); scc.addAll(sc); res.add(scc); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + res = res + + " public static HashSet subcollections(HashSet v)\n" + + " { HashSet res = new HashSet();\n" + + " if (v.size() == 0) { res.add(new HashSet()); return res; }\n" + + " if (v.size() == 1) { res.add(new HashSet()); res.add(v); return res;\n " + + " }\n" + + " HashSet s = new HashSet();\n" + + " Object x = null; int _i = 0;\n" + + " for (Object _o : v)\n" + + " { if (_i == 0) { x = _o; _i++; }\n" + + " else { s.add(_o); }\n" + + " }\n" + + " HashSet scs = subcollections(s);\n" + + " res.addAll(scs);\n" + + " for (Object _obj : scs)\n" + + " { HashSet sc = (HashSet) _obj;\n" + + " HashSet scc = new HashSet();\n" + + " scc.add(x); scc.addAll(sc); res.add(scc); \n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateSubcollectionsOpJava7() + { String res = " public static ArrayList> subcollections(ArrayList v)\n" + + " { ArrayList> res = new ArrayList>();\n" + + " if (v.size() == 0)\n" + + " { res.add(new ArrayList()); return res; }\n" + + " if (v.size() == 1)\n" + + " { res.add(new ArrayList()); res.add(v); return res;\n " + + " }\n" + + " ArrayList s = new ArrayList();\n" + + " T x = v.get(0);\n" + + " s.addAll(v);\n" + + " s.remove(0);\n" + + " ArrayList> scs = subcollections(s);\n" + + " res.addAll(scs);\n" + + " for (int i = 0; i < scs.size(); i++)\n" + + " { ArrayList sc = (ArrayList) scs.get(i);\n" + + " ArrayList scc = new ArrayList();\n" + + " scc.add(x); scc.addAll(sc); res.add(scc); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + res = res + + " public static HashSet> subcollections(HashSet v)\n" + + " { HashSet> res = new HashSet>();\n" + + " if (v.size() == 0) { res.add(new HashSet()); return res; }\n" + + " if (v.size() == 1) { res.add(new HashSet()); res.add(v); return res;\n " + + " }\n" + + " HashSet s = new HashSet();\n" + + " T x = null; int _i = 0;\n" + + " for (T _o : v)\n" + + " { if (_i == 0) { x = _o; _i++; }\n" + + " else { s.add(_o); }\n" + + " }\n" + + " HashSet> scs = subcollections(s);\n" + + " res.addAll(scs);\n" + + " for (Set _obj : scs)\n" + + " { HashSet sc = (HashSet) _obj;\n" + + " HashSet scc = new HashSet();\n" + + " scc.add(x); scc.addAll(sc); res.add(scc); \n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } // and for TreeSet + + public static String generateSubcollectionsOpCPP() + { String res = " static vector*>* subcollections(vector<_T>* v)\n" + + " { vector*>* res = new vector*>();\n" + + " vector<_T>* r = new vector<_T>();\n" + + " if (v->size() == 0)\n" + + " { res->push_back(r); return res; }\n" + + " if (v->size() == 1) { res->push_back(r); res->push_back(v); return res;\n " + + " }\n" + + " _T x = (*v)[0];\n" + + " for (int i = 1; i < v->size(); i++)\n" + + " { r->push_back((*v)[i]); }\n" + + " vector*>* scs = UmlRsdsLib<_T>::subcollections(r);\n" + + " res->insert(res->end(), scs->begin(), scs->end());\n" + + " for (int i = 0; i < scs->size(); i++)\n" + + " { vector<_T>* sc = (*scs)[i];\n" + + " vector<_T>* scc = new vector<_T>();\n" + + " scc->push_back(x);\n" + + " scc->insert(scc->end(), sc->begin(), sc->end());\n" + + " res->push_back(scc); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + res = res + + " static std::set*>* subcollections(std::set<_T>* v)\n" + + " { std::set*>* res = new std::set*>();\n" + + " std::set<_T>* r = new std::set<_T>();\n" + + " if (v->size() == 0)\n" + + " { res->insert(r); return res; }\n" + + " if (v->size() == 1)\n" + + " { res->insert(r);\n" + + " res->insert(v);\n" + + " return res;\n " + + " }\n" + + " std::set<_T>::iterator _pos = v->begin();\n" + + " _T x = *_pos;\n" + + " _pos++; \n" + + " for (; _pos != v->end(); _pos++)\n" + + " { r->insert(*_pos); }\n" + + " std::set*>* scs = UmlRsdsLib<_T>::subcollections(r);\n" + + " res->insert(scs->begin(), scs->end());\n" + + " for (std::set*>::iterator _obj = scs->begin(); _obj != scs->end(); _obj++)\n" + + " { std::set<_T>* sc = *_obj;\n" + + " std::set<_T>* scc = new std::set<_T>();\n" + + " scc->insert(x); \n" + + " scc->insert(sc->begin(), sc->end());\n" + + " res->insert(scc); \n" + + " }\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateConcatAllOp() + { String res = " public static List concatenateAll(List a)\n" + + " { List res = new Vector();\n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { List r = (List) a.get(i);\n" + + " res.addAll(r); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateConcatAllOpJava6() + { String res = " public static ArrayList concatenateAll(List a)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Collection r = (Collection) a.get(i);\n" + + " res.addAll(r); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateConcatAllOpJava7() + { String res = " public static ArrayList concatenateAll(ArrayList a)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < a.size(); i++)\n" + + " { Collection r = (Collection) a.get(i);\n" + + " res.addAll(r); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateConcatAllOpCSharp() + { String res = " public static ArrayList concatenateAll(ArrayList a)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (int i = 0; i < a.Count; i++)\n" + + " { ArrayList r = (ArrayList) a[i];\n" + + " res.AddRange(r); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateConcatAllOpCPP() + { String res = " static vector<_T>* concatenateAll(vector*>* a)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { vector<_T>* r = (*a)[i];\n" + + " res->insert(res->end(), r->begin(), r->end()); \n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateAsSetOpJava6() + { String res = " public static HashSet asSet(Collection c)\n" + + " { HashSet res = new HashSet();\n" + + " res.addAll(c);\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static ArrayList asOrderedSet(Collection c)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (Object x : c)\n" + + " { if (res.contains(x)) { }\n" + + " else \n" + + " { res.add(x); }\n" + + " } \n" + + " return res; \n" + + " }\n\n"; + + res = res + + " public static ArrayList mapAsSequence(Map m)\n" + + " { ArrayList range = new ArrayList();\n" + + " java.util.Set ss = m.entrySet();\n" + + " for (Object x : ss)\n" + + " { Map.Entry ee = (Map.Entry) x;\n" + + " HashMap mx = new HashMap(); \n" + + " mx.put(ee.getKey(), ee.getValue());\n" + + " range.add(mx); \n" + + " } \n" + + " return range;\n" + + " }\n\n"; + + res = res + + " public static HashSet mapAsSet(Map m)\n" + + " { ArrayList range = mapAsSequence(m); \n" + + " return asSet(range); \n" + + " }\n\n"; + + return res; + } + + public static String generateAsSetOpJava7() + { String res = + " public static HashSet asSet(Collection c)\n" + + " { HashSet res = new HashSet();\n" + + " res.addAll(c);\n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static HashSet> asSet(Map m)\n" + + " { ArrayList> res = Ocl.asSequence(m);\n" + + " return Ocl.asSet(res);\n" + + " }\n\n"; + + res = res + " public static ArrayList asOrderedSet(Collection c)\n" + + " { ArrayList res = new ArrayList();\n" + + " for (T x : c)\n" + + " { if (res.contains(x)) { }\n" + + " else \n" + + " { res.add(x); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + " public static ArrayList> asSequence(Map m)\n" + + " { Set> ss = m.entrySet();\n" + + " ArrayList> res = new ArrayList>();\n" + + " for (Map.Entry item : ss)\n" + + " { HashMap maplet = new HashMap();\n" + + " maplet.put(item.getKey(), item.getValue()); \n" + + " res.add(maplet); \n" + + " } \n" + + " return res;\n" + + " }\n"; + + return res; + } + + public String generateAsSortedSetOpJava7() + { String res = + " public static TreeSet asSortedSet(Collection c)\n" + + " { TreeSet res = new TreeSet();\n" + + " res.addAll(c);\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + public static String generateAsSetOpCPP() + { String res = " static std::set<_T>* asSet(vector<_T>* c)\n" + + " { std::set<_T>* res = new std::set<_T>();\n" + + " res->insert(c->begin(), c->end());\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* asSet(std::set<_T>* c)\n" + + " { return c; }\n\n"; + + res = res + " static vector<_T>* asOrderedSet(vector<_T>* c)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " for (vector<_T>::iterator _pos = c->begin(); _pos != c->end(); ++_pos)\n" + + " { if (isIn(*_pos, res)) { }\n" + + " else \n" + + " { res->push_back(*_pos); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + " static vector<_T>* asOrderedSet(set<_T>* c)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " for (set<_T>::iterator _pos = c->begin(); _pos != c->end(); ++_pos)\n" + + " { res->push_back(*_pos); }\n" + + " return res;\n" + + " }\n\n"; + + res = res + " static vector<_T>* randomiseSequence(vector<_T>* sq)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " for (vector<_T>::iterator _pos = sq->begin(); _pos != sq->end(); ++_pos)\n" + + " { res->push_back(*_pos); }\n" + + " std::random_shuffle(res->begin(), res->end());\n" + + " return res; \n" + + " }\n\n"; + + return res; + } // also need asBag operations - same as sort + + public static String generateAsSequenceOpJava6() + { String res = " public static ArrayList asSequence(Collection c)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(c);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList asBag(Collection c)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(c); \n" + + " Collections.sort(res);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateAsSequenceOpJava7() + { String res = " public static ArrayList asSequence(Collection c)\n" + + " { ArrayList res = new ArrayList();\n" + + " res.addAll(c);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static ArrayList asBag(Collection c)\n" + + " { ArrayList res = new ArrayList(); \n" + + " res.addAll(c); \n" + + " Collections.sort(res);\n" + + " return res;\n" + + " }\n\n"; + + return res; + } + + public static String generateAsSequenceOpCPP() + { String res = " static vector<_T>* asSequence(std::set<_T>* c)\n" + + " { vector<_T>* res = new vector<_T>();\n" + + " res->insert(res->end(), c->begin(), c->end());\n" + + " return res;\n" + + " }\n\n" + + " static vector<_T>* asSequence(vector<_T>* c)\n" + + " { return c; }\n\n"; + return res; + } + + public static String symmetricDifferenceOpCPP() + { String res = " static std::set<_T>* symmetricDifference(vector<_T>* a, vector<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>();\n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*a)[i], b)) { }\n" + + " else { res->insert((*a)[i]); }\n" + + " }\n" + + " for (int i = 0; i < b->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*b)[i], a)) { }\n" + + " else { res->insert((*b)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* symmetricDifference(std::set<_T>* a, vector<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>();\n" + + " for (std::set<_T>::iterator _pos = a->begin(); _pos != a->end(); _pos++)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos, b)) { }\n" + + " else { res->insert(*_pos); }\n" + + " }\n" + + " for (int i = 0; i < b->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*b)[i], a)) { }\n" + + " else { res->insert((*b)[i]); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* symmetricDifference(vector<_T>* a, std::set<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>();\n" + + " for (int i = 0; i < a->size(); i++)\n" + + " { if (UmlRsdsLib<_T>::isIn((*a)[i], b)) { }\n" + + " else { res->insert((*a)[i]); }\n" + + " }\n" + + " for (std::set<_T>::iterator _pos = b->begin(); _pos != b->end(); _pos++)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos, a)) { }\n" + + " else { res->insert(*_pos); }\n" + + " }\n" + + " return res;\n" + + " }\n\n" + + " static std::set<_T>* symmetricDifference(std::set<_T>* a, std::set<_T>* b)\n" + + " { std::set<_T>* res = new std::set<_T>();\n" + + " for (std::set<_T>::iterator _pos = a->begin(); _pos != a->end(); _pos++)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos, b)) { }\n" + + " else { res->insert(*_pos); }\n" + + " }\n" + + " for (std::set<_T>::iterator _pos = b->begin(); _pos != b->end(); _pos++)\n" + + " { if (UmlRsdsLib<_T>::isIn(*_pos, a)) { }\n" + + " else { res->insert(*_pos); }\n" + + " }\n" + + " return res;\n" + + " }\n\n"; + return res; + } + + + public static String generateIsUniqueOp() + { String res = + " public static boolean isUnique(List evals)\n" + + " { List vals = new Vector(); \n" + + " for (int i = 0; i < evals.size(); i++)\n" + + " { Object ob = evals.get(i); \n" + + " if (vals.contains(ob)) { return false; }\n" + + " vals.add(ob);\n" + + " }\n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateIsUniqueOpJava6() + { String res = + " public static boolean isUnique(Collection evals)\n" + + " { HashSet vals = new HashSet(); \n" + + " for (Object ob : evals)\n" + + " { if (vals.contains(ob)) { return false; }\n" + + " vals.add(ob);\n" + + " }\n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateIsUniqueOpJava7() + { String res = + " public static boolean isUnique(Collection evals)\n" + + " { HashSet vals = new HashSet(); \n" + + " for (T ob : evals)\n" + + " { if (vals.contains(ob)) { return false; }\n" + + " vals.add(ob);\n" + + " }\n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateIsUniqueOpCSharp() + { String res = + " public static bool isUnique(ArrayList evals)\n" + + " { ArrayList vals = new ArrayList(); \n" + + " for (int i = 0; i < evals.Count; i++)\n" + + " { object ob = evals[i]; \n" + + " if (vals.Contains(ob)) { return false; }\n" + + " vals.Add(ob);\n" + + " }\n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateIsUniqueOpCPP() + { String res = + " static bool isUnique(vector<_T>* evals)\n" + + " { std::set<_T> vals; \n" + + " for (int i = 0; i < evals->size(); i++)\n" + + " { _T ob = (*evals)[i]; \n" + + " if (vals.find(ob) != vals.end()) { return false; }\n" + + " vals.insert(ob);\n" + + " }\n" + + " return true;\n" + + " }\n"; + res = res + " static bool isUnique(std::set<_T>* evals)\n" + + " { return true; }\n"; + return res; + } + + public static String generateByte2CharOp() + { String res = " public static String byte2char(int b)\n" + + " { try { byte[] bb = {(byte) b}; \n" + + " return new String(bb); }\n" + + " catch (Exception _e)\n" + + " { return \"\"; }\n" + + " }\n\n"; + res = res + " public static int char2byte(String s)\n" + + " { if (s == null || s.length() == 0)\n" + + " { return -1; } \n" + + " return (int) s.charAt(0);\n" + + " }\n\n"; + + return res; + } + + public static String generateByte2CharOpCPP() + { String res = " static string byte2char(int b)\n" + + " { int arr[] = {0};\n" + + " arr[0] = b;\n" + + " string str = string((char*) arr);\n" + + " return str;\n" + + " }\n\n"; + res = res + + " static int char2byte(string str)\n" + + " { if (str.length() == 0)\n" + + " { return -1; } \n" + + " char x = str[0];\n" + + " return (int) x;\n" + + " } \n"; + return res; + } + + public static String generateIsIntegerOp() + { String res = + " public static boolean isInteger(String str)\n" + + " { try { Integer.parseInt(str.trim()); return true; }\n" + + " catch (Exception _e) { return false; }\n" + + " }\n\n"; + + res = res + + " public static int toInt(String str)\n" + + " { /* Trim leading 0's */\n" + + " if (str == null || str.length() == 0)\n" + + " { return 0; }\n" + + " String trm = str.trim();\n" + + " while (trm.length() > 0 && trm.charAt(0) == '0')\n" + + " { trm = trm.substring(1); }\n" + + " if (trm.indexOf(\".\") > 0)\n" + + " { trm = trm.substring(0,trm.indexOf(\".\")); }\n" + + " try { int x = Integer.parseInt(trm.trim());\n" + + " return x; }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n\n"; + + res = res + + " public static int toInteger(String str)\n" + + " { if (str == null || str.length() == 0)\n" + + " { return 0; }\n" + + " String trm = str.trim();\n" + + " while (trm.length() > 0 && trm.charAt(0) == '0')\n" + + " { trm = trm.substring(1); }\n" + + " if (trm.indexOf(\".\") > 0)\n" + + " { trm = trm.substring(0,trm.indexOf(\".\")); }\n" + + " try { int x = Integer.decode(trm).intValue();\n" + + " return x; \n" + + " }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n\n"; + + return res; + } + + public static String generateIsLongOp() + { String res = " public static boolean isLong(String str)\n" + + " { try { Long.parseLong(str.trim()); return true; }\n" + + " catch (Exception _e) { return false; }\n" + + " }\n\n"; + res = res + " public static long toLong(String str)\n" + + " { try { long x = Long.parseLong(str.trim());\n" + + " return x; }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n"; + return res; + } + + public static String generateIsRealOp() + { String res = " public static boolean isReal(String str)\n" + + " { try { double d = Double.parseDouble(str.trim()); \n" + + " if (Double.isNaN(d)) { return false; }\n" + + " return true; }\n" + + " catch (Exception _e) { return false; }\n" + + " }\n\n"; + res = res + " public static double toDouble(String str)\n" + + " { try { double x = Double.parseDouble(str.trim());\n" + + " return x; }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n"; + return res; + } + + public static String generateIsIntegerOpCSharp() + { String res = " public static bool isInteger(string str)\n" + + " { try { int.Parse(str); return true; }\n" + + " catch (Exception _e) { return false; }\n" + + " }\n\n"; + + res = res + + " public static int toInt(string str)\n" + + " { /* Trim leading 0's */\n" + + " if (str == null || str.Length == 0)\n" + + " { return 0; }\n" + + " string trm = str.Trim();\n" + + " while (trm.Length > 0 && trm[0] == '0')\n" + + " { trm = trm.Substring(1); }\n" + + " try { int x = int.Parse(trm.Trim());\n" + + " return x; }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n\n"; + + return res; + } + + public static String generateIsLongOpCSharp() + { String res = " public static bool isLong(string str)\n" + + " { try { long.Parse(str); return true; }\n" + + " catch (Exception _e) { return false; }\n" + + " }\n\n"; + + /* res = res + " public static long toLong(String str)\n" + + " { try { long x = long.Parse(str.Trim());\n" + + " return x; }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n"; */ + + return res; + } + + public static String generateIsRealOpCSharp() + { String res = " public static bool isReal(string str)\n" + + " { try { double d = double.Parse(str); \n" + + " if (Double.IsNaN(d)) { return false; }\n" + + " return true; }\n" + + " catch (Exception __e) { return false; }\n" + + " }\n\n"; + + res = res + " public static double toDouble(String str)\n" + + " { try { double x = double.Parse(str.Trim());\n" + + " return x; }\n" + + " catch (Exception _e) { return 0; }\n" + + " }\n"; + + return res; + } + + public static String generateIsIntegerOpCPP() + { String res = " static bool isInteger(string str)\n" + + " { try { std::stoi(str); return true; }\n" + + " catch (exception _e) { return false; }\n" + + " }\n"; + return res; + } + + public static String generateIsLongOpCPP() + { String res = " static bool isLong(string str)\n" + + " { try { std::stol(str); return true; }\n" + + " catch (exception _e) { return false; }\n" + + " }\n"; + return res; + } + + public static String generateIsRealOpCPP() + { String res = " static bool isReal(string str)\n" + + " { try { std::stod(str); return true; }\n" + + " catch (exception _e)\n" + + " { return false; }\n" + + " }\n\n"; + + res = res + " static bool toBoolean(string str)\n" + + " { if (\"true\" == str || \"1\" == str)\n" + + " { return true; }\n" + + " return false; \n" + + " }\n\n"; + + res = res + + " static int toInteger(string str)\n" + + " { if (str.length() == 0)\n" + + " { return 0; }\n" + + "\n" + + " if (str[0] == '0' && str.length() > 1 && str[1] == 'x')\n" + + " { try {\n" + + " int x = std::stoi(str, 0, 16);\n" + + " return x; \n" + + " }\n" + + " catch (exception e) { return 0; }\n" + + " }\n" + + " else if (str[0] == '0' && str.length() > 1)\n" + + " { try { \n" + + " int y = std::stoi(str, 0, 8);\n" + + " return y;\n" + + " } catch (exception f)\n" + + " { return 0; }\n" + + " } \n" + + " try { int z = std::stoi(str, 0, 10);\n" + + " return z;\n" + + " } \n" + + " catch (exception g) { return 0; } \n" + + " return 0;\n" + + " }\n\n"; + + res = res + + " static long toLong(string str)\n" + + " { if (str.length() == 0)\n" + + " { return 0; }\n" + + "\n" + + " if (str[0] == '0' && str.length() > 1 && str[1] == 'x')\n" + + " { try {\n" + + " long x = std::stol(str, 0, 16);\n" + + " return x; \n" + + " }\n" + + " catch (exception e) { return 0; }\n" + + " }\n" + + " else if (str[0] == '0' && str.length() > 1)\n" + + " { try { \n" + + " long y = std::stol(str, 0, 8);\n" + + " return y;\n" + + " } catch (exception f)\n" + + " { return 0; }\n" + + " } \n" + + " try { long z = std::stol(str, 0, 10);\n" + + " return z;\n" + + " } \n" + + " catch (exception g) { return 0; } \n" + + " return 0;\n" + + " }\n\n"; + res = res + + " static double toReal(string str)\n" + + " { if (str.length() == 0)\n" + + " { return 0.0; }\n" + + "\n" + + " try {\n" + + " double x = std::stod(str);\n" + + " return x; \n" + + " }\n" + + " catch (exception e) { return 0.0; }\n" + + " }\n\n"; + + return res; + } + + public static String generateIncludesAllMapOp() + { String res = " public static boolean includesAllMap(Map sup, Map sub)\n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(sub.keySet());\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (sup.containsKey(key))\n" + + " { if (sub.get(key).equals(sup.get(key)))\n" + + " {}\n" + + " else\n" + + " { return false; }\n" + + " }\n" + + " else \n" + + " { return false; }\n" + + " } \n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateExcludesAllMapOp() + { String res = + " public static boolean excludesAllMap(Map sup, Map sub)\n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(sub.keySet());\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (sup.containsKey(key))\n" + + " { if (sub.get(key).equals(sup.get(key)))\n" + + " { return false; }\n" + + " }\n" + + " } \n" + + " return true;\n" + + " }\n"; + return res; + } + + + public static String generateIncludingMapOp() + { String res = + " public static HashMap includingMap(Map m, Object src, Object trg) \n" + + " { HashMap copy = new HashMap();\n" + + " copy.putAll(m); \n" + + " copy.put(src,trg);\n" + + " return copy;\n" + + " } \n"; + return res; + } + + public static String generateExcludeAllMapOp() + { String res = + " public static HashMap excludeAllMap(Map m1, Map m2) \n" + + " { // m1 - m2 \n" + + " Vector keys = new Vector(); \n" + + " keys.addAll(m1.keySet()); \n" + + " HashMap res = new HashMap(); \n" + + " \n" + + " for (int x = 0; x < keys.size(); x++) \n" + + " { Object key = keys.get(x); \n" + + " if (m2.containsKey(key)) \n" + + " { } \n" + + " else \n" + + " { res.put(key,m1.get(key)); } \n" + + " } \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateExcludingMapKeyOp() + { String res = + " public static HashMap excludingMapKey(Map m, Object k) \n" + + " { // m - { k |-> m(k) } \n" + + " HashMap res = new HashMap(); \n" + + " res.putAll(m); \n" + + " res.remove(k); \n" + + " return res; \n" + + " } \n"; + return res; + } + + public static String generateExcludingMapValueOp() + { String res = + " public static HashMap excludingMapValue(Map m, Object v) \n" + + " { // m - { k |-> v } \n" + + " Vector keys = new Vector();\n" + + " keys.addAll(m.keySet());\n" + + " HashMap res = new HashMap();\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (v.equals(m.get(key)))\n" + + " { }\n" + + " else\n" + + " { res.put(key,m.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateUnionMapOp() + { String res = + " public static HashMap unionMap(Map m1, Map m2) \n" + + " { HashMap res = new HashMap();\n" + + " res.putAll(m1);\n" + + " res.putAll(m2); \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateIntersectionMapOp() + { String res = + " public static HashMap intersectionMap(Map m1, Map m2) \n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(m1.keySet());\n" + + " HashMap res = new HashMap();\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (m2.containsKey(key) && m1.get(key) != null && m1.get(key).equals(m2.get(key)))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashMap intersectAllMap(List col)\n" + + " { HashMap res = new HashMap();\n" + + " if (col.size() == 0) \n" + + " { return res; } \n" + + "\n" + + " Map m0 = (Map) col.get(0);\n" + + " res.putAll(m0); \n" + + "\n" + + " for (int i = 1; i < col.size(); i++)\n" + + " { Map m = (Map) col.get(i);\n" + + " res = Set.intersectionMap(res,m);\n" + + " }\n" + + " return res; \n" + + " } \n\n"; + + res = res + + " public static HashMap restrictMap(Map m1, Vector ks) \n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(m1.keySet());\n" + + " HashMap res = new HashMap();\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (ks.contains(key))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + res = res + + " public static HashMap antirestrictMap(Map m1, Vector ks) \n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(m1.keySet());\n" + + " HashMap res = new HashMap();\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (ks.contains(key)) { }\n" + + " else { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + res = res + + " public static boolean includesKey(Map m, Object key) \n" + + " { Object val = m.get(key); \n" + + " if (val == null) { return false; }\n" + + " return true;\n" + + " }\n\n"; + res = res + + " public static boolean excludesKey(Map m, Object key) \n" + + " { Object val = m.get(key); \n" + + " if (val == null) { return true; }\n" + + " return false;\n" + + " }\n\n"; + res = res + + " public static boolean includesValue(Map m, Object val) \n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(m.keySet());\n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object v = m.get(x);\n" + + " if (v != null && v.equals(val))\n" + + " { return true; }\n" + + " } \n" + + " return false;\n" + + " }\n\n"; + res = res + + " public static boolean excludesValue(Map m, Object val) \n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(m.keySet());\n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object v = m.get(x);\n" + + " if (v != null && v.equals(val))\n" + + " { return false; }\n" + + " } \n" + + " return true;\n" + + " }\n\n"; + return res; + } + + public static String generateIncludingMapOpJava7() + { String res = " public static HashMap includingMap(HashMap m, D src, R trg)\n" + + " { HashMap copy = new HashMap();\n" + + " copy.putAll(m); \n" + + " copy.put(src,trg);\n" + + " return copy;\n" + + " } \n\n"; + res = res + + " public static TreeMap includingMap(TreeMap m, D src, R trg)\n" + + " { TreeMap copy = (TreeMap) m.clone();\n" + + " copy.put(src,trg);\n" + + " return copy;\n" + + " } \n"; + return res; + } + + public static String generateIncludesAllMapOpJava7() + { String res = " public static boolean includesAllMap(Map sup, Map sub)\n" + + " { Set keys = sub.keySet();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (sup.containsKey(key))\n" + + " { if (sub.get(key).equals(sup.get(key)))\n" + + " {}\n" + + " else\n" + + " { return false; }\n" + + " }\n" + + " else \n" + + " { return false; }\n" + + " } \n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateExcludesAllMapOpJava7() + { String res = + " public static boolean excludesAllMap(Map sup, Map sub)\n" + + " { Set keys = sub.keySet();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (sup.containsKey(key))\n" + + " { if (sub.get(key).equals(sup.get(key)))\n" + + " { return false; }\n" + + " }\n" + + " } \n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateExcludeAllMapOpJava7() + { String res = + " public static HashMap excludeAllMap(HashMap m1, Map m2)\n" + + " { // m1 - m2\n" + + " HashMap res = new HashMap();\n" + + " Set keys = m1.keySet(); \n" + + " \n" + + " for (D key : keys)\n" + + " { if (m2.containsKey(key))\n" + + " { }\n" + + " else\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap excludeAllMap(TreeMap m1, Map m2)\n" + + " { // m1 - m2\n" + + " TreeMap res = new TreeMap();\n" + + " Set keys = m1.keySet(); \n" + + " \n" + + " for (D key : keys)\n" + + " { if (m2.containsKey(key))\n" + + " { }\n" + + " else\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateExcludingMapKeyOpJava7() + { String res = + " public static HashMap excludingMapKey(HashMap m, D k)\n" + + " { // m - { k |-> m(k) } \n" + + " HashMap res = new HashMap();\n" + + " res.putAll(m);\n" + + " res.remove(k);\n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap excludingMapKey(TreeMap m, D k)\n" + + " { // m - { k |-> m(k) } \n" + + " TreeMap res = (TreeMap) m.clone();\n" + + " res.remove(k);\n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateExcludingMapValueOpJava7() + { String res = + " public static HashMap excludingMapValue(HashMap m, R v)\n" + + " { // m - { k |-> v }\n" + + " HashMap res = new HashMap();\n" + + " Set keys = m.keySet(); \n" + + " \n" + + " for (D key : keys)\n" + + " { if (v.equals(m.get(key)))\n" + + " { }\n" + + " else\n" + + " { res.put(key,m.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap excludingMapValue(TreeMap m, R v)\n" + + " { // m - { k |-> v }\n" + + " TreeMap res = new TreeMap();\n" + + " Set keys = m.keySet(); \n" + + " \n" + + " for (D key : keys)\n" + + " { if (v.equals(m.get(key)))\n" + + " { }\n" + + " else\n" + + " { res.put(key,m.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateUnionMapOpJava7() + { String res = + " public static HashMap unionMap(HashMap m1, Map m2)\n" + + " { HashMap res = new HashMap();\n" + + " res.putAll(m1);\n" + + " res.putAll(m2); \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap unionMap(TreeMap m1, Map m2)\n" + + " { TreeMap res = (TreeMap) m1.clone();\n" + + " res.putAll(m2); \n" + + " return res;\n" + + " }\n"; + + return res; + } + + public static String generateIntersectionMapOpJava7() + { String res = + " public static HashMap intersectionMap(HashMap m1, Map m2)\n" + + " { HashMap res = new HashMap();\n" + + " Set keys = m1.keySet(); \n" + + " \n" + + " for (D key : keys)\n" + + " { if (m2.containsKey(key) && m1.get(key) != null && m1.get(key).equals(m2.get(key)))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap intersectionMap(TreeMap m1, Map m2)\n" + + " { TreeMap res = new TreeMap();\n" + + " Set keys = m1.keySet(); \n" + + " \n" + + " for (D key : keys)\n" + + " { if (m2.containsKey(key) && m1.get(key) != null && m1.get(key).equals(m2.get(key)))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashMap intersectAllMap(Collection col)\n" + + " { HashMap res = new HashMap();\n" + + " if (col.size() == 0) \n" + + " { return res; } \n" + + "\n" + + " Map m0 = (Map) Ocl.any(col);\n" + + " res.putAll(m0); \n" + + "\n" + + " for (Object obj : col)\n" + + " { Map m = (Map) obj;\n" + + " res = Ocl.intersectionMap(res,m);\n" + + " }\n" + + " return res; \n" + + " } \n\n"; + + + res = res + + " public static HashMap restrictMap(HashMap m1, Collection ks) \n" + + " { Set keys = new HashSet();\n" + + " keys.addAll(m1.keySet());\n" + + " HashMap res = new HashMap();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (ks.contains(key))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap restrictMap(TreeMap m1, Collection ks) \n" + + " { Set keys = new HashSet();\n" + + " keys.addAll(m1.keySet());\n" + + " TreeMap res = new TreeMap();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (ks.contains(key))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashMap antirestrictMap(HashMap m1, Collection ks) \n" + + " { Set keys = new HashSet();\n" + + " keys.addAll(m1.keySet());\n" + + " HashMap res = new HashMap();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (ks.contains(key)) { }\n" + + " else \n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static TreeMap antirestrictMap(TreeMap m1, Collection ks) \n" + + " { Set keys = new HashSet();\n" + + " keys.addAll(m1.keySet());\n" + + " TreeMap res = new TreeMap();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (ks.contains(key)) { }\n" + + " else \n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + + res = res + + " public static HashMap selectMap(HashMap m, Predicate f)\n" + + " { HashMap result = new HashMap();\n" + + " Set keys = m.keySet();\n" + + " for (D k : keys)\n" + + " { R value = m.get(k);\n" + + " if (f.test(value))\n" + + " { result.put(k,value); }\n" + + " }\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static TreeMap selectMap(TreeMap m, Predicate f)\n" + + " { TreeMap result = new TreeMap();\n" + + " Set keys = m.keySet();\n" + + " for (D k : keys)\n" + + " { R value = m.get(k);\n" + + " if (f.test(value))\n" + + " { result.put(k,value); }\n" + + " }\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static HashMap rejectMap(HashMap m, Predicate f)\n" + + " { HashMap result = new HashMap();\n" + + " Set keys = m.keySet();\n" + + " for (D k : keys)\n" + + " { R value = m.get(k);\n" + + " if (f.test(value)) {}\n" + + " else\n" + + " { result.put(k,value); }\n" + + " }\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static TreeMap rejectMap(TreeMap m, Predicate f)\n" + + " { TreeMap result = new TreeMap();\n" + + " Set keys = m.keySet();\n" + + " for (D k : keys)\n" + + " { R value = m.get(k);\n" + + " if (f.test(value)) {}\n" + + " else\n" + + " { result.put(k,value); }\n" + + " }\n" + + " return result;\n" + + " }\n\n"; + + res = res + + " public static HashMap collectMap(Map m, Function _f)\n" + + " { HashMap result = new HashMap();\n" + + " Set keys = m.keySet();\n" + + " for (D k : keys)\n" + + " { R value = m.get(k);\n" + + " result.put(k, _f.apply(value));\n" + + " }\n" + + " return result;\n" + + " }\n\n"; + + return res; + } + + public static String cppExceptionClass( + String exceptionName, String oclname, String exceptionText) + { String res = " class " + exceptionName + " : exception\n" + + " { public: \n" + + " " + exceptionName + "() : message(" + exceptionText + ") { }\n" + + "\n" + + " " + exceptionName + "* copy" + exceptionName + "(" + exceptionName + "* self)\n" + + " { " + exceptionName + "* ex = new " + exceptionName + "();\n" + + " ex->message = self->message;\n" + + " return ex; \n" + + " }\n" + + "\n" + + " const char* what() const { return message; }\n" + + "\n" + + " string getMessage() { return string(message); }\n" + + "\n" + + " void printStackTrace()\n" + + " { cout << what() << endl; }\n" + + "\n" + + " exception* getCause()\n" + + " { return this; }\n" + + "\n" + + " static " + exceptionName + "* new" + oclname + "(string m)\n" + + " { " + exceptionName + "* res = new " + exceptionName + "();\n" + + " res->message = m.c_str();\n" + + " return res;\n" + + " }\n" + + " private: \n" + + " const char* message;\n" + + " };\n\n"; + return res; + } + + + public static String exceptionsCPP() + { String exceptionName = "io_exception"; + String exceptionText = "\"IO exception\""; + String oclName = "IOException"; + + String res = cppExceptionClass(exceptionName, oclName, exceptionText); + + exceptionName = "null_access_exception"; + exceptionText = "\"Null access exception\""; + oclName = "NullAccessException"; + res = res + cppExceptionClass(exceptionName, oclName, exceptionText); + + exceptionName = "assertion_exception"; + exceptionText = "\"Assertion exception\""; + oclName = "AssertionException"; + res = res + cppExceptionClass(exceptionName, oclName, exceptionText); + + exceptionName = "accessing_exception"; + exceptionText = "\"Accessing exception\""; + oclName = "AccessingException"; + res = res + cppExceptionClass(exceptionName, oclName, exceptionText); + + return res; + } + + public static void generateLibraryCSharp(String lib, + PrintWriter out) + { // retrieve library code from libraries/lib.cs & print + // to out. + + try + { File libCPP = new File("libraries/" + lib + ".cs"); + BufferedReader br = null; + String sline = null; + boolean eof = false; + br = new BufferedReader(new FileReader(libCPP)); + out.println(); + + while (!eof) + { sline = br.readLine(); + if (sline == null) + { eof = true; } + else + { out.println(sline); } + } + out.println(); + br.close(); + } + catch (IOException _ex) + { System.err.println("!! ERROR: libraries/" + lib + ".cs not found"); } + } + + public static void generateLibraryJava7(String lib, + PrintWriter out) + { // retrieve library code from libraries/lib.java & print + // to out. + + try + { File libCPP = new File("libraries/" + lib + ".java"); + BufferedReader br = null; + String sline = null; + boolean eof = false; + br = new BufferedReader(new FileReader(libCPP)); + out.println(); + + while (!eof) + { sline = br.readLine(); + if (sline == null) + { eof = true; } + else + { out.println(sline); } + } + out.println(); + br.close(); + } + catch (IOException _ex) + { System.err.println("!! ERROR: libraries/" + lib + ".java not found"); } + } + + public static void generateLibraryCPP(String lib, + PrintWriter out) + { // retrieve library code from libraries/lib.cpp & print + // to out. + + try + { File libCPP = new File("libraries/" + lib + ".cpp"); + BufferedReader br = null; + String sline = null; + boolean eof = false; + br = new BufferedReader(new FileReader(libCPP)); + out.println(); + + while (!eof) + { sline = br.readLine(); + if (sline == null) + { eof = true; } + else + { out.println(sline); } + } + out.println(); + br.close(); + } + catch (IOException _ex) + { System.err.println("!! ERROR: libraries/" + lib + ".cpp not found"); } + } + + public static void generateLibraryHPP(String lib, + PrintWriter out) + { // retrieve library code from libraries/lib.hpp & print + // to out. + + try + { File libHPP = new File("libraries/" + lib + ".hpp"); + BufferedReader br = null; + String sline = null; + boolean eof = false; + br = new BufferedReader(new FileReader(libHPP)); + out.println(); + + while (!eof) + { sline = br.readLine(); + if (sline == null) + { eof = true; } + else + { out.println(sline); } + } + out.println(); + br.close(); + } + catch (IOException _ex) + { System.err.println("!! ERROR: libraries/" + lib + ".hpp not found"); } + } + + + public static void main(String[] args) + { Vector test = new Vector(); + // test.add(new Integer(1)); test.add(new Integer(-4)); + // test.add(new Integer(0)); + test.add("aaa"); test.add("abb"); test.add("aaa"); + // System.out.println(isUnique(test)); + // System.out.println(test.notEmpty()); + // java.util.Collections.sort(test); + // System.out.println(test.count("aaa")); + // System.out.println(Math.pow(0.5,0.5)); + // System.out.println("ddd hhh".indexOf("d h")); + // System.out.println(Math.sin(Math.PI/4)); + // System.out.println(Math.cos(Math.PI/4)); + // System.out.println(Math.tan(Math.PI/4)); + // System.out.println(Math.log(0.1)); + // System.out.println(Math.exp(1)); + + + // System.out.println(Math.abs(-2.2)); + // System.out.println(Math.round(-2.2)); + // System.out.println(Math.floor(-2.2)); + + // char[] chars = "abc".toCharArray(); + // Vector res = new Vector(); + // for (int i = 0; i < chars.length; i++) + // { res.add("" + 1i]); } + // System.out.println(count("ssdd gghh","dd ")); + + // if ("aaa".compareTo("aba") >= 0) { System.out.println(1); } + // else { System.out.println(2); } + // res.add(1,"p"); + // System.out.println(res); + + int ind = "ansc~~tr".indexOf("~~"); + System.out.println("ansc~~tr".substring(0,ind)); + System.out.println("ansc~~tr".substring(ind+2,8)); + } +} + diff --git a/version24/BTypeDef.class b/version24/BTypeDef.class new file mode 100644 index 0000000000000000000000000000000000000000..643ef0780a946b783286b841a82a54c11ed7d707 GIT binary patch literal 1351 zcmZ`(OHUI~7(KV8%uuF03J3^jQ68lQii#itRi26|h=HIk2YMxgrEP{Oi5hptAK{XX zTTHYhlDKhU;xF+x7^0p#9ke{$-1#2oJKyWx`Tpzk7XZV!A4C{^Rj5ZS$Ri#^KL#`m z1`$9)9YY$f1)(cN$8{Yy)OT2UZYpU+$Ec258pbr-7O31cGX=RL5Ke8GyJn)`See9{ z+;DRCIK2~A)^d^pz0s08V`euKD~@etH^(yYG7Gqp|vC9xxI=h#>kE!k8?-N}`jDoa-0Dr;JC%#G)ZX5Q^a1F3>5 zxq`hR=PlJ;Xj&zhmCpv%7!5RG!axHW4NRg-L(;$w>`Xd73HG4R&fRkC|4l;8Yxh=EKandqgfu?iz zsRp5Dw#2~;G`Pi_+>SsXuXZKikGi|wv0f5NWr26a%;#k`EiiB%_nGVC^~O2+nNwA? z;BDD0^x^szFCo1r*gR`Fu(Y>hHgxh$g!xc77&U%M8s#Qj;Mq(qPP?Dq>R9{$BG&&2 zz7H8q%-!}x}`${N6n{0olv_t5uzbaltFkH=}2qWcBcC_yyS>{qP9YutSs8N89 z_KNf#n#%y;S}*pEU%dbQwcJxz@~D=4?u14VqTIzbbi+Uo*V4=VMY)PT&Nqf3ZgG^q ny+;_p6AU6l-KMphQH=;3p+-Z`5kle!O=9dPdH4f!*`t2|h*1;6 literal 0 HcmV?d00001 diff --git a/version24/BTypeDef.java b/version24/BTypeDef.java new file mode 100644 index 00000000..23908822 --- /dev/null +++ b/version24/BTypeDef.java @@ -0,0 +1,51 @@ +import java.util.Vector; + +/****************************** +* Copyright (c) 2003--2024 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BTypeDef extends ModelElement +{ private Vector values; // null for given sets + + public BTypeDef(String name, Vector vals) + { super(name); + values = vals; + } + + public void generateJava(java.io.PrintWriter out) + { out.print(getName()); } // not used. + + public Vector getParameters() + { return new Vector(); } + + public void addParameter(Attribute att) + { } + + public Type getType() + { return null; } + + public void setType(Type t) + { } + + public String toString() + { String res = getName(); + if (values == null) + { return res; } // but not for int, String, boolean, double + int vc = values.size(); + if (vc == 0) + { return res; } + res = res + " = {"; + for (int i = 0; i < vc; i++) + { res = res + values.get(i); + if (i < vc - 1) + { res = res + ", "; } + } + return res + "}"; + } +} + diff --git a/version24/BUnaryExpression.class b/version24/BUnaryExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..a80dd51657b0d1a9f4b6fdbe1c22ced211ec9bae GIT binary patch literal 1660 zcmah|U2hvj6g^`*-i^J9Q>Xc8)6gV^#Gf&xA&}Yxa7k&wNuh27DPLXN+h~ik>+VNI ze~NkFnTI|EsdXeGA^O^%gaqQu+M(<80a?CtXXehm=bU@@Ff}I5O z-BR#H0<-dP7GJ8kE!Vn=J951%BWM<}tKcgE)$SOM?%9q&y7o|ite4ulwO^`xj%n?e zd9OSB{()h60%Nu6)=wSBa9z{3conahmg#K@EM;DQITV}S6^LE4TZTZYW?IIMf6y?T zJ9?wdlTp|3cJ;Pzv;?A=>^&B$dwTQ7ZM`#yh&a4Do5}X8_@3D=?HWyDmiS!rpwl)V zJYi}^gb|V-1!IV3_vwU^43pGczu|hO=X=K1BZ1Zb-SA!&)bK6x8otB#8h(%uCxXU?gp+9Q^ZYbadA=er zb9xY}zS(XWjs_hK0g;hTlTKE{6|8A^7wZDakoZ9>+4X+qklGv@!`C)En~Eg%Nv&=4M{pu@bGXNp%5=95Iv)Ffk}t%wEGI9ncRGf}5h{iY z4kmmsR3U@|uAHr*_!EGyjrvJEKdEW{fe3%>bKtSnT;mW@SlSGCCEiE5rgBFRx%_iP za)sxJ{>CGLEbVx3eFmdQ)1Txi+dp{xD<2ESv~tf7NymB^`59LNKOXoifv*JqT;QvL zp9=g@`dy5~o^luMA<@NraGngsXeTkzr>qkR5G@l6NH2{UVwuG{&Y^2|3BMQlMWD;}5vqj~=fD7$w&( z*77fq>Y|wc6RGV&4-;J^3#4*pr+CP1x{LHNQhUdk+&jYABTOA0V|q^}$RA-w)(taS zhRU|gk>dh+tx)A6Ih2TdopuYC14iSB{Ed==%L?B43sXeNp&wu^5BhQG7_+Q+PFCvS ze0q+i5C1}Xo_-H+oF=`_6#Q@oiRu(iPQ_9_*Tcnr4+{T*m#OmPw=hIv8Y6tMfh4YC W3}q6ja01H#=qSV(Q@Wul3(4iRa+}-rp?>VMcvfxWeFpR_Mm2Ha+efq4n=ofH?=~&T-2<0 zYSAER=YeMLip>3qWIK(7ApLG^7XeoU_&zs>)otC#?rJ5wVo{vW+LsWrD{c+cUaJ>t zwr))R?{oyLQAR$3om`zQmdZoP)#pa4gKR+!K@w4R8>ng49$=b zHY-+HHS`*5lXoh0tE6q{qR{9n%e?5{lxVYp+t^SL!%YRZFr?r<#uPljSP(B2yuzl0 zSnD`e>$J$1x?-M%q*>3Ic7}*&28K+9 z9NQKAKf<=PxWv2Snzog>wWGRf)G)$DALQ@jsT`u#k+Q)iG; z=~MVpnN#?`^Gd>9+AhZ(MHqd2@8|73#J%8Qo)R$~sUPs2T!eHwmoeHAjM9oc%}{?U zbci4h--8Nv!5Si~zkxt2T2OIIJoKznBGBieJMw8Erh(4)>B~U3h&Vz{UxX$ui$}2M z5zL<>xOaw7G~9sfa>&sed~fjA_k3yBMOBe#m*;9rGtTBtAcq7KaP_=2TL|z0#soEa zy1%h)Cqi^O(?Cz*9KCzOHF<`p5bkU0eg+Xta*R_*(&L8|At`s)qn;+QkB$Ms)<7TC zx?E|G%bld`fM(c)Sq5_JuMhA4Z+MR3a}4DF;)Um!U2IUy%|37?d@IvBghdi8VF1ev JpLFV+`U@r+8nFNX literal 0 HcmV?d00001 diff --git a/version24/BVarStatement.java b/version24/BVarStatement.java new file mode 100644 index 00000000..ce65f1ab --- /dev/null +++ b/version24/BVarStatement.java @@ -0,0 +1,65 @@ +import java.util.Vector; + +/* Package: B AMN */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BVarStatement extends BStatement +{ private String var; + private BStatement code; + + public BVarStatement(String v, BStatement body) + { var = v; + code = body; + } + + public String getVar() + { return var; } + + public BStatement getCode() + { return code; } + + public Vector wr() + { return code.wr(); } + + public Vector rd() + { Vector res = code.rd(); + res.remove(var); + return res; + } + + public String toString() + { String res = "VAR " + var + " IN\n"; + res = res + code + " END"; + return res; + } + + public BStatement substituteEq(String oldE, BExpression newE) + { if (var.equals(oldE)) { return this; } + BStatement ncode = code.substituteEq(oldE,newE); + return new BVarStatement(var,ncode); + } + + public BStatement simplify() + { BStatement ncode = code.simplify(); + return new BVarStatement(var,ncode); + } + + public BStatement seq2parallel() + { BStatement ncode = code.seq2parallel(); + return new BVarStatement(var,ncode); + } + + public BStatement normalise() + { BStatement stat = code.normalise(); + BStatement res = new BVarStatement(var,stat); + return res; + } +} + diff --git a/version24/BacktrackDialog$BacktrackDialogPanel.class b/version24/BacktrackDialog$BacktrackDialogPanel.class new file mode 100644 index 0000000000000000000000000000000000000000..19d8ac8cc663a741c0102670da0cfc2403e6f6ad GIT binary patch literal 2426 zcmbVNTWl0%6#k|y-3!z1?9y#ZD^j%JvIUBYh!oMbTr8A}mW!>TOm~JdWp}2|%tDK3 zg15wk#5>;N1%2|tM2&3|NiZ=!nfT&^KKkmTKKSB;@jG*2d+|lnv<%V@W(N=P40Sq$!@1l&6!>CE#=d<7srEB;^gUP^^NHz?lRr z1u0vvn8W(GSys?8JgJ}8r+d8%mOasXAVB*fmwlF5HWaikb~$EF`+ zi!HJXDz@WZ6+1AXAh&!uSnRlGc9nDr*`uA}I;r9g6xiS*|C^hlVk3$w&VdV;*c+@2 z!+KCqu?fY6eRP!^+puIc=&)HFwupmPwGF4s^L5|kqkWIYUa6N~R!_D>#a7(O<_FI@ zR>|x#r>FRMnH0nBlAL!-&fG|~R3g5p0MQ(J7foHBJ*DC)xCxN^ z?j@sKdOxb$!RNNbErQh{+cw?7vhH~%lPw;5?Y3wEdmk{IR@#<(kmp&?0cP_58&HnouWO zKn=n-Wu0&w+(~nAC#AuitOh4p3{DajoTMi>$xv{TkKiOFfTqc6^4>^FcHlnBon+@K z8dwQRYq4h*N^u@_#p|da%{9zp#Vi_mNsP`TIg3>BYor?HkPhuD1G`$YH-&g}fM;sB z7UJ0e&+)Q~`C4X?5AoIjZ>#yYhxqCM@2KIOtlt^br_wlwTTT|GqgYX6r72c2v7*IF zE>`lf(iSW2vCEKW zIl@UYw1U-p>&(5D5n$YXd$@!Gr%X<_cr_F+eE`m*7(* z)3@xkQA_jB*4X-O@-}T+%Vd>itz{0k^RCiZsF|B+-n_t^p?P1;tkHaMfjJkX9*dLb zX}0(%&6q-734&hCl!du*jtGI->aRu+-1H6mR@g8pAeGXwT9ty_Dunc93OhK3oD2^2^R%#>% qNUevEvk;}iZ9_>`IVFmoODa#Mjc>#T>#&BZ@!A|uKG literal 0 HcmV?d00001 diff --git a/version24/BacktrackDialog$ButtonHandler.class b/version24/BacktrackDialog$ButtonHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..ba11b303465c042fbc72d21a8c2208a7e72fac45 GIT binary patch literal 1541 zcmb_cSyR(c6#i~0goXfRlSL8Ksx4blQQ1UU1uTmeQ9;KE?G*wc#UyOwvyb}jA8=ns z2#ybq&;Azwf{y2=g(-nYGn13Ee)rsSPR_5t-+usT!-D|I5t31X(=yKBtc0)(KO*^P zkkN=H8O>-3Ac|HQ=MWLxc|k4+(kA0#T6al^mxXh?Ok9WHIwf>T=#g-hAEg6|Swg>jqC9#dCb47#p_YYcKcwQ45# zkS1WuJt?*bNClOsQc#Uv34IFsF~CqJ3>#5vT{GsRqkXHkoiY>*Vu-;vu|&WMu47oj zh=NhXB#bE-$ApAQ1vfFF;Fch9Oi8${U|I-w1i6cQ3TDu&U>5foYCY+M(gzKzMpEY{ z-N+*=BZk4veqFUJZZQPig6JxxI5D@#6E-0pTBDd|*_F2|4)7R9SMG|(+B zLtviU=`xB=M$(PQI+r>vk;@d{pcM8yq)!o}z#p%wI%QpvX=HYMWQJPqDF(GpO(eKQ z!_`XTb)jc87dFr3j@Jd9Dq+pD3k&>lGZM~y}7ar zAFy~jJF0pryXu*yWcBesYs5t5nw-w3E)t#AEY1C|{o$F&H0o(HRe(wc77U8Nj~14X z-fGm4_9$^DNfsKpp>Z3mVF$i1BrzN#nnz#YCDB?O&-nj_M7s@m-sm9bC;Veg4syp! z^O_w) hzCSP|)Jr%)Jk>`apTZUTmJ(M^Te+L~D1C1L{{S1Kj(`9F literal 0 HcmV?d00001 diff --git a/version24/BacktrackDialog.class b/version24/BacktrackDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..d21ec8b1a1f0aae8399fb9afc415414bdb120511 GIT binary patch literal 2791 zcmb_eYgZFj6x{=agkb=Upp90mhzJ1BEeS$r{u6$!M&*kV@2yem7KTh*^(fBZ`L_I>y#q z*S0R3R=%hl4aODAQck*PmP)Fmp?l2CExQiQc)={%OLL~BiW*w8HltR!pSf>7FgH@A z^@6pOn)0?sHN@;?pI1XqJ;Glm#K@UeP8F-L_IxdWe^5##oB3au=US+obH|D3!9$iww<8==V zJ{iR05wKl#j)SUmR9E#5F3g!yN>@3oQ77j&ODb)alwW_{%;i+6)HgCRqT%d7xWPsT z!z=&Qa{3K>&B>|Bg1k&vA16f)2A;{THwM1NcN!urk$X?Fd@nap z7T?6ci#TQAB{46Hc~wjr;|9*k=oK-eV$O*1Z^uP^5t|}Iy=VB zo-eraPCX48TOf=K};pXnCyuZg*2;@@z_GZ182p)u= zJ&|=4d&oaYW2hWh)RMOOOcq6Cv0i(tVw94~j>#r=NbB{L_w?JVelEWUG#se8wZArP zTILdiCDCBb?#}gVbU&NDuX3!?0*>%!YJfkhU1*Y?<)}#{;dzR|^VFH=*;<}wcX^%- z=K0fsKNEO%nzzno^E~^_^K3cKvnM^z?xWYCQ8KU5UgYd=w4j;(=j2e!CYqA*<_cPp zTZk;iTQ?CcBj!)qyotVr_Qm8TjOpZWhz(cJL9cs$3!RIb=qh6um*g*2!R}kZSg($M zN4$bPr0f=&o-(v#1$(!!kFn2GkdT?g#P?TlAedxBT31`SejRqx{;Xf-8GWI5i$~c%D zF5^)0L>bQ|6D?&N=4rH{;S-6L3XbfYVL!8j!j4eaIz`__Y4gv0t-x$+5i9m literal 0 HcmV?d00001 diff --git a/version24/BacktrackDialog.java b/version24/BacktrackDialog.java new file mode 100644 index 00000000..924e4118 --- /dev/null +++ b/version24/BacktrackDialog.java @@ -0,0 +1,189 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; + +import javax.swing.border.Border; +import java.util.EventObject; +import java.util.Vector; +import java.io.*; + +/* Package: GUI */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + + +public class BacktrackDialog extends JDialog +{ private JPanel bottom; + private JButton okButton, cancelButton; + private BacktrackDialogPanel dialogPanel; + private String defaultName; // stereotype + private String defaultEntity; + private String defaultRole; // for add, remove, setatt, findByatt + + private String defaultDescription; + private String extendsUC; + + private String newName; + private String newEntity; + private String newRole; + private String newDescription; + private String newExtends; + private String newType; + + public BacktrackDialog(JFrame owner) + { super(owner, true); + setTitle("Define Backtracking"); + okButton = new JButton("Ok"); + cancelButton = new JButton("Cancel"); + ButtonHandler bHandler = new ButtonHandler(); + okButton.addActionListener(bHandler); + cancelButton.addActionListener(bHandler); + bottom = new JPanel(); + bottom.add(okButton); + bottom.add(cancelButton); + bottom.setBorder(BorderFactory.createEtchedBorder()); + dialogPanel = new BacktrackDialogPanel(); + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(bottom, BorderLayout.SOUTH); + getContentPane().add(dialogPanel, BorderLayout.CENTER); + } + + public void setOldFields(String nme, String ename, String rname, String poss) + { defaultName = nme; + defaultEntity = ename; + defaultRole = rname; + newExtends = poss; + dialogPanel.setOldFields(nme,ename,rname,poss); + } + + public void setFields(String nme, String ename, String rname, + String desc, String ext, String typ) + { newName = nme; + newEntity = ename; + newRole = rname; + newDescription = desc; + newExtends = ext; + newType = typ; + } + + public String getName() { return newName; } // use case name + public String getEntity() { return newEntity; } // context entity + public String getRole() { return newRole; } // backtrack condition + public String getDescription() { return newDescription; } // undo statements + public String getParameters() { return newExtends; } // possible choices expression + public String getUseCaseType() { return newType; } // success condition + + class BacktrackDialogPanel extends JPanel + { private JLabel nameLabel; + JTextField nameField; /* name */ + private JLabel entityLabel; + JTextField entityField; + private JLabel roleLabel; + JTextField roleField; + JLabel descriptionLabel; + JTextArea descriptionArea; + JLabel extendsLabel; + JTextField extendsField; + JLabel typeLabel; + JTextField typeField; + + public BacktrackDialogPanel() + { nameLabel = new JLabel("Use case name:"); + nameField = new JTextField(); + nameField.setEditable(true); + + entityLabel = new JLabel("Entity:"); + entityField = new JTextField(); + roleLabel = new JLabel("Backtrack condition:"); + roleField = new JTextField(); + descriptionLabel = new JLabel("undo statements:"); + descriptionArea = new JTextArea(); + extendsLabel = new JLabel("Choice expression:"); + extendsField = new JTextField(); + typeLabel = new JLabel("Success condition:"); + typeField = new JTextField(); + typeField.setEditable(true); + + add(nameLabel); + add(nameField); + add(entityLabel); + add(entityField); + add(roleLabel); + add(roleField); + add(descriptionLabel); + add(descriptionArea); + add(extendsLabel); + add(extendsField); + add(typeLabel); + add(typeField); + } + + public void setOldFields(String nme, String entity, String role, String poss) + { nameField.setText(nme); + entityField.setText(entity); + roleField.setText(role); + descriptionArea.setText(""); + extendsField.setText(poss); + } + + public Dimension getPreferredSize() + { return new Dimension(450,300); } + + public Dimension getMinimumSize() + { return new Dimension(450,300); } + + public void doLayout() + { nameLabel.setBounds(10,10,110,30); + nameField.setBounds(120,15,270,20); + entityLabel.setBounds(10,40,110,30); + entityField.setBounds(120,45,270,20); + roleLabel.setBounds(10,70,110,30); + roleField.setBounds(120,75,270,20); + descriptionLabel.setBounds(10,110,90,30); + descriptionArea.setBounds(120,105,300,100); + extendsLabel.setBounds(10,210,90,30); + extendsField.setBounds(120,215,270,20); + typeLabel.setBounds(10,240,90,30); + typeField.setBounds(120,245,270,20); + } + + public void reset() + { nameField.setText(""); + entityField.setText(""); + roleField.setText(""); + descriptionArea.setText(""); + extendsField.setText(""); + } + } /* inner class */ + + class ButtonHandler implements ActionListener + { public void actionPerformed(ActionEvent ev) + { JButton button = (JButton) ev.getSource(); + String label = button.getText(); + if ("Ok".equals(label)) + { setFields(dialogPanel.nameField.getText(), + dialogPanel.entityField.getText(), + dialogPanel.roleField.getText(), + dialogPanel.descriptionArea.getText(), + dialogPanel.extendsField.getText(), + dialogPanel.typeField.getText()); + } + else + { setFields(null,null,null,null,null,null); } + + dialogPanel.reset(); + setVisible(false); + } + } +} + + + + diff --git a/version24/BacktrackingSpecification.class b/version24/BacktrackingSpecification.class new file mode 100644 index 0000000000000000000000000000000000000000..c8bc1a7d82c9ae4946f34d4ec101354cb29175d5 GIT binary patch literal 10273 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 L^EPnfpm+Wc;)5m? literal 0 HcmV?d00001 diff --git a/version24/BacktrackingSpecification.java b/version24/BacktrackingSpecification.java new file mode 100644 index 00000000..18f42f24 --- /dev/null +++ b/version24/BacktrackingSpecification.java @@ -0,0 +1,501 @@ +import java.util.Vector; + +/* Package: Transformations */ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BacktrackingSpecification +{ Entity context; + UseCase transformation; + Constraint rule; // first postcond of use case + Expression success = null; // optional + Expression backtrack; + Expression successAction = new UnaryExpression("->display", new BasicExpression("\"search succeeded\"")); // optional + Expression possible; // 1st quantifier range of rule + Statement undoAction; + + Type valueType; // possible.elementType + Attribute history; + Attribute chosen; + String valueVar; + + public BacktrackingSpecification(Entity e, UseCase uc, Expression bktk, + Expression poss, Statement undo) + { context = e; + transformation = uc; + backtrack = bktk; + possible = poss; + undoAction = undo; + + String nme = transformation.getName(); + Type seqtype = new Type("Sequence",null); + Type seqtype1 = new Type("Sequence",null); + Type settype = new Type("Set",null); + valueType = possible.getElementType(); + settype.setElementType(valueType); + + if (valueType == null) + { System.err.println(possible + " must have valid element type"); } + else + { history = new Attribute(nme + "$history",seqtype,ModelElement.DERIVED); + history.setElementType(seqtype1); + history.setEntity(context); + history.setInstanceScope(false); + context.addAttribute(history); + chosen = new Attribute(nme + "$chosen",settype,ModelElement.DERIVED); + chosen.setElementType(valueType); + chosen.setEntity(context); + context.addAttribute(chosen); + rule = (Constraint) transformation.getPostcondition(1); + // valueVar is 1st quantified variable + } + } + + public void generateDesign1(Vector types, Vector entities) + { addGetPossibleValues(types,entities); + modifyRule(); + } + + public void generateDesign2(Vector types, Vector entities) + { addSuccessTest(types,entities); + addSuccessAction(types,entities); + addRedo(types,entities); + // addUndo(types,entities); + addBacktrackTest(types,entities); + addBacktrackop(types,entities); + } + + public void setSuccess(Expression se) + { success = se; } + + public void addSuccessTest(Vector types, Vector entities) + { if (success == null) { return; } + String nme = transformation.getName(); + Type booltype = new Type("boolean",null); + BasicExpression res = new BasicExpression("result"); + res.setType(booltype); + BasicExpression betrue = new BasicExpression(true); + betrue.setType(booltype); + res.setUmlKind(Expression.VARIABLE); + Expression eqtrue = new BinaryExpression("=", res, betrue); + Expression succtest = new BinaryExpression("=>", success, eqtrue); + BehaviouralFeature stest = new BehaviouralFeature(nme + "success", new Vector(), true, booltype); + stest.setPost(succtest); + // stest.setDerived(true); + stest.setEntity(context); + context.addOperation(stest); + stest.typeCheck(types,entities); + } + + public void addSuccessAction(Vector types, Vector entities) + { if (successAction == null) { return; } + String nme = transformation.getName(); + BehaviouralFeature sop = new BehaviouralFeature(nme + "successAction", new Vector(), false, null); + sop.setPost(successAction); + // sop.setDerived(true); + sop.setEntity(context); + context.addOperation(sop); + sop.typeCheck(types,entities); + } + + public Statement getSuccessCase(String evar) + { // if evar.nmesuccess() then (evar.successAction(); return false) + Type booltype = new Type("boolean",null); + String nme = transformation.getName(); + BasicExpression successtest = + new BasicExpression(evar + "." + nme + "success()", 0); + Expression successteste = successtest.checkIfSetExpression(); + if (successteste == null) { return null; } + successteste.setUmlKind(Expression.QUERY); + successteste.setType(booltype); + successteste.setEntity(context); + BasicExpression befalse = new BasicExpression(false); + befalse.setType(booltype); + Statement retfalse = new ReturnStatement(befalse); + BasicExpression successop = + new BasicExpression(evar + "." + nme + "successAction()", 0); + Expression successope = successop.checkIfSetExpression(); + if (successope == null) { return null; } + successope.setUmlKind(Expression.UPDATEOP); + successope.setEntity(context); + InvocationStatement callop = new InvocationStatement(evar + "." + nme + "successAction()",null,null); + callop.setCallExp(successope); + SequenceStatement callsuccess = new SequenceStatement(); + callsuccess.addStatement(callop); + callsuccess.addStatement(retfalse); + callsuccess.setBrackets(true); + Statement res = new IfStatement(successteste, callsuccess); + res.setEntity(context); + return res; + } + + /* public void addUndo(Vector types, Vector entities) + { if (undoAction == null) { return; } + String nme = transformation.getName(); + Vector pars = new Vector(); + String var = rule.getSecondaryVar(0); + BasicExpression v = new BasicExpression(var); + v.setUmlKind(Expression.VARIABLE); + v.setType(valueType); + Attribute valx = new Attribute(var, valueType, ModelElement.INTERNAL); + pars.add(valx); + Type booltype = new Type("boolean",null); + BasicExpression betrue = new BasicExpression("true"); + betrue.setType(booltype); + + BehaviouralFeature sop = new BehaviouralFeature(nme + "undo", pars, false, null); + sop.setPost(betrue); + // sop.setDerived(true); + sop.setEntity(context); + SequenceStatement undoss = new SequenceStatement(); + // _history := _history.front + BasicExpression hist = new BasicExpression(history); + AssignStatement sethistfront = + new AssignStatement(hist, new UnaryExpression("->front", hist)); + undoss.addStatement(sethistfront); + undoss.addStatement(undoAction); + // _chosen := Sequence{} + BasicExpression ch = new BasicExpression(chosen); + SetExpression empty = new SetExpression(); + // empty.setOrdered(true); + AssignStatement setch = + new AssignStatement(ch, empty); + undoss.addStatement(setch); + sop.setActivity(undoss); + context.addOperation(sop); + sop.typeCheck(types,entities); + } */ + + public void addRedo(Vector types, Vector entities) + { if (undoAction == null || rule == null) { return; } + String nme = transformation.getName(); + Vector pars = new Vector(); + String var = rule.getSecondaryVar(0); + BasicExpression v = new BasicExpression(var); + v.setUmlKind(Expression.VARIABLE); + v.setType(valueType); + Attribute valx = new Attribute(var, valueType, ModelElement.INTERNAL); + v.variable = valx; + pars.add(valx); + Type booltype = new Type("boolean",null); + BasicExpression betrue = new BasicExpression(true); + betrue.setType(booltype); + + BehaviouralFeature sop = new BehaviouralFeature(nme + "redo", pars, false, null); + sop.setPost(betrue); + // sop.setDerived(true); + sop.setEntity(context); + + SequenceStatement redoss = new SequenceStatement(); + + + // v := getPossibleValues()->any() + BasicExpression getpossvalues = + new BasicExpression("getPossibleValues()", 0); + Expression possee = getpossvalues.checkIfSetExpression(); + if (possee == null) { return; } + possee.setUmlKind(Expression.QUERY); + possee.setType(possible.getType()); + possee.setElementType(valueType); + possee.setEntity(context); + UnaryExpression anyexp = new UnaryExpression("->any", possee); + AssignStatement reassign = new AssignStatement(v,anyexp); + redoss.addStatement(reassign); + + String rulename = transformation.getName() + rule.getId(); + BehaviouralFeature bf = context.getOperation(rulename); + if (bf == null) + { System.err.println("No operation for rule: " + rulename); + return; + } + + InvocationStatement bfcall = new InvocationStatement(bf); + bfcall.setEntity(context); + redoss.addStatement(bfcall); + + sop.setActivity(redoss); + context.addOperation(sop); + sop.typeCheck(types,entities); + } + + public void addBacktrackTest(Vector types, Vector entities) + { if (backtrack == null) { return; } + String nme = transformation.getName(); + Type booltype = new Type("boolean",null); + BasicExpression res = new BasicExpression("result"); + res.setType(booltype); + BasicExpression betrue = new BasicExpression(true); + betrue.setType(booltype); + res.setUmlKind(Expression.VARIABLE); + BasicExpression zero = new BasicExpression(0); + BasicExpression getpossvalues = + new BasicExpression("getPossibleValues()", 0); + Expression getpossvaluese = getpossvalues.checkIfSetExpression(); + if (getpossvaluese == null) { return; } + getpossvaluese.setUmlKind(Expression.QUERY); + getpossvaluese.setType(possible.getType()); + getpossvaluese.setElementType(valueType); + getpossvaluese.setEntity(context); + UnaryExpression posssize = new UnaryExpression("->size", getpossvaluese); + Expression backtracke = new BinaryExpression("=", posssize, zero); + Expression eqtrue = new BinaryExpression("=", res, betrue); + Expression succtest = + new BinaryExpression("=>", backtracke, eqtrue); + BehaviouralFeature stest = new BehaviouralFeature(nme + "backtracktest", new Vector(), true, booltype); + stest.setPost(succtest); + // stest.setDerived(true); + stest.setEntity(context); + context.addOperation(stest); + stest.typeCheck(types,entities); + } + + public Statement getBacktrackCase(String evar) + { // if evar.nmebacktracktest() then (result = evar.backtrack(); return result) + Type booltype = new Type("boolean",null); + String nme = transformation.getName(); + BasicExpression backtracktest = + new BasicExpression(evar + "." + nme + "backtracktest()", 0); + Expression backtrackteste = backtracktest.checkIfSetExpression(); + if (backtrackteste == null) { return null; } + backtrackteste.setUmlKind(Expression.QUERY); + backtrackteste.setType(booltype); + backtrackteste.setEntity(context); + // BasicExpression befalse = new BasicExpression("false"); + // befalse.setType(booltype); + // Statement retfalse = new ReturnStatement(befalse); + BasicExpression backtrackop = + new BasicExpression(evar + "." + nme + "backtrack()", 0); + Expression backtrackope = backtrackop.checkIfSetExpression(); + if (backtrackope == null) { return null; } + backtrackope.setUmlKind(Expression.UPDATEOP); + backtrackope.setEntity(context); + backtrackope.setType(booltype); + + BasicExpression res = new BasicExpression("result"); + res.setType(booltype); + res.setUmlKind(Expression.VARIABLE); + AssignStatement callop = new AssignStatement(res, backtrackope); + Statement testres = + // new IfStatement(res, new SequenceStatement(), + new ReturnStatement(res); + SequenceStatement callbacktrack = new SequenceStatement(); + callbacktrack.addStatement(callop); + callbacktrack.addStatement(testres); + callbacktrack.setBrackets(true); + Statement resb = new IfStatement(backtrackteste, callbacktrack); + resb.setEntity(context); + return resb; + } + + public void addGetPossibleValues(Vector types, Vector entities) + { if (possible == null) { return; } + String nme = transformation.getName(); + Type settype = possible.getType(); + BasicExpression res = new BasicExpression("result"); + res.setType(settype); + BasicExpression ch = new BasicExpression(chosen); + res.setUmlKind(Expression.VARIABLE); + Expression sub = new BinaryExpression("-", possible, ch); + Expression eqres = new BinaryExpression("=", res, sub); + BehaviouralFeature stest = new BehaviouralFeature("getPossibleValues", new Vector(), true, settype); + stest.setPost(eqres); + // stest.setDerived(true); + stest.setEntity(context); + // stest.setType(settype); + stest.setElementType(valueType); + context.addOperation(stest); + stest.typeCheck(types,entities); + } + + public void addBacktrackop(Vector types, Vector entities) + { if (history == null || possible == null || + chosen == null) + { return; } + String nme = transformation.getName(); + String evar = context.getName().toLowerCase() + "x"; + Type booltype = new Type("boolean",null); + Type settype = possible.getType(); + BasicExpression betrue = new BasicExpression(true); + betrue.setType(booltype); + BasicExpression befalse = new BasicExpression(false); + befalse.setType(booltype); + ReturnStatement rettrue = new ReturnStatement(betrue); + ReturnStatement retfalse = new ReturnStatement(befalse); + + BasicExpression ch = new BasicExpression("chosen"); + ch.setType(chosen.getType()); + ch.setElementType(valueType); + ch.setUmlKind(Expression.VARIABLE); + Expression zeroexp = new BasicExpression(0); + BasicExpression getpossvalues = + new BasicExpression(evar + ".getPossibleValues()", 0); + Expression getpossvaluese = getpossvalues.checkIfSetExpression(); + if (getpossvaluese == null) { return; } + getpossvaluese.setUmlKind(Expression.QUERY); + getpossvaluese.setType(possible.getType()); + getpossvaluese.setElementType(valueType); + getpossvaluese.setEntity(context); + + Expression hist = new BasicExpression(history); + BasicExpression histsize = new BasicExpression("size"); + histsize.setObjectRef(hist); + Expression histtest = new BinaryExpression(">", histsize, zeroexp); + + // _histlast : Sequence := _history.last + // CreationStatement crehistlast = new CreationStatement("Sequence", "_histlast"); + BasicExpression histlast = new BasicExpression("_histlast"); + histlast.setType(history.getElementType()); + histlast.setUmlKind(Expression.VARIABLE); + UnaryExpression lst = new UnaryExpression("->last", hist); + BinaryExpression castlst = + new BinaryExpression("->oclAsType", lst, new BasicExpression("Sequence")); + AssignStatement gethistlast = + new AssignStatement(histlast, castlst); + gethistlast.setType(history.getElementType()); + + // evar : E := _histlast[2] + // CreationStatement creevar = new CreationStatement(context.getName(), evar); + BasicExpression ex = new BasicExpression(evar); + ex.setType(new Type(context)); + ex.setUmlKind(Expression.VARIABLE); + BasicExpression secondind = (BasicExpression) histlast.clone(); + secondind.setArrayIndex(new BasicExpression(2)); + BinaryExpression cast2ndind = new BinaryExpression("->oclAsType", secondind, + new BasicExpression(context + "")); + AssignStatement getevar = + new AssignStatement(ex, cast2ndind); + getevar.setType(new Type(context)); + + // $value : valueType := _histlast.last + // CreationStatement creeval = new CreationStatement(valueType + "", "$value"); + BasicExpression valx = new BasicExpression("$value"); + valx.setType(valueType); + valx.setUmlKind(Expression.VARIABLE); + BasicExpression finalind = (BasicExpression) histlast.clone(); + finalind.setArrayIndex(new BasicExpression(3)); + BinaryExpression castfinal = new BinaryExpression("->oclAsType", finalind, + new BasicExpression("" + valueType)); + AssignStatement getval = + new AssignStatement(valx, castfinal); + getval.setType(valueType); + + // _history := _history.front + BasicExpression hist2 = new BasicExpression(history); + AssignStatement sethistfront = + new AssignStatement(hist2, new UnaryExpression("->front", hist2)); + // redoss.addStatement(sethistfront); + + // redoss.addStatement(undoAction); + + // chosen : Set(valueType) := ex.getPossibleValues() + CreationStatement creech = new CreationStatement("Set", "chosen"); + creech.setType(chosen.getType()); + creech.setElementType(valueType); + + AssignStatement getch = + new AssignStatement(ch, getpossvaluese); + + BasicExpression chsize = new BasicExpression("size"); + chsize.setObjectRef(ch); + chsize.setType(new Type("int", null)); + + BinaryExpression chgr0 = new BinaryExpression(">", chsize, zeroexp); + + BasicExpression redoop = + new BasicExpression(evar + "." + nme + "redo($value)", 0); + Expression redoope = redoop.checkIfSetExpression(); + if (redoope == null) { return; } + redoope.setUmlKind(Expression.UPDATEOP); + redoope.setEntity(context); + InvocationStatement callredo = new InvocationStatement(evar + "." + nme + "redo($value)",null,null); + callredo.setCallExp(redoope); + SequenceStatement redoss = new SequenceStatement(); + redoss.addStatement(callredo); + redoss.addStatement(rettrue); + + /* BasicExpression undoop = + new BasicExpression(evar + "." + nme + "undo($value)", 0); + Expression undoope = undoop.checkIfSetExpression(); + if (undoope == null) { return; } + undoope.setUmlKind(Expression.UPDATEOP); + undoope.setEntity(context); + InvocationStatement callundo = new InvocationStatement(evar + "." + nme + "undo($value)",null,null); + callundo.setCallExp(undoope); */ + + IfStatement ifstat = new IfStatement(chgr0,redoss); + + SequenceStatement sstat2 = new SequenceStatement(); // inner ss + sstat2.setBrackets(true); + // sstat2.addStatement(crehistlast); + sstat2.addStatement(gethistlast); + // sstat2.addStatement(creevar); + sstat2.addStatement(getevar); + // sstat2.addStatement(creeval); + sstat2.addStatement(getval); + sstat2.addStatement(sethistfront); + sstat2.addStatement(undoAction); + sstat2.addStatement(creech); + sstat2.addStatement(getch); + sstat2.addStatement(ifstat); + + SequenceStatement sstat = new SequenceStatement(); + WhileStatement ws = new WhileStatement(histtest, sstat2); + ws.setLoopKind(Statement.WHILE); + sstat.addStatement(ws); + sstat.addStatement(retfalse); + + BehaviouralFeature bop = new BehaviouralFeature(nme + "backtrack", new Vector(), false, booltype); + bop.setPost(betrue); + bop.setInstanceScope(false); + // bop.setDerived(true); + bop.setEntity(context); + bop.setActivity(sstat); + context.addOperation(bop); + bop.typeCheck(types,entities); + } + + public void modifyRule() + { // replaces possible by getPossibleValues(), adds + // assignments to chosen and history + String var = rule.getSecondaryVar(0); + Expression quant = rule.getSecondaryQuantifier(0); + BasicExpression v = new BasicExpression(var); + v.setUmlKind(Expression.VARIABLE); + v.setType(valueType); + BasicExpression getpossvalues = + new BasicExpression("getPossibleValues()", 0); + Expression getpossvaluese = getpossvalues.checkIfSetExpression(); + if (getpossvaluese == null) { return; } + getpossvaluese.setUmlKind(Expression.QUERY); + getpossvaluese.setType(possible.getType()); + getpossvaluese.setElementType(valueType); + getpossvaluese.setEntity(context); + rule.replaceSecondaryRange(1,var,getpossvaluese); + Expression ante = rule.antecedent(); + Expression newante = ante.substitute(quant, getpossvaluese); + rule.setAntecedent(newante); + + BasicExpression che = new BasicExpression(chosen); + BinaryExpression addchosen = new BinaryExpression("->includes",che,v); + BasicExpression histe = new BasicExpression(history); + String rulename = transformation.getName() + "1"; + BasicExpression rle = new BasicExpression("\"" + rulename + "\""); + rle.setType(new Type("String",null)); + BasicExpression selfexp = new BasicExpression("self"); + selfexp.setType(new Type(context)); + Vector vals = new Vector(); + vals.add(rle); vals.add(selfexp); vals.add(v); + SetExpression tuple = new SetExpression(vals); + tuple.setOrdered(true); + BinaryExpression addhist = new BinaryExpression("->includes",histe,tuple); + rule.addSuccedent(addchosen); + rule.addSuccedent(addhist); + } + +} diff --git a/version24/BasicExpression.class b/version24/BasicExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..f9829bff1c87c4f68a1101ca47ef23b5293a9f81 GIT binary patch literal 295604 zcmcG131A#m{r_yT+4;`Qo7wcH(9kVZNYXZ?+@ztX?-TF)zESyqKJU%!&L&$#e*7tU`|jiWzSsM{W1jub zBad5_b!hr_*J_gGj@2PubXL$gj?VFPx}C)HasquP(&?eIlFlkRt3}rE_ar)N>GZmZ zy!6poM`yhwC(9|eoa$QBWVy&`{5@Ud4E~ceHCqN4$cb!X zU^4?-=*!!34g*{13^Hbj&ai_KqOo}SiPCfTU^9k&*&|5a%|)VksC$c>dH-WwgYF7 zzH@E4*|pA=Tj<=%-ri=*+gxiv-fqh~Tx%0kHp%U_ypxG{h}^nHlVLv(gAZa0VW zu*ip5>LVhLu*OH3g4viYA9dhhdLI*cT;yXSPcZgL#(rGn6C$4!c}nDIk!M(DSmaY8 zpCmCwr;h-hCF`4R&_r!TwKoy3GY{DhPCQ<0ysM?V+&1-tx9 z_UTt5zh>ZEk>7~?mid0iLcgc;2X^z1B7YM3GsAyj_^Wjs;|L61G$4T3_Xmb~*LpB*keECnb(8j)>!knqr~yW3B*Z@(@Chd;>;4KNt}JfnJrF6oH^p`C(i!j%tcR}*NAg~ zI0uT;EKZ9!t>VlRXTCTK#Ay>}p*RPLvq+qS#W_TrL&Z5voWsRALYyPTIZB*%aTbfy zA!btXYjVJSW|M%MoD~?lbDTKGi_kK#~NN1Bco5cZ3YH~o(9nLxQZKb38 z52m!s0Rw7s3gQ6aJDhXrjM`37oRXVZ<&4qUMrS)ycG%8NH__*uC(ii{Um(tfw)0vy zaVq#y;#B7%Iv0y`i8z;v^Ezg^jLz%nTrSQPuJZ=xN(Qc?bG7YU!{2Ld=Z*ZmPMkOK z_s!zGMI1o>261i_=dI%01d4TT76+`N$+=aW+r)XBIByr{9pc$w10FHk`H(mdi38R! z+u1G7!{U5coR5g}h&Ydm^HFggBg7sT=VO=(Ia{13*q}vmx+= z4krOehHd9l;(Qt`(|J}Lu!Roivz)@uiSwK|pBLu~;(Sq@FNp(o(ByoDXbp9#M3*!7soPTo= zXNp5wXZ0@v;atmh6K>*pw~kId#IKvA(_p(P{@Qeej>8PDxSqHQ6}Y~*fw*aU8_^GU zlDL!6oI8avQ^~Z!>CU4FYI3KEJDq7Wz}tZU?q1@~6nAfN_hIH)%+f?>UpliHm!WSC zefx>KzqoV7eT}#WhnxL^>oT`~w4tl$WDJ%!m8aZhIDr-*y1 zxTn#3y0~XR9dXYT_bhR#l(=V$n-zDXxc%Y|uyW9Thr5Z+W;&q%T`r)x%RPtAR<4+7k7uaJHLK-0Q@B zlelkY$KJw>U_-my>&3l6+#AJxtGG9bi^;!5+*?`cZOr&Kao;ZPJDBr!ao;KK9pc_8 z?z=#l?z@=_JYbi5m$={nv)%WK`#y2+5%*qk?-Q5$f_tL49}xG0;@&Ur1L8g??uW$1 zFgx5`U~=wmmcz7lxYQ2ZkBIw-xER7m#eGcN$Ho1axKD@+ZJ32{Fu?o;AE zE$%boeoEX=i~Fp&pAq-7;(kut=fwTIxL*+Wi{gGs+%Jp!6>+~R?$^ZqIxF~wxZf1_ zTjG9O-0z6{U2(rB?)Sz0fw<3$`$KVmB<_#J{fW3g758W2{#@K&i2F-%elW_> z@lF)4N4%BPjjx8oVK;fJ#9J-i8u3mNZ>@N};`NEQPQ3Nvoh;rd;+-nqY2uwO-WlSZ zDc)J)Z4mEl@v`D=6t7>r0r7I;Z4z&@cw5BFi+7HATg4j`4>G*NgACv06~r4652VxK zjfz(kuf*6f@wSP#UA!GgfZE~h6z@FoAiigN7l?PEc%)_zq&(ZZm}M^#?-F)h&(o#i zy-vK##CyGXmy1VI_CU(By(^jZ4dPuT-qqq=Bi^;*y-~dD#Cwx?Zx-(@;$1J^4dUI% zx@_^@D&9@v-7MZM;@v9VZQ{L6ytj+@4)Jam@15e^A>N(hQGk0O-`QXb-h0HmOT4?q zdoP=OpLq9(cdvN&iT8f-J|Nx)#k*g;2gG|&JSg_Fy@$lxCEjlF9v1Jz;(bKCN5p%S zg+D6ZW8yt7-p9myLcAx%`?z?Y5bu-XJtf}L;yokYr^NfTc+ZOW8Sy?V-sjkJ5$`$i zJ}=%E#QUOnUlQ-j;(bNDuZs6I@xCtJH^lp=kW_R zu zE6Nk4MERluQE5?)q9%!&ENY4vN7O7)O``S{HCt3h z)ErU!iP~S(Tv4wPb%3Y?MKxody9I@VT8-DD@%z8wnEwnKH=YPp*{PIV#R zJPRsTRbwWu|sP7<|N zRIjK$QR_sl7j?3zQ$(FA>NHWOi#kKpnWD}TwL#R`qOzhkis~0NASx$n6Fa(D)D}@_ z@*GiHMGcA?5;ZKUAZkR^xuQlz6-AXqjfvVOYP+Z%qIQZpPt^IME)aF0sMm_RNYurm zE)jL9sMm?QOw{W|T`uYhQEw1+rKqb!L3(zmYv^1nii)$kP81bq^=3M65p}(&8${hG z>aC2piO$V*pgwmfickd++M(V?=k0VLMmyB)blyql4mx+zAw4S4V~2t`?NE2oxtk71 zvO~R(&OM^;-p}6;i25LZ?-%s|e;*X}A^tujYL}?pq8=6niQ1$-BI*(TKFTTj z2pz!hqoN)Y^*9TBOw<#io)q_F z`jIFQYKQuXsGo`gneI|Q7xfEKzZCT=QNI@T8&SU%^*d3&7xf2Ge-!m6QGaG5f1&eN zQGes_-$g-_p6y=Xs(-2%MEy(DzeW8=)QjR<;wQwf6Te>kBr^F8;-|#7#TW4%@m=vf z@s;?#_<{Io@f*dTB>rUar-(mQ{AuD(7awwRm%o?zGsWLq{C&iqC4Q6m`-(qX{EYZ> z#NSW+{l%Xv{%gcPK>P#6Zx+8r{8sVji4XbM;r&ef1>(1fzfk;x#9t)-!Qvkx{-NR@ zCjQ~#A0hsc;va>)e!KXK#qSXRXz`aY;u!Idstvf0g*FnPrXmCyBpS{9f_<#9t@=dht&d{}l0075_BxPZ$3T@y`_hEb%vp zf42Bp@i&U!FaCh|Iq^4%zghe(;^)ObNBphg4~jn|{;>E3@kf9F{<*e4Dt^)SOK!tO za+}+5p+9E(+uVjr{q45D!)>_C-|jZtft5$Y9sW*s>pT{NgzS*(QN-VA`xm$k*Z3ET z|61F>h}kZ78?N)m#J_}rOT~Yk_?Lv6f z-@>+UrE{C@zs+s<5bE~d?!QC)+aYOu5OR}$hxm7j|1R<0ZTs(W8$Rl97oRljlZO5G zivK>_zsGI(xPLDO2sVjP-bd&CbUwg5A7pg*FjBkz4+f?E8ip>zD4KTbiO10clrB0ra?|O!AbP_KcMqGdC(Z+en{s> z%<^M5b)x?hrv6lXaDpcP=X8F7RgeEm`hLY+zorkOyUG78gTLd%U&!F^;Zx8poBTg8 z;g59w#2|P@lMi0ew$AFT+w}Ze<9f?^?9T}uqppm{w zbS5)MJw2Ez!89y6gXt20*>qsp5bVXonRNE1vyTL`BxrJjeVw&-FdHBXGIZu3CfHAc z{Uw+y!D}QqK!O7$XqKQwf>sIUNibi61#F~Ef`t+sB*7w9cra!#IE21KVfY9Rli+X( zj*#F;367GWU4q3DbVvXlp($A62FC=)O0ZOdWfF9{sn-UO_jf_J2)ZO#0dKHGg5zLP z;6$8<{9wowpY$~a$4k&H!3h$aC_#@MtdwAtgDO_jSp(Z@a1v`=D?zUWeQau-1nU`f za>BCn#jb6+;Znj%oR+X;ps;Qn@`XXXkKo9PUBA_>MIrt{rPN(6U#!UCak?Nn#ycfwV1G`HutO>&W`Sk zYgViW zJ>yb=Wd~G}Pp@>fM#jmge_Zi|wWu0?6G*G2Mn%(65xYF0ve(qWj9L}UKn3fwgJTnG zIHE=kH4w2zr}iQABI29SGYoUW(BgW z?5zP~xXFYuoL;Lx6Gx?E;vCA1JRVc4|7?22*l<6IYeLhVwVJNr=;D{x#L@q)mROCo zy4YQ-{L279t-6TAo!P;`2}9j82L3k)5(7^f%Z=`=S#MWO))&XYmj}dIXvN@J&1M$v zp_xzw)F7Oib2|~L|7C7wqFY+V<_0E!6dWp6I___Y2OyftW2?;_W@HBj)6!(H`T_IDSh66$rg*fFFV+NjL;ql57;<_lvR0sG z+5~r=)?XMdW%I+u-m#6jvY>*PsDcRvhhKy$GniXBR>}^SFr;#Y@i9T3=Zg^WOZ)qw z;Godh2(+Rcg}&BlAiOJZSseFM(s^65#Yi?mh?%lcgsH$8$n_V7MhZo$E&1VXg{`^O z!z=QmMSx{ z6(S#CwGp*k>!v<@Wdz0aP{NnPRAIWuPl<}7^aQj(<;2i(6|6EIW`XXi!6&Q+C?utw z2@8FLLTe+t>023}sx@bi^_8{V0HG=!#p4Ld$te>8a^{O`a|2`jxkzM?HlWM`+qdOL zOI}ij$qf0Tt6t*X#e@*n$i4F zzLejFUQENxb{gW(je`5+MsvgchzGwNPeC!p5w2(^!ekr-h&QoHp?OWHG*ne8(?Cic z&5aCdaw_-78$i#>q1h8F8rO0PTme%IFmJ-Lsgv9fXnA-Xd|*c*jmL3q;wVWxkc$uF?fR%SQn`^{nreRA@})uS98a0ECJ`j=tFmM``eM)f+(8_MojSr`B= zk!HN1{BR{S3Fx7*HlHhkbq#cbfB0AmV)ALxqprJT6(H7Eyj5lN~X(h{L9qU`mJ8X_2lq0CMD5MUxQh=4{2{$i(A1fs_hnMlfj`xj2hL z4W$CsYgo&d3Z1=uJwUi(DLWc!5?FhVr%3YSMxdUS^F4V;HcUQ%lrKhHbm_>*V7UIo zRD(n5h}=Mw4%{jgdh#$vWCu-?Ua6q_Z$gvCin$`an?g+a& zg@xc&!=;lUE^?z-j!Zy6jCUXhvdRsB#EG&4G=qRdv|$9J?>z~Fw(~cx z&^Q4Ug2jBPaM~e|N2S8*e#nNoVY_9@KCNbxtafOdF4jFXQlX6Msh-eRoSOmsP1Cwu zK!T6soUf6HU0YEg*qstIrcUA~rXb$8(6FOtOXCl?I5-~7NdN-Crx|P9NKzisI953$ zLsOG0m{Q|6>e!Ys+bNa7My9@l~rI z6*^#}X~2F2ILfu8k;08}vLpPUD`W@G83PRqzWBtX_pkDhK+=>`v3^68PEPB9FK&}C3 z425A+a%%rzwg|1Fgn`B?oLMWHxO{lR+GE-gFpt$L*V(%zI||a8Q8RJP8Zca)axNFM zrdw00Bf^$z#G*|zgmU4iwMo@gbh4c(BhhLO`dqoOy=ugUE$%4^&CaY*Dr$Rrtu%JP zDR-buOS&h0WECjmu6oXG(PqFm^I_YIQ7@v>boC#+>JW1?c?t*swaO-tD032`LUc-v7wWBAo|u121hv2Ll| zkJ#8q8nG^P4^QltiL35b_i&AFA(D`bbriIhC+$_nqhrE0YDJ@&Y2$K7EybXsYtfCx zXl!k6sKCW*?}Vuuugu2r?X-!wUQ@S=^~y994x(l}MiIkAlRp~9l*;hJ1OhEKj)*nI zYBo_5Tdc%aw`k&Pv=}C^#TYmd8*;rEnM9Fct9wX6yL(jz6qSiut{#GJL(iJKu`FW} z7IqfSsgfsH4aGM3|G#}XsXEV;MUbRom)#Ey|~2|VpXj`%5g=b zZP1OC;Uuic>|f?b6S1YLTF~3FxGbD7w(1Oaa26D>ja}!)+l=;ZDs9HWQC$H`cMr!) zH*VC#5s#X*(M)?hZVKb{gv4W2Kh_DQ(Xsy0vehFA>(p8zL(f%}5Q%rM3K~^`D#+jj z4Ry$S`du z1juxES3#gEFdiKzk86GD04zV)HjD2YzY1-}k#l^L%X3)j1{+}`qm5{|WHcRE)vC#p z7+6K0IGX?y)k>T`$dAy5+1QU01Et(jy&q>Paf{Hmu#*q)(z09*P`#U9YszB{R4p>W zSVuLV?}f1;SJ_d)y7W+3EhcWz$2uP^j^pef12*+l48>A}RRH!`ECwgRi~-@1Gb{wF zUNjS}x8o$BH_wqbvXPmbI66_@VyBgXYiHU;v=uftP@S2^Zc~h=yYP5H*>pDrapmpT zax9eJQaN@_wzLJxFEW7 zNpy1DLO57kjwTg>N~OL6m&ymxS)@71gkeoY)0Y!d)66<;LX&_Nn90R)LVjh2m;a$u z&8{_uUF#zx*1+(bu#S9Ly{cJTTJtGvUz8CpC=$ydRbZe5Zqc|=7~TXN2#!e$7QyYBT;p0l#GcQqo@z~?Ni_953JP8&v2;auZS z_>5y@G(HZ(JWrEFxyz=T)i@P4HIxmja+|eX>d@j?KMpfZhz8Fldj(e@ zB6ed%j>;!PX<~4BZX}0;WW)VC7vq#4c-!cfVs$(^GL$X#Z{g%@btmoI zv}SDHsY@Qz%-N3H$M%TeEjlM!=`Ud4O-nYzW(%W+YafFB(MqRlR~yG-<^a1c?!*>5 zs_XBB@-dj(p|^6T_V2{bJm#W0dQ$%u92~@+p5Bc#cI%hPvH^y=en21Ru{w|AS+QC+ zb3538^Nt{rUL0}5_Gq5MeCjwB*TzAr)Z6WPmAW!@l}cSr=Z&fBRO(H1-kf@i3eHa5 zpiehs1snl($YgOuPjJ^gwXTKn;f{j5xodG+@sbEup-p&|L zp3AtQLz0}aWJzXeX+bGJl*?2EOM6BITY@}LB9kp;lzoETXb0!0U~B3Q<$lL*#Lz0# zse-}O4aiCpD#nv~j|zrTZvnOULbh>l3X#FE3JM(1Na_&~mfnd7cT`nyE`}D221ON= z>_FL*Q@>EDU!{Jnf-(4lZNYY&3{<%M`g^d33T7A#Q%(cQc%^{nI?Ey)TxA@z*|GbS zKQGwHk)4Nq3ha8&dp>%O?aR&dLzPYq6vn^^8M+W$YGVPW;OsC?8LHs5cB2X|3bw1@ zV)pA2v>RN?;Op#vsNk~T^(weL^@s|tVDJsWl`6Oj^B7#6x)wOIV2KK@L4x}nhxohH zlWYMAHiR1ihh7Yi4G!7?v08@jMUzpLmLZ&CizXAjz&Zh z@e4)llRd7cD z9WaUYkVcS)u(7i#J6Hsi?<64J6}%hR0z_OfS{TY8W2XIR{7lab=+gxQ8SHlQz+|Qb zKq0}&fTd@KvLnFK_i!riBDzg3XWyFJ8D$NYpxU*^_v&yv%Ib*1;6Np!Tr8};LD!Dv zqoVQFS%pqu71arZ!QCqL*VOM-@ZR8k%3mGqPGC1nYaY}UFMFsZ}`iIY9(b3VuXgjhD4;M-qb2ul16E_*` z32T{#xXkt~*zjh}tW7xw5=H9g7DfPDs^=bd@OiE1y2S~0Q(j!2}Kvm?O=0vE16=?Q1)INfQp|MQNhOv==$Qh zV71Aj-coAVG*~Dw*q_T|nb@s?E;J!~6L1-dC;Cv-XEc_fJN77c{xD^1 z6p@fY=yWJzFsx0ZFkWde5UhgJb~vE26fpuF5ZJmI1skwc!6;OvPr#s#(6^K)mnKyL zE2+PcI9%uo+{n;J|G5C_hG8cQsmAd_xhUfBIx1#YP;r2^DvAxK4@XPr>e<7t9`e)| z$FTF^b&+%HH3etL)d%Ilw+p1y7~k18l>zCcwb!_S+BT z7PTQ*e^A>&DtMZRHwjp-kG_Dd@S*@&Rg#o~F=Rm6H0-r!u-8jz`HTua6?|IR^KFQL z1uX6wfOX^a9_qrvYjA7;dL~r-5OzESRtee2nA@BiRl&2QjL(38?KV0KNy?w4@8Hz$ z?cj3?SITB8`w+6l=Yr4M!538U#o$X6e_zIMTJbke*@q(8J`4iLKAgTIv|}Hsg0BQ$ zRrXPKJC*?C$16xI8T6!DS+P6pqm_M3>hIX&s%Qx2h(;eyFAjt9KyvlxUpOBGD_}ie zV>iFf2A8pvkJ+n8HL~(=AUh(JeQfG8@HV&12Ub(WLYW&qSOwpNDinMx^;2{#gY;tDqY_u>!~B_`Hp=gK+|Ri-&Mi)g71^hd`Q{L z?JnrL6>W}Z>_)h8tn3x+r_qmMiaX2Uu0q}EXDa)6yc}XBj|J05&CU43kPTX-MnPRfe0^rVc3ZT2 zI^4PpHdpI1Ey`ZW$`YvcB;v_h&O)z_I$PO&46W0;-bS9YslaCgWqf;PT;J^Ac|f^s z04yH&9##PO%lp$@;yvv7te-NgYycupH@|0b!7$ zmwUas0nxSTBX}?|tQjqU6_N!vY`{|UU}djo=iRnK<${yfR@u&GW7+ZrCl&lO z_?fa#N&QsWe+zz&k&e6n0&%=x355}n;~vaO$INvtHKFG?B4| zoT1o{nWhe+wLtVqEm%^PksKJcYy2j#n)Et}ZyWUS7ZvMVOn8bfDAO6%iu6#Zg4)eM3RLE%q|RW!!l%Ogm{GoU;W%X z6@mRWK(cjXU16VNb>@J~v{6nN6oVN8=iE^pbe zD!U4zR(scUuUgT)s=M#hC}LF@D`FN?WX$%P-h& zz!2#(3v~y+wXjGP&=rN#Z3e~|HN=F;o;4juGQzP%Cxd01u}UY{f{QrNvpK1st^|&Q z-Zw(Lq{8R5wzg_Eq_xoosN7n5&(#Mgl5?T4!h$sCX+;<@PvURL?b7!^1OS317X#lm#sFjk0k>qpSPXw-zcS#=on|Rb zjD|Q4s|u~H$l{T-!pg8xwfBKZD(%6PlvcPWOQp0ommMVs*24%nIlCXsBLkShtx+t5 zGBC~*^RO+Id3};KtF#}y9%sSO5y%ECu~|=qTU2(5VX(Z}^_BIBzKR3(*S`hbD{whR zc&y%p1#3EmLAEYg5(m*tf~Y)0^ULCfNVV`~Pb{Wh�|f=1|p!~T?vW#?e_l*Wc^COViI%L_mlBSbk3 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 z%0D4BUr6ow15yY62dN|fo79OvC*39>sk1;! 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 + Type arrayType = null; // in e[i] the type of e + + int kind = Statemachine.NONE; + // Statemachine.STATE, Statemachine.STATEMACHINE, etc + int mult = 1; // multiplicity of the owning statemachine + private boolean prestate = false; // has a @pre at end of name + private Vector parameters = null; + // new Vector(); // for operation calls + Attribute variable = null; // in the case of umlkind == VARIABLE + + private String atTime = ""; // e@t + + private boolean alreadyCorrected = false; + // Don't correct type twice for array references. + + BasicExpression(String dd, int i) + { data = dd; } + + BasicExpression(String dd) + { if (dd == null) + { dd = ""; } + int preindex = dd.indexOf('@'); + if (preindex < 0) + { data = dd; + prestate = false; + } + else + { data = dd.substring(0,preindex); + atTime = dd.substring(preindex+1); + System.out.println(">> At-time expression: " + data + " at " + atTime); + prestate = true; + /* if (dd.length() > preindex+4) + { String d2 = dd.substring(preindex+5,dd.length()); + BasicExpression e2 = new BasicExpression(d2); + BasicExpression selfclone = new BasicExpression(data,0); + selfclone.prestate = prestate; + // e2.setInnerObjectRef(selfclone); + data = e2.data; + e2.objectRef = selfclone; + objectRef = selfclone; + prestate = e2.prestate; + } */ + } + + } + + BasicExpression(Entity e) + { if (e == null) + { data = ""; + return; + } + data = e.getName(); + umlkind = CLASSID; + elementType = new Type(e); + type = new Type("Sequence",null); + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + entity = e; + } + + BasicExpression(Entity e, String ex) + { if (e == null) + { data = ""; + return; + } + data = ex; + umlkind = VARIABLE; + elementType = new Type(e); + type = elementType; + entity = e; + multiplicity = ModelElement.ONE; + } + + BasicExpression(Type t, String ex) + { if (t == null) + { data = ""; + return; + } + data = ex; + umlkind = VARIABLE; + type = t; + if (t != null) + { multiplicity = t.typeMultiplicity(); + elementType = t.getElementType(); + } + } + + BasicExpression(String v, Expression e) + { if (e == null) + { data = v; + return; + } + data = v; + umlkind = VARIABLE; + type = e.elementType; + entity = e.entity; + if (type != null) + { multiplicity = type.typeMultiplicity(); } + } + + BasicExpression(Attribute att) + { if (att == null) + { data = ""; + return; + } + data = att.getName(); + umlkind = VARIABLE; + variable = att; + + if (att.getElementType() != null) + { elementType = (Type) att.getElementType().clone(); } + if (att.getType() != null) + { type = (Type) att.getType().clone(); } + + if (type != null && type.getElementType() == null) + { type.setElementType(elementType); } + + entity = att.getEntity(); + if (type != null) + { multiplicity = type.typeMultiplicity(); } + else + { multiplicity = ModelElement.ONE; } + } + + BasicExpression(BehaviouralFeature bf) + { if (bf == null) + { data = ""; + return; + } + data = bf.getName(); + umlkind = UPDATEOP; + elementType = bf.getElementType(); + type = bf.getType(); + if (type != null) + { type.setElementType(elementType); } + entity = bf.getEntity(); + if (type != null) + { multiplicity = type.typeMultiplicity(); } + else + { multiplicity = ModelElement.ONE; } + isEvent = true; + Vector pars = bf.getParameters(); + parameters = new Vector(); + for (int i = 0; i < pars.size(); i++) + { Attribute att = (Attribute) pars.get(i); + parameters.add(new BasicExpression(att)); + } + } + + BasicExpression(int i) + { data = i + ""; + umlkind = VALUE; + elementType = new Type("int",null); + type = new Type("int",null); + multiplicity = ModelElement.ONE; + } + + BasicExpression(long i) + { data = i + ""; + umlkind = VALUE; + elementType = new Type("long",null); + type = new Type("long",null); + multiplicity = ModelElement.ONE; + } + + BasicExpression(double d) + { data = d + ""; + umlkind = VALUE; + elementType = new Type("double",null); + type = new Type("double",null); + multiplicity = ModelElement.ONE; + } + + BasicExpression(boolean b) + { data = b + ""; + umlkind = VALUE; + elementType = new Type("boolean",null); + type = new Type("boolean",null); + multiplicity = ModelElement.ONE; + } + + BasicExpression(Association ast) + { if (ast == null) + { data = ""; + return; + } + data = ast.getRole2(); + umlkind = ROLE; + elementType = new Type(ast.getEntity2()); + type = ast.getType2(); + if (type != null) + { type.setElementType(elementType); } + multiplicity = ast.getCard2(); + entity = ast.getEntity1(); + } + + BasicExpression(Expression obj, Attribute prop) + { if (prop == null) + { data = ""; return; } + // if (obj == null) + // { return new BasicExpression(prop); } + + data = prop.getName(); + entity = prop.getEntity(); + objectRef = obj; + if (entity != null) + { if (entity.hasDefinedAttribute(data)) + { Attribute att = entity.getDefinedAttribute(data); + umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + prop.setType(att.getType()); + prop.setElementType(att.getElementType()); + } + else if (entity.hasDefinedRole(data)) + { umlkind = ROLE; + Association ast = entity.getDefinedRole(data); + multiplicity = ast.getCard2(); + prop.setElementType(new Type(ast.getEntity2())); + prop.setType(ast.getType2()); + } + else // should not happen + { umlkind = VARIABLE; + variable = prop; + } + } + type = prop.getType(); + elementType = prop.getElementType(); + if (type != null) + { type.setElementType(elementType); } + } // may need to modify type because of obj + + BasicExpression(UnaryExpression uexp) + { if (uexp == null) + { data = ""; return; } + objectRef = uexp.argument; + String op = uexp.operator; + if (op.startsWith("->")) + { op = op.substring(2,op.length()); } + if (uexp.isMultiple()) + { multiplicity = ModelElement.MANY; } + data = op; + type = uexp.type; + elementType = uexp.elementType; + } + + BasicExpression(Type t) + { // if (t == null) + + data = t + ""; + type = new Type("OclType", null); + umlkind = TYPE; + + /* + if ("Set".equals(data) || "Sequence".equals(data)) + { Type tp = t.getElementType(); + if (tp != null) + { // data = data + "(" + tp.getName() + ")"; + type = new Type("OclType", null); + umlkind = TYPE; + } + } + else if ("Map".equals(data) || "Function".equals(data)) + { Type tp = t.getElementType(); + Type kt = t.getKeyType(); + if (kt != null) + { data = data + "(" + kt.getName() + ","; } + else + { data = data + "(String,"; } + + if (tp != null) + { data = data + tp.getName() + ")"; } + else + { data = data + "OclAny)"; } + + type = new Type("OclType", null); + umlkind = TYPE; + } + else + { type = new Type("OclType", null); + umlkind = TYPE; + } */ + + elementType = type; + multiplicity = ModelElement.MANY; + } + + BasicExpression(ObjectSpecification obj) + { if (obj == null) + { data = "null"; } + else + { data = obj.getName(); } + + if (obj != null && obj.entity != null) + { type = new Type(obj.getEntity()); + elementType = type; + } + // multiplicity = ModelElement.MANY; + umlkind = VALUE; + } + + BasicExpression(ASTTerm t) + { if (t instanceof ASTBasicTerm) + { ASTBasicTerm bt = (ASTBasicTerm) t; + data = bt.getTag(); + BasicExpression arg = + new BasicExpression(bt.getValue()); + arg.umlkind = VALUE; + umlkind = QUERY; + isEvent = true; + Vector pars = new Vector(); + pars.add(arg); + parameters = pars; + } + else if (t instanceof ASTSymbolTerm) + { data = ((ASTSymbolTerm) t).getSymbol(); + umlkind = VALUE; + } + else if (t instanceof ASTCompositeTerm) + { ASTCompositeTerm tree = (ASTCompositeTerm) t; + data = tree.getTag(); + umlkind = QUERY; + isEvent = true; + Vector trms = tree.getTerms(); + Vector pars = new Vector(); + for (int i = 0; i < trms.size(); i++) + { ASTTerm trm = (ASTTerm) trms.get(i); + Expression arg = new BasicExpression(trm); + pars.add(arg); + } + parameters = pars; + } + } + + public boolean isNotLocalVariable() + { if (umlkind == VARIABLE && objectRef == null) + { return false; } + return true; + } + + public void setVariableType(Type t) + { if (variable != null) + { variable.setType(t); } + } + + public void setVariableElementType(Type et) + { if (variable != null) + { variable.setElementType(et); } + } + + public void setArrayType(Type tt) + { arrayType = tt; } + + public static BasicExpression newASTBasicExpression(ASTTerm t) + { BasicExpression res = new BasicExpression(""); + if (t instanceof ASTBasicTerm) + { ASTBasicTerm bt = (ASTBasicTerm) t; + res.data = bt.getTag(); + BasicExpression arg = new BasicExpression("_1"); + Vector pars = new Vector(); + pars.add(arg); + res.parameters = pars; + } + else if (t instanceof ASTSymbolTerm) + { res.data = "_1"; + // Vector pars = new Vector(); + // res.parameters = pars; + } + else if (t instanceof ASTCompositeTerm) + { ASTCompositeTerm tree = (ASTCompositeTerm) t; + res.data = tree.getTag(); + Vector trms = tree.getTerms(); + Vector pars = new Vector(); + for (int i = 0; i < trms.size(); i++) + { ASTTerm trm = (ASTTerm) trms.get(i); + String val = "_" + (i+1); + // if (trm instanceof ASTSymbolTerm) + // { val = trm.literalForm(); } + Expression arg = new BasicExpression(val); + pars.add(arg); + } + res.parameters = pars; + } + return res; + } + + public static BasicExpression newASTBasicExpression(ASTTerm t, ASTTerm[] allts) + { BasicExpression res = new BasicExpression(""); + + if (t instanceof ASTBasicTerm) + { ASTBasicTerm bt = (ASTBasicTerm) t; + res.data = bt.getTag(); + BasicExpression arg = new BasicExpression("_1"); + Vector pars = new Vector(); + pars.add(arg); + res.parameters = pars; + return res; + } + + if (t instanceof ASTSymbolTerm) + { res.data = "_1"; + // Vector pars = new Vector(); + // res.parameters = pars; + return res; + } + + if (t instanceof ASTCompositeTerm) + { ASTCompositeTerm tree = (ASTCompositeTerm) t; + res.data = tree.getTag(); + Vector trms = tree.getTerms(); + Vector pars = new Vector(); + + if (ASTTerm.sameTagSameArity(allts)) { } + else + { res.addParameter(new BasicExpression("_*")); + return res; + } + + for (int i = 0; i < trms.size(); i++) + { ASTTerm trm = (ASTTerm) trms.get(i); + String val = "_" + (i+1); + + if (ASTTerm.constantTerms(allts, i)) + { val = trm.literalForm(); } + + Expression arg = new BasicExpression(val); + pars.add(arg); + } + + res.parameters = pars; + } + + return res; + } + + + + public static BasicExpression newBasicExpression(Expression obj, String feat) + { BasicExpression res = new BasicExpression(feat); + res.objectRef = obj; + return res; + } + + public static BasicExpression newTypeBasicExpression(String value) + { BasicExpression res = new BasicExpression(value); + res.umlkind = TYPE; + return res; + } + + + public static BasicExpression newValueBasicExpression(String value) + { BasicExpression res = new BasicExpression(value); + res.umlkind = VALUE; + return res; + } + + public static BasicExpression newValueBasicExpression(String value, String typ) + { BasicExpression res = new BasicExpression(value); + res.umlkind = VALUE; + if (typ != null) + { Type tt = Type.getTypeFor(typ); + res.type = tt; + } + return res; + } + + public static BasicExpression newAttributeBasicExpression(String value) + { BasicExpression res = new BasicExpression(value); + res.umlkind = ATTRIBUTE; + return res; + } + + public static BasicExpression newAttributeBasicExpression(String value, Expression obj) + { BasicExpression res = new BasicExpression(value); + res.umlkind = ATTRIBUTE; + res.objectRef = obj; + return res; + } + + public static BasicExpression newAttributeBasicExpression(String value, Type typ) + { BasicExpression res = new BasicExpression(value); + res.umlkind = ATTRIBUTE; + res.type = typ; + return res; + } + + public static BasicExpression newStaticAttributeBasicExpression(Attribute att) + { BasicExpression res = new BasicExpression(att.getName()); + res.umlkind = ATTRIBUTE; + res.type = att.getType(); + res.elementType = att.getElementType(); + res.isStatic = true; + // res.variable = att; + return res; + } + + public static BasicExpression newVariableBasicExpression(String value) + { BasicExpression res = new BasicExpression(value); + res.umlkind = VARIABLE; + + return res; + } + + public static BasicExpression newVariableBasicExpression(Attribute att) + { BasicExpression res = new BasicExpression(att); + res.umlkind = VARIABLE; + res.variable = att; + return res; + } + + public static BasicExpression newVariableBasicExpression(String f, Expression obj) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = VARIABLE; + return res; + } + + public static BasicExpression newVariableBasicExpression(String value, String typ) + { BasicExpression res = new BasicExpression(value); + res.umlkind = VARIABLE; + if (typ != null) + { Type tt = Type.getTypeFor(typ); + res.type = tt; + if (tt != null) + { res.multiplicity = tt.typeMultiplicity(); + res.elementType = tt.getElementType(); + } + } + return res; + } + + public static BasicExpression newVariableBasicExpression( + String value, String typ, + Vector types, Vector entities) + { BasicExpression res = new BasicExpression(value); + res.umlkind = VARIABLE; + if (typ != null) + { Type tt = Type.getTypeFor(typ,types,entities); + res.type = tt; + if (tt != null) + { res.multiplicity = tt.typeMultiplicity(); + res.elementType = tt.getElementType(); + } + } + return res; + } + + public static BasicExpression newVariableBasicExpression(String value, Type typ) + { BasicExpression res = new BasicExpression(value); + res.umlkind = VARIABLE; + res.type = typ; + if (typ != null) + { res.multiplicity = typ.typeMultiplicity(); + res.elementType = typ.getElementType(); + } + return res; + } + + public static BasicExpression newFunctionBasicExpression(String f, Expression obj) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = FUNCTION; + res.parameters = new Vector(); + return res; + } + + public static BasicExpression newFunctionBasicExpression(String f, Expression obj, Vector pars) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = FUNCTION; + res.parameters = pars; + return res; + } + + + public static BasicExpression newFunctionBasicExpression(String f, Expression obj, Expression par) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = FUNCTION; + Vector pars = new Vector(); + pars.add(par); + res.parameters = pars; + return res; + } + + public static BasicExpression newFunctionBasicExpression(String f, String obj, Vector pars) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(new BasicExpression(obj)); + res.umlkind = FUNCTION; + res.parameters = pars; + return res; + } + + public static BasicExpression newCallBasicExpression(String f) + { BasicExpression res = new BasicExpression(f); + res.umlkind = UPDATEOP; + res.isEvent = true; + res.parameters = new Vector(); + return res; + } + + public static BasicExpression newCallBasicExpression(String f, Vector vars) + { BasicExpression res = new BasicExpression(f); + res.umlkind = UPDATEOP; + res.isEvent = true; + res.parameters = vars; + return res; + } + + public static BasicExpression newCallBasicExpression(String f, Expression obj, Vector pars) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static BasicExpression newCallBasicExpression(String f, Expression obj, Expression par) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.parameters = new Vector(); + res.parameters.add(par); + res.isEvent = true; + return res; + } + + public static BasicExpression newCallBasicExpression(String f, Expression obj) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.parameters = new Vector(); + res.isEvent = true; + return res; + } + + public static BasicExpression newQueryCallBasicExpression( + String f, Expression obj) + { BasicExpression res = new BasicExpression(f); + res.setObjectRef(obj); + res.umlkind = QUERY; + res.parameters = new Vector(); + res.isEvent = true; + return res; + } + + public static BasicExpression newQueryCallBasicExpression( + BehaviouralFeature bf, + Expression obj, + Vector pars) + { BasicExpression res = new BasicExpression(bf); + + res.setObjectRef(obj); + res.umlkind = QUERY; + res.parameters = new Vector(); + for (int i = 0; i < pars.size(); i++) + { // Assumed to be attributes + Attribute par = (Attribute) pars.get(i); + res.parameters.add(new BasicExpression(par)); + } + res.isEvent = true; + return res; + } + + public static BasicExpression newCallBasicExpression( + BehaviouralFeature bf, + Expression obj, + Vector pars) + { BasicExpression res = new BasicExpression(bf); + + res.setObjectRef(obj); + if (bf.isQuery()) + { res.umlkind = QUERY; } + else + { res.umlkind = UPDATEOP; } + + res.parameters = new Vector(); + for (int i = 0; i < pars.size(); i++) + { // Assumed to be attributes + Attribute par = (Attribute) pars.get(i); + res.parameters.add(new BasicExpression(par)); + } + res.isEvent = true; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + BehaviouralFeature bf, Entity ent) + { BasicExpression obj = new BasicExpression(ent.getName()); + obj.umlkind = CLASSID; + BasicExpression res = new BasicExpression(bf); + res.setObjectRef(obj); + res.entity = ent; + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + // res.parameters = pars; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + String f, String arg, Vector pars) + { BasicExpression res = new BasicExpression(f); + BasicExpression obj = new BasicExpression(arg); + obj.umlkind = CLASSID; + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + String f, Expression obj, Vector pars) + { BasicExpression res = new BasicExpression(f); + obj.umlkind = CLASSID; + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + String f, String arg, Expression par) + { Vector pars = new Vector(); + pars.add(par); + BasicExpression res = new BasicExpression(f); + BasicExpression obj = new BasicExpression(arg); + obj.umlkind = CLASSID; + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + String f, Expression obj, Expression par) + { Vector pars = new Vector(); + pars.add(par); + BasicExpression res = new BasicExpression(f); + obj.umlkind = CLASSID; + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + String f, String arg) + { Vector pars = new Vector(); + + BasicExpression res = new BasicExpression(f); + BasicExpression obj = new BasicExpression(arg); + obj.umlkind = CLASSID; + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static BasicExpression newStaticCallBasicExpression( + String f, Expression obj) + { Vector pars = new Vector(); + + BasicExpression res = new BasicExpression(f); + obj.umlkind = CLASSID; + res.setObjectRef(obj); + res.umlkind = UPDATEOP; + res.isStatic = true; + res.isEvent = true; + res.parameters = pars; + return res; + } + + public static Expression newIndexedBasicExpression( + Expression base, Expression ind) + { if (base instanceof BasicExpression) + { BasicExpression be = (BasicExpression) base; + if (be.arrayIndex == null) + { BasicExpression res = (BasicExpression) be.clone(); + res.arrayIndex = ind; + return res; + } + else // multiple indexes + { return new BinaryExpression("->at", base, ind); } + } + return new BinaryExpression("->at", base, ind); + } + + public static BasicExpression newStaticValueBasicExpression(String v, String cls) + { BasicExpression res = new BasicExpression(v); + res.umlkind = VALUE; + res.isStatic = true; + res.objectRef = new BasicExpression(cls); + res.objectRef.umlkind = CLASSID; + return res; + } + + public void addParameterExpressions(Vector pars) + { parameters = new Vector(); + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + parameters.add(new BasicExpression(par)); + } + } + + public Expression getObjectRef() + { return objectRef; } + + + public Expression getArrayIndex() + { return arrayIndex; } + + public Type getArrayType() + { return arrayType; } + + public boolean isCallBasicExpression() + { return parameters != null && + (umlkind == QUERY || umlkind == UPDATEOP); + } + + public Object clone() + { BasicExpression res = new BasicExpression(data); + if (javaForm != null) + { res.javaForm = javaForm; } // clone it? + if (objectRef != null && (objectRef instanceof BasicExpression)) + { res.objectRef = (BasicExpression) ((BasicExpression) objectRef).clone(); } // clone it? + else if (objectRef != null) + { res.objectRef = (Expression) objectRef.clone(); } + res.formalParameter = formalParameter; + + res.isEvent = isEvent; + res.modality = modality; // Surely? + res.kind = kind; + res.type = type; + res.umlkind = umlkind; + res.elementType = elementType; + res.entity = entity; + res.mult = mult; + res.multiplicity = multiplicity; + res.refactorELV = refactorELV; + + if (arrayIndex != null) + { res.arrayIndex = (Expression) arrayIndex.clone(); } + res.arrayType = arrayType; + + if (parameters == null) + { res.parameters = null; } + else + { res.parameters = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { if (parameters.get(i) instanceof Expression) + { Expression par = (Expression) parameters.get(i); + Expression pclone = (Expression) par.clone(); + res.parameters.add(pclone); + } + else + { res.parameters.add(parameters.get(i)); } + } + } + + res.prestate = prestate; + res.atTime = atTime; + res.downcast = downcast; + res.isStatic = isStatic; + return res; + } + + public boolean containsSubexpression(Expression expr) + { if (arrayIndex != null) + { if (arrayIndex.containsSubexpression(expr)) + { return true; } + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression ee = (Expression) parameters.get(i); + if (ee.containsSubexpression(expr)) + { return true; } + } + } + + return (this + "").equals(expr + ""); + } + + public Vector singleMutants() + { Vector res = new Vector(); + if ("true".equals(data)) + { res.add(new BasicExpression(false)); } + else if ("false".equals(data)) + { res.add(new BasicExpression(true)); } + return res; + } + + public static boolean isMapAccess(Expression expr) + { if (expr instanceof BasicExpression) + { BasicExpression be = (BasicExpression) expr; + if (be.arrayIndex != null && + be.arrayType != null && + be.arrayType.isMap()) + { return true; } + } + return false; + } + + public static void updateMapType(Expression lhs, Expression rhs) + { if (lhs instanceof BasicExpression) + { BasicExpression be = (BasicExpression) lhs; + if (be.arrayIndex != null && + be.arrayType != null && + be.arrayType.isMap()) + { Type elemType = rhs.getType(); + Type oldElemType = be.arrayType.getElementType(); + be.arrayType.elementType = + Type.refineType(oldElemType,elemType); + System.out.println(">> From " + lhs + " := " + rhs + " deduced element type " + be.arrayType.elementType + " for map " + be.data); + + Type indType = be.arrayIndex.getType(); + Type oldKeyType = be.arrayType.getKeyType(); + be.arrayType.keyType = + Type.refineType(oldKeyType,indType); + System.out.println(">> From " + lhs + " := " + rhs + " deduced key type " + be.arrayType.keyType + " for map " + be.data); + } + } + } + + public static boolean hasVariable(Expression expr) + { if (expr instanceof BasicExpression) + { BasicExpression be = (BasicExpression) expr; + if (be.variable != null) + { return true; } + } + return false; + } + + public static void updateVariableType(Expression lhs, Expression rhs) + { if (lhs instanceof BasicExpression) + { BasicExpression be = (BasicExpression) lhs; + if (be.variable != null) + { Type vType = rhs.getType(); + + System.out.println(">>> RHS type: " + vType); + + Type oldVType = be.variable.getType(); + + System.out.println(">>> old type: " + oldVType); + + be.variable.setType( + Type.refineType(oldVType, vType)); + System.out.println(">> From " + lhs + " := " + rhs + " deduced type " + be.variable.getType() + " for " + be.data); + + Type elemType = rhs.getElementType(); + + System.out.println(">>> RHS element type: " + elemType); + + Type oldElemType = be.variable.getElementType(); + + System.out.println(">>> old element type: " + oldElemType); + + be.variable.setElementType( + Type.refineType(oldElemType,elemType)); + System.out.println(">> From " + lhs + " := " + rhs + " deduced element type " + be.variable.getElementType() + " for " + be.data); + } + } + } + + public Vector decompose() + { // assuming it represents a navigation path r1.r2.r3.att + Vector res = new Vector(); + if (objectRef == null) + { Attribute finalatt = new Attribute(data, type, ModelElement.INTERNAL); + finalatt.setElementType(elementType); + res.add(finalatt); + return res; + } + + Vector front = ((BasicExpression) objectRef).decompose(); + Attribute finalatt = new Attribute(data, type, ModelElement.INTERNAL); + finalatt.setElementType(elementType); + front.add(finalatt); + return front; + } + + + public BasicExpression invokeOnFirstArg() + { if (parameters == null || parameters.size() == 0) + { return this; } // error + Expression p1 = (Expression) parameters.get(0); + Vector newparams = new Vector(); + newparams.addAll(parameters); + newparams.remove(0); + BasicExpression res = (BasicExpression) this.clone(); + // String newname = data.toLowerCase() + "$op"; + // res.data = newname; + res.type = new Type("boolean", null); + res.elementType = new Type("boolean", null); + res.setParameters(newparams); + res.setObjectRef(p1); + res.umlkind = UPDATEOP; + return res; + } + + public BasicExpression invokeNontopRule(String calltarget, UseCase uc, Vector rules) + { BasicExpression res = (BasicExpression) this.clone(); + Entity ucclass = uc.getClassifier(); + if (ucclass == null) + { System.err.println("!! ERROR: null classifier for use case " + uc.getName()); } + + for (int i = 0; i < rules.size(); i++) + { Relation rel = (Relation) rules.get(i); + String nme = rel.getName(); + if (data.equals(nme)) + { if (rel.isTopLevel()) + { System.err.println("!!! Error: cannot invoke top relation in where clause " + data); + return new BasicExpression(true); + } + else + { String newname = data.toLowerCase() + "$op"; + if (calltarget.length() > 0) + { BasicExpression p1 = new BasicExpression(calltarget); + if (calltarget.endsWith("Pres")) + { newname = data.toLowerCase() + "$pres"; } + else if (calltarget.endsWith("Con")) + { newname = data.toLowerCase() + "$con"; } + + p1.umlkind = CLASSID; + p1.setType(new Type(ucclass)); + p1.setElementType(new Type(ucclass)); + res.setObjectRef(p1); + } + res.data = newname; + res.umlkind = UPDATEOP; + res.isEvent = true; + res.entity = ucclass; + return res; + } + } + } + System.err.println("!!! Relation " + data + " is not known in this transformation"); + return new BasicExpression(true); + } + + public Expression testTraceRelation(Vector entities) + { // data->exists( datax | datax.p1 = p1 & ... & datax.pn = pn) + // + // String var = data.toLowerCase() + "$x"; + + String var = Identifier.nextIdentifier("trace$"); + String traceop = data + "$trace"; + BasicExpression varexp = new BasicExpression(var); + + Entity ent = (Entity) ModelElement.lookupByName(traceop, entities); + // or of the use case? Or relation doms? + Expression pred = new BasicExpression(true); + if (ent == null) + { return pred; } + BasicExpression eexp = new BasicExpression(ent); + BinaryExpression dran = new BinaryExpression(":", varexp, eexp); + + Vector fparams = ent.allProperties(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression pval = (Expression) parameters.get(i); + if (i < fparams.size()) + { Attribute fp = (Attribute) fparams.get(i); + BasicExpression fpexp = new BasicExpression(fp); + fpexp.objectRef = varexp; + BinaryExpression eq = new BinaryExpression("=", fpexp, pval); + pred = Expression.simplifyAnd(pred, eq); + } + } + } + return new BinaryExpression("#", dran, pred); + } + + public Expression testTraceRelationWhen(Vector entities, Vector bound) + { // datax : data$trace & p1 = datax.p1 & ... & pn = datax.pn + // datax : p1.traces$data$p1 & p2 = datax.p2 & ... & pn = datax.pn + + + String var = Identifier.nextIdentifier("trace$"); + // String var = data.toLowerCase() + "$x"; + String traceop = data + "$trace"; + BasicExpression varexp = new BasicExpression(var); + + Entity ent = (Entity) ModelElement.lookupByName(traceop, entities); + // or of the use case? Or relation doms? + Expression pred = new BasicExpression(true); + if (ent == null) + { return pred; } + + varexp.setType(new Type(ent)); + BasicExpression eexp = new BasicExpression(ent); + BinaryExpression dran = new BinaryExpression(":", varexp, eexp); + + int ind = 0; + + Vector fparams = ent.allProperties(); + // System.out.println("*** TEST WHEN for " + this + " " + fparams); + + if (fparams.size() == 0) + { return dran; } + + if (parameters != null) + { Attribute pivot = (Attribute) fparams.get(ind); + Type t = pivot.getElementType(); + + while (!(t.isEntity() && pivot.isSource())) + { if (ind < fparams.size()) + { ind = ind + 1; } + else + { System.err.println("!!! ERROR: No source relation domain in rule " + this); + return pred; + } // no source reference properties, should not occur + pivot = (Attribute) fparams.get(ind); + t = pivot.getElementType(); + } + + // System.out.println("PIVOT for " + this + " is: " + pivot); + + Entity pivotEntity = t.getEntity(); + Association ast = pivotEntity.getRole("traces$" + data + "$" + pivot.getName()); + + // System.out.println("PIVOT ASSOCIATION = " + ast); + + if (ast != null) + { BasicExpression astexp = new BasicExpression(ast); + astexp.setPrestate(true); + BasicExpression pivotexp = new BasicExpression(parameters.get(ind) + ""); + astexp.setObjectRef(pivotexp); + if (bound.contains(pivotexp + "")) { } + else + { bound.add(pivotexp + ""); } + dran = new BinaryExpression(":", varexp, astexp); + } + else + { System.err.println("!!!! ERROR: undefined inverse of " + pivot); } + + for (int i = 0; i < parameters.size(); i++) + { Expression pval = (Expression) parameters.get(i); + if (i < fparams.size() && i != ind) + { Attribute fp = (Attribute) fparams.get(i); + BasicExpression fpexp = new BasicExpression(fp); + fpexp.objectRef = varexp; + BinaryExpression eq = new BinaryExpression("=", pval, fpexp); + if (bound.contains(pval + "")) { } + else + { bound.add(pval + ""); } + pred = Expression.simplifyAnd(pred, eq); + } + } + } + return new BinaryExpression("&", dran, pred); + } + + + public Expression checkWhen(Vector entities, Vector bound) + { // # (datax : data$trace) (p1 = datax.p1 & ... & pn = datax.pn) + + String var = Identifier.nextIdentifier("trace$"); + // String var = data.toLowerCase() + "$x"; + String traceop = data + "$trace"; + BasicExpression varexp = new BasicExpression(var); + varexp.setUmlKind(VARIABLE); + + + Entity ent = (Entity) ModelElement.lookupByName(traceop, entities); + // or of the use case? Or relation doms? + Expression pred = new BasicExpression(true); + if (ent == null) + { return pred; } + + BasicExpression eexp = new BasicExpression(ent); + BinaryExpression dran = new BinaryExpression(":", varexp, eexp); + + Vector fparams = ent.allProperties(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression pval = (Expression) parameters.get(i); + if (i < fparams.size()) + { Attribute fp = (Attribute) fparams.get(i); + BasicExpression fpexp = new BasicExpression(fp); + fpexp.objectRef = varexp; + BinaryExpression eq = new BinaryExpression("=", pval, fpexp); + if (bound.contains(pval + "")) { } + else + { bound.add(pval + ""); } + pred = Expression.simplifyAnd(pred, eq); + } + } + } + return new BinaryExpression("#", dran, pred); + } + + public void setIsEvent() + { isEvent = true; + modality = HASEVENT; + } + + public void setData(String d) + { data = d; } + + public void setParameters(Vector pars) + { parameters = pars; } + + public void setParameter(int ind, Expression par) + { if (parameters == null) + { parameters = new Vector(); } + if (parameters.size() >= ind) + { parameters.set(ind-1,par); } + else + { parameters.add(par); } + } + + public void addParameter(Expression v) + { if (parameters == null) + { parameters = new Vector(); } + parameters.add(v); + } + + public Vector getParameters() + { return parameters; } + + public Expression getParameter(int i) + { if (parameters == null) + { return null; } + + if (i <= parameters.size() && i >= 1) + { return (Expression) parameters.get(i-1); } + return null; + } + + public int arity() + { if (parameters == null) + { return 0; } + return parameters.size(); + } + + public String getData() + { return data; } + + public boolean getPrestate() + { return prestate; } + + public Type getElementType() + { if (isString(data)) + { return type; } + else + { return elementType; } + } + + public void setPrestate(boolean p) + { prestate = p; } + + public void setPre() + { if (umlkind == VALUE || umlkind == CONSTANT || umlkind == VARIABLE || + umlkind == UPDATEOP) + { return; } + + if (umlkind == FUNCTION || umlkind == QUERY) + { } + else + { setPrestate(true); } + + if (objectRef != null) + { objectRef.setPre(); } + + if (arrayIndex != null) + { arrayIndex.setPre(); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression pval = (Expression) parameters.get(i); + pval.setPre(); + } + } + } // parameters and arrayIndex in all cases? + + + public boolean isReduceFunctionCall() // Sequence input, single value output + { if (parameters == null || parameters.size() == 0) { return false; } + else if (entity != null) + { BehaviouralFeature bf = entity.getDefinedOperation(data); + if (bf == null) { return false; } + Attribute p1 = bf.getParameter(0); + if (Type.isSequenceType(p1.getType()) && !Type.isCollectionType(type)) + { return true; } + } + return false; + } // umlkind == QUERYOP + + public Expression convertExcelExpression() // Sequence-valued E.Att becomes E->collect(Att) + { if (parameters == null || parameters.size() == 0) { return this; } + else if (entity != null) + { BasicExpression res = (BasicExpression) clone(); + BehaviouralFeature bf = entity.getDefinedOperation(data); + if (bf == null) { return this; } + // Attribute p1 = bf.getParameter(0); + + Vector newparams = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Attribute par = bf.getParameter(i); + Expression apar = (Expression) parameters.get(i); + + if (Type.isSequenceType(par.getType()) && apar instanceof BasicExpression) + { BasicExpression bpar = (BasicExpression) apar; + if (bpar.objectRef != null && bpar.objectRef.umlkind == CLASSID && bpar.umlkind == ATTRIBUTE) + { BasicExpression paratt = (BasicExpression) bpar.clone(); + BasicExpression ref = (BasicExpression) bpar.objectRef; + paratt.objectRef = null; + Expression newpar = new BinaryExpression("->collect", ref, paratt); + if (ref.prestate) + { paratt.prestate = true; } + newparams.add(newpar); + } + else + { newparams.add(apar); } + } + else // single value expected + if (apar instanceof BasicExpression) + { BasicExpression bpar = (BasicExpression) apar; + if (bpar.objectRef != null && bpar.objectRef.umlkind == CLASSID && bpar.umlkind == ATTRIBUTE) + { BasicExpression paratt = (BasicExpression) bpar.clone(); + BasicExpression ref = (BasicExpression) bpar.objectRef; + String evarname = ref.data.toLowerCase() + "x"; + paratt.objectRef = new BasicExpression(ref.entity, evarname); + if (ref.prestate) + { paratt.prestate = true; } + newparams.add(paratt); + } + else + { newparams.add(apar); } + } + else + { newparams.add(apar); } + } + res.parameters = newparams; + return res; + } + return this; + } + + public Expression convertExcelExpression(Entity target, Vector entities, Vector qvars, Vector antes) { if (parameters == null || parameters.size() == 0) { return this; } + else + { BasicExpression res = (BasicExpression) clone(); + + + Vector newparams = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression bpar = par.excel2Ocl(target, entities, qvars, antes); + newparams.add(bpar); + } + res.parameters = newparams; + return res; + } + } + + + public boolean isQualified() + { if (umlkind == ROLE) + { Association ast = entity.getDefinedRole(data); + if (ast != null && ast.isQualified()) + { return true; } + } + return false; + } // Or its type is a map ... + + public boolean isZeroOneRole() + { if (umlkind == ROLE || umlkind == ATTRIBUTE) + { Association ast = entity.getDefinedRole(data); + if (ast != null && ast.getCard2() == ModelElement.ZEROONE) + { return true; } + } + return false; + } + + // public boolean isZeroOne() + // { return lower == 0 && upper == 1; } + + + public boolean isRuleCall(Vector rules) + { for (int i = 0; i < rules.size(); i++) + { NamedElement ne = (NamedElement) rules.get(i); + if (data.equals(ne.getName())) + { return true; } + } + return false; + } + + public NamedElement getCalledRule(Vector rules) + { for (int i = 0; i < rules.size(); i++) + { NamedElement ne = (NamedElement) rules.get(i); + if (data.equals(ne.getName())) + { return ne; } + } + return null; + } + + public boolean isAssignable() + { if (umlkind == VARIABLE) + { return true; } + if (umlkind == ROLE || umlkind == ATTRIBUTE) + { if (entity != null && entity.isFrozen(data)) + { return false; } + return true; + } + return false; + } // CLASSID also, in special cases: C = {}. And the ROLE is not frozen + + public boolean isExecutable() + { if (umlkind == UPDATEOP || umlkind == QUERY) + { return true; } + if (("" + this).equals("true")) + { return true; } + return false; + } // d.isDeleted not valid syntax. + + public boolean isPrimitive() // A number, boolean or enumeration value + { if (umlkind == ROLE || umlkind == CLASSID) + { return false; } + // if (arrayIndex != null) + // { return (elementType != null && elementType.isPrimitive()); } + + // if (isMultiple()) + // { return false; } + + if (umlkind == FUNCTION) + { if (data.equals("sqr") || data.equals("size") || + data.equals("floor") || data.equals("ceil") || + data.equals("round") || + data.equals("exp") || data.equals("pow") || + data.equals("sin") || data.equals("cos") || + data.equals("tan") || + data.equals("asin") || data.equals("acos") || + data.equals("atan") || + data.equals("sinh") || data.equals("cosh") || + data.equals("tanh") || + data.equals("log10") || data.equals("cbrt") || + data.equals("Prd") || data.equals("prd") || + data.equals("log") || data.equals("count") || + data.equals("hasPrefix") || + data.equals("hasSuffix") || + data.equals("isEmpty") || data.equals("notEmpty") || + data.equals("isUnique") || + data.equals("oclIsKindOf") || + data.equals("sqrt") || data.equals("abs") || + data.equals("indexOf") || data.equals("isDeleted")) + { return true; } + else if (data.equals("Sum")) + { return Type.primitiveType(type); } + else if (data.equals("oclAsType")) + { String cast = "" + parameters.get(0); + if ("int".equals(cast) || "boolean".equals(cast) || "long".equals(cast) || + "double".equals(cast)) + { return true; } + return false; + } + else if (data.equals("toLowerCase") || data.equals("toUpperCase") || + data.equals("flatten") || data.equals("sortedBy") || + data.equals("reverse") || data.equals("sort") || data.equals("asSequence") || + data.equals("front") || data.equals("tail") || data.equals("insertAt") || + data.equals("subrange") || + data.equals("setAt") || + data.equals("replace") || data.equals("replaceAll") || + data.equals("replaceAllMatches") || + data.equals("characters") || data.equals("allInstances") || + data.equals("closure") || data.equals("asSet") || data.equals("subcollections")) + { return false; } // but strings don't need to be wrapped + else if (data.equals("max") || data.equals("min") || data.equals("last") || + data.equals("sum") || data.equals("first") || data.equals("any")) + { if (objectRef != null) + { Type objstype = objectRef.getElementType(); + return Type.primitiveType(objstype); + } + return false; + } + } // not prim if objectRef multiple and data : {sqr, sqrt, floor, exp, sqrt, + // abs, toLower, toUpper + + if (umlkind == VALUE || umlkind == VARIABLE || + umlkind == CONSTANT) + { return Type.primitiveType(type); } + + if (umlkind == ATTRIBUTE || umlkind == QUERY || + umlkind == UPDATEOP) + { // Look it up + + if (objectRef == null) + { if (arrayIndex != null) + { return Type.primitiveType(elementType); } + return Type.primitiveType(type); + } + else if (entity != null) + { if (entity.isStaticFeature(data)) + { if (entity.getName().equals(objectRef + "")) + { return Type.primitiveType(type); } + } + } + + if (arrayIndex != null) + { return Type.primitiveType(elementType); } + + if (!objectRef.isMultiple()) + { return Type.primitiveType(type); } + + // if objectRef not multiple + } + + return false; + } + + public Expression addContainerReference(BasicExpression ref, + String var, + Vector exclusions) + { // var becomes ref.var unless var : exclusions + BasicExpression res = (BasicExpression) clone(); + + if ("self".equals(data) && objectRef == null) + { return res; } // I would have thought? + + if (arrayIndex != null) + { Expression arInd = + arrayIndex.addContainerReference(ref,var,exclusions); + res.arrayIndex = arInd; + } // and to parameters of calls + + if (parameters != null) + { Vector pars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression rpar = + par.addContainerReference(ref,var,exclusions); + pars.add(rpar); + } + res.parameters = pars; + } + + if (data.equals(var)) { } + else if (objectRef == null) + { return res; } + else + { Expression oref1 = + objectRef.addContainerReference(ref,var,exclusions); + res.setObjectRef(oref1); + return res; + } + + if (exclusions.contains(data)) + { return res; } + + if (objectRef == null) + { res.setObjectRef(ref); + return res; + } + else + { Expression oref1 = + objectRef.addContainerReference(ref,var,exclusions); + res.setObjectRef(oref1); + return res; + } + + } + + public Expression addReference(BasicExpression ref, Type t) + { BasicExpression res = (BasicExpression) clone(); + // if (umlkind == FUNCTION) + // { Expression oref1 = objectRef.addReference(ref,t); + // res.setObjectRef(oref1); + // return res; + // } + + if ("self".equals(data) && objectRef == null) + { return ref; } // I would have thought? + + if (arrayIndex != null) + { Expression arInd = arrayIndex.addReference(ref,t); + res.arrayIndex = arInd; + } // and to parameters of calls + + if (parameters != null) + { Vector pars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression rpar = par.addReference(ref,t); + pars.add(rpar); + } + res.parameters = pars; + } + + if (umlkind == ATTRIBUTE || umlkind == ROLE || umlkind == FUNCTION || + umlkind == CONSTANT || umlkind == QUERY || umlkind == UPDATEOP) + { if (objectRef == null) // && (objectRef.isMultiple())) + { res.setObjectRef(ref); + return res; + } // only if it is a feature of t. What about variables? + else + { Expression oref1 = objectRef.addReference(ref,t); + res.setObjectRef(oref1); + return res; + } + } + return res; + } + + public Expression replaceReference(BasicExpression ref, Type t) + { BasicExpression res = (BasicExpression) clone(); + // if (umlkind == FUNCTION) + // { Expression oref1 = objectRef.addReference(ref,t); + // res.setObjectRef(oref1); + // return res; + // } + + if ("self".equals(data) && objectRef == null) + { return ref; } // I would have thought? + + if (arrayIndex != null) + { Expression arInd = arrayIndex.replaceReference(ref,t); + res.arrayIndex = arInd; + } // and to parameters of calls + + if (parameters != null) + { Vector pars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression rpar = par.replaceReference(ref,t); + pars.add(rpar); + } + res.parameters = pars; + } + + if (umlkind == ATTRIBUTE || umlkind == ROLE || umlkind == FUNCTION || + umlkind == CONSTANT || umlkind == QUERY || umlkind == UPDATEOP) + { if (objectRef == null) // && (objectRef.isMultiple())) + { res.setObjectRef(ref); + return res; + } // only if it is a feature of t. What about variables? + else if (entity == t.entity) + { res.setObjectRef(ref); + return res; + } + } + return res; + } + + public Expression dereference(BasicExpression ref) + { // Clone this? + BasicExpression res = (BasicExpression) clone(); + + if (arrayIndex != null) + { res.arrayIndex = arrayIndex.dereference(ref); } + + if (parameters != null) + { Vector pars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression par1 = par.dereference(ref); + pars.add(par1); + } + res.parameters = pars; + } + + if (objectRef == null) + { if (data.equals("" + ref)) + { res.data = "self"; + res.setEntity(entity); + res.setType(type); + res.setElementType(elementType); + res.setUmlKind(VARIABLE); + res.variable = new Attribute("self", res.type, ModelElement.INTERNAL); + return res; + } + } + else if (("" + objectRef).equals("" + ref)) + { res.objectRef = null; + return res; + } // objectRef.data = "self" + else + { res.objectRef = objectRef.dereference(ref); } + + return res; + } // also dereference parameters of operation calls + + public Expression invert() + { return (Expression) clone(); } + // For all of these also update the array ref + + public void findClones(java.util.Map clones, String rule, String op) + { return; } + + public void findClones(java.util.Map clones, + java.util.Map cloneDefs, + String rule, String op) + { return; } + + public void findMagicNumbers(java.util.Map mgns, String rule, String op) + { if (umlkind == VALUE) + { if ("0".equals(data) || "1".equals(data) || + "\"\"".equals(data) || "true".equals(data) || + "false".equals(data) || + "null".equals(data) || + "1.0".equals(data) || + "0.0".equals(data)) + { return; } + + // Or if type is enumerated, also ok. + if (type != null && type.isEnumerated()) + { return; } + + System.err.println("!! Magic number: " + this + " in " + op + " context: " + rule); + Vector occs = (Vector) mgns.get(data); + if (occs == null) + { occs = new Vector(); } + occs.add(this); + mgns.put(data, occs); + return; + } + + if (objectRef != null) + { objectRef.findMagicNumbers(mgns, this + "", op); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + par.findMagicNumbers(mgns, this + "", op); + } + } + + // and array index + + return; + } + + + + public boolean isOrdered() // assume isMultiple() + { if (umlkind == VARIABLE) + { if (type != null) + { return "Sequence".equals(type.getName()); } + return false; + } + + if (umlkind == CLASSID) + { if (arrayIndex == null || arrayIndex.isOrdered()) + { return true; } + else + { return false; } + } + + if (umlkind == FUNCTION) + { if (data.equals("asSet") || data.equals("closure") || + data.equals("subcollections")) + { return false; } + + if (data.equals("sort") || data.equals("allInstances") || + data.equals("asSequence") || + data.equals("sortedBy") || data.equals("characters")) + { return true; } + + if (objectRef == null) + { return false; } // invalid anyway + + if (data.equals("any") || data.equals("first") || + data.equals("last")) + { return Type.isSequenceType(elementType); } + + if (objectRef.isOrdered()) + { if (data.equals("front") || data.equals("reverse") || + data.equals("tail") || + data.equals("insertInto") || + data.equals("excludingSubrange") || + data.equals("setSubrange") || + data.equals("insertAt") || data.equals("setAt") || + data.equals("subrange")) + { return true; } + } + else if ("Integer".equals("" + objectRef) && + "subrange".equals(data)) + { return true; } + + return false; + } + + if (objectRef == null || !objectRef.isMultiple()) // singletons are ordered? + { if (umlkind == ROLE && entity != null) + { Association ast = entity.getDefinedRole(data); + if (ast != null) + { return ast.isOrdered(); } + // else + // { return result; } + } + return false; + } + + if (objectRef.isOrdered()) + { if (umlkind == ATTRIBUTE) + { return !Type.isSetType(type); } // was: true; + + if (umlkind == ROLE && entity != null) + { Association ast = entity.getDefinedRole(data); + if (ast != null) + { return (ast.isOrdered() || ast.isSingleValued()); } + } + + if (umlkind == QUERY || umlkind == UPDATEOP) + { if (type == null) { return false; } + BehaviouralFeature op = entity.getDefinedOperation(data); + if (op != null) + { if (op.isOrdered() || op.isSingleValued()) + { return true; } + } + } // the result type of the op is needed in type. + } + + return false; // but it could be a singleton + } + + public boolean isOrderedB() // assume isMultiple() + { if (umlkind == VARIABLE) + { if (type != null) + { return "Sequence".equals(type.getName()); } + return false; + } // or return false if "Set".equals(type.getName()) + + if (umlkind == CLASSID) + { return false; } // strange, could be a sequence if the arrayInd is? + + if (umlkind == FUNCTION) + { if (data.equals("asSet") || data.equals("closure") || + data.equals("subcollections")) + { return false; } + + if (data.equals("sort") || data.equals("allInstances") || data.equals("asSequence") || + data.equals("sortedBy") || data.equals("characters")) + { return true; } + + if (objectRef == null) { return false; } // invalid anyway + + if (objectRef.isOrderedB()) + { if (data.equals("front") || data.equals("reverse") || + data.equals("tail") || + data.equals("insertAt") || + data.equals("insertInto") || + data.equals("excludingSubrange") || + data.equals("setSubrange") || + data.equals("setAt") || data.equals("subrange")) + { return true; } + } + else if ("Integer".equals("" + objectRef) && "subrange".equals(data)) + { return true; } + + return false; + } + + if (objectRef == null || !objectRef.isMultiple()) // singletons are ordered? + { if (umlkind == ROLE && entity != null) + { Association ast = entity.getDefinedRole(data); + if (ast != null) + { return ast.isOrdered(); } + } + return false; + } + + if (objectRef.isOrderedB()) + { if (umlkind == ATTRIBUTE) + { return true; } // but could be set-valued + + if (umlkind == ROLE && entity != null) + { Association ast = entity.getDefinedRole(data); + if (ast != null) + { return (ast.isOrdered() || ast.isSingleValued()); } + } + + if (umlkind == QUERY || umlkind == UPDATEOP) + { if (type == null) { return false; } + BehaviouralFeature op = entity.getDefinedOperation(data); + if (op != null) + { if (op.isOrdered() || op.isSingleValued()) + { return true; } + } + } // the result type of the op is needed in type. + } + + if (type != null) + { return "Sequence".equals(type.getName()); } + + return false; // but it could be a singleton + } + + public boolean isSorted() // assume isMultiple() + { // if (umlkind == VARIABLE) + // { if (type != null) + // { return "Sequence".equals(type.getName()); } + // return false; + // } + + if (type != null && type.isSorted()) + { return true; } + + if (umlkind == FUNCTION) + { if (data.equals("asSet") || data.equals("closure") || + data.equals("subcollections")) + { return false; } + + if (data.equals("sort")) // || data.equals("sortedBy")) + { return true; } + + if (objectRef == null) + { return false; } // invalid anyway + + if (objectRef.isSorted()) + { if (data.equals("front") || + data.equals("tail") || + data.equals("excludingSubrange") || + data.equals("subrange")) + { return true; } // NOT setSubrange + } + else if ("Integer".equals("" + objectRef) && + "subrange".equals(data)) + { return true; } + + return false; + } + + if (objectRef == null || !objectRef.isMultiple()) // singletons are ordered? + { if (umlkind == ROLE && entity != null) + { Association ast = entity.getDefinedRole(data); + if (ast != null) + { return ast.isSorted(); } + } + + if (umlkind == ATTRIBUTE && entity != null) + { Attribute ast = entity.getDefinedAttribute(data); + if (ast != null) + { return ast.isSorted(); } + } + + return false; + } + + if (objectRef == null && umlkind == VARIABLE && + type != null) + { return type.isSorted(); } + + // if (objectRef.isSorted()) + // { if (umlkind == ATTRIBUTE && + // multiplicity == ModelElement.ONE) + // { return true; } // if single-valued + // } + + if (objectRef == null && + (umlkind == QUERY || umlkind == UPDATEOP)) + { if (type == null) { return false; } + BehaviouralFeature op = + entity.getDefinedOperation(data); + return op.isSorted(); + } // the result type of the op is needed in type. + + return false; // but it could be a singleton + } + + public int maxModality() { return modality; } + + public int minModality() { return modality; } + + public Vector allEntitiesUsedIn() + { Vector res = new Vector(); + if (entity != null && isFeature()) + { res.add(entity); } + // Perhaps also variables of type entity??? + + if (objectRef != null) + { res = VectorUtil.union(res,objectRef.allEntitiesUsedIn()); } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.allEntitiesUsedIn()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = VectorUtil.union(res,par.allEntitiesUsedIn()); + } + } + + return res; + } // and parameters or arrayIndex? + + public Vector metavariables() + { Vector res = new Vector(); + + if (objectRef != null) + { res = objectRef.metavariables(); } + + for (int i = 0; i < data.length() - 1; i++) + { if ('_' == data.charAt(i) && + Character.isDigit(data.charAt(i+1)) && + i + 2 < data.length() && + Character.isDigit(data.charAt(i+2))) + { res.add(data.charAt(i) + "" + data.charAt(i+1) + "" + data.charAt(i+2)); } + else if ('_' == data.charAt(i) && + Character.isDigit(data.charAt(i+1))) + { res.add(data.charAt(i) + "" + data.charAt(i+1)); } + else if ('_' == data.charAt(i) && + '*' == data.charAt(i+1)) + { res.add(data.charAt(i) + "*"); } + else if ('_' == data.charAt(i) && + '+' == data.charAt(i+1)) + { res.add(data.charAt(i) + "+"); } + } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.metavariables()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = VectorUtil.union(res,par.metavariables()); + } + } + + + return res; + } // and parameters or arrayIndex? + + public Vector innermostEntities() + { Vector res = new Vector(); + if (objectRef == null) + { if (isFeature() && entity != null) + { res.add(entity); } // also the superclasses? + } + else + { res = objectRef.innermostEntities(); } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.innermostEntities()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = VectorUtil.union(res,par.innermostEntities()); + } + } + + return res; + } // parameters, arrayIndex also + + public String innermostData() + { if (objectRef == null) + { return data; } + if (objectRef instanceof BasicExpression) + { return ((BasicExpression) objectRef).innermostData(); } + return ""; + } + + public Vector innermostVariables() + { Vector res = new Vector(); + if (umlkind == ATTRIBUTE || umlkind == ROLE || + umlkind == UPDATEOP || umlkind == QUERY) + { if (objectRef == null) // and feature isn't static + { res.add("self"); } + else if (objectRef.umlkind == VARIABLE) + { res.add(objectRef + ""); } + else + { res.addAll(objectRef.innermostVariables()); } + } + else if (umlkind == FUNCTION) + { res.addAll(objectRef.innermostVariables()); } + else if (umlkind == VARIABLE) + { res.add(data); } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.innermostVariables()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = VectorUtil.union(res,par.innermostVariables()); + } + } + + return res; + } // parameters, arrayIndex also + + public Vector allPreTerms() + { Vector res = new Vector(); + + if (prestate) + { res.add(this); } + if (objectRef != null) + { res.addAll(objectRef.allPreTerms()); } + if (arrayIndex != null) + { res.addAll(arrayIndex.allPreTerms()); } + + + if ("Integer".equals(objectRef + "") && "Sum".equals(data)) + { // ignore pre-terms inside the 4th argument + for (int i = 0; i < parameters.size() - 1; i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allPreTerms()); + } + } + else if ("Integer".equals(objectRef + "") && "Prd".equals(data)) + { // ignore pre-terms inside the 4th argument + for (int i = 0; i < parameters.size() - 1; i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allPreTerms()); + } + } + else if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allPreTerms()); + } + } + return res; + } // and in object ref? + + public Vector allPreTerms(String var) + { Vector res = new Vector(); + if (prestate && var.equals(objectRef + "")) + { res.add(this); } + else if (objectRef != null) + { res.addAll(objectRef.allPreTerms(var)); } + + if (arrayIndex != null) + { res.addAll(arrayIndex.allPreTerms(var)); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allPreTerms(var)); + } + } + return res; + } // and in object ref? + + public boolean relevantOccurrence(String op, Entity ent, + String val, + String f) + { if (data.equals(f)) + { if (objectRef == null) + { return true; } + else + { Type elemT = objectRef.elementType; + // System.out.println("Element type of " + objectRef + " is: " + + // elemT); + // System.out.println("Operation entity is: " + ent); + if (elemT == null) // a variable + { elemT = objectRef.getType(); + if (elemT.entity == null) { return false; } + } + Entity et = elemT.getEntity(); + if (Entity.comparable(et,ent)) { return true; } + return false; + } + } + if (objectRef == null) { return false; } + return objectRef.relevantOccurrence(op,ent,val,f); + } // But ignore it if object ref type (an entity) isn't comparable to src + // and look in arrayIndex or parameters? + + // Can't have {} inside () or vice-versa + + public Expression checkIfSetExpression() + { int n = data.length(); + if (n > 0 && + data.charAt(n-1) == '}') + { System.out.println(">>> Found set expression: " + this); + return buildSetExpression(data); + } + // return checkIfObjectExpression(); + // return checkIfObjectRef(); + return checkIfCallExpression(); + } // should start with Set{, Sequence{ or { + + private static SetExpression buildSetExpression(String d) + { StringTokenizer st = + new StringTokenizer(d,"{},"); + Vector ids = new Vector(); + while (st.hasMoreTokens()) + { String s = st.nextToken(); + BasicExpression be = new BasicExpression(s); + ids.add(be.checkIfObjectRef()); // can't allow . inside {} at present + } + + if (ids.size() > 0 && "Sequence".equals("" + ids.get(0))) + { ids.remove(0); + return new SetExpression(ids,true); + } + + if (ids.size() > 0 && "Set".equals("" + ids.get(0))) + { ids.remove(0); + return new SetExpression(ids,false); + } + + return new SetExpression(ids,false); + } + + public BasicExpression checkIfCallExpression() + { int n = data.length(); + int i = data.indexOf('('); + if (n > 0 && + data.charAt(n-1) == ')' && + i > 0) + { // System.out.println("Found call expression: " + this); + return buildCallExpression(data); + } + return checkIfObjectRef(); + } + + private static BasicExpression buildCallExpression(String d) + { StringTokenizer st = + new StringTokenizer(d,"(),"); + Vector ids = new Vector(); + while (st.hasMoreTokens()) + { String s = st.nextToken(); + Compiler2 c2 = new Compiler2(); + c2.nospacelexicalanalysis(s); + Expression be1 = c2.parse(); + // BasicExpression be = new BasicExpression(s); + // BasicExpression be1 = (BasicExpression) be.checkIfObjectRef(); + // be1.setPrestate(be.getPrestate()); + if (be1 != null) { ids.add(be1); } // can't allow . inside {} at present + else + { System.err.println("ERROR: Invalid expression " + s + " in call " + d); } + } + + if (ids.size() > 0 && (ids.get(0) instanceof BasicExpression)) { } + else + { System.err.println("ERROR: Invalid call expression: " + d); + return null; + } + + BasicExpression op = (BasicExpression) ids.get(0); + ids.remove(0); + + if (isFunction(op.data)) + { op.umlkind = FUNCTION; } + else + { op.setIsEvent(); } + + op.setParameters(ids); + return op; + } + // can't have calls within calls: op(op1(x,y),z) + +/* public Expression checkIfObjectExpression() + { Vector ids = new Vector(); + StringTokenizer st = + new StringTokenizer(data,"(),"); + while (st.hasMoreTokens()) + { ids.add(st.nextToken()); + System.out.println(ids); + } + if (ids.size() > 1) // ObjectExpression data.charAt(0) == '(' + { return buildObjectExpression(ids); } + else + { return checkIfObjectRef(); } + } + + public static Expression buildObjectExpression(Vector ids) + { String ent = (String) ids.get(0); + Vector res = new Vector(); + ids.remove(0); + for (int i = 0; i < ids.size(); i++) + { String e = (String) ids.get(i); + BasicExpression be = new BasicExpression(e); + res.add(be.checkIfObjectRef()); + } + return new ObjectExpression(ent,res); + } */ + + public BasicExpression checkIfObjectRef() + { Vector ids = new Vector(); + BasicExpression res; + + /* StringTokenizer st = + new StringTokenizer(data,"."); + + while (st.hasMoreTokens()) + { ids.add(st.nextToken()); } */ + + ids = topLevelSplit(data); + + // System.out.println("Top level split of " + data + " is " + ids); + + if (ids.size() > 1) + { try + { double dd = Double.parseDouble(ids.get(0) + "." + ids.get(1)); + BasicExpression doub = new BasicExpression(dd); + ids.remove(0); + ids.remove(0); + if (ids.size() == 0) { return doub; } + BasicExpression ref = (BasicExpression) buildObjectRef(ids); + ref.setObjectRef(doub); + return ref; + } catch (Exception ee) { } + res = buildObjectRef(ids); + // res.prestate = prestate; + // System.out.println("MAIN EXPRESSION IS: " + res); + return res; + } + else + { res = checkIfArrayRef(data); + // res.prestate = prestate; + // System.out.println("INNER EXPRESSION IS: " + res); + return res; + } + } + + private static BasicExpression buildObjectRef(Vector ids) + { /** Precondition: ids.size() > 0 */ + int n = ids.size(); + if (n == 0) { return null; } + if (n == 1) + { return checkIfArrayRef((String) ids.get(0)); } + String last = (String) ids.get(n - 1); + BasicExpression ee = new BasicExpression(last,0); + BasicExpression res = // new BasicExpression(last); + ee.checkIfCallExpression(); + Vector rem = new Vector(); + rem.addAll(ids); + // Vector rem = (Vector) ids.clone(); + rem.remove(n-1); + Expression obj = buildObjectRef(rem); + res.objectRef = obj; + // System.out.println("Built object ref " + res); + return res; + } + + private static BasicExpression checkIfArrayRef(String d) + { int n = d.length(); + BasicExpression res; + if (n > 0 && d.charAt(n-1) == ']') + { // System.out.println("Found array expression: " + d); + StringTokenizer st = new StringTokenizer(d,"[]"); + Vector ids = new Vector(); + while (st.hasMoreTokens()) + { ids.add(st.nextToken()); } + String basic = (String) ids.get(0); + BasicExpression index; + if (ids.size() > 0) + { BasicExpression inde = + new BasicExpression((String) ids.get(1), 0); + index = inde.checkIfObjectRef(); + } + else // syntax error + { index = null; } + res = new BasicExpression(basic,0); + BasicExpression res1 = res.checkIfCallExpression(); + res1.arrayIndex = index; + return res1; + } + res = new BasicExpression(d); + + // System.out.println("Build array ref: " + res + " from " + d); + return res; + } // does not deal with qualified associations with asst[i,j] + + + public void setObjectRef(Expression e) + { objectRef = e; } + + public void setInnerObjectRef(Expression e) + { if (objectRef == null) + { objectRef = e; } + else if (objectRef instanceof BasicExpression) + { ((BasicExpression) objectRef).setInnerObjectRef(e); } + } + + public void setArrayIndex(Expression ind) + { arrayIndex = ind; } + + public String toString() // the RSDS form ref.data + { String res; + if (objectRef != null) + { res = objectRef + "." + data; } + else + { res = data; } + + if (prestate) + { res = res + "@pre"; } + + if (parameters != null) + { res = res + "("; + for (int i = 0; i < parameters.size(); i++) + { res = res + parameters.get(i); + if (i < parameters.size() - 1) + { res = res + ","; } + } + res = res + ")"; + } + + if (arrayIndex != null) + { res = res + "[" + arrayIndex + "]"; } + + if (needsBracket) + { res = "(" + res + ")"; } + + return res; + } + + public String basicString() + { String res; + if (objectRef != null) + { res = objectRef + "." + data; } + else + { res = data; } + + if (prestate) + { res = res + "@pre"; } + + if (parameters != null) + { res = res + "("; + for (int i = 0; i < parameters.size(); i++) + { res = res + parameters.get(i); + if (i < parameters.size() - 1) + { res = res + ","; } + } + res = res + ")"; + } + + if (arrayIndex != null) + { res = res + "[" + arrayIndex + "]"; } + + return res; + } + + public String toAST() + { String res = "(OclBasicExpression "; + if (objectRef != null) + { res = res + objectRef.toAST() + " . " + data; } + else + { res = res + data; } + + if (prestate) + { res = res + " @pre"; } + + if (parameters != null) + { res = res + " ( "; + + if (parameters.size() > 0) + { res = res + " (ParameterArguments "; } + + for (int i = 0; i < parameters.size(); i++) + { res = res + ((Expression) parameters.get(i)).toAST(); + if (i < parameters.size() - 1) + { res = res + " , "; } + } + + if (parameters.size() > 0) + { res = res + " ) "; } + + res = res + " ) "; + } + + if (arrayIndex != null) + { res = res + " [ " + arrayIndex.toAST() + " ]"; } + + return res + " )"; + } + + public String toCSTL() + { String res = data; + + if (parameters != null && parameters.size() > 0) + { res = ""; + for (int i = 0; i < parameters.size(); i++) + { String par = ((BasicExpression) parameters.get(i)).toCSTL(); + res = res + par + " "; + } + } + return res; + } + + public static int starIndex(BasicExpression be) + { if (be.parameters == null) + { return 0; } + for (int i = 0; i < be.parameters.size(); i++) + { if ("_*".equals(be.parameters.get(i) + "")) + { return i+1; } + } + return 0; + } + + public boolean isSingleListTerm() + { // contents of expression are constants, with no "_v" + // except _* + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { String par = "" + parameters.get(i); + if (par.startsWith("_*")) { } + else if (par.startsWith("_")) + { return false; } + } + return true; + } + + return false; + } + + public boolean isFunctionApplication() + { if (umlkind == FUNCTION && parameters != null && + parameters.size() == 1) + { String par = "" + parameters.get(0); + if ("_*".equals(par)) + { return false; } + return true; + } + + if (parameters != null && parameters.size() == 1) + { BasicExpression par = ((BasicExpression) parameters.get(0)); + return par.isFunctionApplication(); + } + + return false; + } + + public String getAppliedFunction() + { if (umlkind == FUNCTION && parameters != null && + parameters.size() == 1) + { return data; } + + if (parameters != null && parameters.size() == 1) + { BasicExpression par = ((BasicExpression) parameters.get(0)); + return par.getAppliedFunction(); + } + + return null; + } + + + public String toLiteralCSTL() + { String res = data; + + if (umlkind == FUNCTION) + { if (parameters != null && parameters.size() == 1 && + parameters.get(0) instanceof BasicExpression) + { BasicExpression par = (BasicExpression) parameters.get(0); + if (par.umlkind == FUNCTION) + { res = par.toLiteralCSTL(); } + else + { res = par + "`" + data; } + } + return res; + } + + if (parameters != null && parameters.size() > 0) + { res = ""; + for (int i = 0; i < parameters.size(); i++) + { String par = ((BasicExpression) parameters.get(i)).toLiteralCSTL(); + // if (res.length() > 0 && + // par.startsWith("_") && + // ( Character.isDigit(res.charAt(res.length()-1)) || + // Character.isLetter(res.charAt(res.length()-1)) ) + // ) + // { res = res + " " + par; } + // else + + if (par.endsWith(" ")) + { res = res + par; } + else + { res = res + par + " "; } + } + } + return res; + } + + public String toInnerCSTL() + { String res = data; + + if (umlkind == FUNCTION) + { if (parameters != null && parameters.size() == 1) + { String par = ((BasicExpression) parameters.get(0)).toInnerCSTL(); + res = par; + } + return res; + } + + if (parameters != null && parameters.size() > 0) + { res = ""; + for (int i = 0; i < parameters.size(); i++) + { String par = ((BasicExpression) parameters.get(i)).toLiteralCSTL(); + // if (res.length() > 0 && + // par.startsWith("_") && + // ( Character.isDigit(res.charAt(res.length()-1)) || + // Character.isLetter(res.charAt(res.length()-1)) ) + // ) + // { res = res + " " + par; } + // else + + if (par.endsWith(" ")) + { res = res + par; } + else + { res = res + par + " "; } + } + } + return res; + } // No nesting of metafeatures. + + public Vector usesCSTLfunctions() + { Vector res = new Vector(); + + if (umlkind == FUNCTION) + { if (parameters != null && parameters.size() == 1) + { res.add(data); + Expression par = (Expression) parameters.get(0); + if (par instanceof BasicExpression) + { res.addAll(((BasicExpression) par).usesCSTLfunctions()); } + } + + // System.out.println(">>>--- CSTL functions used in " + this + " are: " + res); + return res; + } + + if (parameters != null && parameters.size() > 0) + { for (int i = 0; i < parameters.size(); i++) + { if (parameters.get(i) instanceof BasicExpression) + { BasicExpression par = (BasicExpression) parameters.get(i); + res.addAll(par.usesCSTLfunctions()); + } + } + } + + // System.out.println(">>>--- CSTL functions used in " + this + " are: " + res); + + return res; + } + + + // saveTextModel + public String saveModelData(PrintWriter out) // the RSDS internal representation + { String res = Identifier.nextIdentifier("basicexpression_"); + out.println(res + " : BasicExpression"); + out.println(res + ".data = \"" + data + "\""); + out.println(res + ".expId = \"" + res + "\""); + // type and element type, prestate umlKind, needsBracket + + String tname = "void"; + if (type != null) + { tname = type.getUMLModelName(out); } + out.println(res + ".type = " + tname); + + if (elementType != null) + { String etname = elementType.getUMLModelName(out); + out.println(res + ".elementType = " + etname); + } + else if (type != null && type.elementType != null) + { String tet = type.elementType.getUMLModelName(out); + out.println(res + ".elementType = " + tet); + } + else if (type != null && + type.getElementType() != null) + { String etname = + type.getElementType().getUMLModelName(out); + out.println(res + ".elementType = " + etname); + } + else if (type != null && + Type.isBasicType(type)) + { out.println(res + ".elementType = " + tname); } + else + { System.err.println("!!! Warning!: no element type for " + this); + out.println(res + ".elementType = " + tname); + } + + if (entity != null) + { out.println(entity.getName() + " : " + res + ".context"); } + + out.println(res + ".needsBracket = " + needsBracket); + + if (umlkind == QUERY) + { out.println(res + ".umlKind = " + UPDATEOP); } + else + { out.println(res + ".umlKind = " + umlkind); } + + out.println(res + ".isStatic = " + isStatic); + + out.println(res + ".prestate = " + prestate); + + + if (umlkind == ATTRIBUTE) + { if (entity != null) + { Entity owner = entity.getAttributeOwner(data); + out.println(data + "_" + owner.getName() + " : " + res + ".referredProperty"); + } + } // must be the owner of the attribute, not this entity. + + if (umlkind == ROLE) + { if (entity != null) + { Association ast = entity.getDefinedRole(data); + String aname = ast.getName() + "_end2"; + out.println(aname + " : " + res + ".referredProperty"); + } + } + + + if (objectRef != null) + { String objid = objectRef.saveModelData(out); + out.println(objid + " : " + res + ".objectRef"); + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + String parid = par.saveModelData(out); + out.println(parid + " : " + res + ".parameters"); + } + } + + if (arrayIndex != null) + { String arrayid = arrayIndex.saveModelData(out); + out.println(arrayid + " : " + res + ".arrayIndex"); + } + return res; + } + + public Expression definedness() + { Expression res = new BasicExpression(true); + + // for E[ind] for E entity with primary key key, ind : E.key + if (umlkind == CLASSID) + { if (arrayIndex != null && entity != null) + { Attribute pk = entity.getPrincipalKey(); + if (pk == null) { return res; } + String pkname = pk.getName(); + res = arrayIndex.definedness(); + BasicExpression edom = new BasicExpression(pkname); + edom.setObjectRef(new BasicExpression(data)); + Expression indom = new BinaryExpression(":",arrayIndex,edom); + res = simplify("&",res,indom,null); + } + return res; + } + + // For s[ind] with s a sequence, ind >= 1 & ind <= s.size: + + if ((umlkind == ROLE || umlkind == ATTRIBUTE || umlkind == VARIABLE) + && arrayIndex != null) + { // if not qualified, but is ordered + if (objectRef != null) + { res = objectRef.definedness(); } + res = simplify("&",res,arrayIndex.definedness(),null); + if (isQualified()) + { if (multiplicity == ModelElement.MANY) + { return res; } + else + { // E2->exists( e2 | this = e2 ) + Type t2 = getElementType(); + if (t2 != null && t2.isEntity()) + { Entity e2 = t2.getEntity(); + BasicExpression e2x = new BasicExpression(e2.getName().toLowerCase()); + BinaryExpression eqe2x = new BinaryExpression("=", this, e2x); + return new BinaryExpression("#", + new BinaryExpression(":", e2x, new BasicExpression(e2)), + eqe2x); + } + } + return res; + } + BasicExpression newdata = new BasicExpression(data); + newdata.setObjectRef(objectRef); + newdata.umlkind = ROLE; + UnaryExpression selfsize = new UnaryExpression("->size", newdata); + Expression lbnd = new BinaryExpression("<=", new BasicExpression(1), arrayIndex); + Expression ubnd = new BinaryExpression("<=", arrayIndex, selfsize); + Expression inrange = new BinaryExpression("&",lbnd,ubnd); + return simplify("&",res,inrange,null); + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression pdef = par.definedness(); + res = simplify("&", res, pdef, null); + } + } + + if ((umlkind == UPDATEOP || umlkind == QUERY) && entity != null) + { BehaviouralFeature bf = entity.getDefinedOperation(data); + if (bf != null) + { Expression spre = bf.definedness(parameters); + return simplify("&",res,spre,null); + } + } + + if (objectRef == null) + { return res; } + res = objectRef.definedness(); + + + if (umlkind == FUNCTION) + { Expression zero = new BasicExpression(0); + if ("sqrt".equals(data)) + { Expression nneg = new BinaryExpression(">=",objectRef,zero); + return simplify("&",nneg,res,null); + } + else if ("log".equals(data) || "log10".equals(data)) + { Expression pos = new BinaryExpression(">",objectRef,zero); + return simplify("&",pos,res,null); + } + else if ("acos".equals(data) || "asin".equals(data)) + { Expression minus1 = new BasicExpression(-1); + Expression one = new BasicExpression(1); + Expression pos1 = new BinaryExpression(">=",objectRef,minus1); + Expression pos2 = new BinaryExpression("<=",objectRef,one); + Expression res1 = simplify("&",pos2,res,null); + return simplify("&",pos1,res1,null); + } + else if ("last".equals(data) || "first".equals(data) || + "front".equals(data) || "tail".equals(data) || + "max".equals(data) || "min".equals(data) || "any".equals(data)) + { UnaryExpression orsize = new UnaryExpression("->size",objectRef); + Expression pos = + new BinaryExpression(">",orsize,zero); + return simplify("&",pos,res,null); + } + else if ("toReal".equals(data)) + { BasicExpression checkReal = new BasicExpression("isReal"); + checkReal.setObjectRef(objectRef); + return simplify("&",checkReal,res,null); + } + else if ("toInteger".equals(data)) + { BasicExpression checkInt = new BasicExpression("isInteger"); + checkInt.setObjectRef(objectRef); + return simplify("&",checkInt,res,null); + } + else if ("oclAsType".equals(data)) + { BasicExpression iko = new BasicExpression("oclIsKindOf"); + iko.setObjectRef(objectRef); + iko.setParameters(parameters); + return iko; + } + // Operation call defined if precondition[args/params] is true + } + + return res; + } + + public Expression determinate() + { Expression res = new BasicExpression(true); + if (objectRef != null) + { res = objectRef.determinate(); } + if (arrayIndex != null) + { res = simplify("&",res,arrayIndex.determinate(),null); } + + if ("any".equals(data)) + { Expression one = new BasicExpression(1); + UnaryExpression andsize = new UnaryExpression("->size",objectRef); + Expression isone = + new BinaryExpression("=",andsize,one); + return simplify("&",res,isone,null); + } + + if ("asSequence".equals(data)) + { if ("Set".equals(objectRef.getType().getName())) + { Expression det1 = new BinaryExpression("<=", new UnaryExpression("->size",objectRef), + new BasicExpression(1)); + return simplify("&",res,det1,null); + } + else + { return res; } + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression pdef = par.determinate(); + res = simplify("&", res, pdef, null); + } + } + + if ((umlkind == UPDATEOP || umlkind == QUERY) && entity != null) + { BehaviouralFeature bf = entity.getDefinedOperation(data); + if (bf != null) + { Expression spre = bf.determinate(parameters); + return simplify("&",res,spre,null); + } + } + + return res; + } // operations determinate if postcondition[args/params] is + // also case of flatten + + public String toSQL() + { String res = ""; + if (umlkind == VALUE || umlkind == CONSTANT) + { String tname = type.getName(); + if (tname.equals("String") || + tname.equals("boolean")) + { res = "'" + data + "'"; } + else + { res = data; } + return res; + } + + if (umlkind == FUNCTION) + { String pre = objectRef.toSQL(); + if (data.equals("size")) + { return "LENGTH(" + pre + ")"; } + if (data.equals("abs") || data.equals("floor") || + data.equals("sqrt") || data.equals("max") || data.equals("ceil") || + data.equals("round") || data.equals("exp") || data.equals("log") || + data.equals("min") || data.equals("sum")) // exp, floor + { return data.toUpperCase() + "(" + pre + ")"; } + else if (data.equals("toUpperCase")) + { return "UCASE(" + pre + ")"; } + else if (data.equals("toLowerCase")) + { return "LCASE(" + pre + ")"; } + else if (data.equals("sqr")) + { return "(" + pre + "*" + pre + ")"; } + } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { return entity.getName() + "." + data; } + } + return data; + } + + private String impName() // removes "." + { if (objectRef != null) + { return ((BasicExpression) objectRef).impName() + data; } + else + { return data; } + } + + public String toB() + { String res = ""; + if (data.equals("closure")) // objectRef not null + { BasicExpression objs = (BasicExpression) objectRef; + return "(closure(" + objs.data + ")(" + objs.objectRef.toB() + "))"; + } + else if (data.equals("asSet")) + { return "ran(" + objectRef.toB() + ")"; } + else if (objectRef != null) + { res = data + "(" + objectRef.toB() + ")"; } + else + { res = data; } + if (data.equals("true")) { return "TRUE"; } + if (data.equals("false")) { return "FALSE"; } + if (parameters != null) + { res = res + "("; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = res + par.toB(); + if (i < parameters.size() - 1) + { res = res + ","; } + } + res = res + ")"; + } + if (arrayIndex == null) + { return res; } + return "(" + res + ")(" + arrayIndex.toB() + ")"; + } // + between strings also different in B + + public String toJava() + { String res = ""; + if (objectRef != null) + { res = objectRef.toJava() + "." + data; } // for multiples only + else + { res = data; } // "M" + mysm.label + "." + data surely??? + if (parameters != null) + { res = res + "("; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = res + par; + if (i < parameters.size() - 1) + { res = res + ","; } + } + res = res + ")"; + } + if (arrayIndex != null) + { return res + ".get(" + arrayIndex.toJava() + " - 1)"; } // not for qualified + return res; + } // if data is a method name also add () at end. + + public String toZ3() // not considering parameters. Arrays/lists indexed from 1 + { String res = data; + if ("Set{}".equals(data) || "{}".equals(data) || "Sequence{}".equals(data)) + { return "nil"; } + if (umlkind == FUNCTION) + { String pre = objectRef.toZ3(); + if (data.equals("sqr") || data.equals("abs") || data.equals("floor") || + data.equals("tan") || data.equals("sin") || data.equals("cos") || + data.equals("exp") || data.equals("log") || data.equals("round") || + data.equals("sqrt") || data.equals("toUpperCase") || data.equals("ceil") || + data.equals("toLowerCase")) + { res = res + "(" + data + " " + pre + ")"; } + else if (data.equals("subrange")) // Integer.subrange is special case + { // if a String, substring, otherwise subSequence + if (parameters.size() == 2) + { res = "(" + data + " " + pre + " " + parameters.get(0) + " " + parameters.get(1) + ")"; } + else if (parameters.size() == 1) + { res = "(" + data + " " + pre + " " + parameters.get(0) + ")"; } + } + else if (data.equals("first")) + { res = "(head " + pre + ")"; } + else // min, max, sum, size, any, asSet, last, front, tail + { res = "(" + data + " " + pre + ")"; } + return res; + } + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { Attribute pk = entity.getPrincipalKey(); + if (pk == null) { return ""; } + String pkname = pk.getName(); + String ind = arrayIndex.toZ3(); + res = "(get" + data + "By" + pkname + " " + ind + ")"; + } + return res; + } + if (objectRef != null) + { res = "(" + data + " " + objectRef.toZ3() + ")"; } + if (arrayIndex != null) + { res = "(at " + res + " " + arrayIndex.toZ3() + ")"; } + + if (parameters != null) + { String parstring = "("; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parstring = parstring + par.toZ3(); + if (i < parameters.size() - 1) { parstring = parstring + ","; } + } + res = "(" + res + " " + parstring + "))"; + } + + return res; + } + + public String toOcl(java.util.Map env, boolean local) + { // System.out.println(this + " umlkind = " + umlkind); + + String res = ""; + if (objectRef != null) + { res = objectRef.toOcl(env,local); } + if (umlkind == FUNCTION) + { if (data.equals("exp") || data.equals("abs") || + data.equals("log") || data.equals("round") || + data.equals("ceil") || data.equals("floor") || + data.equals("sin") || data.equals("cos") || + data.equals("tan") || data.equals("cbrt") || + data.equals("sqrt") || data.equals("toUpperCase") || + data.equals("toLowerCase")) + { res = res + "." + data + "()"; } + else if (data.equals("subrange") || + data.equals("pow") || + data.equals("setAt") || + data.equals("excludingSubrange") || + data.equals("setSubrange") || + data.equals("insertAt") || + data.equals("insertInto")) + { // if a String, substring, otherwise subSequence + if (parameters != null && parameters.size() > 1) + { res = res + "." + data + "(" + parameters.get(0) + "," + + parameters.get(1) + ")"; + } + } + else if (data.equals("indexOf") || data.equals("count") || + data.equals("oclAsType") || + data.equals("oclIsKindOf")) + { // if a String, substring, otherwise subSequence + if (parameters != null && parameters.size() > 0) + { res = + res + "->" + data + "(" + ((Expression) parameters.get(0)).toOcl(env,local) + ")"; + } + } + else // min, max, sum, size, any, asSet, first, last, front, tail + { res = res + "->" + data + "()"; } + } + else if (umlkind == VALUE || umlkind == CONSTANT || umlkind == VARIABLE) + { res = data; } // if CLASS, then data + ".allInstances()" + else if (umlkind == CLASSID) + { res = data + ".allInstances()"; + if (arrayIndex != null) + { Attribute pk = entity.getPrincipalKey(); + String pkname = pk.getName(); + String ind = arrayIndex.toOcl(env,local); + if (arrayIndex.isMultiple()) + { res = res + "->select(" + ind + "->includes(" + pkname + "))"; } + else + { res = res + "->select(" + ind + " = " + pkname + ")->any()"; } + } + } + else + { String nme = entity.getName(); + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (entity.isClassScope(data)) // also for ops + { res = nme + "." + data; } // and arrayIndex + else + { String var = (String) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclassJava(env); + if (var == null) + { var = entity.searchForSuperclassJava(env); + if (var == null) + { System.err.println("!! ERROR: No variable in scope of class " + nme); + // var = nme.toLowerCase() + "x"; + res = data; + } + else + { var = "(" + var + "->oclAsType(" + nme + "))"; + res = var + "." + data; + } + } + else + { res = var + "." + data; } + } + else + { res = var + "." + data; } + } + } + } // valid but unecesary for static attributes + else + { if (entity.isClassScope(data)) // also for ops + { res = nme + "." + data; } // and arrayIndex + else + { String pre = objectRef.toOcl(env,local); + res = pre + "." + data; + } + } + } + + if (parameters != null) + { res = res + "("; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = res + par.toOcl(env,local); + if (i < parameters.size() - 1) + { res = res + ","; } + } + res = res + ")"; + } + + if (prestate) + { res = res + "@pre"; } + + if (arrayIndex != null) + { res = res + "->at(" + arrayIndex.toOcl(env,local) + ")"; } + + return res; + } // constants and variables? + + public Expression toSmv(Vector cnames) + { if (cnames.contains(toString())) + { if (objectRef == null) + { return new BasicExpression("M" + data + "." + data); } + else + { return new BasicExpression("M" + toJava()); } + } + else if (isEvent) + { return new BinaryExpression("=", + new BasicExpression("C.con_event"), + new BasicExpression(data)); + } + else + { return new BasicExpression(data); } + } + + public String toImp(final Vector components) + { // System.out.println(data); + // System.out.println(components); + + Statemachine sm = (Statemachine) VectorUtil.lookup(data,components); + if (sm != null) + { return impName() + "x"; } + else + { return data; } + } + + public String toJavaImp(final Vector components) + { // System.out.println(data); + // System.out.println(components); + + Statemachine sm = (Statemachine) VectorUtil.lookup(data,components); + if (sm != null) + { return impName() + "x"; } + else + { return data; } + } + + + public boolean isOrExpression() { return false; } + + public Expression buildJavaForm(final Vector comps) + { int whatis = -1; + int mysm = -1; + int multip = 0; + Statemachine sm = null; + + for (int i = 0; i < comps.size(); i++) + { sm = (Statemachine) comps.get(i); + whatis = sm.getCategory(data); + if (whatis >= 0) + { mysm = i; + multip = sm.getMultiplicity(); + break; + } + } + + if (whatis == Statemachine.EVENT) + { + if (sm.cType == DCFDArea.ACTUATOR && multip <= 1) + { javaForm = new BasicExpression("M" + sm.label + "." + data + "()"); } + else if (sm.cType == DCFDArea.ACTUATOR && multip > 1) + { javaForm = new BasicExpression(toJava() + "()"); } // toString() + else if (sm.cType == DCFDArea.CONTROLLER) + { javaForm = new BasicExpression(sm.label.toLowerCase() + "." + + data + "()"); + } + else // invalid + { javaForm = this; } + } + else if (whatis == Statemachine.ATTRIBUTE || + whatis == Statemachine.STATEMACHINE) + { if (multip <= 1) + { javaForm = new BasicExpression("M" + sm.label + "." + data); } + else + { javaForm = new BasicExpression(toJava()); } // toString() in fact + } + return javaForm; + } // Must be an event if valid. + + + public int typeCheck(final Vector sms) + { if (data.equals("true") || data.equals("false")) + { modality = SENSOR; + return SENSOR; + } + + String comp = Statemachine.findComponentOf(data, sms); + + if (comp == null || comp.equals("")) + { System.out.println("Error: must have equality expressions " + + " or valid event names\n" + + "at base level, not: " + toString()); + modality = ERROR; + return ERROR; + } + else + { isEvent = true; + modality = HASEVENT; + return HASEVENT; + } + } + + public Expression checkConversions(Type propType, Type propElemType, java.util.Map interp) + { // if (umlkind == CLASSID) { return this; } + // System.out.println("CONVERTING " + this + " " + type + "(" + elementType + ")"); + + + if ("resolveTemp".equals(data)) + { // x.resolveTemp(p) becomes propElemType[p + x.$id] + + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Expression p = (Expression) par1.clone(); + BasicExpression b = new BasicExpression(propElemType); + BasicExpression id = new BasicExpression("$id"); + BasicExpression underscore = new BasicExpression("\"_\""); + id.setObjectRef(objectRef); + BinaryExpression prefix = new BinaryExpression("+", p, underscore); + BinaryExpression ind = new BinaryExpression("+", prefix, id); + b.setArrayIndex(ind); + return b; + } + } // for attributes it is entity.getName() + "." + data + + if ("boolean".equals(type + "") || "int".equals(type + "") || "long".equals(type + "") || + "double".equals(type + "") || "String".equals(type + "")) + { return this; } + + if (objectRef != null) + { Expression objs = objectRef.checkConversions(propType,propElemType,interp); + objectRef = objs; + } + + if (type != null && type.isEntity()) + { Entity ent = type.getEntity(); + if (ent.hasStereotype("source")) + { Entity tent = (Entity) interp.get(ent + ""); + + // System.out.println("INTERPRETATION OF " + ent + " IS= " + tent); + + if (tent == null) // use the expected target type instead + { if (propType != null && propType.isEntity()) + { tent = propType.getEntity(); } + } + BasicExpression res = new BasicExpression(tent + ""); + res.setType(new Type(tent)); + res.setUmlKind(Expression.CLASSID); + res.setMultiplicity(ModelElement.ONE); + res.setElementType(new Type(tent)); + BasicExpression ind = new BasicExpression("$id"); + ind.setObjectRef(this); + ind.setType(new Type("String",null)); + res.setArrayIndex(ind); + return res; + } + else + { return this; } // it must already be of target type + } + else if (elementType != null && elementType.isEntity()) + { Entity ent = elementType.getEntity(); + if (ent.hasStereotype("source")) + { Entity tent = (Entity) interp.get(ent + ""); + + // System.out.println("INTERPRETATION OF " + ent + " IS= " + tent); + + if (tent == null) + { if (propElemType != null && propElemType.isEntity()) + { tent = propElemType.getEntity(); } + } + BasicExpression res = new BasicExpression(tent + ""); + res.setType(type); + res.setMultiplicity(multiplicity); + res.setElementType(new Type(tent)); + res.setUmlKind(Expression.CLASSID); + BinaryExpression ind = + new BinaryExpression("->collect",this,new BasicExpression("$id")); + + ind.setType(type); // Sequence or Set + ind.setElementType(new Type("String",null)); + res.setArrayIndex(ind); + return res; + } // More general to use Tent[this->collect($id)] + else + { return this; } + } + else + { return this; } + } + + public Expression replaceModuleReferences(UseCase uc) + { Entity e = uc.getClassifier(); + + BasicExpression res = new BasicExpression(data); + + res.setType(type); + res.setElementType(elementType); + res.umlkind = umlkind; + + Expression objs = null; + + Vector pars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression pp = (Expression) parameters.get(i); + Expression newpp = pp.replaceModuleReferences(uc); + pars.add(newpp); + } + res.setParameters(pars); + } + else + { res.parameters = null; } + + // and arrayIndex + + if (objectRef != null && (objectRef instanceof BasicExpression)) + { String odata = ((BasicExpression) objectRef).data; + + // if ("thisModule".equals(odata) && "resolveTemp".equals(data)) + // { // thisModule.resolveTemp(x,v) becomes TargetType[v + x.$id] + + + if ("thisModule".equals(odata) && !e.hasOperation(data)) + { // thisModule.op(pars) becomes pars1.op(parsTail) + + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) pars.get(0); + Expression par1c = (Expression) par1.clone(); + par1c.needsBracket = true; + res.setObjectRef(par1c); + Vector parst = new Vector(); + parst.addAll(pars); + parst.remove(0); + res.setParameters(parst); + return res; + } + else + { Expression eref = new BasicExpression(e); + res.setObjectRef(eref); + return res; + } + } + // for attributes it is e.getName() + "." + data + else if ("thisModule".equals(odata) && e.hasOperation(data)) + { // thisModule.op(pars) becomes e.getName().op(pars) + Expression eref = new BasicExpression(e); + res.setObjectRef(eref); + return res; + } + } + + if (objectRef != null) + { objs = objectRef.replaceModuleReferences(uc); } + res.setObjectRef(objs); + return res; + + } + + + // for UMLRSDS: also do doubles with E-, E+ syntax. + + public boolean typeInference(final Vector types, + final Vector entities, + final Vector contexts, final Vector env, + java.util.Map vartypes) + { boolean res = true; + + if ("null".equals(data)) + { type = new Type("OclAny", null); + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + return true; + } + + if ("Math_NaN".equals(data) || + "Math_PINFINITY".equals(data) || + "Math_NINFINITY".equals(data)) + { type = new Type("double", null); + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + return true; + } // double values that represent invalid doubles + + if (isInteger(data)) + { type = new Type("int",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + data = "" + Expression.convertInteger(data); + // System.out.println("**Type of " + data + " is int"); + return true; + } + + if (Expression.isLong(data)) + { type = new Type("long",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + data = "" + Expression.convertLong(data); + // System.out.println("**Type of " + data + " is long"); + return true; + } + + if (isDouble(data)) + { type = new Type("double",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + // System.out.println("**Type of " + data + " is double"); + return true; + } + + if (isString(data)) + { type = new Type("String",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + // System.out.println("**Type of " + data + " is String"); + if (arrayIndex != null) + { // System.out.println(">>It has array index " + arrayIndex); + arrayIndex.typeCheck(types,entities,contexts,env); + } + return true; + } + + if (isBoolean(data)) + { type = new Type("boolean",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + // System.out.println("**Type of " + data + " is boolean"); + return true; + } + + if ("int".equals(data) || "long".equals(data) || + "boolean".equals(data) || "void".equals(data) || + "double".equals(data) || "String".equals(data) || + "OclDate".equals(data) || "OclAny".equals(data) || + "OclType".equals(data) || "OclFile".equals(data) || + "OclRandom".equals(data) || + "SQLStatement".equals(data) || + "OclDatasource".equals(data) || + "OclAttribute".equals(data) || + "OclOperation".equals(data) || + Type.isOclExceptionType(data) || + "OclProcess".equals(data) || + "OclProcessGroup".equals(data)) + { type = new Type("OclType", null); + elementType = new Type(data, null); + umlkind = TYPE; + type.elementType = elementType; + multiplicity = ModelElement.MANY; + entity = null; + } // for use in oclAsType(typ) + + if ("now".equals(data)) + { type = new Type("long", null); + elementType = type; + umlkind = VARIABLE; + variable = + new Attribute("now", type, ModelElement.INTERNAL); + multiplicity = ModelElement.ONE; + System.out.println("***Type of " + this + " is: " + type); + return true; + } + + if ("$act".equals(data) || "$fin".equals(data)) + { type = new Type("int", null); + elementType = type; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + System.out.println("***Type of " + this + " is: " + type); + return true; + } + + if ("self".equals(data)) + { if (contexts.size() == 0) + { System.err.println("!WARNING!: Invalid occurrence of self, not in instance context"); + // JOptionPane.showMessageDialog(null, "ERROR: Invalid occurrence of self, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); + } + else + { if (contexts.size() > 1) + { System.err.println("!WARNING!: Ambiguous occurrence of self, contexts: " + contexts); + } + entity = (Entity) contexts.get(0); // the most local context + type = new Type(entity); + elementType = type; + umlkind = VARIABLE; + variable = new Attribute("self", type, ModelElement.INTERNAL); + multiplicity = ModelElement.ONE; + System.out.println("***Type of self (most local context) is: " + type); + vartypes.put("self", type); + return true; + } // but may deduce type from features used with self + } + + + if ("super".equals(data)) + { if (contexts.size() == 0) + { if (objectRef == null) + { System.err.println("!!ERROR!!: Invalid occurrence of super, not instance context"); + JOptionPane.showMessageDialog(null, "ERROR!!: Invalid occurrence of super, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); + } + else if (objectRef.elementType != null && + objectRef.elementType.isEntity()) + { entity = objectRef.elementType.getEntity(); + if (entity.getSuperclass() != null) + { type = new Type(entity.getSuperclass()); } + else + { System.err.println("!!ERROR!!: Invalid occurrence of super, no superclass for " + entity); + JOptionPane.showMessageDialog(null, + "ERROR!!: Invalid occurrence of super, no superclass of " + entity, + "Semantic error", JOptionPane.ERROR_MESSAGE); + } + } + else + { System.err.println("!!ERROR!!: Invalid occurrence of super: " + this + + " no defined instance context"); + } + } + else + { if (contexts.size() > 1) + { System.err.println("WARNING!: Ambiguous occurrence of super, contexts: " + contexts); + } + + for (int i = 0; i < contexts.size(); i++) + { entity = (Entity) contexts.get(i); + if (entity != null && entity.getSuperclass() != null) + { type = new Type(entity.getSuperclass()); + break; + } + } + + elementType = type; + umlkind = VARIABLE; + variable = + new Attribute("super", type, ModelElement.INTERNAL); + multiplicity = ModelElement.ONE; + System.out.println("***Type of super is: " + type); + vartypes.put("super", type); + return true; + } + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { if (parameters.get(i) instanceof Expression) + { Expression ep = (Expression) parameters.get(i); + ep.typeInference(types,entities,contexts, + env,vartypes); + } + } + } + + + if (arrayIndex != null) + { boolean res1 = + arrayIndex.typeInference(types,entities,contexts, + env,vartypes); + arrayType = type; + res = res && res1; + } // might reduce multiplicity to ONE - although not for --* qualified roles + + Vector context = new Vector(); + + if (objectRef != null) + { if (objectRef instanceof BasicExpression) + { BasicExpression oref = (BasicExpression) objectRef; + res = objectRef.typeInference(types,entities,contexts, + env,vartypes); + } + else + { res = + objectRef.typeInference(types,entities,contexts, + env,vartypes); + } + + Entity staticent = + (Entity) ModelElement.lookupByName(objectRef + "", entities); + // System.out.println("**Type of " + this + " is static operation, of: " + staticent); + + if (staticent != null) + { objectRef.umlkind = Expression.CLASSID; + // isStatic = true; + + BehaviouralFeature bf = + staticent.getStaticOperation(data,parameters); + + if (bf != null) + { if (bf.parametersMatch(parameters)) { } + else + { JOptionPane.showMessageDialog(null, + "Actual parameters do not match operation formal pars: " + this + " /= " + bf, + "Type warning", JOptionPane.WARNING_MESSAGE); + } + + bf.setFormalParameters(parameters); + System.out.println("** Setting formal parameters of " + this); + + type = bf.getResultType(); + elementType = bf.getElementType(); + entity = staticent; + isStatic = true; + + if (bf.isQuery()) + { umlkind = QUERY; } + else + { umlkind = UPDATEOP; + if (type == null || type.equals("") || + type.equals("void")) + { type = new Type("boolean",null); } + } + // System.out.println("**Type of " + this + " is static operation call, of: " + entity); + return true; + } + else if (staticent.hasDefinedAttribute(data)) + { umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + Attribute att = staticent.getDefinedAttribute(data); + if (att != null && att.isStatic()) + { modality = att.getKind(); + type = att.getType(); + elementType = att.getElementType(); + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + entity = staticent; + isStatic = true; + // variable = att; // For precise type-analysis + + arrayType = type; + adjustTypeForArrayIndex(att); + System.out.println("*** Type of " + data + " is static ATTRIBUTE in entity " + + staticent + " type is " + type + "(" + elementType + ") Modality = " + modality); + return res; + } + } + else + { System.out.println("!! Cannot locate static feature " + + data + " of entity " + + staticent); + } + } + + if (objectRef.elementType != null && + objectRef.elementType.isEntity(entities)) + { context.add(0, + objectRef.elementType.getEntity(entities)); + } + else if (objectRef.type != null && + objectRef.type.isEntity(entities)) + { context.add(0,objectRef.type.getEntity(entities)); } + else + { System.out.println(">>> Searching for class of " + objectRef); + + // Search for a class with data. + + for (int i = 0; i < entities.size(); i++) + { Entity ex = (Entity) entities.get(i); + if (ex.hasAttribute(data)) + { JOptionPane.showMessageDialog(null, + "Located possible class " + ex + " of " + objectRef, + "", JOptionPane.INFORMATION_MESSAGE); + objectRef.type = new Type(ex); + + vartypes.put("" + objectRef, objectRef.type); + + Attribute attx = ex.getAttribute(data); + type = attx.getType(); + elementType = attx.getElementType(); + + vartypes.put(data, type); + } + } + } + } + else // objectRef == null + { context.addAll(contexts); } + + // System.out.println("Context of " + this + "(event: " + isEvent + ") is " + context); + + if (context.size() == 0) + { if (entity == null) + { System.out.println("!! No owning class found for " + this); + System.out.println(); + // + + // " -- it must be a local variable/parameter"); + // System.out.println(">> Or static feature/global use case"); + // System.out.println(">> Static features should be prefixed by their class: C.f"); + } + } + + // System.out.println(); + + if (isEvent && isFunction(data)) + { isEvent = false; + umlkind = FUNCTION; + } // this should not arise. + + if (isEvent && + !data.equals("subrange") && + !data.equals("indexOf") && + !data.equals("setAt") && + !data.equals("insertAt") && + !data.equals("insertInto") && + !data.equals("excludingSubrange") && + !data.equals("setSubrange") && + !(data.equals("replace")) && + !(data.equals("replaceFirstMatch")) && + !(data.equals("replaceAll")) && + !(data.equals("replaceAllMatches")) && + !(data.equals("Sum")) && !(data.equals("Prd")) && + !(data.equals("oclIsKindOf")) && + !(data.equals("oclIsTypeOf")) && + !(data.equals("oclAsType"))) + { // data must be an event of the owning class, the elementType of + // the objectRef, or of an ancestor of it. + BehaviouralFeature bf; + + + for (int i = 0; i < context.size(); i++) + { Entity e = (Entity) context.get(i); + bf = e.getDefinedOperation(data,parameters); + + if (bf != null) + { System.out.println("*>>* Type of " + data + " is operation, of class: " + e); + entity = e; + if (bf.parametersMatch(parameters)) { } + else + { JOptionPane.showMessageDialog(null, + "Actual parameters do not match operation pars: " + this + " " + bf, + "Type warning", JOptionPane.WARNING_MESSAGE); + continue; + } + + System.out.println("** Setting formal parameters of " + data + " operation: " + parameters); + System.out.println(); + + bf.setFormalParameters(parameters); + + if (bf.isQuery()) + { umlkind = QUERY; + type = bf.getResultType(); + elementType = bf.getElementType(); + // System.out.println("QUERY OPERATION, type: " + type); + // System.out.println("QUERY OPERATION, element type: " + elementType); + } + else + { umlkind = UPDATEOP; + type = bf.getResultType(); + elementType = bf.getElementType(); + if (type == null || + type.equals("") || type.equals("void")) + { type = new Type("boolean",null); } + // System.out.println("UPDATE OPERATION, type: " + type); + } // shouldn't be object ref of anything. Should + // only occur as part of action invariant. + + setObjectRefType(); + + adjustTypeForObjectRef(bf); + arrayType = type; + + adjustTypeForArrayIndex(bf); + + if (objectRef instanceof BasicExpression) + { String vname = + ((BasicExpression) objectRef).basicString(); + vartypes.put(vname, new Type(entity)); + } + + return true; + } // type check the actual parameters, also + else if (e.getEventNames().contains(data)) + { umlkind = UPDATEOP; + entity = e; + multiplicity = ModelElement.ONE; + type = new Type("boolean",null); + setObjectRefType(); + // adjustTypeForObjectRef(bf); + // adjustTypeForArrayIndex(bf); + arrayType = type; + + if (objectRef instanceof BasicExpression) + { String vname = + ((BasicExpression) objectRef).basicString(); + vartypes.put(vname, new Type(entity)); + } + + return true; + } // else, downcast if in a subclass + else + { Entity subent = + e.searchForSubclassWithOperation(data); + if (subent != null) + { downcast = true; + entity = subent; + bf = subent.getOperation(data); + if (bf != null) + { type = bf.getResultType(); + elementType = bf.getElementType(); + + bf.setFormalParameters(parameters); + + if (bf.isQuery()) + { umlkind = QUERY; } + else + { umlkind = UPDATEOP; + if (type == null || type.equals("") || + type.equals("void")) + { type = new Type("boolean",null); } + } + setObjectRefType(); + adjustTypeForObjectRef(bf); + arrayType = type; + adjustTypeForArrayIndex(bf); + + if (objectRef instanceof BasicExpression) + { String vname = + ((BasicExpression) objectRef).basicString(); + vartypes.put(vname, new Type(entity)); + } + + return true; + } + } + } + } + + // If it is a function parameter of the current operation: + + Attribute fvar = + (Attribute) ModelElement.lookupByName(data,env); + if (fvar != null) + { type = fvar.getType(); + arrayType = type; + + if (type != null && type.isFunctionType()) + { umlkind = UPDATEOP; + elementType = fvar.getElementType(); + System.out.println(">> Function parameter " + data + " of type " + type + "(" + elementType + ")"); + } + else + { JOptionPane.showMessageDialog(null, data + " is not a function parameter or known function in " + this + ".\n" + + "Please re-type-check or correct your specification.", + "Type warning", JOptionPane.WARNING_MESSAGE); + + if (parameters != null && parameters.size() == 1) + { // assume it is a function + type = new Type("Function", null); + Expression par1 = (Expression) parameters.get(0); + type.keyType = par1.getType(); + type.elementType = new Type("OclAny", null); + + vartypes.put(data, type); + } // data->apply(par1) + } + } // default + else if (objectRef != null) + { if (objectRef.type != null) + { String ename = objectRef.type.getName(); + Entity cent = + (Entity) ModelElement.lookupByName(ename, entities); + if (cent != null) + { BehaviouralFeature op = cent.getOperation(data); + if (op != null) + { System.out.println(">>> Found operation " + op + " of class " + cent); + umlkind = UPDATEOP; + type = op.getType(); + elementType = op.getElementType(); + } + } + } + else + { System.err.println("!Warning!: Unknown operation " + data + " at call " + this + ".\n"); + System.out.println(">> " + objectRef + " of type: " + objectRef.type); + type = new Type("boolean",null); + elementType = new Type("boolean",null); + } + umlkind = UPDATEOP; + } + } + + if (isFunction(data)) + { umlkind = FUNCTION; + if (objectRef == null) // error + { System.err.println("!! TYPE ERROR: OCL operator " + data + + " should have object ref: arg." + data + "(pars)"); + + if (parameters != null && parameters.size() > 0) + { objectRef = (Expression) parameters.get(0); + parameters.remove(0); + } + else + { type = null; + return false; + } + } + + entity = objectRef.entity; // default + multiplicity = ModelElement.ONE; // default + modality = objectRef.modality; + + if (("Sum".equals(data) || "Prd".equals(data)) && + "Integer".equals(objectRef + "") && + parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + // must both be numeric. + + if (par1.isNumeric()) { } + else + { System.err.println("! 1st parameter of " + this + + " must be numeric"); + par1.setType(new Type("int", null)); + if (par1 instanceof BasicExpression) + { vartypes.put(((BasicExpression) par1).basicString(), + par1.getType()); + } + } + + if (par2.isNumeric()) { } + else + { System.err.println("! 2nd parameter of " + this + + " must be numeric"); + par2.setType(new Type("int", null)); + if (par2 instanceof BasicExpression) + { vartypes.put(((BasicExpression) par2).basicString(), + par2.getType()); + } + } + + Expression par3 = (Expression) parameters.get(2); + par3.setType(new Type("int",null)); + par3.setElementType(new Type("int",null)); + Vector env1 = (Vector) ((Vector) env).clone(); + env1.add(new Attribute(par3 + "", + par3.type, ModelElement.INTERNAL)); + Expression par4 = (Expression) parameters.get(3); + par4.typeCheck(types,entities,contexts,env1); + + + if ("Prd".equals(data) && !par4.isNumeric()) + { System.err.println("! 4th parameter of " + this + + " must be numeric"); + par4.setType(new Type("double", null)); + if (par4 instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) par4).basicString(), + par4.getType()); + } + } + + type = par4.getType(); + elementType = par4.getElementType(); + type.setElementType(elementType); + + return true; + } + + if (data.equals("toLong") || data.equals("gcd")) + { type = new Type("long", null); + elementType = type; + } + else if (data.equals("size") || + data.equals("floor") || data.equals("count") || + data.equals("toInteger") || + data.equals("indexOf") || data.equals("ceil") || + data.equals("round")) + { type = new Type("int",null); + elementType = type; + + if (data.equals("floor") || + data.equals("ceil") || + data.equals("round")) + { if (objectRef.isNumeric()) { } + else + { System.err.println("! object ref of " + this + + " must be numeric"); + objectRef.setType(new Type("double", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + } + else if (data.equals("toInteger") && + !objectRef.isString()) + { System.err.println("! object ref of " + this + + " must be a string"); + objectRef.setType(new Type("String", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + + } + else if (data.equals("sort") || + data.equals("characters") || + data.equals("sortedBy") || + data.equals("asSequence") || + data.equals("allInstances")) + { type = new Type("Sequence",null); + elementType = objectRef.elementType; + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + arrayType = type; + + adjustTypeForArrayIndex(); + + if (data.equals("characters") && + !objectRef.isString()) + { System.err.println("! object ref of " + this + + " must be a string"); + objectRef.setType(new Type("String", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + else if (data.equals("allInstances")) + { // object ref must be an entity name + Entity eref = + (Entity) ModelElement.lookupByName(objectRef + "", + entities); + if (eref == null) + { System.err.println("! object ref of " + this + + " must be an entity name"); + objectRef.setType(new Type("OclType", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + } + else if (objectRef.isCollection() || + objectRef.isMap()) + { } + else + { System.err.println("! object ref of " + this + + " must be a collection or map"); + } + } + else if (data.equals("isDeleted") || + data.equals("oclIsTypeOf") || + data.equals("oclIsKindOf")) + { type = new Type("boolean",null); + elementType = type; + } + else if (data.equals("isReal") || + data.equals("toBoolean") || + data.equals("isInteger") || + data.equals("isLong") || + data.equals("hasPrefix") || + data.equals("hasSuffix")) + { type = new Type("boolean",null); + elementType = type; + + if (!objectRef.isString()) + { System.err.println("! object ref of " + this + + " must be a string"); + objectRef.setType(new Type("String", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + } + else if (data.equals("oclAsType") && + parameters != null && + parameters.size() > 0) // type cast + { Expression par1 = (Expression) parameters.get(0); + type = par1.elementType; // Type is the casted type + elementType = type; + } + else if (data.equals("subrange")) + { // 3 cases - Integer.subrange, + // str.subrange, col.subrange + if ("Integer".equals(objectRef + "")) + { type = new Type("Sequence", null); + elementType = new Type("int", null); + // could be long if the 2nd argument is long + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + arrayType = type; + adjustTypeForArrayIndex(); + + // Both parameters should be integers + Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + + if (par1.isInteger()) { } + else + { System.err.println("! 1st parameter of " + this + + " must be integer"); + par1.setType(new Type("int", null)); + if (par1 instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) par1).basicString(), + par1.getType()); + } + } + + if (par2.isInteger()) { } + else + { System.err.println("! 2nd parameter of " + this + + " must be integer"); + par2.setType(new Type("int", null)); + if (par2 instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) par2).basicString(), + par2.getType()); + } + } + + return res; + } + else if (objectRef.isString()) + { type = new Type("String", null); + elementType = new Type("String", null); + // could be long if the 2nd argument is long + type.setElementType(elementType); + multiplicity = ModelElement.ONE; + arrayType = type; + adjustTypeForArrayIndex(); + + Expression par1 = (Expression) parameters.get(0); + + if (par1.isInteger()) { } + else + { System.err.println("! 1st parameter of " + this + + " must be integer"); + par1.setType(new Type("int", null)); + if (par1 instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) par1).basicString(), + par1.getType()); + } + } + + return res; + } + + // Otherwise, assume it is a collection + type = new Type("Sequence", null); + elementType = objectRef.elementType; + multiplicity = ModelElement.MANY; + arrayType = type; + adjustTypeForArrayIndex(); + + Expression par1 = (Expression) parameters.get(0); + + if (par1.isInteger()) { } + else + { System.err.println("! 1st parameter of " + this + + " must be integer"); + par1.setType(new Type("int", null)); + if (par1 instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) par1).basicString(), + par1.getType()); + } + } + + return res; + } + else if (data.equals("reverse") || + data.equals("tail") || + data.equals("front") || + data.equals("excludingSubrange") || + data.equals("setSubrange") || + data.equals("insertAt") || + data.equals("insertInto") || + data.equals("setAt")) + { type = objectRef.getType(); // Sequence or String + elementType = objectRef.elementType; + + if (objectRef.isString() || + objectRef.isSequence()) + { } + else + { System.err.println("! objectRef of " + this + + " must be string or sequence"); + } + + if (data.equals("insertAt") || + data.equals("setAt")) + { Expression par2 = (Expression) parameters.get(1); + Type partyp = par2.getType(); + Type newleftET = + Type.refineType(elementType,partyp); + System.out.println(">> Deduced element type of " + this + " = " + newleftET); + elementType = newleftET; + type.setElementType(newleftET); + + Expression par1 = (Expression) parameters.get(0); + if (par1.isInteger()) { } + else + { System.err.println("! 1st parameter of " + this + + " must be integer"); + par1.setType(new Type("int", null)); + if (par1 instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) par1).basicString(), + par1.getType()); + } + } + } + + if (type != null && + type.isCollectionType()) + { multiplicity = ModelElement.MANY; + arrayType = type; + adjustTypeForArrayIndex(); + return res; + } + } + else if (data.equals("toReal")) + { if (objectRef.isString()) { } + else + { System.err.println("! objectRef of " + this + + " must be a string"); + objectRef.setType(new Type("String", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + + type = new Type("double",null); + elementType = type; + } + else if (data.equals("sqrt") || + data.equals("exp") || data.equals("pow") || + data.equals("sqr") || data.equals("abs") || + data.equals("sin") || data.equals("cos") || + data.equals("cbrt") || + data.equals("sinh") || data.equals("cosh") || + data.equals("tanh") || + data.equals("atan") || data.equals("acos") || + data.equals("asin") || + data.equals("tan") || data.equals("log") || + data.equals("log10")) + { if (objectRef.isNumeric()) { } + else + { System.err.println("! objectRef of " + this + + " must be numeric"); + objectRef.setType(new Type("double", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + + type = new Type("double",null); + elementType = type; + } + else if (data.equals("toLowerCase") || + data.equals("toUpperCase") || + data.equals("replace") || + data.equals("replaceAll") || + data.equals("replaceFirstMatch") || + data.equals("replaceAllMatches") ) + { if (objectRef.isString()) { } + else + { System.err.println("! objectRef of " + this + + " must be a string"); + objectRef.setType(new Type("String", null)); + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + objectRef.getType()); + } + } + + type = new Type("String",null); + elementType = type; + } + else if (data.equals("closure") || data.equals("asSet")) + { type = new Type("Set",null); + elementType = objectRef.elementType; + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + return res; + } + else if (data.equals("subcollections")) + { type = new Type("Set",null); + elementType = objectRef.getType(); + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + return res; + } + else // max,min,sum,prd,last,first,any + { type = objectRef.getElementType(); + elementType = type; + if (data.equals("sum") || data.equals("prd")) + { entity = null; } + + if (type == null) // objectRef is multiple but an attribute + { type = objectRef.getType(); + Entity e = objectRef.getEntity(); + if (type == null && e != null && (objectRef instanceof BasicExpression)) + { type = e.getFeatureType(((BasicExpression) objectRef).data); } + // System.out.println("Element type of " + data + ": " + e + " " + type); + if (type == null) // || type.getName().equals("Set")) + { System.err.println("!!! ERROR: Can't determine element type of " + this); + JOptionPane.showMessageDialog(null, "ERROR: Can't determine element type of " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + type = new Type("void",null); + } // actually a void or Object type. + } + } + // entity = null; + // System.out.println("**Type of " + this + " is " + type); + return res; + } // toUpper, toLower, sqr, sqrt, exp, abs, floor, could have objectRef + // multiple, in which case result is multiple + + + + // Parameters or local variables of the + // current operation/usecase: + + Attribute paramvar = + (Attribute) ModelElement.lookupByName(data,env); + if (paramvar != null && objectRef == null) + { type = paramvar.getType(); + elementType = paramvar.getElementType(); + entity = paramvar.getEntity(); + if (entity == null && elementType != null) + { entity = elementType.getEntity(); } + if (entity == null && type != null) + { entity = type.getEntity(); } + if (elementType == null && type != null) + { elementType = type.getElementType(); } + arrayType = type; + adjustTypeForArrayIndex(paramvar); + + // System.out.println(">>> Parameter/local variable: " + this + " type= " + type + " (" + elementType + ")"); + // System.out.println(); + variable = paramvar; + umlkind = VARIABLE; + modality = paramvar.getKind(); + + return true; + } // And adjust type for any array index. + + for (int j = 0; j < context.size(); j++) + { Entity ent = (Entity) context.get(j); + if (ent.hasDefinedAttribute(data)) + { umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + Attribute att = ent.getDefinedAttribute(data); + if (att == null) // something very bad has happened + { System.err.println("!! TYPE ERROR: attribute: " + data + " is not defined in class " + ent.getName()); + return false; + } + modality = att.getKind(); + type = att.getType(); + if (att.isStatic()) + { isStatic = true; } + + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + new Type(ent)); + } + + elementType = att.getElementType(); + if (elementType == null || + "OclAny".equals("" + elementType)) + { elementType = type.getElementType(); } + + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + entity = ent; // may not be att.owner, but a subclass of this. + if (objectRef == null) + { res = true; } + else + { setObjectRefType(); } + + System.out.println(">+>+> Attribute: " + this + " type= " + type + " (" + elementType + ")"); + + /* if (arrayIndex != null) + { System.out.println("** Unadjusted type of " + this + " is ATTRIBUTE in entity " + + ent + " type is " + type + "(" + elementType + ") Modality = " + modality); + } */ + + adjustTypeForObjectRef(att); + arrayType = type; + + // if (alreadyCorrected) { } + // else + // { + adjustTypeForArrayIndex(att); + + elementType = Type.correctElementType( + type,elementType,types,entities); + // att.setElementType(elementType); + // variable = att; + System.out.println("*>>* Adjusted type of " + this + " is " + type + "(" + elementType + ")"); + System.out.println(); + // alreadyCorrected = true; + // } + + return res; + } // couldn't it have an array ref if objectRef was a sequence? + else + { Entity subent = ent.searchForSubclassWithAttribute(data); + if (subent != null) + { umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + Attribute att = subent.getAttribute(data); + if (att == null) // something very bad has happened + { System.err.println("!! TYPE ERROR: attribute: " + data + " is not defined in class " + subent); + JOptionPane.showMessageDialog(null, "Undefined attribute: " + data, "Type error", JOptionPane.ERROR_MESSAGE); + return false; + } + modality = att.getKind(); + downcast = true; + if (att.isStatic()) + { isStatic = true; } + + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + new Type(subent)); + } + + type = att.getType(); + elementType = att.getElementType(); + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + entity = subent; + adjustTypeForObjectRef(att); + arrayType = type; + adjustTypeForArrayIndex(att); + // System.out.println("**Type of " + data + " is downcast ATTRIBUTE in entity " + + // subent + " type is " + type); + // variable = att; + return res; + } + } + + if (ent.hasDefinedRole(data)) + { umlkind = ROLE; + Association ast = ent.getDefinedRole(data); + if (ast == null) // something very bad has happened + { System.err.println("!! TYPE ERROR: role: " + data + " is not defined in class " + ent.getName()); + JOptionPane.showMessageDialog(null, "Undefined role " + data, "Type error", + JOptionPane.ERROR_MESSAGE); + return false; + } + + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + new Type(ent)); + } + + + multiplicity = ast.getCard2(); + elementType = new Type(ast.getEntity2()); + modality = ModelElement.INTERNAL; // ??? + + if (ast.isQualified() && arrayIndex == null) // a naked qualified role, it is a map + { type = ast.getRole2Type(); } + else if (multiplicity == ModelElement.ONE) + { type = new Type(ast.getEntity2()); } + else + { if (ast.isOrdered()) + { type = new Type("Sequence",null); } + else + { type = new Type("Set",null); } + type.setElementType(elementType); + + // type = new Type(ast.getEntity2()); + } // index must be int type, + // and ast is ordered/sorted. Also for any att or role + + adjustTypeForObjectRef(); + arrayType = type; + + if (arrayIndex != null && !ast.isQualified()) + { adjustTypeForArrayIndex(); } + + // if (Type.isCollectionType(type)) + // { multiplicity = ModelElement.MANY; } + // else + // { multiplicity = ModelElement.ONE; } + // System.out.println("**Type of " + data + " is ROLE in entity " + ent + + // "\n type is: " + type + " element type: " + + // elementType + " Modality = " + modality); + entity = ent; + if (objectRef == null) + { res = true; } + else + { setObjectRefType(); } + + // variable = attribute for the role? + + return res; + } + else + { Entity subent = ent.searchForSubclassWithRole(data); + if (subent != null) + { umlkind = ROLE; + Association ast = subent.getRole(data); + if (ast == null) // something very bad has happened + { System.err.println("!! ERROR: Undefined role: " + data); + return false; + } + + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + new Type(subent)); + } + + multiplicity = ast.getCard2(); + modality = ModelElement.INTERNAL; + downcast = true; + elementType = new Type(ast.getEntity2()); + if (multiplicity == ModelElement.ONE) + { type = new Type(ast.getEntity2()); } + else + { if (ast.isOrdered()) + { type = new Type("Sequence",null); } + else + { type = new Type("Set",null); } + type.setElementType(elementType); + } + adjustTypeForObjectRef(); + arrayType = type; + if (arrayIndex != null && !ast.isQualified()) + { adjustTypeForArrayIndex(); } + // System.out.println("**Type of " + data + " is downcast ROLE in entity " + + // subent + " type is " + type); + entity = subent; + + // variable = attribute for the role? + return res; + } // objectRefTypeAssignment + } // or it could be a query op of the entity + } + // prestate == true only for VARIABLE, ATTRIBUTE, ROLE, CONSTANT + + /* Is data in some enumerated type? */ + + for (int i = 0; i < types.size(); i++) + { Type t = (Type) types.get(i); + if (t != null && t.hasValue(data)) + { umlkind = VALUE; + multiplicity = ModelElement.ONE; + System.out.println("*** " + data + " is enumerated literal in type " + t); + type = t; + elementType = type; + + if (objectRef == null) + { return true; } + else if (t.getName().equals(objectRef + "")) + { return true; } + } + } // if T1.value and T2.value may both occur, must be distinguished by the type name + + if (data.equals("Integer")) + { type = new Type("OclType",null); + elementType = new Type("int",null); + type.setElementType(elementType); + umlkind = TYPE; + modality = ModelElement.INTERNAL; + multiplicity = ModelElement.MANY; + return true; + } + + Attribute var = + (Attribute) ModelElement.lookupByName(data,env); + if (var != null) + { type = var.getType(); + elementType = var.getElementType(); + umlkind = VARIABLE; // its a parameter or local variable. + variable = var; + modality = var.getKind(); + if (type != null) + { String tname = type.getName(); + if (tname.equals("Set") || + tname.equals("Sequence") || + tname.equals("Map")) + { multiplicity = ModelElement.MANY; } + else + { multiplicity = ModelElement.ONE; } // assume + } + else + { multiplicity = ModelElement.ONE; } // assume + + arrayType = type; + if (arrayIndex != null) + { adjustTypeForArrayIndex(var); } + + if (parameters != null && + var.getType().isFunctionType()) // application of a Function(S,T) + { Type ftype = var.getType(); + type = ftype.getElementType(); + elementType = type.getElementType(); + System.out.println(">>>> TYPE CHECKED: Type of variable expression " + this + " is " + type + " entity: " + entity); + } + + entity = var.getEntity(); + if (entity == null && elementType != null) + { entity = elementType.getEntity(); } + if (entity == null && type != null) + { entity = type.getEntity(); } + + return true; + } // entity = var.getEntity() ? + + Entity ee = + (Entity) ModelElement.lookupByName(data,entities); + if (ee != null) + { umlkind = CLASSID; + // System.out.println("**umlkind of " + this + " is CLASSID"); + modality = ModelElement.INTERNAL; + elementType = new Type(ee); + if (arrayIndex != null) // a lookup by primary key + { if (!arrayIndex.isMultiple()) // (arrayIndex.multiplicity == ModelElement.ONE) + { multiplicity = ModelElement.ONE; + type = new Type(ee); + } + else + { multiplicity = ModelElement.MANY; + + if (arrayIndex.isOrdered()) + { type = new Type("Sequence", null); } + else + { type = new Type("Set",null); } + type.setElementType(elementType); + } + } + else + { multiplicity = ModelElement.MANY; + type = new Type("Sequence",null); + type.setElementType(elementType); + } + entity = ee; // ?? + elementType = new Type(ee); // type.setElementType(elementType); ?? + return res; + } + + /* if (isConstant(data)) + { umlkind = CONSTANT; + // System.out.println("**Type of " + data + " is CONSTANT"); + modality = ModelElement.INTERNAL; + multiplicity = ModelElement.ONE; // as for variables + return res; + } */ + + if (umlkind != UNKNOWN && type != null && elementType != null) + { return res; } + + if (parameters != null && umlkind == UNKNOWN) // must be an operation, external, not a variable + { umlkind = UPDATEOP; } + else if (parameters == null) + { umlkind = VARIABLE; } + modality = ModelElement.INTERNAL; + multiplicity = ModelElement.ONE; // assume + + if (objectRef != null && entity == null) + { Type oret = objectRef.getElementType(); + if (oret != null && oret.isEntity()) + { entity = oret.getEntity(); } + } + + if (isEvent && type == null && objectRef == null && + context.size() == 0) + { // A usecase, or a static operation of the local class + + BehaviouralFeature bf; + + for (int i = 0; i < entities.size(); i++) + { Entity e = (Entity) entities.get(i); + bf = e.getDefinedOperation(data,parameters); + + if (bf != null && bf.isStatic()) + { System.out.println("**Type of " + data + " is static operation, of class: " + e); + entity = e; + if (bf.parametersMatch(parameters)) { } + else + { JOptionPane.showMessageDialog(null, + "Parameters do not match operation pars: " + this + " " + bf, + "Type warning", JOptionPane.WARNING_MESSAGE); + continue; + } + + if (objectRef instanceof BasicExpression) + { vartypes.put( + ((BasicExpression) objectRef).basicString(), + new Type(e)); + } + + System.out.println("** Setting formal parameters of " + data + " operation: " + parameters); + System.out.println(); + + bf.setFormalParameters(parameters); + + if (bf.isQuery()) + { umlkind = QUERY; + type = bf.getResultType(); + elementType = bf.getElementType(); + // System.out.println("QUERY OPERATION, type: " + type); + // System.out.println("QUERY OPERATION, element type: " + elementType); + } + else + { umlkind = UPDATEOP; + type = bf.getResultType(); + elementType = bf.getElementType(); + if (type == null || + type.equals("") || type.equals("void")) + { type = new Type("boolean",null); } + // System.out.println("UPDATE OPERATION, type: " + type); + } // shouldn't be object ref of anything. Should + // only occur as part of action invariant. + + arrayType = type; + + adjustTypeForArrayIndex(bf); + return true; + } // type check the actual parameters, also + } + } + + if ("skip".equals(data)) + { } + else if (type == null) + { System.out.println("***! WARNING: Type of " + this + " is unknown"); + System.out.println("***! Re-run type-checking/correct your specification"); + } + + return true; + } + + public boolean typeCheck(final Vector types, final Vector entities, + final Vector contexts, final Vector env) + { boolean res = true; + + modality = ModelElement.NONE; // default + // check if a number, boolean or String. + // if so, umlkind = VALUE and should have no objectRef + // Also doubles. + Vector context = new Vector(); // local context + + + if ("null".equals(data)) + { type = new Type("OclAny", null); + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + return true; + } + + if ("Math_NaN".equals(data) || + "Math_PINFINITY".equals(data) || + "Math_NINFINITY".equals(data)) + { type = new Type("double", null); + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + return true; + } // double values that represent invalid doubles + + if (isInteger(data)) + { type = new Type("int",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + data = "" + Expression.convertInteger(data); + // System.out.println("**Type of " + data + " is int"); + return true; + } + + if (Expression.isLong(data)) + { type = new Type("long",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + data = "" + Expression.convertLong(data); + // System.out.println("**Type of " + data + " is long"); + return true; + } + + if (isDouble(data)) + { type = new Type("double",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + // System.out.println("**Type of " + data + " is double"); + return true; + } + + if (isString(data)) + { type = new Type("String",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + // System.out.println("**Type of " + data + " is String"); + if (arrayIndex != null) + { // System.out.println(">>It has array index " + arrayIndex); + arrayIndex.typeCheck(types,entities,contexts,env); + } + return true; + } + + if (isBoolean(data)) + { type = new Type("boolean",null); + elementType = type; + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + // System.out.println("**Type of " + data + " is boolean"); + return true; + } + + // Expression.isSetValue(data) + if (isSet(data)) // convert it to a SetExpression + { type = new Type("Set",null); // or Sequence if ordered + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.MANY; + SetExpression se = (SetExpression) buildSetExpression(data); + elementType = Type.determineType(se.getElements()); + type.setElementType(elementType); + // System.out.println("**Type of " + data + " is " + type); + return true; + } // could have an array index. Also deduce elementType + + // Expression.isSequenceValue(data) + if (isSequence(data)) // convert it to a SetExpression + { type = new Type("Sequence",null); // or Sequence if ordered + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.MANY; + SetExpression se = (SetExpression) buildSetExpression(data); + elementType = Type.determineType(se.getElements()); + type.setElementType(elementType); + if (arrayIndex != null) + { type = elementType; + elementType = elementType.getElementType(); + arrayIndex.typeCheck(types,entities,contexts,env); + if (type != null) + { multiplicity = type.typeMultiplicity(); } + } + // System.out.println("**Type of " + this + " is " + type); + return true; + } // and deduce elementType + + // Expression.isMapValue(data) + if (isMap(data)) // convert it to a SetExpression + { type = new Type("Map",null); // or Sequence if ordered + entity = null; + umlkind = VALUE; + multiplicity = ModelElement.MANY; + SetExpression se = (SetExpression) buildSetExpression(data); + elementType = Type.determineType(se.getElements()); + type.setElementType(elementType); + // System.out.println("**Type of " + data + " is " + type); + return true; + } // could have an array index. Also deduce elementType + + if ("int".equals(data) || "long".equals(data) || + "boolean".equals(data) || "void".equals(data) || + "double".equals(data) || "String".equals(data) || + "OclDate".equals(data) || "OclAny".equals(data) || + "OclType".equals(data) || "OclFile".equals(data) || + "OclRandom".equals(data) || + "SQLStatement".equals(data) || + "OclDatasource".equals(data) || + "OclAttribute".equals(data) || + "OclOperation".equals(data) || + Type.isOclExceptionType(data) || + "OclProcess".equals(data) || + "OclProcessGroup".equals(data)) + { type = new Type("OclType", null); + elementType = new Type(data, null); + umlkind = TYPE; + type.elementType = elementType; + multiplicity = ModelElement.MANY; + entity = null; + } // for use in oclAsType(typ) + + if ("now".equals(data)) + { type = new Type("long", null); + elementType = type; + umlkind = VARIABLE; + variable = new Attribute("now", type, ModelElement.INTERNAL); + multiplicity = ModelElement.ONE; + System.out.println("***Type of " + this + " is: " + type); + return true; + } + + if ("$act".equals(data) || "$fin".equals(data)) + { type = new Type("int", null); + elementType = type; + umlkind = VALUE; + multiplicity = ModelElement.ONE; + System.out.println("***Type of " + this + " is: " + type); + return true; + } + + if ("self".equals(data)) + { if (contexts.size() == 0) + { System.err.println("!WARNING!: Invalid occurrence of self, not in instance context"); + // JOptionPane.showMessageDialog(null, "ERROR: Invalid occurrence of self, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); + } + else + { if (contexts.size() > 1) + { System.err.println("!WARNING!: Ambiguous occurrence of self, contexts: " + contexts); + } + entity = (Entity) contexts.get(0); // the most local context + type = new Type(entity); + elementType = type; + umlkind = VARIABLE; + variable = new Attribute("self", type, ModelElement.INTERNAL); + multiplicity = ModelElement.ONE; + System.out.println("***Type of self (most local context) is: " + type); + return true; + } + } + + if ("super".equals(data)) + { if (contexts.size() == 0) + { if (objectRef == null) + { System.err.println("!!ERROR!!: Invalid occurrence of super, not instance context"); + JOptionPane.showMessageDialog(null, "ERROR!!: Invalid occurrence of super, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); + } + else if (objectRef.elementType != null && + objectRef.elementType.isEntity()) + { entity = objectRef.elementType.getEntity(); + if (entity.getSuperclass() != null) + { type = new Type(entity.getSuperclass()); } + else + { System.err.println("!!ERROR!!: Invalid occurrence of super, no superclass for " + entity); + JOptionPane.showMessageDialog(null, + "ERROR!!: Invalid occurrence of super, no superclass of " + entity, + "Semantic error", JOptionPane.ERROR_MESSAGE); + } + } + else + { System.err.println("!!ERROR!!: Invalid occurrence of super: " + this + " no defined instance context"); } + } + else + { if (contexts.size() > 1) + { System.err.println("WARNING!: Ambiguous occurrence of super, contexts: " + contexts); + } + + for (int i = 0; i < contexts.size(); i++) + { entity = (Entity) contexts.get(i); + if (entity != null && entity.getSuperclass() != null) + { type = new Type(entity.getSuperclass()); + break; + } + } + elementType = type; + umlkind = VARIABLE; + variable = new Attribute("super", type, ModelElement.INTERNAL); + multiplicity = ModelElement.ONE; + System.out.println("***Type of super is: " + type); + return true; + } + } + + if ("equivalent".equals(data)) + { if (contexts.size() == 0) + { System.err.println("!!ERROR!!: no context for ETL equivalent() operator"); + JOptionPane.showMessageDialog(null, "ERROR!!: Invalid occurrence of equivalent, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); + } + else + { // entity = (Entity) contexts.get(0); // the most local context + entity = (Entity) ModelElement.lookupByName("$IN", entities); + Entity outent = (Entity) ModelElement.lookupByName("$OUT", entities); + type = new Type(outent); + elementType = type; + umlkind = UPDATEOP; + multiplicity = ModelElement.ONE; + return true; + } + } // Only for formalisation of ETL + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { if (parameters.get(i) instanceof Expression) + { Expression ep = (Expression) parameters.get(i); + ep.typeCheck(types,entities,contexts,env); + } + } + } + + if ("newOclDate".equals(data) || + "newOclDate_Time".equals(data)) + { type = new Type("OclDate", null); + umlkind = UPDATEOP; + isStatic = true; + entity = (Entity) ModelElement.lookupByName("OclDate",entities); + multiplicity = ModelElement.ONE; + // set the formal parameters + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Attribute fpar1 = new Attribute("t", + new Type("long", null), + ModelElement.INTERNAL); + par1.formalParameter = fpar1; + } + return true; + } + + if (data.startsWith("new")) + { String createdClass = data.substring(3); + if (Type.isExceptionType(createdClass)) + { type = new Type(createdClass,null); + umlkind = UPDATEOP; + isStatic = true; + entity = (Entity) + ModelElement.lookupByName(createdClass,entities); + multiplicity = ModelElement.ONE; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + if (par.isString()) + { Attribute fparmessage = + new Attribute("m", new Type("String", null), + ModelElement.INTERNAL); + par.formalParameter = fparmessage; + } + else + { Attribute fparcause = + new Attribute("c", new Type("OclException", null), ModelElement.INTERNAL); + par.formalParameter = fparcause; + } + } + } + + return true; + } + else if (createdClass.startsWith("OclIterator")) + { type = new Type("OclIterator",null); + umlkind = UPDATEOP; + isStatic = true; + entity = (Entity) + ModelElement.lookupByName("OclIterator",entities); + multiplicity = ModelElement.ONE; + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + if (par1.isString()) + { elementType = new Type("String", null); } + else + { elementType = par1.getElementType(); } + + if (createdClass.equals("OclIterator_Sequence")) + { Attribute fparsq = + new Attribute("sq", new Type("Sequence", null), ModelElement.INTERNAL); + par1.formalParameter = fparsq; + } + else if (createdClass.equals("OclIterator_Set")) + { Attribute fparst = + new Attribute("st", new Type("Set", null), ModelElement.INTERNAL); + par1.formalParameter = fparst; + } + else if (createdClass.startsWith("OclIterator_String")) + { Attribute fparss = + new Attribute("ss", new Type("String", null), ModelElement.INTERNAL); + par1.formalParameter = fparss; + } + } // and String_String, _Function + + return true; + } + + } // and the parameters + + if ("length".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("String")) + { type = new Type("int", null); + umlkind = FUNCTION; + data = "size"; + parameters = null; + multiplicity = ModelElement.ONE; + + return true; + } + } + + if ("time".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { type = new Type("long", null); + umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + entity = (Entity) ModelElement.lookupByName("OclDate",entities); + + return true; + } + } + + if ("getSystemTime".equals(data) && "OclDate".equals(objectRef + "")) + { type = new Type("long", null); + umlkind = QUERY; + isStatic = true; + entity = (Entity) ModelElement.lookupByName("OclDate",entities); + + multiplicity = ModelElement.ONE; + entity = + (Entity) ModelElement.lookupByName("OclDate",entities); + + return true; + } + + if ("getTime".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { umlkind = QUERY; + multiplicity = ModelElement.ONE; + type = new Type("long", null); + entity = (Entity) ModelElement.lookupByName("OclDate",entities); + return true; + } + } + + if ("setTime".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { type = new Type("void", null); + umlkind = UPDATEOP; + multiplicity = ModelElement.ONE; + entity = + (Entity) ModelElement.lookupByName("OclDate",entities); + // set the formal parameters + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Attribute fpar1 = new Attribute("t", + new Type("long", null), + ModelElement.INTERNAL); + par1.formalParameter = fpar1; + } + + return true; + } + } + + if ("dateAfter".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { type = new Type("boolean", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = (Entity) ModelElement.lookupByName("OclDate",entities); + // set the formal parameters + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Attribute fpar1 = new Attribute("d", + new Type("OclDate", null), + ModelElement.INTERNAL); + par1.formalParameter = fpar1; + } + + return true; + } + } + + if ("dateBefore".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { type = new Type("boolean", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = + (Entity) ModelElement.lookupByName("OclDate",entities); + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Attribute fpar1 = new Attribute("d", + new Type("OclDate", null), + ModelElement.INTERNAL); + par1.formalParameter = fpar1; + } + return true; + + // set the formal parameters + + } + } + + if ("elements".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclIterator")) + { type = new Type("Sequence", null); + entity = (Entity) + ModelElement.lookupByName("OclIterator",entities); + + umlkind = ATTRIBUTE; + multiplicity = ModelElement.MANY; + + return true; + } + } + + if ("printStackTrace".equals(data) && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.isOclException()) + { type = new Type("void", null); + umlkind = UPDATEOP; + multiplicity = ModelElement.ONE; + entity = (Entity) + ModelElement.lookupByName(objectRef.type.getName(), + entities); + + return true; + } + } + + if (("getCurrent".equals(data) || "read".equals(data) || + "readLine".equals(data) || "getName".equals(data) || + "getAbsolutePath".equals(data) || + "readAll".equals(data) || "getPath".equals(data) || + "getParent".equals(data)) + && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclFile")) + { type = new Type("String", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = (Entity) + ModelElement.lookupByName("OclFile",entities); + + return true; + } + } + + if (("lastModified".equals(data) || "length".equals(data)) + && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclFile")) + { type = new Type("long", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = (Entity) + ModelElement.lookupByName("OclFile",entities); + + return true; + } + } + + if (("hasNext".equals(data) || "canRead".equals(data) || + "canWrite".equals(data) || "exists".equals(data) || + "isFile".equals(data) || "mkdir".equals(data) || + "mkdirs".equals(data) || + "isDirectory".equals(data) || + "isAbsolute".equals(data)) + && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclFile")) + { type = new Type("boolean", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + // set the formal parameters + entity = (Entity) + ModelElement.lookupByName("OclFile",entities); + + return true; + } + } + + if (("isAlive".equals(data) || "isDaemon".equals(data)) + && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclProcess")) + { type = new Type("boolean", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = (Entity) + ModelElement.lookupByName("OclProcess",entities); + return true; + } + } + + if ("getName".equals(data) + && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclProcess")) + { type = new Type("String", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = (Entity) + ModelElement.lookupByName("OclProcess",entities); + + return true; + } // and for OclType + } + + if ("currentThread".equals(data) + && "OclProcess".equals(objectRef + "")) + { objectRef.typeCheck(types,entities,contexts,env); + type = new Type("OclProcess", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + isStatic = true; + entity = (Entity) + ModelElement.lookupByName("OclProcess",entities); + return true; + } + + if (("getPriority".equals(data) || "activeCount".equals(data)) + && objectRef != null) + { objectRef.typeCheck(types,entities,contexts,env); + if (objectRef.type != null && + objectRef.type.getName().equals("OclProcess")) + { type = new Type("int", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + entity = (Entity) + ModelElement.lookupByName("OclProcess",entities); + + return true; + } + } + + if ("randomString".equals(data) + && objectRef != null && + "OclRandom".equals(objectRef + "")) + { type = new Type("String", null); + umlkind = QUERY; + multiplicity = ModelElement.ONE; + if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Attribute fpar1 = new Attribute("n", + new Type("int", null), + ModelElement.INTERNAL); + par1.formalParameter = fpar1; + } + + return true; + } + + + if (arrayIndex != null) + { boolean res1 = arrayIndex.typeCheck(types,entities,contexts,env); + arrayType = type; + res = res && res1; + } // might reduce multiplicity to ONE - although not for --* qualified roles + + if (objectRef != null) + { if (objectRef instanceof BasicExpression) + { BasicExpression oref = (BasicExpression) objectRef; + if (isSet(oref.data)) + { Expression newset = buildSetExpression(oref.data); + objectRef = newset; + // what is its element type? + res = objectRef.typeCheck(types,entities,contexts,env); + } + else if (isSequence(oref.data)) // needed? + { Expression newset = buildSetExpression(oref.data); + objectRef = newset; + res = objectRef.typeCheck(types,entities,contexts,env); + } + else if (isCall(oref.data)) + { BasicExpression newcall = buildCallExpression(oref.data); + newcall.objectRef = oref.objectRef; + objectRef = newcall; + // contexts = { entity of result type } + res = objectRef.typeCheck(types,entities,contexts,env); + } + else + { res = objectRef.typeCheck(types,entities,contexts,env); } + // Also case of literal maps Map{...}. But not really needed + } + else + { res = objectRef.typeCheck(types,entities,contexts,env); } + + Entity staticent = + (Entity) ModelElement.lookupByName(objectRef + "", entities); + // System.out.println("**Type of " + this + " is static operation, of: " + staticent); + + if (staticent != null) + { objectRef.umlkind = Expression.CLASSID; + // isStatic = true; + + BehaviouralFeature bf = staticent.getStaticOperation(data,parameters); + + if (bf != null) + { if (bf.parametersMatch(parameters)) { } + else + { JOptionPane.showMessageDialog(null, "Actual parameters do not match operation formal pars: " + this + " /= " + bf, + "Type warning", JOptionPane.WARNING_MESSAGE); + } + + bf.setFormalParameters(parameters); + System.out.println("** Setting formal parameters of " + this); + + type = bf.getResultType(); + elementType = bf.getElementType(); + entity = staticent; + isStatic = true; + + if (bf.isQuery()) + { umlkind = QUERY; } + else + { umlkind = UPDATEOP; + if (type == null || type.equals("") || type.equals("void")) + { type = new Type("boolean",null); } + } + // System.out.println("**Type of " + this + " is static operation call, of: " + entity); + return true; + } + else if (staticent.hasDefinedAttribute(data)) + { umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + Attribute att = staticent.getDefinedAttribute(data); + if (att != null && att.isStatic()) + { modality = att.getKind(); + type = att.getType(); + elementType = att.getElementType(); + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + entity = staticent; + isStatic = true; + // variable = att; // For precise type-analysis + + arrayType = type; + adjustTypeForArrayIndex(att); + System.out.println("*** Type of " + data + " is static ATTRIBUTE in entity " + + staticent + " type is " + type + "(" + elementType + ") Modality = " + modality); + return res; + } + } + } + + if (objectRef.elementType != null && objectRef.elementType.isEntity(entities)) + { context.add(0,objectRef.elementType.getEntity(entities)); } + else if (objectRef.type != null && objectRef.type.isEntity(entities)) + { context.add(0,objectRef.type.getEntity(entities)); } + } + else // objectRef == null + { context.addAll(contexts); } + + // System.out.println("Context of " + this + "(event: " + isEvent + ") is " + context); + + if (context.size() == 0) + { if (entity == null) + { // System.out.println(">> No owning class found for " + this); + // System.out.println(); + // + + // " -- it must be a local variable/parameter"); + // System.out.println(">> Or static feature/global use case"); + // System.out.println(">> Static features should be prefixed by their class: C.f"); + } + } + + // System.out.println(); + + + if (isEvent && isFunction(data)) + { isEvent = false; + umlkind = FUNCTION; + } // this should not arise. + + if (isEvent && + !data.equals("subrange") && + !data.equals("indexOf") && + !data.equals("setAt") && + !data.equals("excludingSubrange") && + !data.equals("setSubrange") && + !data.equals("insertAt") && + !data.equals("insertInto") && + // !(data.equals("split")) && + !(data.equals("replace")) && + !(data.equals("replaceFirstMatch")) && + !(data.equals("replaceAll")) && + !(data.equals("replaceAllMatches")) && + !(data.equals("Sum")) && !(data.equals("Prd")) && + !(data.equals("oclIsKindOf")) && + !(data.equals("oclIsTypeOf")) && + !(data.equals("oclAsType"))) + { // data must be an event of the owning class, the elementType of + // the objectRef, or of an ancestor of it. + BehaviouralFeature bf; + + + for (int i = 0; i < context.size(); i++) + { Entity e = (Entity) context.get(i); + bf = e.getDefinedOperation(data,parameters); + + if (bf != null) + { System.out.println("** Type of " + data + " is operation, of: " + e); + entity = e; + if (bf.parametersMatch(parameters)) { } + else + { JOptionPane.showMessageDialog(null, + "Parameters do not match operation pars: " + this + " " + bf, + "Type warning", JOptionPane.WARNING_MESSAGE); + continue; + } + + System.out.println("** Setting formal parameters of " + data + " operation: " + parameters); + System.out.println(); + + bf.setFormalParameters(parameters); + + if (bf.isQuery()) + { umlkind = QUERY; + type = bf.getResultType(); + elementType = bf.getElementType(); + // System.out.println("QUERY OPERATION, type: " + type); + // System.out.println("QUERY OPERATION, element type: " + elementType); + } + else + { umlkind = UPDATEOP; + type = bf.getResultType(); + elementType = bf.getElementType(); + if (type == null || + type.equals("") || type.equals("void")) + { type = new Type("boolean",null); } + // System.out.println("UPDATE OPERATION, type: " + type); + } // shouldn't be object ref of anything. Should + // only occur as part of action invariant. + + setObjectRefType(); + + adjustTypeForObjectRef(bf); + arrayType = type; + + adjustTypeForArrayIndex(bf); + return true; + } // type check the actual parameters, also + else if (e.getEventNames().contains(data)) + { umlkind = UPDATEOP; + entity = e; + multiplicity = ModelElement.ONE; + type = new Type("boolean",null); + setObjectRefType(); + // adjustTypeForObjectRef(bf); + // adjustTypeForArrayIndex(bf); + arrayType = type; + + return true; + } // else, downcast if in a subclass + else + { Entity subent = + e.searchForSubclassWithOperation(data); + if (subent != null) + { downcast = true; + entity = subent; + bf = subent.getOperation(data); + if (bf != null) + { type = bf.getResultType(); + elementType = bf.getElementType(); + + bf.setFormalParameters(parameters); + + if (bf.isQuery()) + { umlkind = QUERY; } + else + { umlkind = UPDATEOP; + if (type == null || type.equals("") || + type.equals("void")) + { type = new Type("boolean",null); } + } + setObjectRefType(); + adjustTypeForObjectRef(bf); + arrayType = type; + adjustTypeForArrayIndex(bf); + return true; + } + } + } + } + + // If it is a function parameter of the current operation: + + Attribute fvar = (Attribute) ModelElement.lookupByName(data,env); + if (fvar != null) + { type = fvar.getType(); + arrayType = type; + + if (type != null && type.isFunctionType()) + { umlkind = UPDATEOP; + elementType = fvar.getElementType(); + System.out.println(">> Function parameter " + data + " of type " + type + "(" + elementType + ")"); + } + else + { JOptionPane.showMessageDialog(null, data + " is not a function parameter or known function in " + this + ".\n" + + "Please re-type-check or correct your specification.", + "Type warning", JOptionPane.WARNING_MESSAGE); + + if (parameters != null && parameters.size() == 1) + { // assume it is a function + type = new Type("Function", null); + Expression par1 = (Expression) parameters.get(0); + type.keyType = par1.getType(); + type.elementType = new Type("OclAny", null); + } // data->apply(par1) + } + } // default + else if (objectRef != null) + { if (objectRef.type != null) + { String ename = objectRef.type.getName(); + Entity cent = + (Entity) ModelElement.lookupByName(ename, entities); + if (cent != null) + { BehaviouralFeature op = cent.getOperation(data); + if (op != null) + { System.out.println(">>> Found operation " + op + " of class " + cent); + umlkind = UPDATEOP; + type = op.getType(); + elementType = op.getElementType(); + } + } + } + else + { System.err.println("!Warning!: Unknown operation " + data + " at call " + this + ".\n"); + System.out.println(">> " + objectRef + " of type: " + objectRef.type); + type = new Type("boolean",null); + elementType = new Type("boolean",null); + } + umlkind = UPDATEOP; + } + + // System.err.println("Operation " + data + " at call " + this + ".\n"); + // System.out.println(">> " + objectRef + " of type: " + objectRef.type); + // type = new Type("boolean",null); + // elementType = new Type("boolean",null); + // umlkind = UPDATEOP; + // } + } + + // JOptionPane.showInputDialog(this + " is function: " + isFunction(data)); + + if (isFunction(data)) + { umlkind = FUNCTION; + if (objectRef == null) // error + { System.err.println("!! TYPE ERROR: OCL operator " + data + + " should have an argument: arg->" + data + "(pars)"); + if (parameters != null && parameters.size() > 0) + { objectRef = (Expression) parameters.get(0); + parameters.remove(0); + } + else + { type = null; + return false; + } + } + entity = objectRef.entity; // default + multiplicity = ModelElement.ONE; // default + modality = objectRef.modality; + + if (("Sum".equals(data) || "Prd".equals(data)) && + "Integer".equals(objectRef + "") && + parameters != null && parameters.size() > 3) + { Expression par3 = (Expression) parameters.get(2); + par3.setType(new Type("int",null)); + par3.setElementType(new Type("int",null)); + Vector env1 = (Vector) ((Vector) env).clone(); + env1.add(new Attribute(par3 + "", + par3.type, ModelElement.INTERNAL)); + Expression par4 = (Expression) parameters.get(3); + par4.typeCheck(types,entities,contexts,env1); + type = par4.getType(); + elementType = par4.getElementType(); + type.setElementType(elementType); + // System.out.println("*** Type of " + this + " is " + type); + return true; + } + + if (data.equals("toLong") || data.equals("gcd")) + { type = new Type("long", null); + elementType = type; + } + else if (data.equals("size") || + data.equals("floor") || data.equals("count") || + data.equals("toInteger") || + data.equals("indexOf") || + data.equals("ceil") || data.equals("round")) + { type = new Type("int",null); + elementType = type; + } + else if (data.equals("sort") || + data.equals("characters") || + data.equals("sortedBy") || + data.equals("asSequence") || + data.equals("allInstances")) + { type = new Type("Sequence",null); + elementType = objectRef.elementType; + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + arrayType = type; + + adjustTypeForArrayIndex(); + } + else if (data.equals("isDeleted") || + data.equals("oclIsKindOf") || + data.equals("oclIsTypeOf") || + data.equals("isReal") || + data.equals("toBoolean") || + data.equals("isInteger") || + data.equals("isLong") || + data.equals("hasPrefix") || + data.equals("hasSuffix")) + { type = new Type("boolean",null); + elementType = type; + } + else if (data.equals("oclAsType") && parameters != null && + parameters.size() > 0) // type cast + { Expression par1 = (Expression) parameters.get(0); + type = par1.elementType; + elementType = type; + } + else if (data.equals("subrange")) + { // 3 cases - Integer.subrange, + // str.subrange, col.subrange + if ("Integer".equals(objectRef + "")) + { type = new Type("Sequence", null); + elementType = new Type("int", null); + // could be long if the 2nd argument is long + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + arrayType = type; + adjustTypeForArrayIndex(); + return res; + } + else if (objectRef.isString()) + { type = new Type("String", null); + elementType = new Type("String", null); + // could be long if the 2nd argument is long + type.setElementType(elementType); + multiplicity = ModelElement.ONE; + arrayType = type; + adjustTypeForArrayIndex(); + return res; + } + // Otherwise, assume it is a collection + type = new Type("Sequence", null); + elementType = objectRef.elementType; + multiplicity = ModelElement.MANY; + arrayType = type; + adjustTypeForArrayIndex(); + return res; + } + else if (data.equals("reverse") || + data.equals("tail") || + data.equals("front") || + data.equals("insertAt") || + data.equals("insertInto") || + data.equals("excludingSubrange") || + data.equals("setSubrange") || + data.equals("setAt")) + { type = objectRef.getType(); // Sequence or String + elementType = objectRef.elementType; + + if (data.equals("insertAt") || + data.equals("setAt")) + { Expression par2 = (Expression) parameters.get(1); + Type partyp = par2.getType(); + Type newleftET = + Type.refineType(elementType,partyp); + System.out.println(">> Deduced element type of " + this + " = " + newleftET); + elementType = newleftET; + type.setElementType(newleftET); + } + + if (type != null && + type.isCollectionType()) + { multiplicity = ModelElement.MANY; + arrayType = type; + adjustTypeForArrayIndex(); + return res; + } + } + else if (data.equals("sqrt") || data.equals("exp") || + data.equals("pow") || + data.equals("sqr") || data.equals("abs") || + data.equals("toReal") || + data.equals("sin") || data.equals("cos") || + data.equals("cbrt") || + data.equals("sinh") || data.equals("cosh") || + data.equals("tanh") || + data.equals("atan") || data.equals("acos") || + data.equals("asin") || + data.equals("tan") || data.equals("log") || + data.equals("log10")) + { type = new Type("double",null); + elementType = type; + } + else if (data.equals("toLowerCase") || + data.equals("toUpperCase") || + data.equals("replace") || + data.equals("replaceAll") || + data.equals("replaceFirstMatch") || + data.equals("replaceAllMatches") ) + { type = new Type("String",null); + elementType = type; + } + else if (data.equals("closure") || data.equals("asSet")) + { type = new Type("Set",null); + elementType = objectRef.elementType; + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + return res; + } + else if (data.equals("subcollections")) + { type = new Type("Set",null); + elementType = objectRef.getType(); + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + return res; + } + else // max,min,sum,prd,last,first,any + { type = objectRef.getElementType(); + elementType = type; + if (data.equals("sum") || data.equals("prd")) + { entity = null; } + + if (type == null) // objectRef is multiple but an attribute + { type = objectRef.getType(); + Entity e = objectRef.getEntity(); + if (type == null && e != null && (objectRef instanceof BasicExpression)) + { type = e.getFeatureType(((BasicExpression) objectRef).data); } + // System.out.println("Element type of " + data + ": " + e + " " + type); + if (type == null) // || type.getName().equals("Set")) + { System.err.println("!!! ERROR: Can't determine element type of " + this); + JOptionPane.showMessageDialog(null, "ERROR: Can't determine element type of " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + type = new Type("void",null); + } // actually a void or Object type. + } + } + // entity = null; + // System.out.println("**Type of " + this + " is " + type); + return res; + } // toUpper, toLower, sqr, sqrt, exp, abs, floor, could have objectRef + // multiple, in which case result is multiple + + + + // Parameters or local variables of the + // current operation/usecase: + + Attribute paramvar = + (Attribute) ModelElement.lookupByName(data,env); + + if (paramvar != null && objectRef == null) + { type = paramvar.getType(); + elementType = paramvar.getElementType(); + entity = paramvar.getEntity(); + if (entity == null && elementType != null) + { entity = elementType.getEntity(); } + if (entity == null && type != null) + { entity = type.getEntity(); } + if (elementType == null && type != null) + { elementType = type.getElementType(); } + arrayType = type; + adjustTypeForArrayIndex(paramvar); + + // System.out.println(">>> Parameter/local variable: " + this + " type= " + type + " (" + elementType + ")"); + // System.out.println(); + variable = paramvar; + umlkind = VARIABLE; + modality = paramvar.getKind(); + + return true; + } // And adjust type for any array index. + + for (int j = 0; j < context.size(); j++) + { Entity ent = (Entity) context.get(j); + if (ent.hasDefinedAttribute(data)) + { umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + Attribute att = ent.getDefinedAttribute(data); + if (att == null) // something very bad has happened + { System.err.println("!! TYPE ERROR: attribute: " + data + " is not defined in class " + ent.getName()); + return false; + } + modality = att.getKind(); + type = att.getType(); + if (att.isStatic()) + { isStatic = true; } + + elementType = att.getElementType(); + if (elementType == null || + "OclAny".equals("" + elementType)) + { elementType = type.getElementType(); } + + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + entity = ent; // may not be att.owner, but a subclass of this. + if (objectRef == null) + { res = true; } + else + { setObjectRefType(); } + + System.out.println(">+>+> Attribute: " + this + " type= " + type + " (" + elementType + ")"); + + /* if (arrayIndex != null) + { System.out.println("** Unadjusted type of " + this + " is ATTRIBUTE in entity " + + ent + " type is " + type + "(" + elementType + ") Modality = " + modality); + } */ + + adjustTypeForObjectRef(att); + arrayType = type; + + // if (alreadyCorrected) { } + // else + // { + adjustTypeForArrayIndex(att); + + elementType = Type.correctElementType( + type,elementType,types,entities); + // att.setElementType(elementType); + // variable = att; + System.out.println("*>>* Adjusted type of " + this + " is " + type + "(" + elementType + ")"); + System.out.println(); + // alreadyCorrected = true; + // } + + return res; + } // couldn't it have an array ref if objectRef was a sequence? + else + { Entity subent = ent.searchForSubclassWithAttribute(data); + if (subent != null) + { umlkind = ATTRIBUTE; + multiplicity = ModelElement.ONE; + Attribute att = subent.getAttribute(data); + if (att == null) // something very bad has happened + { System.err.println("!! TYPE ERROR: attribute: " + data + " is not defined in class " + subent); + JOptionPane.showMessageDialog(null, "Undefined attribute: " + data, "Type error", JOptionPane.ERROR_MESSAGE); + return false; + } + modality = att.getKind(); + downcast = true; + if (att.isStatic()) + { isStatic = true; } + + type = att.getType(); + elementType = att.getElementType(); + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + entity = subent; + adjustTypeForObjectRef(att); + arrayType = type; + adjustTypeForArrayIndex(att); + // System.out.println("**Type of " + data + " is downcast ATTRIBUTE in entity " + + // subent + " type is " + type); + // variable = att; + return res; + } + } + + if (ent.hasDefinedRole(data)) + { umlkind = ROLE; + Association ast = ent.getDefinedRole(data); + if (ast == null) // something very bad has happened + { System.err.println("!! TYPE ERROR: role: " + data + " is not defined in class " + ent.getName()); + JOptionPane.showMessageDialog(null, "Undefined role " + data, "Type error", + JOptionPane.ERROR_MESSAGE); + return false; + } + + multiplicity = ast.getCard2(); + elementType = new Type(ast.getEntity2()); + modality = ModelElement.INTERNAL; // ??? + + if (ast.isQualified() && arrayIndex == null) // a naked qualified role, it is a map + { type = ast.getRole2Type(); } + else if (multiplicity == ModelElement.ONE) + { type = new Type(ast.getEntity2()); } + else + { if (ast.isOrdered()) + { type = new Type("Sequence",null); } + else + { type = new Type("Set",null); } + type.setElementType(elementType); + + // type = new Type(ast.getEntity2()); + } // index must be int type, + // and ast is ordered/sorted. Also for any att or role + + adjustTypeForObjectRef(); + arrayType = type; + + if (arrayIndex != null && !ast.isQualified()) + { adjustTypeForArrayIndex(); } + + // if (Type.isCollectionType(type)) + // { multiplicity = ModelElement.MANY; } + // else + // { multiplicity = ModelElement.ONE; } + // System.out.println("**Type of " + data + " is ROLE in entity " + ent + + // "\n type is: " + type + " element type: " + + // elementType + " Modality = " + modality); + entity = ent; + if (objectRef == null) + { res = true; } + else + { setObjectRefType(); } + + // variable = attribute for the role? + + return res; + } + else + { Entity subent = ent.searchForSubclassWithRole(data); + if (subent != null) + { umlkind = ROLE; + Association ast = subent.getRole(data); + if (ast == null) // something very bad has happened + { System.err.println("!! ERROR: Undefined role: " + data); + return false; + } + multiplicity = ast.getCard2(); + modality = ModelElement.INTERNAL; + downcast = true; + elementType = new Type(ast.getEntity2()); + if (multiplicity == ModelElement.ONE) + { type = new Type(ast.getEntity2()); } + else + { if (ast.isOrdered()) + { type = new Type("Sequence",null); } + else + { type = new Type("Set",null); } + type.setElementType(elementType); + } + adjustTypeForObjectRef(); + arrayType = type; + if (arrayIndex != null && !ast.isQualified()) + { adjustTypeForArrayIndex(); } + // System.out.println("**Type of " + data + " is downcast ROLE in entity " + + // subent + " type is " + type); + entity = subent; + + // variable = attribute for the role? + return res; + } // objectRefTypeAssignment + } // or it could be a query op of the entity + } + // prestate == true only for VARIABLE, ATTRIBUTE, ROLE, CONSTANT + + /* Is data in some enumerated type? */ + + for (int i = 0; i < types.size(); i++) + { Type t = (Type) types.get(i); + if (t != null && t.hasValue(data)) + { umlkind = VALUE; + multiplicity = ModelElement.ONE; + System.out.println("*** " + data + " is enumerated literal in type " + t); + type = t; + elementType = type; + + if (objectRef == null) + { return true; } + else if (t.getName().equals(objectRef + "")) + { return true; } + } + } // if T1.value and T2.value may both occur, must be distinguished by the type name + + if (data.equals("Integer")) + { type = new Type("OclType",null); + elementType = new Type("int",null); + type.setElementType(elementType); + umlkind = TYPE; + modality = ModelElement.INTERNAL; + multiplicity = ModelElement.MANY; + return true; + } + + Attribute var = + (Attribute) ModelElement.lookupByName(data,env); + if (var != null) + { type = var.getType(); + elementType = var.getElementType(); + umlkind = VARIABLE; // its a parameter or local variable. + variable = var; + modality = var.getKind(); + if (type != null) + { String tname = type.getName(); + if (tname.equals("Set") || + tname.equals("Sequence") || + tname.equals("Map")) + { multiplicity = ModelElement.MANY; } + else + { multiplicity = ModelElement.ONE; } // assume + } + else + { multiplicity = ModelElement.ONE; } // assume + + arrayType = type; + if (arrayIndex != null) + { adjustTypeForArrayIndex(var); } + + if (parameters != null && + var.getType().isFunctionType()) // application of a Function(S,T) + { Type ftype = var.getType(); + type = ftype.getElementType(); + elementType = type.getElementType(); + System.out.println(">>>> TYPE CHECKED: Type of variable expression " + this + " is " + type + " entity: " + entity); + } + + entity = var.getEntity(); + if (entity == null && elementType != null) + { entity = elementType.getEntity(); } + if (entity == null && type != null) + { entity = type.getEntity(); } + + return true; + } // entity = var.getEntity() ? + + Entity ee = (Entity) ModelElement.lookupByName(data,entities); + if (ee != null) + { umlkind = CLASSID; + // System.out.println("**umlkind of " + this + " is CLASSID"); + modality = ModelElement.INTERNAL; + elementType = new Type(ee); + if (arrayIndex != null) // a lookup by primary key + { if (!arrayIndex.isMultiple()) // (arrayIndex.multiplicity == ModelElement.ONE) + { multiplicity = ModelElement.ONE; + type = new Type(ee); + } + else + { multiplicity = ModelElement.MANY; + + if (arrayIndex.isOrdered()) + { type = new Type("Sequence", null); } + else + { type = new Type("Set",null); } + type.setElementType(elementType); + } + } + else + { multiplicity = ModelElement.MANY; + type = new Type("Sequence",null); + type.setElementType(elementType); + } + entity = ee; // ?? + elementType = new Type(ee); // type.setElementType(elementType); ?? + return res; + } + + /* if (isConstant(data)) + { umlkind = CONSTANT; + // System.out.println("**Type of " + data + " is CONSTANT"); + modality = ModelElement.INTERNAL; + multiplicity = ModelElement.ONE; // as for variables + return res; + } */ + + if (umlkind != UNKNOWN && type != null && elementType != null) + { return res; } + + if (parameters != null && umlkind == UNKNOWN) // must be an operation, external, not a variable + { umlkind = UPDATEOP; } + else if (parameters == null) + { umlkind = VARIABLE; } + modality = ModelElement.INTERNAL; + multiplicity = ModelElement.ONE; // assume + + if (objectRef != null && entity == null) + { Type oret = objectRef.getElementType(); + if (oret != null && oret.isEntity()) + { entity = oret.getEntity(); } + } + + if (isEvent && type == null && objectRef == null && + context.size() == 0) + { // A usecase, or a static operation of the local class + + BehaviouralFeature bf; + + for (int i = 0; i < entities.size(); i++) + { Entity e = (Entity) entities.get(i); + bf = e.getDefinedOperation(data,parameters); + + if (bf != null && bf.isStatic()) + { System.out.println("**Type of " + data + " is static operation, of class: " + e); + entity = e; + if (bf.parametersMatch(parameters)) { } + else + { JOptionPane.showMessageDialog(null, + "Parameters do not match operation pars: " + this + " " + bf, + "Type warning", JOptionPane.WARNING_MESSAGE); + continue; + } + + System.out.println("** Setting formal parameters of " + data + " operation: " + parameters); + System.out.println(); + + bf.setFormalParameters(parameters); + + if (bf.isQuery()) + { umlkind = QUERY; + type = bf.getResultType(); + elementType = bf.getElementType(); + // System.out.println("QUERY OPERATION, type: " + type); + // System.out.println("QUERY OPERATION, element type: " + elementType); + } + else + { umlkind = UPDATEOP; + type = bf.getResultType(); + elementType = bf.getElementType(); + if (type == null || + type.equals("") || type.equals("void")) + { type = new Type("boolean",null); } + // System.out.println("UPDATE OPERATION, type: " + type); + } // shouldn't be object ref of anything. Should + // only occur as part of action invariant. + + arrayType = type; + + adjustTypeForArrayIndex(bf); + return true; + } // type check the actual parameters, also + } + } + + if ("skip".equals(data)) + { } + else if (type == null) + { System.out.println("***! WARNING: Type of " + this + " is unknown"); + System.out.println("***! Re-run type-checking/correct your specification"); + } + + return true; + } + + public boolean isOperationCall() + { if (isEvent && parameters != null) + { return true; } + if (umlkind == UPDATEOP || + umlkind == QUERY) + { return true; } + return false; + } + + private void setObjectRefType() + { if (entity != null && objectRef != null && objectRef.umlkind == VARIABLE && + objectRef.getType() == null) + { objectRef.setType(new Type(entity)); + objectRef.setElementType(new Type(entity)); + } + else if (entity != null && objectRef != null && objectRef.umlkind == CONSTANT && + objectRef.getType() == null) + { objectRef.setType(new Type(entity)); + objectRef.setElementType(new Type(entity)); + } + } + + private void adjustTypeForObjectRef(BehaviouralFeature bf) + { if (objectRef != null) + { if (bf.isStatic()) + { objectRef.multiplicity = ModelElement.ONE; + objectRef.umlkind = CLASSID; + objectRef.type = new Type(entity); + } + else if (objectRef.isMultiple()) + { Type resType = bf.getResultType(); + Type elemType = bf.getElementType(); + // Actual type is Set or Sequence + if (objectRef.isOrdered()) + { if (resType != null && Type.isSequenceType(resType)) + { type = new Type("Sequence",null); + elementType = elemType; + type.setElementType(elemType); + } + else if (resType == null || resType.typeMultiplicity() == ModelElement.ONE) + { elementType = resType; + type = new Type("Sequence",null); + type.setElementType(elementType); + } + else // set-valued operation + { elementType = resType; + type = new Type("Set",null); + type.setElementType(elementType); + } + } + else // objectRef is a set + { if (resType != null && Type.isCollectionType(resType)) + { elementType = elemType; + type = new Type("Set",null); + type.setElementType(elementType); + } + else + { type = new Type("Set",null); + elementType = resType; + type.setElementType(elementType); + } + } + } + } + // System.out.println("Actual type of " + this + " is " + type); + } + + private void adjustTypeForObjectRef(Attribute att) + { if (objectRef != null) + { if (att.isStatic() && objectRef != null && objectRef.equals(entity + "")) + { objectRef.multiplicity = ModelElement.ONE; + objectRef.umlkind = CLASSID; + objectRef.type = new Type(entity); + } + else if (objectRef.isMultiple()) + { Type resType = att.getType(); + Type elemType = att.getElementType(); + // Actual type is Set or Sequence + if (objectRef.isOrdered()) + { if (resType != null && Type.isSequenceType(resType)) + { type = new Type("Sequence",null); + elementType = elemType; + type.setElementType(elemType); + } + else if (resType == null || resType.typeMultiplicity() == ModelElement.ONE) + { elementType = resType; + type = new Type("Sequence",null); + type.setElementType(elementType); + } + else // set-valued operation + { elementType = resType; + type = new Type("Set",null); + type.setElementType(elementType); + } + } + else // objectRef is a set + { if (resType != null && Type.isCollectionType(resType)) + { elementType = elemType; + type = new Type("Set",null); + type.setElementType(elementType); + } + else + { type = new Type("Set",null); + elementType = resType; + type.setElementType(elementType); + } + } + } + } + // System.out.println("Actual type of " + this + " is " + type); + } + + private void adjustTypeForObjectRef() + { if (objectRef != null) + { if (objectRef.isMultiple()) + { Type resType = type; + Type elemType = elementType; + // Actual type is Set or Sequence + if (objectRef.isOrdered()) + { if (resType != null && Type.isSequenceType(resType)) + { type = new Type("Sequence",null); + elementType = elemType; + type.setElementType(elemType); + } + else if (resType == null || resType.typeMultiplicity() == ModelElement.ONE) + { elementType = resType; + type = new Type("Sequence",null); + type.setElementType(elementType); + } + else // set-valued feature + { elementType = elemType; + type = new Type("Set",null); + type.setElementType(elementType); + } + } + else // objectRef is a set + { if (resType != null && Type.isCollectionType(resType)) + { elementType = elemType; + type = new Type("Set",null); + type.setElementType(elementType); + } + else // single-valued feature + { type = new Type("Set",null); + elementType = resType; + type.setElementType(elementType); + } + } + } + } + // System.out.println("Actual type of " + this + " is " + type); + } + + + + private void adjustTypeForArrayIndex() + { // if there is an arrayIndex, make type = elementType, etc + + // System.out.println("+++ Adjusting type " + type + " " + + // elementType + " " + arrayIndex); + + if (arrayIndex != null && type != null && + "String".equals(type.getName())) + { elementType = new Type("String", null); + multiplicity = ModelElement.ONE; + } // access to a string element + else if (arrayIndex != null) + { if (elementType == null) + { type = new Type("OclAny", null); + elementType = new Type("OclAny", null); + multiplicity = ModelElement.ONE; // assume + } // access to sequence element; no element type + else if (Type.isMapOrCollectionType(type)) + { type = elementType; + elementType = elementType.getElementType(); + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + else + { multiplicity = ModelElement.ONE; } + } // access to element of typed sequence + // System.out.println("TYPE CHECKED: Type of " + this + " is " + type); + } + } + + private void adjustTypeForArrayIndex(BehaviouralFeature bf) + { // if there is an arrayIndex, make type = elementType, etc + + if (arrayIndex != null && "String".equals(type + "")) + { elementType = new Type("String", null); + multiplicity = ModelElement.ONE; + } + else if (arrayIndex != null) + { if (bf.getElementType() == null) + { type = new Type("OclAny", null); + elementType = new Type("OclAny", null); + multiplicity = ModelElement.ONE; + } + else + { type = bf.getElementType(); + elementType = type.getElementType(); + + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + else + { multiplicity = ModelElement.ONE; } + } + } + } + + private void adjustTypeForArrayIndex(Attribute var) + { // if there is an arrayIndex, make type = elementType, etc + + // System.out.println("+++ Adjusting type " + type + " " + + // elementType + " " + arrayIndex + " " + var); + + if (arrayIndex != null && "String".equals(type + "")) + { elementType = new Type("String", null); + multiplicity = ModelElement.ONE; + } + else if (arrayIndex != null) + { Type elemT = var.getElementType(); + if (elemT == null || "OclAny".equals("" + elemT)) + // { elemT = type.getElementType(); } + // if (elemT == null) + { type = new Type("OclAny", null); + elementType = new Type("OclAny", null); + multiplicity = ModelElement.ONE; // assume + } // Sequence access, no type + else + { type = (Type) elemT.clone(); + elementType = type.getElementType(); + + if (Type.isCollectionType(type)) + { multiplicity = ModelElement.MANY; } + else + { multiplicity = ModelElement.ONE; } + } // Sequence access, defined type + } + + // System.out.println("+++ Adjusted type " + type + " " + + // elementType); + } + + private boolean eventTypeCheck(Vector types, Vector entities, Vector env) + { // data must be an event of the owning class, the elementType of + // the objectRef, or of an ancestor of it. + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression ep = (Expression) parameters.get(i); + ep.typeCheck(types,entities,env); + } + } + + for (int i = 0; i < entities.size(); i++) + { Entity e = (Entity) entities.get(i); + BehaviouralFeature bf = e.getOperation(data); + if (bf != null) + { System.out.println("**Type of " + data + " is operation, of: " + e); + entity = e; + if (bf.isQuery()) + { umlkind = QUERY; + type = bf.getResultType(); + System.out.println("query operation, type: " + type); + } + else + { umlkind = UPDATEOP; + type = new Type("boolean",null); + System.out.println("update operation, type: " + type); + } // shouldn't be object ref of anything. Should + // only occur as part of action invariant. + multiplicity = type.typeMultiplicity(); + return true; + } + else if (e.getEventNames().contains(data)) + { umlkind = UPDATEOP; + entity = e; + multiplicity = ModelElement.ONE; + type = new Type("boolean",null); + return true; + } + } + return true; + } + + private boolean functionTypeCheck(Vector types, Vector entities, Vector env) + { boolean res = true; + umlkind = FUNCTION; + if (objectRef == null) // error + { System.out.println("**Error: function " + data + + " must have argument"); + type = null; + return false; + } + if (data.equals("size") || data.equals("floor")) + { type = new Type("int",null); } + else if (data.equals("sort")) + { type = new Type("Sequence",null); + elementType = objectRef.elementType; + } + else if (data.equals("isDeleted") || data.equals("oclIsKindOf")) + { type = new Type("boolean",null); } + else if (data.equals("sqr") || data.equals("reverse") || data.equals("abs") || + data.equals("tail") || data.equals("front")) + { type = objectRef.getType(); + if (type.isCollectionType()) + { elementType = objectRef.elementType; + multiplicity = ModelElement.MANY; + modality = objectRef.modality; + return res; + } + } + else if (data.equals("sqrt") || data.equals("exp")) + { type = new Type("double",null); } + else if (data.equals("toLowerCase") || data.equals("toUpperCase")) + { type = new Type("String",null); } + else if (data.equals("closure") || data.equals("asSet")) + { type = new Type("Set",null); + elementType = objectRef.elementType; + multiplicity = ModelElement.MANY; + modality = objectRef.modality; + return res; + } + else // max,min,sum,prd,last,first + { type = objectRef.getElementType(); + if (type == null) // objectRef is multiple but an attribute + { type = objectRef.getType(); + Entity e = objectRef.getEntity(); + if (type == null && e != null) + { type = e.getFeatureType(((BasicExpression) objectRef).data); } + System.out.println("Element type of " + data + ": " + e + " " + type); + if (type == null || type.getName().equals("Set")) + { type = new Type("int",null); } // hack + } + } + entity = null; + multiplicity = ModelElement.ONE; // not for closure though + modality = objectRef.modality; + System.out.println("**Type of " + this + " is " + + type); + return res; + } + + public Expression skolemize(Expression sourceVar, java.util.Map env) + { return this; } + + public String cstlQueryForm(java.util.Map srcfeatureMap) + { if (parameters != null && parameters.size() > 0) // (umlKind == QUERY || umlKind == UPDATEOP) + { Expression par1 = (Expression) parameters.get(0); + String expr = par1.cstlQueryForm(srcfeatureMap); + return expr + "`" + data; + } + if (isString()) + { if (data.endsWith("\"") && data.startsWith("\"")) + { int dlen = data.length(); + return data.substring(1,dlen-2); + } + } + if (objectRef != null) + { String obj = objectRef.cstlQueryForm(srcfeatureMap); + return obj + "`" + data; + } + String vv = (String) srcfeatureMap.get(data); + System.out.println(srcfeatureMap + " " + data); + if (vv != null) + { return vv; } + return data; + } + + public String cstlConditionForm(java.util.Map fmap) + { return cstlQueryForm(fmap); } + + public String classExtentQueryForm(java.util.Map env, boolean local) + { // umlkind == CLASSID + String cont = "Controller.inst()"; + + int preindex = data.indexOf('@'); + if (preindex < 0) + { prestate = false; } + else + { data = data.substring(0,preindex); + prestate = true; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + if ("OclFile".equals(data)) + { return "OclFile.OclFile_index.get(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getByPKOclType(" + ind + ")"; } + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return cont + "." + data.toLowerCase() + "s"; + } + + public String classExtentQueryFormJava6(java.util.Map env, boolean local) + { // umlkind == CLASSID + String cont = "Controller.inst()"; + + int preindex = data.indexOf('@'); + if (preindex < 0) + { prestate = false; } + else + { data = data.substring(0,preindex); + prestate = true; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if ("OclFile".equals(data)) + { return "OclFile.OclFile_index.get(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getByPKOclType(" + ind + ")"; } + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return cont + "." + data.toLowerCase() + "s"; + } + + public String classExtentQueryFormJava7(java.util.Map env, boolean local) + { // umlkind == CLASSID + String cont = "Controller.inst()"; + + int preindex = data.indexOf('@'); + if (preindex < 0) + { prestate = false; } + else + { data = data.substring(0,preindex); + prestate = true; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if ("OclFile".equals(data)) + { return "OclFile.OclFile_index.get(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getByPKOclType(" + ind + ")"; } + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return cont + "." + data.toLowerCase() + "s"; + } + + public String classExtentQueryFormCSharp(java.util.Map env, boolean local) + { // umlkind == CLASSID + String cont = "Controller.inst()"; + + int preindex = data.indexOf('@'); + if (preindex < 0) + { prestate = false; } + else + { data = data.substring(0,preindex); + prestate = true; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + if (data.equals("OclFile")) + { return "OclFile.getOclFileByPK(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getOclTypeByPK(" + ind + ")"; } + + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return cont + ".get" + data.toLowerCase() + "_s()"; + } + + public String classExtentQueryFormCPP(java.util.Map env, boolean local) + { // umlkind == CLASSID + String cont = "Controller::inst"; + + int preindex = data.indexOf('@'); + if (preindex < 0) + { prestate = false; } + else + { data = data.substring(0,preindex); + prestate = true; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (data.equals("OclType")) + { return "OclType::getOclTypeByPK(" + ind + ")"; } + if (data.equals("OclFile")) + { return "OclFile::getOclFileByPK(" + ind + ")"; } + return cont + "->get" + data + "ByPK(" + ind + ")"; + } + return cont + "->get" + data.toLowerCase() + "_s()"; + } + + public String classqueryForm(java.util.Map env, boolean local) + { if (umlkind == CLASSID) + { return classExtentQueryForm(env,local); } + return queryForm(env,local); + } + + public String classqueryFormJava6(java.util.Map env, boolean local) + { if (umlkind == CLASSID) + { return classExtentQueryFormJava6(env,local); } + return queryFormJava6(env,local); + } + + public String classqueryFormJava7(java.util.Map env, boolean local) + { if (umlkind == CLASSID) + { return classExtentQueryFormJava7(env,local); } + return queryFormJava7(env,local); + } + + public String classqueryFormCSharp(java.util.Map env, boolean local) + { if (umlkind == CLASSID) + { return classExtentQueryFormCSharp(env,local); } + return queryFormCSharp(env,local); + } + + public String classqueryFormCPP(java.util.Map env, boolean local) + { if (umlkind == CLASSID) + { return classExtentQueryFormCPP(env,local); } + return queryFormCPP(env,local); + } + + public String parametersQueryForm(java.util.Map env, boolean local) + { String parString = ""; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parString = parString + par.classqueryForm(env,local); + if (i < parameters.size() - 1) + { parString = parString + ","; } + } + } + parString = parString + ")"; + return parString; + } + + public String parametersQueryFormJava6(java.util.Map env, boolean local) + { String parString = ""; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parString = parString + + par.classqueryFormJava6(env,local); + if (i < parameters.size() - 1) + { parString = parString + ","; } + } + } + parString = parString + ")"; + return parString; + } + + public String parametersQueryFormJava7(java.util.Map env, boolean local) + { String parString = ""; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parString = parString + par.classqueryFormJava7(env,local); + if (i < parameters.size() - 1) + { parString = parString + ","; } + } + } + parString = parString + ")"; + return parString; + } + + public String parametersQueryFormCSharp(java.util.Map env, boolean local) + { String parString = ""; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parString = parString + par.classqueryFormCSharp(env,local); + if (i < parameters.size() - 1) + { parString = parString + ","; } + } + } + parString = parString + ")"; + return parString; + } + + public String parametersQueryFormCPP(java.util.Map env, boolean local) + { String parString = ""; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parString = parString + par.classqueryFormCPP(env,local); + if (i < parameters.size() - 1) + { parString = parString + ","; } + } + } + parString = parString + ")"; + return parString; + } + + public String queryForm(java.util.Map env, boolean local) + { // already type-checked. Ignores prestate + String ename = ""; + String cont = "Controller.inst()"; + + if (data.equals("$act") && parameters.size() > 0) + { return "$act_" + parameters.get(0); } + else if (data.equals("$fin") && parameters.size() > 0) + { return "$fin_" + parameters.get(0); } + + if ((data.equals("systemTime") || + data.equals("getSystemTime")) && + "OclDate".equals(objectRef + "")) + { return "Set.getTime()"; } + + if (data.startsWith("new")) + { String createdClass = data.substring(3); + if ("OclDate".equals(createdClass)) + { return "new Date()"; } + } + + if (data.equals("formattedString") && + "StringLib".equals(objectRef + "")) + { Expression par = (Expression) parameters.get(0); + String pqf = par.queryForm(env,local); + String cmd = "(new Object() { public String call(Object _x) { return " + Expression.formattedString(pqf) + "; } }).call(this)"; + return cmd; + } + + + if (umlkind == VALUE || umlkind == CONSTANT) + { if (data.equals("Set{}") || data.equals("Sequence{}")) + { return "new Vector()"; } // new Set really + if (data.equals("Map{}")) + { return "new HashMap()"; } + + if (data.equals("null")) + { return "null"; } + + if (data.equals("Math_NaN")) + { return "Double.NaN"; } + if (data.equals("Math_PINFINITY")) + { return "Double.POSITIVE_INFINITY"; } + if (data.equals("Math_NINFINITY")) + { return "Double.NEGATIVE_INFINITY"; } + + if (isSet(data)) + { Expression se = buildSetExpression(data); + return se.queryForm(env,local); + } + + if (isSequence(data)) + { Expression se = buildSetExpression(data); + if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + String indopt = evaluateString("-",ind,"1"); + if (se.elementType != null) + { if (Type.isPrimitiveType(se.elementType)) + { return se.unwrap(se.queryForm(env,local) + ".get(" + indopt + ")"); } + else + { String jtype = se.elementType.getJava(); + return "((" + jtype + ") " + se.queryForm(env,local) + ".get(" + indopt + "))"; + } + } + return se.queryForm(env,local) + ".get(" + indopt + ")"; + } + return se.queryForm(env,local); + } + + // Also case of literal maps Map{...}[arrayIndex] + + if (isString(data) && arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + String indopt = evaluateString("-",ind,"1"); + return "(\"" + "\" + " + data + ".charAt(" + indopt + "))"; + } + + if (needsBracket) + { return "(" + data + ")"; } + + return data; + } + + if (umlkind == VARIABLE) + { if (data.equals("self")) // but return "self" if it is a genuine variable + { if (env.containsValue("self")) + { return data; } + else if (type != null && type.isEntity()) + { // System.out.println("^^^^^^^^ Type of self = " + type); + String tname = type.getName(); + Object obj = env.get(tname); + if (obj != null) + { return obj + ""; } + else + { return "this"; } + } + else + { return "this"; } + } + else if (data.equals("now")) + { return "Set.getTime()"; } + else // entity == null) + if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + String indopt = evaluateString("-",ind,"1"); + if (type != null) + { if (variable != null && "String".equals(variable.getType() + "")) + { return "(" + data + ".charAt(" + indopt + ") + \"\")"; } + if (arrayIndex.type != null && arrayIndex.type.getName().equals("int")) + // if (Type.isPrimitiveType(type)) + { return unwrap(data + ".get(" + indopt + ")"); } + else if (arrayIndex.type != null && arrayIndex.type.getName().equals("String")) + { return unwrap(data + ".get(" + ind + ")"); } + + String jType = type.getJava(); + return "((" + jType + ") " + data + ".get(" + indopt + "))"; + } + return data + ".get(" + indopt + ")"; + } // unwrap ints, doubles, etc, also + else if (parameters != null && variable != null && variable.getType().isFunctionType()) // application of a Function(S,T) + { String pars = ""; + for (int h = 0; h < parameters.size(); h++) + { Expression par = (Expression) parameters.get(h); + pars = pars + par.queryForm(env,local); + if (h < parameters.size()-1) + { pars = pars + ","; } + } + return data + ".evaluate(" + pars + ")"; + } + else + { return data; } + } + + if (umlkind == CLASSID) + { + if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + if ("OclFile".equals(data)) + { return "OclFile.OclFile_index.get(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getByPKOclType(" + ind + ")"; } + + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return data; // But library classes may map to language-specific name + } + + if (umlkind == FUNCTION) + { if (objectRef == null) + { return data; } // Invalid function + + + if (data.equals("$act") && parameters.size() > 0) + { return "$act_" + parameters.get(0); } + + String pre = objectRef.queryForm(env,local); + + if (data.equals("allInstances")) // objectRef is a CLASSID + { return cont + "." + pre.toLowerCase() + "s"; } + + + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryForm(env,local); } + + if (data.equals("asSequence")) + { return pre; } + + if (data.equals("oclIsUndefined")) + { return "(" + pre + " == null)"; } + + if (data.equals("size")) + { if (objectRef.type != null && objectRef.type.getName().equals("String")) + { return pre + ".length()"; } + else + { return pre + ".size()"; } + } + + if (("Sum".equals(data) || "Prd".equals(data)) + && "Integer".equals(objectRef + "") && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + Type sumtype = par4.getType(); + String tname = sumtype.getName(); + BasicExpression subrexp = new BasicExpression("subrange"); + subrexp.umlkind = FUNCTION; + subrexp.objectRef = objectRef; + subrexp.addParameter(par1); + subrexp.addParameter(par2); + Type seqtype = new Type("Sequence", null); + subrexp.setType(seqtype); + Type inttype = new Type("int", null); + subrexp.setElementType(inttype); + seqtype.setElementType(inttype); + if (("" + par3).equals("" + par4)) + { String sqf = subrexp.queryForm(env,local); + return "Set." + data.toLowerCase() + tname + "(" + sqf + ")"; + } + Expression colexp = new BinaryExpression("|C",new BinaryExpression(":", par3, subrexp), par4); + String colqf = colexp.queryForm(env,local); + return "Set." + data.toLowerCase() + tname + "(" + colqf + ")"; + } + + if (data.equals("isDeleted")) // assume objectRef is single object + { return "true"; // "false" really + /* String objstype = objectRef.type.getName(); + if (objectRef.isMultiple()) + { return "Set.intersection(" + pre + + ",Controller.inst()." + objstype.toLowerCase() + "s).size() == 0"; + } + else + { return "!(Controller.inst()." + objstype.toLowerCase() + + "s.contains(" + pre + "))"; + } */ + } + + if (data.equals("oclIsKindOf") && parameters != null && parameters.size() > 0) + { Expression arg1 = (Expression) parameters.get(0); + String arg1s = arg1 + ""; + + if ("int".equals(arg1s) && Type.isNumericType(objectRef.type)) + { return "Set.isInteger(\"\" + " + pre + ")"; } + else if ("long".equals(arg1s) && Type.isNumericType(objectRef.type)) + { return "Set.isLong(\"\" + " + pre + ")"; } + else if ("double".equals(arg1s) && Type.isNumericType(objectRef.type)) + { return "Set.isReal(\"\" + " + pre + ")"; } + + return "(" + pre + " instanceof " + arg1s + ")"; // works for external classes also + // return "(Controller.inst()." + arg1s.toLowerCase() + "s.contains(" + pre + "))"; + } + + if (data.equals("oclAsType") && parameters != null && parameters.size() > 0) + { Expression arg1 = (Expression) parameters.get(0); + return "((" + arg1 + ") " + pre + ")"; // casting + } + + if (data.equals("sqr")) + { return "(" + pre + ") * (" + pre + ")"; } + else if (data.equals("cbrt")) + { return "Math.pow(" + pre + ", 1.0/3)"; } + else if (data.equals("log10")) + { return "(Math.log(" + pre + ")/Math.log(10))"; } + else if (data.equals("abs") || data.equals("sin") || data.equals("cos") || + data.equals("sqrt") || data.equals("exp") || data.equals("log") || + data.equals("tan") || + data.equals("atan") || data.equals("acos") || data.equals("asin") || + data.equals("cosh") || data.equals("sinh") || + data.equals("tanh")) + // exp, floor can be applied to sets/sequences + { return "Math." + data + "(" + pre + ")"; } + else if (data.equals("round") || data.equals("ceil") || data.equals("floor")) + { return "((int) Math." + data + "(" + pre + "))"; } // (long) is better + else if (data.equals("toUpperCase") || data.equals("toLowerCase")) + { return pre + "." + data + "()"; } + else if (data.equals("sum")) + { Type sumtype = objectRef.getElementType(); + // Must be int, long, double, String only + String tname = sumtype.getName(); + return "Set.sum" + tname + "(" + pre + ")"; + } + else if (data.equals("prd")) + { Type sumtype = objectRef.getElementType(); + // Must be int, long, double only + String tname = sumtype.getName(); + return "Set.prd" + tname + "(" + pre + ")"; + } + else if (data.equals("reverse") || data.equals("sort") || + data.equals("asSet") || data.equals("characters")) + { return "Set." + data + "(" + pre + ")"; } // sortedBy? + else if (data.equals("subrange") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + if ("Integer".equals(objectRef + "")) + { return "Set.integerSubrange(" + par1 + "," + par2 + ")"; } + return "Set.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("subrange") && parameters != null && parameters.size() == 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + UnaryExpression ue = new UnaryExpression("->size", objectRef); + ue.setType(new Type("int", null)); + String par2 = ue.queryForm(env,local); + return "Set.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("indexOf") && parameters != null && parameters.size() > 0) + // for strings or sequences + { Expression par1 = (Expression) parameters.get(0); + String qpar1 = par1.queryForm(env,local); + String wpar1 = par1.wrap(qpar1); + return "(" + pre + ".indexOf(" + wpar1 + ") + 1)"; + } // Surely it should be qpar1 not wpar1 here. + else if (data.equals("pow") && parameters != null && parameters.size() > 0) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + return "Math.pow(" + pre + ", " + par1 + ")"; + } + else if (data.equals("closure")) + { String rel = ((BasicExpression) objectRef).data; + Expression arg = ((BasicExpression) objectRef).objectRef; + if (arg != null) + { return "Set.closure" + entity.getName() + rel + "(" + arg.queryForm(env,local) + ")"; } + return "Set.closure" + entity.getName() + rel + "(" + pre + ")"; + } // entity may be a subclass of the owner of rel. + else if (data.equals("insertAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.insertAt(" + pre + "," + par1 + "," + par2 + ")"; + // ".add(" + par1 + ", " + par2 + ")"; + } + else if (data.equals("insertInto") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.insertInto(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("excludingSubrange") && + parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.excludingSubrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setSubrange") && + parameters != null && parameters.size() > 2) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + String par3 = ((Expression) parameters.get(2)).queryForm(env,local); + return "Set.setSubrange(" + pre + "," + par1 + "," + par2 + "," + par3 + ")"; + } + else if (data.equals("setAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.setAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replace") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.replace(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAll") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAllMatches") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceFirstMatch") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryForm(env,local); + String par2 = ((Expression) parameters.get(1)).queryForm(env,local); + return "Set.replaceFirstMatch(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("count") && parameters != null && parameters.size() > 0) + // for strings or collections + { String par1 = + ((Expression) parameters.get(0)).queryForm(env,local); + return "Set.count(" + pre + "," + par1 + ")"; + } + else if (objectRef != null && (objectRef.getType() + "").equals("String")) + { // last,first,front,tail on strings + if (data.equals("first") || data.equals("any")) + { return "(" + pre + ".charAt(0) + \"\")"; } + if (data.equals("last")) + { return "(" + pre + ".charAt(" + pre + ".length()-1) + \"\")"; } + if (data.equals("front")) + { return pre + ".substring(0," + pre + ".length()-1)"; } + if (data.equals("tail")) + { return pre + ".substring(1," + pre + ".length())"; } + } + else if (data.equals("max") || data.equals("min")) + { Type compertype = objectRef.getElementType(); + if (compertype == null) + { compertype = type; } + String ctname = compertype.getName(); // only int, double, String are valid + if ("int".equals(ctname)) + { return "((Integer) Set." + data + "(" + pre + ")).intValue()"; } + else if ("double".equals(ctname)) + { return "((Double) Set." + data + "(" + pre + ")).doubleValue()"; } + else if ("long".equals(ctname)) + { return "((Long) Set." + data + "(" + pre + ")).longValue()"; } + else + { return "((" + ctname + ") Set." + data + "(" + pre + "))"; } + } + else if (data.equals("any") || data.equals("last") || data.equals("first")) + { Type et = objectRef.elementType; + if (et != null) + { if ("String".equals("" + et) || et.isEntity()) + { return "((" + et + ") Set." + data + "(" + pre + "))"; } + else + { return unwrap("Set." + data + "(" + pre + ")"); } + } + else + { return "Set." + data + "(" + pre + ")"; } + } + else // sum, prd, front tail on sequences, subcollections + // -- separate versions for numbers & objects? + { return "Set." + data + "(" + pre + ")"; } + } // and s.count(x) in Java + + if (objectRef != null && isEvent && "equivalent".equals(data)) // obj.equivalent() + { String arg = objectRef.queryForm(env,local); + ename = entity.getName(); + if (objectRef.isMultiple()) + { return "(($OUT) $Trace.getAlltarget(" + ename + ".getAll$trace(" + arg + ")).get(0))"; } + else + { return "(($OUT) $Trace.getAlltarget(" + arg + ".get$trace()).get(0))"; } + } // likewise for equivalents + + if (umlkind == UPDATEOP) + { System.err.println("WARNING: Update operations should not be used in query expression:\n " + this); + // JOptionPane.showMessageDialog(null, "Update operation in query context: " + this, + // "Poor specification style", JOptionPane.WARNING_MESSAGE); + + // return this; // or return its postcondition if not recursive. + } + + if (umlkind == QUERY || umlkind == UPDATEOP) + { String res = data + "("; + String parString = parametersQueryForm(env,local); + + if (entity != null) + { ename = entity.getName(); } + + if (entity != null && entity.isExternalApplication()) + { res = ename + "." + cont + "." + res + parString; + return res; + } + else if (entity != null && entity.isClassScope(data)) + { res = ename + "." + res + parString; + return res; + } + else if (objectRef != null) + { String pre = objectRef.queryForm(env,local); + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryForm(env,local); } + + if (objectRef.isMultiple()) // iterate, assume parameters.size() > 0 + { if (parameters == null || parameters.size() == 0) + { res = " " + cont + ".All" + ename + data + "(" + pre + ")"; } + else + { res = " " + cont + ".All" + ename + data + "(" + pre + "," + parString; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + "." + res + parString; + } + return res; + } + String var = findEntityVariable(env); + if (var == null || "".equals(var)) + { return "Controller.inst()." + res + parString; } + return var + "." + res + parString; + } // may also be an arrayIndex + + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { // String etype = elementType + ""; + String ind = arrayIndex.queryForm(env,local); + if (isQualified()) + { return "get" + data + "(" + ind + ")"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return "(\"\" + " + + data + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrap(data + ".get(" + indopt + ")"); } + else + { String jtype = type.getJava(); + return "((" + jtype + ") " + data + ".get(" + indopt + "))"; + } + } + return data; + } + + if (entity == null) { return data; } + + String nme = entity.getName(); + + if (entity.isClassScope(data)) // entity cannot be an interface + { if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return "(\"\" + " + + nme + "." + data + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrap(nme + "." + data + ".get(" + indopt + ")"); } + else + { String jtype = type.getJava(); + return "((" + jtype + ") " + nme + "." + data + ".get(" + indopt + "))"; + } + } + return nme + "." + data; + } + + String var = findEntityVariable(env); + + String res = var + ".get" + data + "()"; + if (var == null || var.length() == 0) + { res = data; } + + if (arrayIndex != null) + { String etype = elementType + ""; + String ind = arrayIndex.queryForm(env,local); + if (isQualified()) + { return var + ".get" + data + "(" + ind + ")"; } + + String indopt = evaluateString("-",ind,"1"); // not for qualified + if (type.getName().equals("String")) + { return "(\"\" + " + + res + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrap(res + ".get(" + indopt + ")"); } + else + { String jtype = type.getJava(); + return "((" + jtype + ") " + res + ".get(" + indopt + "))"; + } + } // not for strings + return res; + } // valid but unecesary for static attributes + } + else if (entity != null) // objectRef != null + { ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) { eref = ename + "." + ename + "Ops"; } + + String res = ""; + String pre = objectRef.queryForm(env,local); + if (objectRef.umlkind == CLASSID) + { Expression refindex = ((BasicExpression) objectRef).arrayIndex; + if (refindex != null) + { if (refindex.isMultiple()) + { if (refindex.isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } // E[inds].data + } + else + { res = pre + ".get" + data + "()"; } // E[ind].data + } + else if (entity.isClassScope(data)) + { res = pre + ".get" + data + "()"; } // E.data + else + { pre = cont + "." + ename.toLowerCase() + "s"; + res = eref + ".getAll" + data + "(" + pre + ")"; + } + } + else if (objectRef.isMultiple()) + { if (isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + ".get" + data + "()"; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + + if (isQualified()) + { return "(" + res + ").get(" + ind + ")"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified, Strings + + if (type.getName().equals("String")) + { return "(\"\" + " + + res + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrap(res + ".get(" + indopt + ")"); } + else + { String jtype = type.getJava(); + return "((" + jtype + ") (" + res + ".get(" + indopt + ")))"; + } + } + return res; + } // version with array? obj.r[i] for each obj: objs? + return data; + } + + public String queryFormJava6(java.util.Map env, boolean local) + { // already type-checked. Ignores prestate + String ename = ""; + String cont = "Controller.inst()"; + + if ((data.equals("systemTime") || + data.equals("getSystemTime")) && + "OclDate".equals(objectRef + "")) + { return "Set.getTime()"; } + + if (data.startsWith("new")) + { String createdClass = data.substring(3); + if ("OclDate".equals(createdClass)) + { return "new Date()"; } + } + + if (data.equals("formattedString") && + "StringLib".equals(objectRef + "")) + { Expression par = (Expression) parameters.get(0); + String pqf = par.queryFormJava6(env,local); + String cmd = "(new Object() { public String call(Object _x) { return " + Expression.formattedString(pqf) + "; } }).call(this)"; + return cmd; + } + + if (type != null && type.isEnumeration() && + type.hasValue(data)) + { return type.getName() + "." + data; } + + if (umlkind == VALUE || umlkind == CONSTANT) + { if (data.equals("Set{}")) + { return "new HashSet()"; } // new Set really + if (data.equals("Sequence{}")) + { return "new ArrayList()"; } + if (data.equals("Map{}")) + { return "new HashMap()"; } + + if (data.equals("null")) + { return "null"; } + + if (data.equals("Math_NaN")) + { return "Double.NaN"; } + if (data.equals("Math_PINFINITY")) + { return "Double.POSITIVE_INFINITY"; } + if (data.equals("Math_NINFINITY")) + { return "Double.NEGATIVE_INFINITY"; } + + if (isSet(data)) + { Expression se = buildSetExpression(data); + return se.queryFormJava6(env,local); + } + + if (isSequence(data)) + { Expression se = buildSetExpression(data); + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + String indopt = evaluateString("-",ind,"1"); + if (se.elementType != null) + { if (Type.isPrimitiveType(se.elementType)) + { return se.unwrapJava6( + se.queryFormJava6(env,local) + ".get(" + indopt + ")"); + } + else + { String jtype = se.elementType.getJava6(); + return "((" + jtype + ") " + se.queryFormJava6(env,local) + ".get(" + indopt + "))"; + } + } + return se.queryFormJava6(env,local) + ".get(" + indopt + ")"; + } // primitive types + return se.queryFormJava6(env,local); + } + + // Also case of literal maps Map{...}[arrayIndex] + + if (isString(data) && arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + String indopt = evaluateString("-",ind,"1"); + return "(\"" + "\" + " + data + ".charAt(" + indopt + "))"; + } + + if (needsBracket) + { return "(" + data + ")"; } + + return data; + } + + if (umlkind == VARIABLE) + { if (data.equals("self")) // but return "self" if it is a genuine variable + { if (env.containsValue("self")) + { return data; } + // else if (entity != null) // Assume it is the most local instance in scope + // { String enme = entity.getName(); + // String var = (String) env.get(enme); + // if (var == null) { return "this"; } + // return var; + // } + else + { return "this"; } + } + else // entity == null) + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + String indopt = evaluateString("-",ind,"1"); + if (type != null) + { if (variable != null && "String".equals(variable.getType() + "")) + { return "(" + data + ".charAt(" + indopt + ") + \"\")"; } + + if (arrayIndex.type != null && arrayIndex.type.getName().equals("int")) + // if (Type.isPrimitiveType(type)) + { return unwrapJava6(data + ".get(" + indopt + ")"); } + else if (arrayIndex.type != null && arrayIndex.type.getName().equals("String")) + { return unwrapJava6(data + ".get(" + ind + ")"); } + else if (Type.isPrimitiveType(type)) + { return unwrapJava6(data + ".get(" + indopt + ")"); } + String jType = type.getJava6(); + return "((" + jType + ") " + data + ".get(" + indopt + "))"; + } + return data + ".get(" + indopt + ")"; + } // unwrap it, also for primitive types + else if (parameters != null && variable != null && variable.getType().isFunctionType()) // application of a Function(S,T) + { String pars = ""; + for (int h = 0; h < parameters.size(); h++) + { Expression par = (Expression) parameters.get(h); + pars = pars + par.queryFormJava6(env,local); + if (h < parameters.size()-1) + { pars = pars + ","; } + } + return data + ".evaluate(" + pars + ")"; + } + else + { return data; } + } + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if ("OclFile".equals(data)) + { return "OclFile.OclFile_index.get(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getByPKOclType(" + ind + ")"; } + + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return data; // But library classes may map to language-specific name + } + + if (umlkind == FUNCTION) + { if (objectRef == null) + { return data; } // Invalid function + + String pre = objectRef.queryFormJava6(env,local); + + if (data.equals("allInstances")) // objectRef is a CLASSID + { return cont + "." + pre.toLowerCase() + "s"; } + + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormJava6(env,local); } + + if (data.equals("size")) + { if (objectRef.type != null && objectRef.type.getName().equals("String")) + { return pre + ".length()"; } + else + { return pre + ".size()"; } + } + + if (("Sum".equals(data) || "Prd".equals(data)) + && "Integer".equals(objectRef + "") && parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + Type sumtype = par4.getType(); + String tname = sumtype.getName(); + BasicExpression subrexp = new BasicExpression("subrange"); + subrexp.umlkind = FUNCTION; + subrexp.objectRef = objectRef; + subrexp.addParameter(par1); + subrexp.addParameter(par2); + Type seqtype = new Type("Sequence", null); + subrexp.setType(seqtype); + Type inttype = new Type("int", null); + subrexp.setElementType(inttype); + seqtype.setElementType(inttype); + if (("" + par3).equals("" + par4)) + { String sqf = subrexp.queryFormJava6(env,local); + return "Set." + data.toLowerCase() + tname + "(" + sqf + ")"; + } + Expression colexp = new BinaryExpression("|C",new BinaryExpression(":", par3, subrexp), par4); + String colqf = colexp.queryFormJava6(env,local); + return "Set." + data.toLowerCase() + tname + "(" + colqf + ")"; + } + + if (data.equals("isDeleted")) // assume objectRef is single object + { return "true"; // "false" really + /* String objstype = objectRef.type.getName(); + if (objectRef.isMultiple()) + { return "Set.intersection(" + pre + + ",Controller.inst()." + objstype.toLowerCase() + "s).size() == 0"; + } + else + { return "!(Controller.inst()." + objstype.toLowerCase() + + "s.contains(" + pre + "))"; + } */ + } + + if (data.equals("asSequence")) + { return "Set.asSequence(" + pre + ")"; } + + if (data.equals("oclIsUndefined")) + { return "(" + pre + " == null)"; } + + if (data.equals("oclIsKindOf") && parameters != null && parameters.size() > 0) + { Expression arg1 = (Expression) parameters.get(0); + String arg1s = arg1 + ""; + return "(" + pre + " instanceof " + arg1s + ")"; // works for external classes also + // return "(Controller.inst()." + arg1s.toLowerCase() + "s.contains(" + pre + "))"; + } + if (data.equals("oclAsType") && parameters != null && parameters.size() > 0) + { Expression arg1 = (Expression) parameters.get(0); + return "((" + arg1 + ") " + pre + ")"; // casting + } + if (data.equals("sqr")) + { return "(" + pre + ") * (" + pre + ")"; } + else if (data.equals("abs") || data.equals("sin") || data.equals("cos") || + data.equals("sqrt") || data.equals("exp") || data.equals("log") || data.equals("log10") || + data.equals("tan") || data.equals("asin") || data.equals("acos") || data.equals("cbrt") || + data.equals("atan") || data.equals("sinh") || data.equals("cosh") || data.equals("tanh")) + // exp, floor can be applied to sets/sequences + { return "Math." + data + "(" + pre + ")"; } + else if (data.equals("round") || data.equals("ceil") || data.equals("floor")) + { return "((int) Math." + data + "(" + pre + "))"; } + else if (data.equals("toUpperCase") || data.equals("toLowerCase")) + { return pre + "." + data + "()"; } + else if (data.equals("sum")) + { Type sumtype = objectRef.getElementType(); + String tname = sumtype.getName(); // must be int, double, long, String + return "Set.sum" + tname + "(" + pre + ")"; + } + else if (data.equals("prd")) + { Type sumtype = objectRef.getElementType(); + String tname = sumtype.getName(); // must be int, double, long + return "Set.prd" + tname + "(" + pre + ")"; + } + else if (data.equals("reverse") || data.equals("sort") || + data.equals("asSet") || data.equals("characters")) + { return "Set." + data + "(" + pre + ")"; } // what about an index? + else if (data.equals("subrange") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + if ("Integer".equals(objectRef + "")) + { return "Set.integerSubrange(" + par1 + "," + par2 + ")"; } + return "Set.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("subrange") && parameters != null && parameters.size() == 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + UnaryExpression ue = new UnaryExpression("->size", objectRef); + ue.setType(new Type("int", null)); + String par2 = ue.queryFormJava6(env,local); + return "Set.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("indexOf") && parameters != null && parameters.size() > 0) + // for strings or sequences + { Expression par1 = (Expression) parameters.get(0); + String spar1 = par1.queryFormJava6(env,local); + String wpar1 = par1.wrap(spar1); + return "(" + pre + ".indexOf(" + wpar1 + ") + 1)"; + } + else if (data.equals("pow") && parameters != null && parameters.size() > 0) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + return "Math.pow(" + pre + ", " + par1 + ")"; + } + else if (data.equals("closure")) + { String rel = ((BasicExpression) objectRef).data; + Expression arg = ((BasicExpression) objectRef).objectRef; + if (arg != null) + { return "Set.closure" + entity.getName() + rel + "(" + arg.queryFormJava6(env,local) + ")"; } + return "Set.closure" + entity.getName() + rel + "(" + pre + ")"; + } + else if (data.equals("insertAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.insertAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("excludingSubrange") && + parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.excludingSubrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setSubrange") && + parameters != null && parameters.size() > 2) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + String par3 = ((Expression) parameters.get(2)).queryFormJava6(env,local); + return "Set.setSubrange(" + pre + "," + par1 + "," + par2 + "," + par3 + ")"; + } + else if (data.equals("insertInto") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.insertInto(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.setAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replace") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.replace(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAll") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAllMatches") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceFirstMatch") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava6(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava6(env,local); + return "Set.replaceFirstMatch(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("count")) // for strings or collections + { if (parameters != null && parameters.size() > 0) + { String par1 = + ((Expression) parameters.get(0)).queryFormJava6(env,local); + return "Set.count(" + pre + "," + par1 + ")"; + } + } + else if (objectRef != null && (objectRef.getType() + "").equals("String")) + { // last,first,front,tail on strings + if (data.equals("first") || data.equals("any")) + { return "(" + pre + ".charAt(0) + \"\")"; } + if (data.equals("last")) + { return "(" + pre + ".charAt(" + pre + ".length()-1) + \"\")"; } + if (data.equals("front")) + { return pre + ".substring(0," + pre + ".length()-1)"; } + if (data.equals("tail")) + { return pre + ".substring(1," + pre + ".length())"; } + } + else if (data.equals("max") || data.equals("min")) + { Type compertype = objectRef.getElementType(); + String ctname = compertype.getName(); // only int, double, String are valid + if ("int".equals(ctname)) + { return "((Integer) Set." + data + "(" + pre + ")).intValue()"; } + else if ("long".equals(ctname)) + { return "((Long) Set." + data + "(" + pre + ")).longValue()"; } + else if ("double".equals(ctname)) + { return "((Double) Set." + data + "(" + pre + ")).doubleValue()"; } + else + { return "((" + ctname + ") Set." + data + "(" + pre + "))"; } + } + else if (data.equals("any") || data.equals("last") || data.equals("first")) + { Type et = objectRef.elementType; + if (et != null) + { if ("String".equals("" + et) || et.isEntity()) + { return "((" + et + ") Set." + data + "(" + pre + "))"; } + else + { return unwrapJava6("Set." + data + "(" + pre + ")"); } + } + else + { return "Set." + data + "(" + pre + ")"; } + } + else // sum, prd, front tail on sequences, subcollections + // -- separate versions for numbers & objects? + { return "Set." + data + "(" + pre + ")"; } + } // and s.count(x) in Java + + if (umlkind == QUERY || umlkind == UPDATEOP) + { String res = data + "("; + String parString = parametersQueryFormJava6(env,local); + + if (entity != null) + { ename = entity.getName(); } + + if (entity != null && entity.isExternalApplication()) + { res = ename + "." + cont + "." + res + parString; + return res; + } + else if (entity != null && entity.isClassScope(data)) + { res = ename + "." + res + parString; + return res; + } + else if (objectRef != null) + { String pre = objectRef.queryFormJava6(env,local); + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormJava6(env,local); } + + if (objectRef.isMultiple()) // iterate, assume parameters.size() > 0 + { if (parameters == null || parameters.size() == 0) + { res = " " + cont + ".All" + ename + data + "(" + pre + ")"; } + else + { res = " " + cont + ".All" + ename + data + "(" + pre + "," + parString; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + "." + res + parString; + } + return res; + } + + String var = findEntityVariable(env); + if (var != null && var.length() > 0) + { return var + "." + res + parString; } + else + { return "Controller.inst()." + res + parString; } + } // may also be an arrayIndex + + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified()) + { return "get" + data + "(" + ind + ")"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return "(\"\" + " + + data + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava6(data + ".get(" + indopt + ")"); } + String jType = type.getJava6(); + return "((" + jType + ") " + data + ".get(" + indopt + "))"; + } + return data; + } + + if (entity == null) { return data; } + + String nme = entity.getName(); + + if (entity.isClassScope(data)) // entity cannot be an interface + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return "(\"\" + " + + nme + "." + data + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava6(nme + "." + data + ".get(" + indopt + ")"); } + else + { String jtype = type.getJava6(); + return "((" + jtype + ") " + nme + "." + data + ".get(" + indopt + "))"; + } + } + return nme + "." + data; + } + + String var = findEntityVariable(env); + + String res = var + ".get" + data + "()"; + if (var == null || var.length() == 0) + { res = data; } + + if (arrayIndex != null) + { String etype = elementType + ""; + String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified()) + { return var + ".get" + data + "(" + ind + ")"; } + + String indopt = evaluateString("-",ind,"1"); // not for qualified + if (type.getName().equals("String")) + { return "(\"\" + " + + res + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava6(var + ".get" + data + "().get(" + indopt + ")"); } + String jType = type.getJava6(); + return "((" + jType + ") " + var + ".get" + data + "().get(" + indopt + "))"; + } // not for strings; unwrap primitives + return res; + } // valid but unecesary for static attributes + } + else if (entity != null) // objectRef != null + { ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) { eref = ename + "." + ename + "Ops"; } + + String res = ""; + String pre = objectRef.queryFormJava6(env,local); + if (objectRef.umlkind == CLASSID) + { Expression refindex = ((BasicExpression) objectRef).arrayIndex; + if (refindex != null) + { if (refindex.isMultiple()) + { if (isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } // E[inds].data + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } // E[inds].data + } + else + { res = pre + ".get" + data + "()"; } // E[ind].data + } + else if (entity.isClassScope(data)) + { res = pre + ".get" + data + "()"; } // E.data + else + { pre = cont + "." + ename.toLowerCase() + "s"; + res = eref + ".getAll" + data + "(" + pre + ")"; + } + } + else if (objectRef.isMultiple()) + { if (isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + ".get" + data + "()"; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified()) + { return "(" + res + ").get(" + ind + ")"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return "(\"\" + " + + res + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava6(res + ".get(" + indopt + ")"); } + String jType = type.getJava6(); + return "((" + jType + ") " + res + ".get(" + indopt + "))"; + } + return res; + } // version with array? obj.r[i] for each obj: objs? + return data; + } + + + // should extend to allow class names in constrants, also + // action names -- check they are in the class of the objectRef + + public String queryFormJava7(java.util.Map env, boolean local) + { // already type-checked. Ignores prestate + String ename = ""; + String cont = "Controller.inst()"; + + if ((data.equals("systemTime") || + data.equals("getSystemTime")) && + "OclDate".equals(objectRef + "")) + { return "Ocl.getTime()"; } + + /* if (data.startsWith("new")) + { String createdClass = data.substring(3); + if ("OclDate".equals(createdClass)) + { return "new Date()"; } + } */ + + if (data.equals("formattedString") && + "StringLib".equals(objectRef + "")) + { Expression par = (Expression) parameters.get(0); + String pqf = par.queryFormJava7(env,local); + String cmd = "(new Object() { public String call(Object _x) { return " + Expression.formattedString(pqf) + "; } }).call(this)"; + return cmd; + } + + if (data.equals("OclFile") && arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + return "OclFile.OclFile_index.get(" + ind + ")"; + } + + if (umlkind == VALUE || umlkind == CONSTANT) + { if (data.equals("{}") || data.equals("Set{}")) + { return "new HashSet()"; } // new Set really + if (data.equals("Sequence{}")) + { return "new ArrayList()"; } + if (data.equals("Map{}")) + { return "new HashMap()"; } + + if (data.equals("null")) + { return "null"; } + + if (data.equals("Math_NaN")) + { return "Double.NaN"; } + if (data.equals("Math_PINFINITY")) + { return "Double.POSITIVE_INFINITY"; } + if (data.equals("Math_NINFINITY")) + { return "Double.NEGATIVE_INFINITY"; } + + if (isSet(data)) + { Expression se = buildSetExpression(data); + return se.queryFormJava7(env,local); + } + + if (isSequence(data)) + { Expression se = buildSetExpression(data); + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String indopt = evaluateString("-",ind,"1"); + if (se.elementType != null) + { if (Type.isPrimitiveType(se.elementType)) + { return se.unwrapJava7( + se.queryFormJava7(env,local) + + ".get(" + indopt + ")"); + } + else + { String jtype = se.elementType.getJava7(se.elementType.getElementType()); + return "((" + jtype + ") " + se.queryFormJava7(env,local) + ".get(" + indopt + "))"; + } + } + return se.queryFormJava7(env,local) + ".get(" + indopt + ")"; + } // primitive types + return se.queryFormJava7(env,local); + } + + if (isString(data) && arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String indopt = evaluateString("-",ind,"1"); + return "(\"" + "\" + " + data + ".charAt(" + indopt + "))"; + } + + if (needsBracket) + { return "(" + data + ")"; } + + return data; + } + + // Also case of literal maps Map{...}[arrayIndex] + + if (umlkind == VARIABLE) + { if (data.equals("self")) // but return "self" if it is a genuine variable + { if (env.containsValue("self")) + { return data; } + // else if (entity != null) // Assume it is the most local instance in scope + // { String enme = entity.getName(); + // String var = (String) env.get(enme); + // if (var == null) { return "this"; } + // return var; + // } + else + { return "this"; } + } + else // entity == null) + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String indopt = evaluateString("-",ind,"1"); + if (type != null) + { if (variable != null && + "String".equals(variable.getType() + "")) + { return "(" + data + ".charAt(" + indopt + ") + \"\")"; } + + if (arrayIndex.type != null && + arrayIndex.type.getName().equals("int")) + // if (Type.isPrimitiveType(type)) + { return unwrapJava7(data + ".get(" + indopt + ")"); } + else if (arrayIndex.type != null && + arrayIndex.type.getName().equals("String")) + { return unwrapJava7(data + ".get(\"\" + " + ind + ")"); } + else if (arrayType != null && arrayType.isMap()) + { return unwrapJava7(data + ".get(" + ind + ")"); } + else if (Type.isPrimitiveType(type)) + { return unwrapJava7(data + ".get(" + indopt + ")"); } + String jType = type.getJava7(elementType); + return "((" + jType + ") " + data + ".get(" + indopt + "))"; + } + return data + ".get(" + indopt + ")"; + } // unwrap it, also for primitive types + else if (parameters != null && variable != null) + { String pars = ""; + for (int h = 0; h < parameters.size(); h++) + { Expression par = (Expression) parameters.get(h); + pars = pars + par.queryFormJava7(env,local); + if (h < parameters.size()-1) + { pars = pars + ","; } + } + + if (variable.getType() != null && variable.getType().isFunctionType()) // application of a Function(S,T) + { + return data + ".evaluate(" + pars + ")"; + } + else + { System.err.println("!! ERROR: function application " + this + " should be expressed as " + data + "->apply(" + pars + ")"); + return "((Evaluation) " + data + ").evaluate(" + pars + ")"; + } + + } + else + { return data; } + } + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if ("OclFile".equals(data)) + { return "OclFile.OclFile_index.get(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getByPKOclType(" + ind + ")"; } + + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return data; // But library classes may map to language-specific name + } + + if (umlkind == FUNCTION) + { if (objectRef == null) + { return data; } // Invalid function + + String pre = objectRef.queryFormJava7(env,local); + + if (data.equals("allInstances")) // objectRef is a CLASSID + { return cont + "." + pre.toLowerCase() + "s"; } + + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormJava7(env,local); } + + if (data.equals("size")) + { if (objectRef.type != null && objectRef.type.getName().equals("String")) + { return pre + ".length()"; } + else + { return pre + ".size()"; } + } + + if (("Sum".equals(data) || "Prd".equals(data)) + && "Integer".equals(objectRef + "") && parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + Type sumtype = par4.getType(); + String tname = sumtype.getName(); + BasicExpression subrexp = new BasicExpression("subrange"); + subrexp.umlkind = FUNCTION; + subrexp.objectRef = objectRef; + subrexp.addParameter(par1); + subrexp.addParameter(par2); + Type seqtype = new Type("Sequence", null); + subrexp.setType(seqtype); + Type inttype = new Type("int", null); + subrexp.setElementType(inttype); + seqtype.setElementType(inttype); + if (("" + par3).equals("" + par4)) + { String sqf = subrexp.queryFormJava7(env,local); + return "Ocl." + data.toLowerCase() + tname + "(" + sqf + ")"; + } + Expression colexp = new BinaryExpression("|C",new BinaryExpression(":", par3, subrexp), par4); + String colqf = colexp.queryFormJava7(env,local); + return "Ocl." + data.toLowerCase() + tname + "(" + colqf + ")"; + } + + if (data.equals("isDeleted")) // assume objectRef is single object + { return "true"; // "false" really + /* String objstype = objectRef.type.getName(); + if (objectRef.isMultiple()) + { return "Ocl.intersection(" + pre + + ",Controller.inst()." + objstype.toLowerCase() + "s).size() == 0"; + } + else + { return "!(Controller.inst()." + objstype.toLowerCase() + + "s.contains(" + pre + "))"; + } */ + } + + if (data.equals("asSequence")) + { return "Ocl.asSequence(" + pre + ")"; } + + if (data.equals("oclIsUndefined")) + { return "(" + pre + " == null)"; } + + if (data.equals("oclIsKindOf") && parameters != null && parameters.size() > 0) + { Expression arg1 = (Expression) parameters.get(0); + String arg1s = arg1 + ""; + return "(" + pre + " instanceof " + arg1s + ")"; // works for external classes also + } + + if (data.equals("oclAsType") && parameters != null && parameters.size() > 0) + { Expression arg1 = (Expression) parameters.get(0); + return "((" + arg1 + ") " + pre + ")"; // casting + } + + if (data.equals("sqr")) + { return "(" + pre + ") * (" + pre + ")"; } + else if (data.equals("abs") || data.equals("sin") || + data.equals("cos") || + data.equals("sqrt") || data.equals("exp") || + data.equals("log") || data.equals("log10") || + data.equals("tan") || data.equals("asin") || + data.equals("acos") || data.equals("cbrt") || + data.equals("atan") || data.equals("sinh") || + data.equals("cosh") || data.equals("tanh")) + // exp, floor can be applied to sets/sequences + { return "Math." + data + "(" + pre + ")"; } + else if (data.equals("round") || data.equals("ceil") || data.equals("floor")) + { return "((int) Math." + data + "(" + pre + "))"; } + else if (data.equals("toUpperCase") || data.equals("toLowerCase")) + { return pre + "." + data + "()"; } + else if (data.equals("sum")) + { Type sumtype = objectRef.getElementType(); + String tname = sumtype.getName(); // must be int, double, long, String + return "Ocl.sum" + tname + "(" + pre + ")"; + } + else if (data.equals("prd")) + { Type sumtype = objectRef.getElementType(); + String tname = sumtype.getName(); // must be int, double, long + return "Ocl.prd" + tname + "(" + pre + ")"; + } + else if (data.equals("reverse") || + data.equals("sort") || + data.equals("asSet") || + data.equals("characters")) + { return "Ocl." + data + "(" + pre + ")"; } // what about an index? + else if (data.equals("subrange") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + if ("Integer".equals(objectRef + "")) + { return "Ocl.integerSubrange(" + par1 + "," + par2 + ")"; } + return "Ocl.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("subrange") && parameters != null && parameters.size() == 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + UnaryExpression ue = new UnaryExpression("->size", objectRef); + ue.setType(new Type("int", null)); + String par2 = ue.queryFormJava7(env,local); + return "Ocl.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("indexOf") && parameters != null && parameters.size() > 0) + // for strings or sequences + { Expression par1 = (Expression) parameters.get(0); + String spar1 = par1.queryFormJava7(env,local); + String wpar1 = par1.wrap(spar1); + return "(" + pre + ".indexOf(" + wpar1 + ") + 1)"; + } + else if (data.equals("pow") && parameters != null && + parameters.size() > 0) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + return "Math.pow(" + pre + ", " + par1 + ")"; + } + else if (data.equals("closure")) + { String rel = ((BasicExpression) objectRef).data; + Expression arg = ((BasicExpression) objectRef).objectRef; + if (arg != null) + { return "Ocl.closure" + entity.getName() + rel + "(" + arg.queryFormJava7(env,local) + ")"; } + return "Ocl.closure" + entity.getName() + rel + "(" + pre + ")"; + } + else if (data.equals("insertAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.insertAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("excludingSubrange") && + parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.excludingSubrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setSubrange") && + parameters != null && parameters.size() > 2) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + String par3 = ((Expression) parameters.get(2)).queryFormJava7(env,local); + return "Ocl.setSubrange(" + pre + "," + par1 + "," + par2 + "," + par3 + ")"; + } + else if (data.equals("insertInto") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.insertInto(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.setAt(" + pre + "," + par1 + "," + par2 + ")"; + // ".add(" + par1 + ", " + par2 + ")"; + } + else if (data.equals("replace") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.replace(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAll") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAllMatches") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceFirstMatch") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormJava7(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormJava7(env,local); + return "Ocl.replaceFirstMatch(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("count")) // for strings or collections + { if (parameters != null && parameters.size() > 0) + { String par1 = + ((Expression) parameters.get(0)).queryFormJava7(env,local); + return "Ocl.count(" + pre + "," + par1 + ")"; + } + } + else if (objectRef != null && + (objectRef.getType() + "").equals("String")) + { // last,first,front,tail on strings + if (data.equals("first") || data.equals("any")) + { return "(" + pre + ".charAt(0) + \"\")"; } + if (data.equals("last")) + { return "(" + pre + ".charAt(" + pre + ".length()-1) + \"\")"; } + if (data.equals("front")) + { return pre + ".substring(0," + pre + ".length()-1)"; } + if (data.equals("tail")) + { return pre + ".substring(1," + pre + ".length())"; } + } + else if (data.equals("max") || data.equals("min")) + { Type compertype = objectRef.getElementType(); + String ctname = compertype.getName(); // only int, double, String are valid + if ("int".equals(ctname)) + { return "((Integer) Ocl." + data + "(" + pre + ")).intValue()"; } + else if ("long".equals(ctname)) + { return "((Long) Ocl." + data + "(" + pre + ")).longValue()"; } + else if ("double".equals(ctname)) + { return "((Double) Ocl." + data + "(" + pre + ")).doubleValue()"; } + else + { return "((" + ctname + ") Ocl." + data + "(" + pre + "))"; } + } + else if (data.equals("any") || data.equals("last") || + data.equals("first")) + { Type et = objectRef.elementType; + if (et != null) + { if ("String".equals("" + et) || et.isEntity()) + { return "((" + et + ") Ocl." + data + "(" + pre + "))"; } + else + { return unwrapJava7("Ocl." + data + "(" + pre + ")"); } + } + else + { return "Ocl." + data + "(" + pre + ")"; } + } + else // sum, prd, front tail on sequences, subcollections + // -- separate versions for numbers & objects? + { return "Ocl." + data + "(" + pre + ")"; } + } // and s.count(x) in Java + + if (umlkind == QUERY || umlkind == UPDATEOP) + { String res = data + "("; + String parString = parametersQueryFormJava7(env,local); + + if (entity != null) + { ename = entity.getName(); } + + if (entity != null && entity.isExternalApplication()) + { res = ename + "." + cont + "." + res + parString; + return res; + } + else if (entity != null && entity.isClassScope(data)) + { res = ename + "." + res + parString; + return res; + } + else if (objectRef != null) + { String pre = objectRef.queryFormJava7(env,local); + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormJava7(env,local); } + + if (objectRef.isMultiple()) // iterate, assume parameters.size() > 0 + { if (parameters == null || parameters.size() == 0) + { res = " " + cont + ".All" + ename + data + "(" + pre + ")"; } + else + { res = " " + cont + ".All" + ename + data + "(" + pre + "," + parString; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + "." + res + parString; + } + return res; + } + + String var = findEntityVariable(env); + if (var != null && var.length() > 0) + { return var + "." + res + parString; } + else + { return "Controller.inst()." + res + parString; } + } // may also be an arrayIndex + + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return "get" + data + "(" + ind + ")"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + + if (arrayIndex.isString()) + { return unwrapJava7(data + ".get(\"\" + " + ind + ")"); } + + if (arrayType != null && arrayType.isMap()) + { return unwrapJava7(data + ".get(" + ind + ")"); } + + if (arrayType != null && + arrayType.isSequence()) + { return unwrapJava7(data + ".get(" + indopt + ")"); } + + if (type.getName().equals("String")) + { return "(\"\" + " + + data + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava7(data + ".get(" + indopt + ")"); } + String jType = type.getJava7(elementType); + return "((" + jType + ") " + data + ".get(" + indopt + "))"; + } + return data; + } + + if (entity == null) { return data; } + + String nme = entity.getName(); + + if (entity.isClassScope(data)) // entity cannot be an interface + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (arrayIndex.isString()) + { return unwrapJava7(nme + "." + data + ".get(\"\" + " + ind + ")"); } + + if (type.getName().equals("String")) + { return "(\"\" + " + + nme + "." + data + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava7(nme + "." + data + ".get(" + indopt + ")"); } + else + { String jtype = type.getJava7(elementType); + return "((" + jtype + ") " + nme + "." + data + ".get(" + indopt + "))"; + } + } + return nme + "." + data; + } + + String var = findEntityVariable(env); // could be null, or "" + + String res = var + ".get" + data + "()"; + if (var == null || var.length() == 0) + { res = data; } + + if (arrayIndex != null) + { String etype = elementType + ""; + String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return var + ".get" + data + "(" + ind + ")"; } + + String indopt = evaluateString("-",ind,"1"); // not for qualified + + if (arrayType != null && arrayType.isMap()) + { return unwrapJava7(var + ".get" + data + "().get(" + ind + ")"); } + + if (arrayType != null && arrayType.isSequence()) + { return unwrapJava7(var + ".get" + data + "().get(" + indopt + ")"); } + + if (type.getName().equals("String")) + { return "(\"\" + " + + res + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava7(var + ".get" + data + "().get(" + indopt + ")"); } + String jType = type.getJava7(elementType); + return "((" + jType + ") " + var + ".get" + data + "().get(" + indopt + "))"; + } // not for strings; unwrap primitives + return res; + } // valid but unecesary for static attributes + } + else if (entity != null) // objectRef != null + { ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + + String res = ""; + String pre = objectRef.queryFormJava7(env,local); + if (objectRef.umlkind == CLASSID) + { Expression refindex = ((BasicExpression) objectRef).arrayIndex; + if (refindex != null) + { if (refindex.isMultiple()) + { if (isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } // E[inds].data + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } // E[inds].data + } + else + { res = pre + ".get" + data + "()"; } // E[ind].data + } + else if (entity.isClassScope(data)) + { res = pre + ".get" + data + "()"; } // E.data + else + { pre = cont + "." + ename.toLowerCase() + "s"; + res = eref + ".getAll" + data + "(" + pre + ")"; + } + } + else if (objectRef.isMultiple()) + { if (isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + ".get" + data + "()"; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return "(" + res + ").get(" + ind + ")"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return "(\"\" + " + + res + ".charAt(" + indopt + "))"; + } + else if (Type.isPrimitiveType(type)) + { return unwrapJava7(res + ".get(" + indopt + ")"); } + String jType = type.getJava7(elementType); + return "((" + jType + ") " + res + ".get(" + indopt + "))"; + } + return res; + } // version with array? obj.r[i] for each obj: objs? + return data; + } + + public String leftQueryFormJava7(java.util.Map env, boolean local) + { // already type-checked. Ignores prestate + String ename = ""; + String cont = "Controller.inst()"; + + if (umlkind == VARIABLE) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String indopt = evaluateString("-",ind,"1"); + if (type != null) + { if (arrayIndex.type != null && arrayIndex.type.getName().equals("int")) + { return data + "[" + indopt + "]"; } + return data + "[" + indopt + "]"; + } + return data + "[" + indopt + "]"; + } // unwrap it, also for primitive types + else + { return data; } + } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return data + "[" + ind + "]"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + + if (arrayIndex.isString()) + { return data + "[" + ind + "]"; } + else if (arrayType != null && arrayType.isMap()) + { return data + "[" + ind + "]"; } + else if (arrayType != null && arrayType.isSequence()) + { return data + "[" + indopt + "]"; } + } + return data; + } + + if (entity == null) + { return data; } + + String nme = entity.getName(); + + if (entity.isClassScope(data)) // entity cannot be an interface + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (arrayIndex.isString()) + { return nme + "." + data + "[" + ind + "]"; } + + return nme + "." + data + "[" + indopt + "]"; + } + return nme + "." + data; + } + + String var = findEntityVariable(env); // could be null, or "" + + String res = var + "." + data; + if (var == null || var.length() == 0) + { res = data; } + + if (arrayIndex != null) + { String etype = elementType + ""; + String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return var + "." + data + "[" + ind + "]"; } + + String indopt = evaluateString("-",ind,"1"); // not for qualified + if (arrayType != null && arrayType.isMap()) + { return var + "." + data + "[" + ind + "]"; } + else if (arrayType != null && arrayType.isSequence()) + { return var + "." + data + "[" + indopt + "]"; } + + return var + "." + data + "[" + indopt + "]"; + } // not for strings; unwrap primitives + return res; + } // valid but unecesary for static attributes + } + else if (entity != null) // objectRef != null + { ename = entity.getName(); + String eref = ename; + + String res = ""; + String pre = objectRef.queryFormJava7(env,local); + if (objectRef.umlkind == CLASSID) + { Expression refindex = ((BasicExpression) objectRef).arrayIndex; + if (refindex != null) + { res = pre + "." + data; } // E[ind].data + else if (entity.isClassScope(data)) + { res = pre + "." + data; } // E.data + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + "." + data + ""; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return "(" + res + ")[" + ind + "]"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + return res + "[" + indopt + "]"; + } + return res; + } // version with array? obj.r[i] for each obj: objs? + return data; + } + + + // public String classqueryFormCSharp(java.util.Map env, boolean local) + // { if (umlkind == CLASSID) + // { return classExtentQueryForm(env,local); } + // return queryFormCSharp(env,local); + // } + + /* public String parametersQueryFormCSharp(java.util.Map env, boolean local) + { String parString = ""; + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parString = parString + par.queryFormCSharp(env,local); + if (i < parameters.size() - 1) + { parString = parString + ","; } + } + } + parString = parString + ")"; + return parString; + } */ + + public String queryFormCSharp(java.util.Map env, boolean local) + { // already type-checked. Ignores prestate + String ename = ""; + String cont = "Controller.inst()"; + + String pars = ""; + if (parameters != null) + { for (int h = 0; h < parameters.size(); h++) + { Expression par = (Expression) parameters.get(h); + pars = pars + par.queryFormCSharp(env,local); + if (h < parameters.size()-1) + { pars = pars + ","; } + } + } + + if ((data.equals("rawString")) && + "StringLib".equals(objectRef + "")) + { return "@" + pars; } + + if ("getMessage".equals(data) && objectRef != null && + Type.isOclExceptionType(objectRef)) + { String rqf = objectRef.queryFormCSharp(env,local); + return rqf + ".Message"; + } + + if ("getCause".equals(data) && objectRef != null && + Type.isOclExceptionType(objectRef)) + { String rqf = objectRef.queryFormCSharp(env,local); + return rqf + ".InnerException"; + } + + if ("getName".equals(data) && objectRef != null && + objectRef.getType() != null && + "OclType".equals(objectRef.getType().getName())) + { String rqf = objectRef.queryFormCSharp(env,local); + return rqf + ".Name"; + } + + // if ("printStackTrace".equals(data) && objectRef != null && + // Type.isOclExceptionType(objectRef)) + // { String rqf = objectRef.queryFormCSharp(env,local); + // return "Console.WriteLine(" + rqf + ".StackTrace)"; + // } + + if (data.equals("System_in") || + data.equals("System_out") || + data.equals("System_err")) + { return "OclFile." + data; } + + if ((data.equals("systemTime") || + "getSystemTime".equals(data)) && + "OclDate".equals(objectRef + "")) + { return "SystemTypes.getTime()"; } + + if (data.startsWith("new")) + { String createdClass = data.substring(3); + if ("OclDate".equals(createdClass)) + { return "OclDate.newOclDate()"; } + if (Type.isExceptionType(createdClass)) + { String csharpClass = + (String) Type.exceptions2csharp.get(createdClass); + return "new " + csharpClass + "(" + pars + ")"; + } + } + + if (data.startsWith("new") && objectRef != null) + { String entname = data.substring(3); + System.out.println(">>> Creation operation for " + entname); + + if ((objectRef + "").equals(entname)) + { return objectRef + "." + data + "(" + pars + ")"; } + } + + if (("time".equals(data) || "getTime".equals(data)) && + objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { String rqf = objectRef.queryFormCSharp(env,local); + return "SystemTypes.getTime(" + rqf + ")"; + } + } + + /* Update form: + if ("setTime".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + String par1qf = par1.queryFormCSharp(env,local); + String rqf = objectRef.queryFormCSharp(env,local); + + return " " + rqf + + " = DateTimeOffset.FromUnixTimeMilliseconds(" + par1qf + ").DateTime;"; + } + } + } + + if ("dateAfter".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + String par1qf = par1.queryFormCSharp(env,local); + String rqf = objectRef.queryFormCSharp(env,local); + + return rqf + " > " + par1qf; + } + } + } + + if ("dateBefore".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + String par1qf = par1.queryFormCSharp(env,local); + String rqf = objectRef.queryFormCSharp(env,local); + + return rqf + " < " + par1qf; + } + } + } + + if (data.startsWith("create") && objectRef == null) + { String entname = data.substring(6); + System.out.println(">>> Creation operation for " + entname); + + // Entity entx = (Entity) ModelElement.lookupByName(entname,entities); + if (entity != null && entity.getName().equals(entname)) + { return cont + "." + data + "(" + pars + ")"; } + } +*/ + + if (type != null && type.isEnumeration() && + type.hasValue(data)) + { return type.getName() + "." + data; } + + if (umlkind == VALUE || umlkind == CONSTANT) + { if (data.equals("{}") || data.equals("Set{}") || data.equals("Sequence{}")) + { return "new ArrayList()"; } // new Set really + if (data.equals("Map{}")) + { return "new Hashtable()"; } + + if (data.equals("null")) + { return "null"; } + + if (data.equals("Math_NaN")) + { return "double.NaN"; } + if (data.equals("Math_PINFINITY")) + { return "double.PositiveInfinity"; } + if (data.equals("Math_NINFINITY")) + { return "double.NegativeInfinity"; } + + if (isSet(data)) + { Expression se = buildSetExpression(data); + return se.queryFormCSharp(env,local); + } + + if (isSequence(data)) + { Expression se = buildSetExpression(data); + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + String indopt = evaluateString("-",ind,"1"); + String cstype = type.getCSharp(); + return "((" + cstype + ") " + se.queryFormCSharp(env,local) + "[" + indopt + "])"; + } + return se.queryFormCSharp(env,local); + } + + if (isString(data) && arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + String indopt = evaluateString("-",ind,"1"); + return "(\"" + "\" + " + data + "[" + indopt + "])"; + } + + if (type != null && type.isEnumeration()) + { return type.getName() + "." + data; } + + return data; + } // literal maps? + + if (umlkind == VARIABLE) + { if (data.equals("self")) // but return "self" if it is a genuine variable + { if (env.containsValue("self")) + { return data; } + // else if (entity != null) // Assume it is the most local instance in scope + // { String enme = entity.getName(); + // String var = (String) env.get(enme); + // if (var == null) { return "this"; } + // return var; + // } + else + { return "this"; } + } + else if (data.equals("super")) + { return "base"; } + else // entity == null) + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + String indopt = evaluateString("-",ind,"1"); + + // JOptionPane.showMessageDialog(null, "Variable: " + this + " arrayType: " + arrayType + " variable: " + variable, + // "Error", JOptionPane.ERROR_MESSAGE); + + if (arrayType != null && arrayType.isSequence()) + { return data + "[" + indopt + "]"; } + + if (arrayIndex.type != null && + arrayIndex.type.getName().equals("String")) + { return data + "[\"\" + " + ind + "]"; } + + if (arrayType != null && arrayType.isMap()) + { return data + "[" + ind + "]"; } + + if (variable != null && + "String".equals(variable.getType() + "")) + { return data + ".Substring(" + indopt + ", 1)"; } + + if (variable != null && variable.getType() != null && + "Map".equals(variable.getType().getName())) + { return data + "[" + ind + "]"; } + + String cstype = type.getCSharp(); + return "((" + cstype + ") " + data + "[" + indopt + "])"; + } + else if (parameters != null && variable != null && + variable.getType().isFunctionType()) + // application of a Function(S,T) + { return data + "(" + pars + ")"; } + + return data; + } + + // if (data.equals("OclFile")) + // { return "OclFile.getOclFileByPK(" + ind + ")"; } + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + if (data.equals("OclFile")) + { return "OclFile.getOclFileByPK(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType.getOclTypeByPK(" + ind + ")"; } + return cont + ".get" + data + "ByPK(" + ind + ")"; + } + return data; + // But library classes may map to language-specific name + } + + if (umlkind == FUNCTION) + { if (objectRef == null) + { return data; } // Invalid function + + String pre = objectRef.queryFormCSharp(env,local); + + if (data.equals("allInstances")) // objectRef is a CLASSID + { return cont + ".get" + pre.toLowerCase() + "_s()"; } + + if (data.equals("oclIsUndefined")) + { return "(" + pre + " == null)"; } + + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormCSharp(env,local); } + + if (data.equals("size")) + { if (objectRef.type != null && objectRef.type.getName().equals("String")) + { return pre + ".Length"; } + else + { return pre + ".Count"; } + } + if (data.equals("isDeleted")) // assume objectRef is single object + { return "true"; // "false" really + } + + if (("Sum".equals(data) || "Prd".equals(data)) + && "Integer".equals(objectRef + "") && parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + BasicExpression subrexp = new BasicExpression("subrange"); + subrexp.umlkind = FUNCTION; + subrexp.objectRef = objectRef; + subrexp.addParameter(par1); + subrexp.addParameter(par2); + Type seqtype = new Type("Sequence",null); + subrexp.setType(seqtype); + Type inttype = new Type("int",null); + subrexp.setElementType(inttype); + seqtype.setElementType(inttype); + Type sumtype = par4.getType(); + String tname = sumtype.getName(); + if (("" + par3).equals("" + par4)) + { String sqf = subrexp.queryFormCSharp(env,local); + return "SystemTypes." + data.toLowerCase() + tname + "(" + sqf + ")"; + } + Expression colexp = new BinaryExpression("|C",new BinaryExpression(":", par3, subrexp), par4); + String colqf = colexp.queryFormCSharp(env,local); + return "SystemTypes." + data.toLowerCase() + tname + "(" + colqf + ")"; + } + + if (data.equals("oclIsKindOf") & parameters != null) + { Expression arg1 = (Expression) parameters.get(0); + String arg1s = arg1 + ""; + return "(" + pre + " is " + arg1s + ")"; + // Controller.inst().get" + arg1s.toLowerCase() + "_s().contains(" + pre + "))"; + } + if (data.equals("oclAsType") && parameters != null) + { Expression arg1 = (Expression) parameters.get(0); + return "((" + arg1 + ") " + pre + ")"; // casting + } + if (data.equals("sqr")) + { return "(" + pre + ") * (" + pre + ")"; } + else if (data.equals("abs") || data.equals("sin") || data.equals("cos") || + data.equals("sqrt") || data.equals("exp") || data.equals("log") || data.equals("log10") || + data.equals("tan") || data.equals("asin") || data.equals("acos") || data.equals("cbrt") || + data.equals("atan") || data.equals("sinh") || data.equals("cosh") || data.equals("tanh")) + // exp, floor can be applied to sets/sequences + { String csop = ("" + data.charAt(0)).toUpperCase() + data.substring(1,data.length()); + return "Math." + csop + "(" + pre + ")"; + } // to uppercase? + else if (data.equals("round")) + { return "((int) Math.Round(" + pre + "))"; } + else if (data.equals("ceil")) + { return "((int) Math.Ceiling(" + pre + "))"; } + else if (data.equals("floor")) + { return "((int) Math.Floor(" + pre + "))"; } + else if (data.equals("toUpperCase")) + { return pre + ".ToUpper()"; } + else if (data.equals("toLowerCase")) + { return pre + ".ToLower()"; } + else if (data.equals("sum")) + { Type sumtype = objectRef.getElementType(); + String tname = sumtype.getName(); // int, double, long, String + return "SystemTypes.sum" + tname + "(" + pre + ")"; + } + else if (data.equals("prd")) + { Type sumtype = objectRef.getElementType(); + String tname = sumtype.getName(); // int, double, long + return "SystemTypes.prd" + tname + "(" + pre + ")"; + } + else if (data.equals("reverse") || data.equals("sort") || + data.equals("asSet") || data.equals("characters")) + { return "SystemTypes." + data + "(" + pre + ")"; } + else if (data.equals("subrange") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + if ("Integer".equals(objectRef + "")) + { return "SystemTypes.integerSubrange(" + par1 + "," + par2 + ")"; } + return "SystemTypes.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("subrange") && parameters != null && parameters.size() == 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + UnaryExpression ue = new UnaryExpression("->size", objectRef); + ue.setType(new Type("int", null)); + String par2 = ue.queryFormCSharp(env,local); + return "SystemTypes.subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("indexOf") && parameters != null && parameters.size() > 0) // for strings or sequences + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + return "(" + pre + ".IndexOf(" + par1 + ") + 1)"; + } + else if (data.equals("pow") && parameters != null && parameters.size() > 0) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + return "Math.Pow(" + pre + ", " + par1 + ")"; + } + else if (data.equals("asSequence")) + { return pre; } + else if (data.equals("closure")) + { String rel = ((BasicExpression) objectRef).data; + Expression arg = ((BasicExpression) objectRef).objectRef; + if (arg != null) + { return "SystemTypes.closure" + entity.getName() + rel + "(" + arg.queryFormCSharp(env,local) + ")"; } + return "SystemTypes.closure" + entity.getName() + rel + "(" + pre + ")"; + } + else if (data.equals("insertAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.insertAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("excludingSubrange") && + parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.excludingSubrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setSubrange") && + parameters != null && parameters.size() > 2) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + String par3 = ((Expression) parameters.get(2)).queryFormCSharp(env,local); + return "SystemTypes.setSubrange(" + pre + "," + par1 + "," + par2 + "," + par3 + ")"; + } + else if (data.equals("insertInto") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.insertInto(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("setAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.setAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replace") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.replace(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAll") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAllMatches") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceFirstMatch") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCSharp(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCSharp(env,local); + return "SystemTypes.replaceFirstMatch(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("count")) // for strings or collections + { if (parameters != null && parameters.size() > 0) + { String par1 = + ((Expression) parameters.get(0)).queryFormCSharp(env,local); + return "SystemTypes.count(" + pre + "," + par1 + ")"; + } + } + else if (objectRef != null && (objectRef.getType() + "").equals("String")) + { // last,first,front,tail on strings + if (data.equals("first") || data.equals("any")) + { return pre + ".Substring(0,1)"; } + if (data.equals("last")) + { return pre + ".Substring(" + pre + ".Length-1, 1)"; } + if (data.equals("front")) + { return pre + ".Substring(0," + pre + ".Length-1)"; } + if (data.equals("tail")) + { return pre + ".Substring(1," + pre + ".Length-1)"; } + } + else if (data.equals("max") || data.equals("min")) + { Type et = objectRef.elementType; + if (et != null) + { return "((" + et.getCSharp() + ") SystemTypes." + data + "(" + pre + "))"; } + else + { return "SystemTypes." + data + "(" + pre + ")"; } + } + else if (data.equals("any") || data.equals("last") || data.equals("first")) + { Type et = objectRef.elementType; + if (et != null) + { return "((" + et.getCSharp() + ") SystemTypes." + data + "(" + pre + "))"; } + else + { return "SystemTypes." + data + "(" + pre + ")"; } + } + else // sum, prd, front tail on sequences, subcollections + // -- separate versions for numbers & objects? + { return "SystemTypes." + data + "(" + pre + ")"; } + } // and s.count(x) in Java + + if (umlkind == QUERY || umlkind == UPDATEOP) + { String res = data + "("; + String parString = parametersQueryFormCSharp(env,local); + + System.out.println(">>> C# query form of: " + this + " " + + isStatic() + " " + entity); + + if (entity == null && objectRef == null) // use case + { return cont + "." + res + parString; } + + BehaviouralFeature bf = null; + + if (entity != null) + { ename = entity.getName(); + bf = entity.getDefinedOperation(data); + } + + if (bf == null && (objectRef instanceof BasicExpression) + && isStatic() && + objectRef.umlkind == CLASSID && + ((BasicExpression) objectRef).arrayIndex == null) + { Type et = objectRef.getElementType(); + if (et != null && et.isEntity()) + { bf = et.getEntity().getDefinedOperation(data); } + System.out.println(">>> Static call: " + objectRef + " " + et + " " + bf); + + if (bf != null) + { res = et.getName() + "." + res + parString; + return res; + } + } + + if (bf != null && bf.isGeneric()) + { String tpars = + Type.resolveTypeParametersCSharp( + bf.getTypeParameters(), + bf.getParameters(), parameters); + res = data + tpars + "("; + } + + if (entity != null && entity.isExternalApplication()) + { res = ename + "." + cont + "." + res + parString; + return res; + } + else if (entity != null && entity.isClassScope(data)) + { res = ename + "." + res + parString; + return res; + } + else if (entity != null && data.startsWith("create") && + objectRef == null) + { if (data.substring(6).equals(ename)) + { return cont + "." + res + parString; } + } + else if (objectRef != null) + { String pre = objectRef.queryFormCSharp(env,local); + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormCSharp(env,local); } + + if (objectRef.isSequenceValued() || + objectRef.isSetValued()) + // iterate, assume parameters.size() > 0 + { if (parameters == null || parameters.size() == 0) + { res = " " + cont + ".All" + ename + data + "(" + pre + ")"; } + else + { res = " " + cont + ".All" + ename + data + "(" + pre + "," + parString; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + "." + res + parString; + } + return res; + } + + String var = findEntityVariable(env); + if (var != null && var.length() > 0) + { return var + "." + res + parString; } + else + { return res + parString; } + } // may also be an arrayIndex + + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) { + if (arrayIndex != null) + { String etype = type.getCSharp(); + String ind = + arrayIndex.queryFormCSharp(env,local); + + if (isQualified()) + { return "((" + etype + ") " + data + "[" + ind + "])"; } + String indopt = evaluateString("-",ind,"1"); + // not for qualified ones + + if (arrayIndex.isString()) + { return data + "[\"\" + " + ind + "]"; } + + if (arrayType != null && arrayType.isMap()) + { return "((" + etype + ") " + data + "[" + ind + "])"; } + + if (arrayType != null && + arrayType.getName().startsWith("Sequence")) + { return "((" + etype + ") " + data + "[" + indopt + "])"; } + + if (type.getName().equals("String")) + { return "(\"\" + " + + data + ".Substring(" + indopt + ",1))"; + } + + return "((" + etype + ") " + data + "[" + indopt + "])"; + } + + return data; + } + + if (entity == null) { return data; } + + String nme = entity.getName(); + + if (entity.isClassScope(data)) // entity cannot be an interface + { if (arrayIndex != null) + { String ind = + arrayIndex.queryFormCSharp(env,local); + String indopt = evaluateString("-",ind,"1"); + // not for qualified ones + String etype = type.getCSharp(); + + if (arrayType != null && + arrayType.getName().startsWith("Sequence")) + { return "((" + etype + ") " + data + "[" + indopt + "])"; } + + if (arrayIndex.isString()) + { return data + "[\"\" + " + ind + "]"; } + + if (arrayType != null && arrayType.isMap()) + { return "((" + etype + ") " + data + "[" + ind + "])"; } + + if (type.getName().equals("String")) + { return "(\"\" + " + + nme + "." + data + ".Substring(" + indopt + ",1))"; + } + else + { + return "((" + etype + ") " + nme + "." + data + "[" + indopt + "])"; + } + } + return nme + "." + data; + } + + String var = findEntityVariable(env); + + String res = var + ".get" + data + "()"; + if (var == null || var.length() == 0) + { res = data; } + + if (arrayIndex != null) + { String etype = type.getCSharp(); + String ind = arrayIndex.queryFormCSharp(env,local); + if (isQualified()) + { return "((" + etype + ") " + res + "[" + ind + "])"; } + + /* JOptionPane.showMessageDialog(null, + "Attribute: " + this + " arrayType: " + arrayType + + " variable: " + variable + + " type: " + type, + "Error", JOptionPane.ERROR_MESSAGE); */ + + String indopt = evaluateString("-",ind,"1"); // not for qualified + + if (arrayType != null && arrayType.isMap()) + { return "((" + etype + ") " + var + ".get" + data + "()[" + ind + "])"; } + + if (arrayType != null && arrayType.isSequence()) + { return "((" + etype + ") " + var + ".get" + data + "()[" + indopt + "])"; } + + if (type.getName().equals("String")) + { return data + ".Substring(" + indopt + ", 1)"; } + + return "((" + etype + ") " + res + "[" + indopt + "])"; + } // not for strings + + return res; + } // valid but unecesary for static attributes + } + else if (entity != null) // objectRef != null + { ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) { eref = ename + "Ops"; } + + String res = ""; + String pre = objectRef.queryFormCSharp(env,local); + if (objectRef.umlkind == CLASSID) + { Expression refindex = ((BasicExpression) objectRef).arrayIndex; + if (refindex != null) + { if (refindex.isMultiple()) + { if (refindex.isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } // E[inds].data + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } + } + else + { res = pre + ".get" + data + "()"; } // E[ind].data + } + else if (entity.isClassScope(data)) + { res = pre + ".get" + data + "()"; } // E.data + else + { pre = cont + "." + ename.toLowerCase() + "_s"; + res = eref + ".getAll" + data + "(" + pre + ")"; + } + } + else if (objectRef.isMultiple()) + { if (isOrdered()) + { res = eref + ".getAllOrdered" + data + "(" + pre + ")"; } + else + { res = eref + ".getAll" + data + "(" + pre + ")"; } + } + else + { if (downcast) + { pre = "((" + ename + ") " + pre + ")"; } + res = pre + ".get" + data + "()"; + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + if (isQualified()) + { return res + "[" + ind + "]"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified, Strings + if (type.getName().equals("String")) + { return res + ".Substring(" + indopt + ", 1)"; } + String cstype = type.getCSharp(); + return "((" + cstype + ") " + res + "[" + indopt + "])"; + } + return res; + } // version with array? obj.r[i] for each obj: objs? + return data; + } + + public String queryFormCPP(java.util.Map env, boolean local) + { // already type-checked. Ignores prestate + String ename = ""; + String cont = "Controller::inst->"; + Type elemT = getElementType(); + String cetype = "void*"; + if (elemT != null) + { cetype = elemT.getCPP(elemT.getElementType()); } + + if ("null".equals(data)) + { return "NULL"; } + + if ("getMessage".equals(data) && objectRef != null && + Type.isOclExceptionType(objectRef)) + { String rqf = objectRef.queryFormCPP(env,local); + return rqf + ".what()"; + } + + if ((data.equals("systemTime") || + data.equals("getSystemTime")) && + "OclDate".equals(objectRef + "")) + { return "UmlRsdsLib::getTime()"; } + + if (("time".equals(data) || "getTime".equals(data)) && + objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { String rqf = objectRef.queryFormCPP(env,local); + return rqf + "->getTime()"; + } + } + + if (data.startsWith("new")) + { String createdClass = data.substring(3); + String pars = ""; + if (parameters != null) + { for (int h = 0; h < parameters.size(); h++) + { Expression par = (Expression) parameters.get(h); + pars = pars + par.queryFormCPP(env,local); + if (h < parameters.size()-1) + { pars = pars + ","; } + } + } + + if ("OclDate".equals(createdClass)) + { return "OclDate::newOclDate(" + pars + ")"; } + + if (createdClass.startsWith("OclIterator") && + parameters != null && + parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + Type et = par1.getElementType(); + if (et != null) + { String cpptype = et.getCPP(et.getElementType()); + return "OclIterator<" + cpptype + ">::" + data + "(" + pars + ")"; + } + else + { System.err.println("!! ERROR: No element type for: " + par1); } + } + + if (Type.isExceptionType(createdClass)) + { String cppClass = + (String) Type.exceptions2cpp.get(createdClass); + if (cppClass == null) + { cppClass = createdClass; } + + return cppClass + "::" + data + "(" + pars + ")"; + } + } + + if ("elements".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclIterator")) + { return objectRef.queryFormCPP(env,local) + "->getelements()"; } + } + + if ("delete".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclFile")) + { return objectRef.queryFormCPP(env,local) + + "->deleteFile()"; + } + } + + if ("printf".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclFile") && + parameters != null && + parameters.size() > 1 && + parameters.get(1) instanceof SetExpression) + { Expression format = (Expression) parameters.get(0); + Expression sq = (Expression) parameters.get(1); + String p1 = format.queryFormCPP(env,local); + String cseq = + ((SetExpression) sq).toCSequence(env,local); + return objectRef.queryFormCPP(env,local) + + "->printf(" + p1 + "," + cseq + ")"; + } + } + + if (umlkind == VALUE || umlkind == CONSTANT) + { if (data.equals("{}") || data.equals("Set{}")) + { return "(new set<" + cetype + ">())"; } + if (data.equals("Sequence{}")) + { return "(new vector<" + cetype + ">())"; } + if (data.equals("Map{}")) + { return "(new map<" + cetype + ">())"; } + + if (data.equals("null")) + { return "NULL"; } + + if (data.equals("Math_NaN")) + { return "std::numeric_limits::quiet_NaN()"; } + if (data.equals("Math_PINFINITY")) + { return "std::numeric_limits::infinity()"; } + if (data.equals("Math_NINFINITY")) + { return "-(std::numeric_limits::infinity())"; } + + if (isSet(data)) + { Expression se = buildSetExpression(data); + return se.queryFormCPP(env,local); + } + + if (isSequence(data)) + { Expression se = buildSetExpression(data); + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + String indopt = evaluateString("-",ind,"1"); + return "(" + se.queryFormCPP(env,local) + ")->at(" + indopt + ")"; + } + return se.queryFormCPP(env,local); + } + + if (isString(data) && arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + String indopt = evaluateString("-",ind,"1"); + return data + ".substr(" + indopt + ", 1)"; + } + if (type != null && type.isEnumeration()) + { return data; } // "(int) " + type.getName() + "." + data; } + return data; + } + + if (umlkind == VARIABLE) + { if (data.equals("self")) // but return "self" if it is a genuine variable + { if (env.containsValue("self")) + { return data; } + else + { return "this"; } + } + else if (data.equals("super")) + { if (env.containsValue("super")) + { return data; } + else if (entity != null && entity.getSuperclass() != null) + { return entity.getSuperclass().getName(); } + else + { System.err.println(">> Warning!: cannot find superclass for " + this); + return data; + } + } + else // entity == null) + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + String indopt = evaluateString("-",ind,"1"); + if (variable != null && "String".equals(variable.getType() + "")) + { return data + ".substr(" + indopt + ", 1)"; } + if (variable != null && variable.getType() != null && "Map".equals(variable.getType().getName())) + { return data + "->at(" + ind + ")"; } + return "(" + data + ")->at(" + indopt + ")"; + } + else if (parameters != null && variable != null && variable.getType().isFunctionType()) // application of a Function(S,T) + { String pars = ""; + for (int h = 0; h < parameters.size(); h++) + { Expression par = (Expression) parameters.get(h); + pars = pars + par.queryFormCPP(env,local); + if (h < parameters.size()-1) + { pars = pars + ","; } + } + return "(*" + data + ")(" + pars + ")"; + } + return data; + } + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (data.equals("OclFile")) + { return "OclFile::getOclFileByPK(" + ind + ")"; } + if (data.equals("OclType")) + { return "OclType::getOclTypeByPK(" + ind + ")"; } + return cont + "get" + data + "ByPK(" + ind + ")"; + } + return data; // But library classes may map to language-specific name + } + + if (umlkind == FUNCTION) + { if (objectRef == null) + { return data; } // Invalid function + + String pre = objectRef.queryFormCPP(env,local); + + if (data.equals("allInstances")) // objectRef is a CLASSID + { return cont + "get" + pre.toLowerCase() + "_s()"; } + + if (data.equals("oclIsUndefined")) + { return "(" + pre + " == NULL)"; } + + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormCPP(env,local); } + + if (data.equals("size")) + { if (objectRef.type != null && objectRef.type.getName().equals("String")) + { return pre + ".length()"; } + else // must be a collection + { return pre + "->size()"; } + } + if (data.equals("isDeleted")) // assume objectRef is single object + { return "true"; // "false" really + } + if (data.equals("oclIsKindOf") && parameters != null) // Does not work for external classes + { Expression arg1 = (Expression) parameters.get(0); + String arg1s = arg1 + ""; + String rinstances = cont + "get" + arg1s.toLowerCase() + "_s()"; + return "UmlRsdsLib<" + arg1s + "*>::isIn(" + pre + ", " + rinstances + ")"; + } + + if (data.equals("oclAsType") && parameters != null) + { Expression arg1 = (Expression) parameters.get(0); + return "((" + arg1 + "*) " + pre + ")"; // casting - assuming it is an entity + } + + if (data.equals("sqr")) + { return "(" + pre + ") * (" + pre + ")"; } + else if (data.equals("abs") || data.equals("sin") || data.equals("cos") || + data.equals("sqrt") || data.equals("exp") || data.equals("log") || + data.equals("tan") || data.equals("atan") || data.equals("acos") || + data.equals("asin") || data.equals("cbrt") || data.equals("log10") || + data.equals("cosh") || data.equals("sinh") || data.equals("tanh")) + // exp, floor can be applied to sets/sequences + { return data + "(" + pre + ")"; } + else if (data.equals("floor") || data.equals("ceil")) + { return "((int) " + data + "(" + pre + "))"; } + else if (data.equals("round")) + { return "UmlRsdsLib::oclRound(" + pre + ")"; } + else if (data.equals("toUpperCase")) + { return "UmlRsdsLib::toUpperCase(" + pre + ")"; } + else if (data.equals("toLowerCase")) + { return "UmlRsdsLib::toLowerCase(" + pre + ")"; } + else if (("Sum".equals(data) || "Prd".equals(data)) + && "Integer".equals(objectRef + "") && parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + Type sumtype = par4.getType(); + String tname = sumtype.getName(); + BasicExpression subrexp = new BasicExpression("subrange"); + subrexp.umlkind = FUNCTION; + subrexp.objectRef = objectRef; + subrexp.addParameter(par1); + subrexp.addParameter(par2); + Type seqtype = new Type("Sequence", null); + subrexp.setType(seqtype); + Type inttype = new Type("int", null); + subrexp.setElementType(inttype); + seqtype.setElementType(inttype); + if (("" + par3).equals("" + par4)) + { String sqf = subrexp.queryFormCPP(env,local); + return "UmlRsdsLib<" + tname + ">::" + data.toLowerCase() + "(" + sqf + ")"; + } + Expression colexp = new BinaryExpression("|C",new BinaryExpression(":", par3, subrexp), par4); + String colqf = colexp.queryFormCPP(env,local); + if (tname.equals("string") && "Sum".equals(data)) + { return "UmlRsdsLib<" + tname + ">::sumString(" + pre + ")"; } + return "UmlRsdsLib<" + tname + ">::" + data.toLowerCase() + "(" + colqf + ")"; + } + else if (data.equals("sum")) + { // String collname = "Set"; + // if (isOrdered()) { collname = "Sequence"; } + Type sumtype = objectRef.getElementType(); + String tname = sumtype.getCPP(); // int, double only + if (tname.equals("string")) + { return "UmlRsdsLib<" + tname + ">::sumString(" + pre + ")"; } + return "UmlRsdsLib<" + tname + ">::sum(" + pre + ")"; + } + else if (data.equals("prd")) + { // String collname = "Set"; + // if (isOrdered()) { collname = "Sequence"; } + Type sumtype = objectRef.getElementType(); + String tname = sumtype.getCPP(); // int, double only + return "UmlRsdsLib<" + tname + ">::prd(" + pre + ")"; + } + else if (data.equals("reverse") || data.equals("sort") || + data.equals("asSet") || data.equals("characters")) + { return "UmlRsdsLib<" + cetype + ">::" + data + "(" + pre + ")"; } + else if (data.equals("subrange") && parameters != null && parameters.size() >= 2) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + if ("Integer".equals(objectRef + "")) + { return "UmlRsdsLib::integerSubrange(" + par1 + "," + par2 + ")"; } + return "UmlRsdsLib<" + cetype + ">::subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("subrange") && parameters != null && parameters.size() == 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + UnaryExpression ue = new UnaryExpression("->size", objectRef); + ue.setType(new Type("int", null)); + String par2 = ue.queryFormCPP(env,local); + return "UmlRsdsLib<" + cetype + ">::subrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("excludingSubrange") && + parameters != null && parameters.size() > 1) + { String par1 = + ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = + ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib<" + cetype + ">::excludingSubrange(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("indexOf") && parameters != null && parameters.size() > 0) // for strings or sequences + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + Type oreftype = objectRef.getType(); + if ("String".equals(oreftype.getName())) + { return "UmlRsdsLib::indexOf(" + par1 + ", " + pre + ")"; } + else // a sequence + { return "UmlRsdsLib<" + cetype + ">::indexOf(" + par1 + ", " + pre + ")"; } + } + else if (data.equals("pow") && parameters != null && parameters.size() > 0) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + return "pow(" + pre + ", " + par1 + ")"; + } + else if (data.equals("closure")) + { String rel = ((BasicExpression) objectRef).data; + Expression arg = ((BasicExpression) objectRef).objectRef; + if (objectRef.entity != null) + { ename = objectRef.entity.getName(); } + if (arg != null) + { return "UmlRsdsLib<" + cetype + ">::closure" + ename + + rel + "(" + arg.queryFormCPP(env,local) + ")"; + } + return "UmlRsdsLib<" + cetype + ">::closure" + ename + rel + "(" + pre + ")"; + } + else if (data.equals("insertAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib<" + cetype + ">::insertAt(" + pre + "," + par1 + "," + par2 + ")"; + // ".add(" + par1 + ", " + par2 + ")"; + } + else if (data.equals("setAt") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib<" + cetype + ">::setAt(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAll") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib::replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceAllMatches") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib::replaceAll(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replaceFirstMatch") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib::replaceFirstMatch(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("replace") && parameters != null && parameters.size() > 1) + { String par1 = ((Expression) parameters.get(0)).queryFormCPP(env,local); + String par2 = ((Expression) parameters.get(1)).queryFormCPP(env,local); + return "UmlRsdsLib::replace(" + pre + "," + par1 + "," + par2 + ")"; + } + else if (data.equals("count")) // for strings or collections + { if (parameters == null || parameters.size() > 0) + { String par1 = + ((Expression) parameters.get(0)).queryFormCPP(env,local); + return "UmlRsdsLib<" + cetype + ">::count(" + pre + "," + par1 + ")"; + } + } + else if (objectRef != null && (objectRef.getType() + "").equals("String")) + { // last,first,front,tail on strings + if (data.equals("first") || data.equals("any")) + { return pre + ".substr(0,1)"; } + if (data.equals("last")) + { return pre + ".substr(" + pre + ".length()-1, 1)"; } + if (data.equals("front")) + { return pre + ".substr(0," + pre + ".length()-1)"; } + if (data.equals("tail")) + { return pre + ".substr(1," + pre + ".length()-1)"; } + } + else if (data.equals("max") || data.equals("min")) + { return "UmlRsdsLib<" + cetype + ">::" + data + "(" + pre + ")"; } + else if (data.equals("any") || data.equals("last") || data.equals("first")) + { return "UmlRsdsLib<" + cetype + ">::" + data + "(" + pre + ")"; } + else // sum, prd, front tail on sequences, subcollections + // -- separate versions for numbers & objects? + { return "UmlRsdsLib<" + cetype + ">::" + data + "(" + pre + ")"; } + } // and s.count(x) in Java + + if (umlkind == QUERY || umlkind == UPDATEOP) + { String res = data + "("; + String parString = parametersQueryFormCPP(env,local); + + if (entity != null) + { ename = entity.getName(); } + + if (entity != null && entity.isExternalApplication()) + { res = ename + "::" + cont + res + parString; + return res; + } + + if (entity != null && data.startsWith("create") && + objectRef == null) + { if (data.substring(6).equals(ename)) + { return cont + res + parString; } + } + + BehaviouralFeature bf = null; + + if (entity != null) + { ename = entity.getName(); + bf = entity.getDefinedOperation(data); + } + + if (bf != null && bf.isGeneric()) + { String tpars = + Type.resolveTypeParametersCPP( + bf.getTypeParameters(), + bf.getParameters(), parameters); + res = data + tpars + "("; + } + + + if (entity != null && entity.isClassScope(data)) + { res = ename + "::" + res + parString; + return res; + } + else if (objectRef != null) + { String pre = objectRef.queryFormCPP(env,local); + + if ("super".equals(objectRef + "")) + { res = pre + "::" + res + parString; + return res; + } + + if (objectRef.umlkind == CLASSID) + { pre = ((BasicExpression) objectRef).classExtentQueryFormCPP(env,local); } + + if (objectRef.isMultiple()) // iterate, assume parameters.size() > 0 + { if (parameters == null || parameters.size() == 0) + { res = " " + cont + "All" + ename + data + "(" + pre + ")"; } + else + { res = " " + cont + "All" + ename + data + "(" + pre + "," + parString; } + } + else + { if (downcast) + { pre = "((" + ename + "*) " + pre + ")"; } + res = pre + "->" + res + parString; + } + return res; + } + + String var = findEntityVariable(env); + if (var != null && var.length() > 0) + { return var + "->" + res + parString; } + else + { return res + parString; } + } // may also be an arrayIndex + + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String etype = elementType + ""; + String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified()) + { return "((*" + data + ")[" + ind + "])"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified ones + if (type.getName().equals("String")) + { return data + ".substr(" + indopt + ", 1)"; } + else + { return "((*" + data + ")[" + indopt + "])"; } + } + return data; + } + + if (entity == null) { return data; } + + String nme = entity.getName(); + + if (entity.isClassScope(data)) + { if (arrayIndex != null) + { String etype = type.getCPP(elementType); + String ind = arrayIndex.queryFormCPP(env,local); + + String indopt = evaluateString("-",ind,"1"); // not for qualified + if (type.getName().equals("String")) + { return nme + "::" + data + ".substr(" + indopt + ", 1)"; } + return "(" + nme + "::" + data + "->at(" + indopt + "))"; + } + return nme + "::" + data; + } + + + String var = findEntityVariable(env); + + String res = var + "->get" + data + "()"; + if (var == null || var.length() == 0) + { res = data; } + + if (arrayIndex != null) + { String etype = type.getCPP(elementType); + String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified()) + { return "((*(" + res + "))[" + ind + "])"; } + + String indopt = evaluateString("-",ind,"1"); // not for qualified + if (type.getName().equals("String")) + { return data + ".substr(" + indopt + ", 1)"; } + return "(" + res + "->at(" + indopt + "))"; + } // not for strings + return res; + } // valid but unecesary for static attributes + } + else if (entity != null) // objectRef != null + { ename = entity.getName(); + String res = ""; + String pre = objectRef.queryFormCPP(env,local); + Entity eref = objectRef.getEntity(); // Could be subclass of entity of data + String cast = ""; + + if (objectRef.umlkind == CLASSID) + { Expression refindex = ((BasicExpression) objectRef).arrayIndex; + if (refindex != null) + { if (refindex.isMultiple()) + { if (objectRef.isOrdered()) + { cast = "(vector<" + ename + "*>*) "; } + else + { cast = "(set<" + ename + "*>*) "; } + + res = ename + "::getAll" + data + "(" + cast + pre + ")"; + } // E[inds].data + else + { res = pre + "->get" + data + "()"; } // E[ind].data + } + else if (entity.isClassScope(data)) + { res = pre + "::get" + data + "()"; } // E.data + else + { pre = cont + "get" + ename.toLowerCase() + "_s()"; + res = ename + "::getAll" + data + "(" + pre + ")"; + } + } + else if ("super".equals(objectRef + "")) + { res = pre + "::" + res; + return res; + } + else if (objectRef.isMultiple()) + { if (objectRef.isOrdered()) + { cast = "(vector<" + ename + "*>*) "; } + else + { cast = "(set<" + ename + "*>*) "; } + + if (isOrdered()) + { res = ename + "::getAllOrdered" + data + "(" + cast + pre + ")"; } + else + { res = ename + "::getAll" + data + "(" + cast + pre + ")"; } + } + else + { if (downcast) + { pre = "((" + ename + "*) " + pre + ")"; } + if (entity != null && entity.isClassScope(data)) + { res = pre + "::get" + data + "()"; } + else + { res = pre + "->get" + data + "()"; } + } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified()) + { return "(" + res + "->at(" + ind + "))"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified, Strings + if (type.getName().equals("String")) + { return res + ".substr(" + indopt + ", 1)"; } + return "(" + res + "->at(" + indopt + "))"; + } + return res; + } // version with array? obj.r[i] for each obj: objs? + return data; + } + + public Statement generateDesign(java.util.Map env, boolean local) + { // if multiple objectRef: for (v : objectRef) { v.data(pars) } + // otherwise objectRef.data(pars) + // objs.isDeleted is a call KillAllE(objs) + + if (isEvent || umlkind == Expression.UPDATEOP) // an operation of entity + { if (entity != null) + { BehaviouralFeature bf = entity.getDefinedOperation(data); + if (bf != null && bf.isStatic()) + { InvocationStatement res = new InvocationStatement(this); + return res; + } + } + + if (objectRef != null && objectRef.isMultiple()) + { String v = Identifier.nextIdentifier("v_"); + BasicExpression ve = new BasicExpression(v); + ve.setType(objectRef.getElementType()); + ve.umlkind = Expression.VARIABLE; + BinaryExpression test = new BinaryExpression(":", ve, objectRef); + BasicExpression invokee = (BasicExpression) clone(); + invokee.setObjectRef(ve); + InvocationStatement invoke = new InvocationStatement(invokee); + WhileStatement lp = new WhileStatement(test, invoke); + lp.setLoopKind(Statement.FOR); + lp.setLoopRange(ve,objectRef); + // lp.setLoopTest(test); + return lp; + } + InvocationStatement res = new InvocationStatement(this); + return res; + } + + if (umlkind == Expression.FUNCTION && data.equals("isDeleted")) + { if (objectRef.umlkind == Expression.CLASSID && (objectRef instanceof BasicExpression) && + ((BasicExpression) objectRef).arrayIndex == null) + { BasicExpression killset = new BasicExpression("allInstances"); + killset.setObjectRef(objectRef); + killset.setType(objectRef.getType()); + killset.setElementType(objectRef.getElementType()); + BasicExpression killop = new BasicExpression("killAll" + ((BasicExpression) objectRef).data); + killop.umlkind = Expression.UPDATEOP; + killop.addParameter(killset); + // killop.setStatic(true); + return new InvocationStatement(killop); + } // Could be abstract class + String eename = objectRef.type.getName(); + Entity ent = null; + String all = ""; + String opname = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + ent = objectRef.elementType.entity; + } + else + { ent = objectRef.type.entity; } + + if (ent.isAbstract()) + { opname = "killAbstract" + eename; } + else + { opname = "kill" + all + eename; } + BasicExpression killop = new BasicExpression(opname); + killop.umlkind = Expression.UPDATEOP; + killop.addParameter(objectRef); + return new InvocationStatement(killop); + } + else + { return new SequenceStatement(); } + } + + public Statement generateDesign(java.util.Map env, + String operator, + Expression rhs, boolean local) + { if (operator.equals("=")) + { return generateDesignEq(rhs); } + else if (operator.equals(":")) + { return generateDesignIn(rhs); } + /* else if (operator.equals("/:")) + { return generateDesignNotIn(rhs); } + else if (operator.equals("<:")) + { return generateDesignSubset(rhs); } + else if (operator.equals("-")) + { return generateDesignSubtract(rhs); } */ + else + { return new SequenceStatement(); } + } + +public Statement generateDesignEq(Expression rhs) +{ if (objectRef == null) + { return new AssignStatement(this, rhs); } + else if (objectRef.isMultiple()) + { BasicExpression lhs = (BasicExpression) clone(); + String v = Identifier.nextIdentifier("v_"); + BasicExpression var = new BasicExpression(v, objectRef); + lhs.setObjectRef(var); // will change typing/multiplicity + AssignStatement update = new AssignStatement(lhs, rhs); + Statement lp = Expression.iterationLoop(var, objectRef, update); + return lp; + } + else + { return new AssignStatement(this, rhs); } +} + + public Statement generateDesignIn(Expression rhs) + { // for rhs : lhs, same as + // lhs := lhs->including(rhs) + + if (umlkind == CLASSID && arrayIndex == null) + { CreationStatement cs = new CreationStatement(data, rhs + ""); + cs.setInstanceType(type); + cs.setElementType(type); + return cs; + } + else if (objectRef == null) + { BinaryExpression inclu = new BinaryExpression("->including", this, rhs); + return new AssignStatement(this, inclu); + } + else if (objectRef.isMultiple()) + { BasicExpression lhs = (BasicExpression) clone(); + String v = Identifier.nextIdentifier("v_"); + BasicExpression var = new BasicExpression(v, objectRef); + lhs.setObjectRef(var); // will change typing/multiplicity + BinaryExpression inclu = new BinaryExpression("->including", lhs, rhs); + AssignStatement update = new AssignStatement(lhs, inclu); + Statement lp = Expression.iterationLoop(var, objectRef, update); + return lp; + } + else if (multiplicity == ModelElement.ZEROONE) + { Expression sizeiszero = new UnaryExpression("->isEmpty", this); + SequenceStatement skip = new SequenceStatement(); + SetExpression sett = new SetExpression(); + sett.addElement(rhs); + AssignStatement setthis = new AssignStatement(this, sett); + return new ConditionalStatement(sizeiszero, setthis, skip); + } + else + { BinaryExpression inclu = new BinaryExpression("->including", this, rhs); + return new AssignStatement(this, inclu); + } +} + + +public Statement generateDesignNotIn(Expression rhs) +{ // for rhs /: lhs, same as + // lhs := lhs->excluding(rhs) + + if (objectRef == null) + { BinaryExpression exclu = new BinaryExpression("->excluding", this, rhs); + return new AssignStatement(this, exclu); } + else if (objectRef.isMultiple()) + { BasicExpression lhs = (BasicExpression) clone(); + String v = Identifier.nextIdentifier("v_"); + BasicExpression var = new BasicExpression(v, objectRef); + lhs.setObjectRef(var); // will change typing/multiplicity + BinaryExpression exclu = new BinaryExpression("->excluding", lhs, rhs); + AssignStatement update = new AssignStatement(lhs, exclu); + Statement lp = iterationLoop(var, objectRef, update); + return lp; + } + else + { BinaryExpression exclu = new BinaryExpression("->excluding", this, rhs); + return new AssignStatement(this, exclu); } +} + +public Statement generateDesignSubset(Expression rhs) +{ // for rhs <: lhs, same as + // lhs := lhs->union(rhs) + + if (objectRef == null) + { BinaryExpression inclu = new BinaryExpression("->union", this, rhs); + return new AssignStatement(this, inclu); } + else if (objectRef.isMultiple()) + { BasicExpression lhs = (BasicExpression) clone(); + String v = Identifier.nextIdentifier("v_"); + BasicExpression var = new BasicExpression(v, objectRef); + lhs.setObjectRef(var); // will change typing/multiplicity + BinaryExpression inclu = new BinaryExpression("->union", lhs, rhs); + AssignStatement update = new AssignStatement(lhs, inclu); + Statement lp = iterationLoop(var, objectRef, update); + return lp; + } + else + { BinaryExpression inclu = new BinaryExpression("->union", this, rhs); + return new AssignStatement(this, inclu); } +} + +public Statement generateDesignSubtract(Expression rhs) +{ // for rhs /<: lhs, same as + // lhs := lhs - rhs + + if (objectRef == null) + { BinaryExpression inclu = new BinaryExpression("-", this, rhs); + return new AssignStatement(this, inclu); } + else if (objectRef.isMultiple()) + { BasicExpression lhs = (BasicExpression) clone(); + String v = Identifier.nextIdentifier("v_"); + BasicExpression var = new BasicExpression(v, objectRef); + lhs.setObjectRef(var); // will change typing/multiplicity + BinaryExpression inclu = new BinaryExpression("-", lhs, rhs); + AssignStatement update = new AssignStatement(lhs, inclu); + Statement lp = iterationLoop(var, objectRef, update); + return lp; + } + else + { BinaryExpression inclu = new BinaryExpression("-", this, rhs); + return new AssignStatement(this, inclu); } +} + + + + public String updateForm(java.util.Map env, boolean local) + { String pars = "(" + parametersQueryForm(env,local); + String cont = "Controller.inst()"; + + if (isEvent) // an operation of entity + { + if (entity == null) + { System.err.println("WARNING: No defined entity for operation: " + this); + System.err.println("Assuming it is a global operation (use case, library op, etc)"); + + if (objectRef == null) + { return cont + "." + data + pars + ";"; } + else + { String preref = objectRef.queryForm(env,local); + return preref + "." + data + pars + ";"; + } + } + + String ename = entity.getName(); + + if (objectRef == null) + { if (entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + if (entity.isClassScope(data)) + { return ename + "." + data + pars + ";"; } + if (local) + { return data + pars + ";"; } + + String var = findEntityVariable(env); + return var + "." + data + pars + ";"; + } + else if (objectRef.umlkind == CLASSID && entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + else if (objectRef.umlkind == CLASSID && + entity.isClassScope(data)) // || entity.hasStereotype("external"))) // E.op() + { return ename + "." + data + pars + ";"; } + else if ("self".equals(objectRef + "")) // if (env.containsValue("self")) then just "self" + { return "this." + data + pars + ";"; } + else if (local || "super".equals(objectRef + "")) + { String pre = objectRef.queryForm(env,local); + return pre + "." + data + pars + ";"; + } + else if (objectRef.isMultiple()) + { String pre = objectRef.queryForm(env,local); + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression oref = (BasicExpression) objectRef; + if (oref.arrayIndex == null) + { ename = oref.data; // pre; + pre = cont + "." + ename.toLowerCase() + "s"; + } + } + else if (objectRef.elementType != null && objectRef.elementType.isEntity()) + { Type et = objectRef.elementType; + Entity ent = et.getEntity(); + if (ent != null) + { ename = ent.getName(); } + } + String var = ename.toLowerCase() + data + "x"; + String ind = Identifier.nextIdentifier(var + "_ind"); + String call; + if (local) + { call = " ((" + ename + ") " + var + ".get(" + ind + "))." + data + pars; } + else + { call = cont + "." + + data + "((" + ename + ") " + var + ".get(" + ind + ")"; + if (parameters != null && parameters.size() > 0) + { call = call + ","; } + call = call + + pars.substring(1,pars.length()); + } + return " List " + var + " = new Vector();\n" + + " " + var + ".addAll(" + pre + ");\n" + + " for (int " + ind + " = 0; " + ind + " < " + var + ".size(); " + + ind + "++)\n" + + " { " + call + "; }\n"; + } + else // for !(objectRef.isMultiple()) + { String pre = objectRef.queryForm(env,local); + String ss = cont + "." + data + "(" + pre; + if (parameters != null && parameters.size() > 0) + { ss = ss + ","; } + return ss + pars.substring(1,pars.length()) + ";"; + } + } + else if (umlkind == FUNCTION && data.equals("isDeleted")) + { String pre = objectRef.queryForm(env,local); + Type otype = objectRef.type; + if (otype == null) + { System.err.println("!! ERROR: no type for " + objectRef); + return ""; + } + String eename = otype.getName(); + String all = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + } + return cont + ".kill" + all + eename + "(" + pre + ");"; + } + else + { return "{} /* No update form for: " + this + " */"; } + // Controller.inst()." + data + pars + ";"; } + // no sensible update form?; + } + // and similarly for B? + + public String deltaUpdateForm(java.util.Map env, boolean local) + { String pars = "(" + parametersQueryForm(env,local); + String cont = "Controller.inst()"; + + if (isEvent) // an operation of entity + { + if (entity == null) + { System.err.println("! WARNING: No defined entity for operation: " + this); + System.err.println("! Assuming it is a global operation (use case, library op, etc)"); + + if (objectRef == null) + { return cont + "." + data + pars + ";"; } + else + { String preref = objectRef.queryForm(env,local); + return preref + "." + data + pars + ";"; + } + } + + String ename = entity.getName(); + + if (objectRef == null) + { if (entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + if (entity.isClassScope(data)) + { return ename + "." + data + pars + ";"; } + if (local) + { return data + pars + ";"; } + + String var = findEntityVariable(env); + return var + "." + data + pars + ";"; + } + else if (objectRef.umlkind == CLASSID && entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + else if (objectRef.umlkind == CLASSID && + entity.isClassScope(data)) // || entity.hasStereotype("external"))) // E.op() + { return ename + "." + data + pars + ";"; } + else if ("self".equals(objectRef + "")) + { return "this." + data + pars + ";"; } + else if (local || "super".equals(objectRef + "") || + entity.isComponent()) + { String pre = objectRef.queryForm(env,local); + return pre + "." + data + pars + ";"; + } + else if (objectRef.isMultiple()) + { String pre = objectRef.queryForm(env,local); + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression oref = (BasicExpression) objectRef; + if (oref.arrayIndex == null) + { ename = oref.data; // pre; + pre = cont + "." + ename.toLowerCase() + "s"; + } + } + else if (objectRef.elementType != null && objectRef.elementType.isEntity()) + { Type et = objectRef.elementType; + Entity ent = et.getEntity(); + if (ent != null) + { ename = ent.getName(); } + } + String var = ename.toLowerCase() + data + "x"; + String ind = Identifier.nextIdentifier(var + "_ind"); + String call; + if (local) + { call = " ((" + ename + ") " + var + ".get(" + ind + "))." + data + pars; } + else + { call = cont + "." + + data + "((" + ename + ") " + var + ".get(" + ind + ")"; + if (parameters != null && parameters.size() > 0) + { call = call + ","; } + call = call + + pars.substring(1,pars.length()); + } + return " List " + var + " = new Vector();\n" + + " " + var + ".addAll(_newobjs);\n" + + " " + var + ".addAll(_modobjs);\n" + + " for (int " + ind + " = 0; " + ind + " < " + var + ".size(); " + + ind + "++)\n" + + " { if (" + var + ".get(" + ind + ") instanceof " + ename + ")\n" + + " { " + call + "; }\n" + + " }\n"; + } + else // for !(objectRef.isMultiple()) + { String pre = objectRef.queryForm(env,local); + String ss = cont + "." + data + "(" + pre; + if (parameters != null && parameters.size() > 0) + { ss = ss + ","; } + return ss + pars.substring(1,pars.length()) + ";"; + } + } + else if (umlkind == FUNCTION && data.equals("isDeleted")) + { String pre = objectRef.queryForm(env,local); + Type otype = objectRef.type; + if (otype == null) + { System.err.println("!! ERROR: no type for " + objectRef); + return ""; + } + String eename = otype.getName(); + String all = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + } + return cont + ".kill" + all + eename + "(" + pre + ");"; + } + else + { return "{}"; } // Controller.inst()." + data + pars + ";"; } + // no sensible update form?; + } + + public String updateFormJava6(java.util.Map env, boolean local) + { String pars = "(" + parametersQueryFormJava6(env,local); + String cont = "Controller.inst()"; + + if (isEvent) // an operation of entity + { + if (entity == null) + { System.err.println("! WARNING: No defined entity for operation: " + this); + System.err.println("! Assuming it is a global operation (use case, library op, etc)"); + + if (objectRef == null) + { return cont + "." + data + pars + ";"; } + else + { String preref = objectRef.queryFormJava6(env,local); + return preref + "." + data + pars + ";"; + } + } + + String ename = entity.getName(); + + if (objectRef == null) + { if (entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + if (entity.isClassScope(data)) + { return ename + "." + data + pars + ";"; } + if (local) + { return data + pars + ";"; } + + String var = findEntityVariable(env); + return var + "." + data + pars + ";"; + } + else if (objectRef.umlkind == CLASSID && entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + else if (objectRef.umlkind == CLASSID && entity.isClassScope(data)) // E.op() + { return ename + "." + data + pars + ";"; } + else if ("self".equals(objectRef + "")) + { return "this." + data + pars + ";"; } + else if (local || "super".equals(objectRef + "") || + entity.isComponent()) + { String pre = objectRef.queryFormJava6(env,local); + return pre + "." + data + pars + ";"; + } + else if (objectRef.isMultiple()) + { String pre = objectRef.queryFormJava6(env,local); + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression oref = (BasicExpression) objectRef; + if (oref.arrayIndex == null) + { ename = oref.data; // pre; + pre = cont + "." + ename.toLowerCase() + "s"; + } + } + else if (objectRef.elementType != null && objectRef.elementType.isEntity()) + { Type et = objectRef.elementType; + Entity ent = et.getEntity(); + if (ent != null) + { ename = ent.getName(); } + } + String var = ename.toLowerCase() + data + "x"; + String ind = Identifier.nextIdentifier(var + "_ind"); + String call; + if (local) + { call = " ((" + ename + ") " + var + ".get(" + ind + "))." + data + pars; } + else + { call = cont + "." + + data + "((" + ename + ") " + var + ".get(" + ind + ")"; + if (parameters != null && parameters.size() > 0) + { call = call + ","; } + call = call + + pars.substring(1,pars.length()); + } + return " ArrayList " + var + " = new ArrayList();\n" + + " " + var + ".addAll(" + pre + ");\n" + + " for (int " + ind + " = 0; " + ind + " < " + var + ".size(); " + + ind + "++)\n" + + " { " + call + "; }\n"; + } + else // for !(objectRef.isMultiple()) + { String pre = objectRef.queryFormJava6(env,local); + String ss = cont + "." + data + "(" + pre; + if (parameters != null && parameters.size() > 0) + { ss = ss + ","; } + return ss + pars.substring(1,pars.length()) + ";"; + } + } + else if (umlkind == FUNCTION && data.equals("isDeleted")) + { String pre = objectRef.queryFormJava6(env,local); + Type otype = objectRef.type; + if (otype == null) + { System.err.println("!! ERROR: no type for " + objectRef); + return ""; + } + String eename = otype.getName(); + String all = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + } + return cont + ".kill" + all + eename + "(" + pre + ");"; + } + else + { return "{} /* No update form for: " + this + " */"; } + // Controller.inst()." + data + pars + ";"; } + // no sensible update form?; + } + // and similarly for B? + + public String updateFormJava7(java.util.Map env, boolean local) + { String pars = "(" + parametersQueryFormJava7(env,local); + String cont = "Controller.inst()"; + + if (isEvent) // an operation of entity + { + if (entity == null) + { System.err.println("!! WARNING: No defined entity for operation: " + this); + System.err.println("!! Assuming it is a global operation (use case, library op, etc)"); + + if (objectRef == null) + { return cont + "." + data + pars + ";"; } + else + { String preref = objectRef.queryFormJava7(env,local); + return preref + "." + data + pars + ";"; + } + } + + String ename = entity.getName(); + + if (objectRef == null) + { if (entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + if (entity.isClassScope(data)) + { return ename + "." + data + pars + ";"; } + if (local) + { return data + pars + ";"; } + + String var = findEntityVariable(env); + return var + "." + data + pars + ";"; + } + else if (objectRef.umlkind == CLASSID && entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + else if (objectRef.umlkind == CLASSID && entity.isClassScope(data)) // E.op() + { return ename + "." + data + pars + ";"; } + else if ("self".equals(objectRef + "")) + { return "this." + data + pars + ";"; } + else if (local || "super".equals(objectRef + "") || + entity.isComponent()) + { String pre = objectRef.queryFormJava7(env,local); + return pre + "." + data + pars + ";"; + } + else if (objectRef.isMultiple()) + { String pre = objectRef.queryFormJava7(env,local); + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression oref = (BasicExpression) objectRef; + if (oref.arrayIndex == null) + { ename = oref.data; // pre; + pre = cont + "." + ename.toLowerCase() + "s"; + } + } + else if (objectRef.elementType != null && objectRef.elementType.isEntity()) + { Type et = objectRef.elementType; + Entity ent = et.getEntity(); + if (ent != null) + { ename = ent.getName(); } + } + String var = ename.toLowerCase() + data + "x"; + String ind = Identifier.nextIdentifier(var + "_ind"); + String call; + if (local) + { call = " ((" + ename + ") " + var + ".get(" + ind + "))." + data + pars; } + else + { call = cont + "." + + data + "((" + ename + ") " + var + ".get(" + ind + ")"; + if (parameters != null && parameters.size() > 0) + { call = call + ","; } + call = call + + pars.substring(1,pars.length()); + } + return " ArrayList<" + ename + "> " + var + " = new ArrayList<" + ename + ">();\n" + + " " + var + ".addAll(" + pre + ");\n" + + " for (int " + ind + " = 0; " + ind + " < " + var + ".size(); " + + ind + "++)\n" + + " { " + call + "; }\n"; + } + else // for !(objectRef.isMultiple()) + { String pre = objectRef.queryFormJava7(env,local); + String ss = cont + "." + data + "(" + pre; + if (parameters != null && parameters.size() > 0) + { ss = ss + ","; } + return ss + pars.substring(1,pars.length()) + ";"; + } + } + else if (umlkind == FUNCTION && data.equals("isDeleted")) + { String pre = objectRef.queryFormJava7(env,local); + Type otype = objectRef.type; + if (otype == null) + { System.err.println("!! ERROR: no type for " + objectRef); + return ""; + } + String eename = otype.getName(); + String all = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + } + return cont + ".kill" + all + eename + "(" + pre + ");"; + } + else + { return ""; } + // Controller.inst()." + data + pars + ";"; } + // no sensible update form?; + } + + + public String updateFormCSharp(java.util.Map env, boolean local) + { String pars = "(" + parametersQueryFormCSharp(env,local); + String cont = "Controller.inst()"; + + if ("printStackTrace".equals(data) && objectRef != null && + Type.isOclExceptionType(objectRef)) + { String rqf = objectRef.queryFormCSharp(env,local); + return "Console.WriteLine(" + rqf + ".StackTrace);"; + } + + // Update form: + /* if ("setTime".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclDate")) + { if (parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + String par1qf = par1.queryFormCSharp(env,local); + String rqf = objectRef.queryFormCSharp(env,local); + + return " " + rqf + + " = DateTimeOffset.FromUnixTimeMilliseconds(" + par1qf + ").DateTime;"; + } + } + } */ + + if (data.startsWith("create") && objectRef == null) + { String entname = data.substring(6); + System.out.println(">>> Creation operation for " + entname); + + // Entity entx = (Entity) ModelElement.lookupByName(entname,entities); + if (entity != null && entity.getName().equals(entname)) + { return cont + "." + data + pars + ";"; } + } + + + if (isEvent) // an operation of entity + { + if (entity == null) + { System.err.println("!! WARNING: No defined entity for operation: " + this); + System.err.println("!! Assuming it is a global operation (use case, library op, etc)"); + + if (objectRef == null) + { return cont + "." + data + pars + ";"; } + else + { String preref = objectRef.queryFormCSharp(env,local); + return preref + "." + data + pars + ";"; + } + } + + String ename = entity.getName(); + + if (objectRef == null) + { if (entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + if (entity.isClassScope(data)) + { return ename + "." + data + pars + ";"; } + + if (local) + { return data + pars + ";"; } + + String var = findEntityVariable(env); + return var + "." + data + pars + ";"; + } + else if (objectRef.umlkind == CLASSID && + entity.isExternalApplication()) + { return ename + "." + cont + "." + data + pars + ";"; } + else if (objectRef.umlkind == CLASSID && + entity.isClassScope(data)) // E.op() + { return ename + "." + data + pars + ";"; } + else if ("self".equals(objectRef + "")) + { return "this." + data + pars + ";"; } + else if (local || "super".equals(objectRef + "") || + entity.isComponent()) + { String pre = objectRef.queryFormCSharp(env,local); // base? + return pre + "." + data + pars + ";"; + } + else if (objectRef.isMultiple()) + { String pre = objectRef.queryFormCSharp(env,local); + if (objectRef.umlkind == CLASSID && + (objectRef instanceof BasicExpression)) + { BasicExpression oref = (BasicExpression) objectRef; + if (oref.arrayIndex == null) + { ename = oref.data; // pre; + pre = cont + ".get" + ename.toLowerCase() + "_s()"; + } + } + else if (objectRef.elementType != null && + objectRef.elementType.isEntity()) + { Type et = objectRef.elementType; + Entity ent = et.getEntity(); + if (ent != null) + { ename = ent.getName(); } + } + String var = ename.toLowerCase() + data + "x"; + String ind = Identifier.nextIdentifier(var + "_ind"); + String call; + if (local) + { call = " ((" + ename + ") " + var + "[" + ind + "])." + data + pars; } + else + { call = cont + "." + + data + "((" + ename + ") " + var + "[" + ind + "]"; + if (parameters != null && parameters.size() > 0) + { call = call + ","; } + call = call + + pars.substring(1,pars.length()); + } + return " ArrayList " + var + " = new ArrayList();\n" + + " " + var + ".AddRange(" + pre + ");\n" + + " for (int " + ind + " = 0; " + ind + " < " + var + ".Count; " + + ind + "++)\n" + + " { " + call + "; }\n"; + } + else // for !(objectRef.isMultiple()) + { String pre = objectRef.queryFormCSharp(env,local); + String ss = cont + "." + data + "(" + pre; + if (parameters != null && parameters.size() > 0) + { ss = ss + ","; } + return ss + pars.substring(1,pars.length()) + ";"; + } + } + else if (umlkind == FUNCTION && data.equals("isDeleted")) + { String pre = objectRef.queryFormCSharp(env,local); + Type otype = objectRef.type; + if (otype == null) + { System.err.println("!! ERROR: no type for " + objectRef); + return ""; + } + String eename = otype.getName(); + String all = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + } + return cont + ".kill" + all + eename + "(" + pre + ");"; + } + else + { return "{} /* No update form for: " + this + " */"; } + // Controller.inst()." + data + pars + ";"; } + // no sensible update form?; + } + // and similarly for B? + + public String updateFormCPP(java.util.Map env, boolean local) + { String pars = "(" + parametersQueryFormCPP(env,local); + String cont = "Controller::inst->"; + + if ("printStackTrace".equals(data) && objectRef != null && + Type.isOclExceptionType(objectRef)) + { String rqf = objectRef.queryFormCPP(env,local); + return "cerr << " + rqf + ".what() << endl;"; + } + + if (data.startsWith("create") && objectRef == null) + { String entname = data.substring(6); + System.out.println(">>> Creation operation for " + entname); + + // Entity entx = (Entity) ModelElement.lookupByName(entname,entities); + if (entity != null && entity.getName().equals(entname)) + { return cont + data + pars + ";"; } + } + + if ("delete".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclFile")) + { return objectRef.queryFormCPP(env,local) + + "->deleteFile();"; + } + } + + if ("printf".equals(data) && objectRef != null) + { if (objectRef.type != null && + objectRef.type.getName().equals("OclFile") && + parameters != null && + parameters.size() > 1 && + parameters.get(1) instanceof SetExpression) + { Expression format = (Expression) parameters.get(0); + Expression sq = (Expression) parameters.get(1); + String p1 = format.queryFormCPP(env,local); + String cseq = + ((SetExpression) sq).toCSequence(env,local); + return objectRef.queryFormCPP(env,local) + + "->printf(" + p1 + "," + cseq + ");"; + } + } + + + if (isEvent) // an operation of entity + { + if (entity == null) + { System.err.println("Warning!: No defined entity for: " + this); + if (objectRef == null) + { return cont + data + pars + ";"; } + else + { String preref = objectRef.queryFormCPP(env,local); + return preref + "->" + data + pars + ";"; + } + } + + String ename = entity.getName(); + + if (objectRef == null) + { if (entity.isExternalApplication()) + { return ename + "::" + cont + data + pars + ";"; } + if (entity.isClassScope(data)) + { return ename + "::" + data + pars + ";"; } + if (local) + { return data + pars + ";"; } + + String var = findEntityVariable(env); + return var + "->" + data + pars + ";"; + } + else if ("super".equals(objectRef + "")) + { String pre = objectRef.queryFormCPP(env,local); + String res = pre + "::" + data + pars + ";"; + return res; + } + else if (objectRef.umlkind == CLASSID && entity.isExternalApplication()) + { return ename + "::" + cont + data + pars + ";"; } + else if (objectRef.umlkind == CLASSID && entity.isClassScope(data)) // E.op() + { return ename + "::" + data + pars + ";"; } + else if ("self".equals(objectRef + "")) + { return "this->" + data + pars + ";"; } + else if (local || + entity.isComponent()) + { String pre = objectRef.queryFormCPP(env,local); // base? + return pre + "->" + data + pars + ";"; + } + else if (objectRef.isMultiple()) + { String pre = objectRef.queryFormCPP(env,local); + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression oref = (BasicExpression) objectRef; + if (oref.arrayIndex == null) + { ename = oref.data; // pre; + pre = cont + "get" + ename.toLowerCase() + "_s()"; + } + } + else if (objectRef.elementType != null && objectRef.elementType.isEntity()) + { Type et = objectRef.elementType; + Entity ent = et.getEntity(); + if (ent != null) + { ename = ent.getName(); } + } + String var = ename.toLowerCase() + data + "x"; + String ind = Identifier.nextIdentifier(var + "_ind"); + String call; + if (local) + { call = " ((*" + var + ")[" + ind + "])->" + data + pars; } + else + { call = cont + + data + "((*" + var + ")[" + ind + "]"; + if (parameters != null && parameters.size() > 0) + { call = call + ","; } + call = call + + pars.substring(1,pars.length()); + } + return " vector<" + ename + "*>* " + var + " = new vector<" + ename + "*>();\n" + + " " + var + "->insert(" + var + "->end(), " + pre + "->begin(), " + + pre + "->end());\n" + + " for (int " + ind + " = 0; " + ind + " < " + var + "->size(); " + + ind + "++)\n" + + " { " + call + "; }\n"; + } + else // for !(objectRef.isMultiple()) + { String pre = objectRef.queryFormCPP(env,local); + String ss = cont + data + "(" + pre; + if (parameters != null && parameters.size() > 0) + { ss = ss + ","; } + return ss + pars.substring(1,pars.length()) + ";"; + } + } + else if (umlkind == FUNCTION && data.equals("isDeleted")) + { String pre = objectRef.queryFormCPP(env,local); + Type otype = objectRef.type; + if (otype == null) + { System.err.println("!! ERROR: no type for " + objectRef); + return ""; + } + String eename = otype.getName(); + String all = ""; + if (objectRef.isMultiple()) + { all = "All"; + eename = objectRef.elementType.getName(); + } + return cont + "kill" + all + eename + "(" + pre + ");"; + } + else + { return "{} /* Update form for: " + this + " */"; } + // Controller.inst()." + data + pars + ";"; } + // no sensible update form?; + } + // and similarly for B? + + public String updateForm(java.util.Map env, + String operator, + String val2, Expression exp2, boolean local) + { if (operator.equals("=")) + { return updateFormEq(env,val2,exp2,local); } + else if (operator.equals(":")) + { return updateFormIn(env,val2,local); } + else if (operator.equals("/:")) + { return updateFormNotin(env,val2,exp2,local); } + else if (operator.equals("<:")) + { return updateFormSubset(env,val2,local); } + else if (operator.equals("-")) + { return updateFormSubtract(env,val2,exp2,local); } + else if (operator.equals("/<:")) + { return updateFormSubtract(env,val2,exp2,local); } + else + { return "{} /* invalid update to " + this + " by " + operator + " with " + val2 + " */"; } + } + + public String updateFormJava6(java.util.Map env, + String operator, + String val2, Expression exp2, boolean local) + { if (operator.equals("=")) + { return updateFormEqJava6(env,val2,exp2,local); } + else if (operator.equals(":")) + { return updateFormInJava6(env,val2,local); } + else if (operator.equals("/:")) + { return updateFormNotinJava6(env,val2,exp2,local); } + else if (operator.equals("<:")) + { return updateFormSubsetJava6(env,val2,local); } + else if (operator.equals("-")) + { return updateFormSubtractJava6(env,val2,exp2,local); } + else if (operator.equals("/<:")) + { return updateFormSubtractJava6(env,val2,exp2,local); } + else + { return "{} /* invalid update to " + this + " by " + operator + " with " + val2 + " */"; } + } + + public String updateFormJava7(java.util.Map env, + String operator, + String val2, Expression exp2, boolean local) + { if (operator.equals("=")) + { return updateFormEqJava7(env,val2,exp2,local); } + else if (operator.equals(":")) + { return updateFormInJava7(env,val2,local); } + else if (operator.equals("/:")) + { return updateFormNotinJava7(env,val2,exp2,local); } + else if (operator.equals("<:")) + { return updateFormSubsetJava7(env,val2,local); } + else if (operator.equals("-")) + { return updateFormSubtractJava7(env,val2,exp2,local); } + else if (operator.equals("/<:")) + { return updateFormSubtractJava7(env,val2,exp2,local); } + else + { return "{} /* invalid update to " + this + " by " + operator + " with " + val2 + " */"; } + } + + public String updateFormCSharp(java.util.Map env, + String operator, + String val2, Expression exp2, boolean local) + { if (operator.equals("=")) + { return updateFormEqCSharp(env,val2,exp2,local); } + else if (operator.equals(":")) + { return updateFormInCSharp(env,val2,local); } + else if (operator.equals("/:")) + { return updateFormNotinCSharp(env,val2,exp2,local); } + else if (operator.equals("<:")) + { return updateFormSubsetCSharp(env,val2,local); } + else if (operator.equals("-")) + { return updateFormSubtractCSharp(env,val2,exp2,local); } + else if (operator.equals("/<:")) + { return updateFormSubtractCSharp(env,val2,exp2,local); } + else + { return "{} /* invalid update to " + this + " by " + operator + " with " + val2 + " */"; } + } + + public String updateFormCPP(java.util.Map env, + String operator, + String val2, Expression exp2, boolean local) + { if (operator.equals("=")) + { return updateFormEqCPP(env,val2,local); } + else if (operator.equals(":")) + { return updateFormInCPP(env,val2,local); } + else if (operator.equals("/:")) + { return updateFormNotinCPP(env,val2,exp2,local); } + else if (operator.equals("<:")) + { return updateFormSubsetCPP(env,val2,local); } + else if (operator.equals("-")) + { return updateFormSubtractCPP(env,val2,exp2,local); } + else if (operator.equals("/<:")) + { return updateFormSubtractCPP(env,val2,exp2,local); } + else + { return "{} /* invalid update to " + this + " by " + operator + " with " + val2 + " */"; } + } + + public static String updateFormEqIndex(String lang, Expression obj, Expression ind, + String val2, Expression var, java.util.Map env, boolean local) + { if ("Java4".equals(lang)) + { return updateFormEqIndex(obj,ind,val2,var,env,local); } + else if ("Java6".equals(lang)) + { return updateFormEqIndexJava6(obj,ind,val2,var,env,local); } + else if ("Java7".equals(lang)) + { return updateFormEqIndexJava7(obj,ind,val2,var,env,local); } + else if ("CSharp".equals(lang)) + { return updateFormEqIndexCSharp(obj,ind,val2,var,env,local); } + else if ("CPP".equals(lang)) + { return updateFormEqIndexCPP(obj,ind,val2,var,env,local); } + else + { return "/* Unsupported language for x->at(y) := z */"; } + } + + public static String updateFormEqIndex(Expression obj, Expression ind, + String val2, Expression var, java.util.Map env, boolean local) + { // obj[ind] = val2 where obj is complex expression, + // either a sequence, ref or map, or + // itself an indexed expression + + Type objt = obj.getType(); + if (objt == null) + { return "/* No type for: " + obj + " */"; } + + Type objet = objt.getElementType(); + + if (ind != null) + { String indopt = ind.queryForm(env,local); + String lexp = obj.queryForm(env,local); + String wind = ind.wrap(indopt); + String wval = var.wrap(val2); + + if (ind.type != null && + "String".equals(ind.type.getName())) + { return "((Map) " + lexp + ").put(" + wind + ", " + wval + ");"; } // map[ind] = val2 + else if (obj.isRef()) + { return lexp + "[" + indopt + " -1] = " + val2 + ";"; } + else if (Type.isSequenceType(objet) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // obj[ind] := + // MatrixLib.singleValueMatrix( + // Sequence{obj[ind]->size()}, var) + + Expression col = + new BinaryExpression("->at", obj, ind); + + SetExpression setexpr = + new SetExpression(true); + Expression uex = new UnaryExpression("->size", col); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "(new SystemTypes.Set().add( " + + uex.queryForm(env,local) + " )).getElements()"; + + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + BasicExpression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "Set", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + + return + BasicExpression.updateFormEqIndex(obj,ind, + "Set.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, env, local); + } + else + { return "((Vector) " + lexp + ").set((" + indopt + " -1), " + wval + ");"; } + } + return "/* Error: null index */"; + } + + public static String updateFormEqIndexJava6(Expression obj, Expression ind, + String val2, Expression var, java.util.Map env, boolean local) + { // obj[ind] = val2 where obj is complex expression, + // either a sequence or map, or + // itself an indexed expression + + Type objt = obj.getType(); + if (objt == null) + { return "/* No type for: " + obj + " */"; } + + Type objet = objt.getElementType(); + + if (ind != null) + { String indopt = ind.queryFormJava6(env,local); + String lexp = obj.queryFormJava6(env,local); + String wind = ind.wrapJava6(indopt); + String wval = var.wrapJava6(val2); + + if (ind.type != null && "String".equals(ind.type.getName())) + { return "((HashMap) " + lexp + ").put(" + wind + ", " + wval + ");"; } // map[ind] = val2 + else if (obj.isRef()) + { return lexp + "[" + indopt + " -1] = " + val2 + ";"; } + else if (Type.isSequenceType(objet) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // obj[ind] := + // MatrixLib.singleValueMatrix( + // Sequence{obj[ind]->size()}, var) + + Expression col = + new BinaryExpression("->at", obj, ind); + + SetExpression setexpr = + new SetExpression(true); + Expression uex = new UnaryExpression("->size", col); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "Set.addSequence(new ArrayList(), " + + uex.queryFormJava6(env,local) + " )"; + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + BasicExpression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "Set", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + return + BasicExpression.updateFormEqIndexJava6(obj,ind, + "Set.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, env, local); + } + else + { return "((ArrayList) " + lexp + ").set((" + indopt + " -1), " + wval + ");"; } + } + return "/* Error: null index */"; + } + + public static String updateFormEqIndexJava7(Expression obj, Expression ind, + String val2, Expression var, java.util.Map env, boolean local) + { // obj[ind] = val2 where obj is complex expression, + // either a sequence or map, or + // itself an indexed expression + + JOptionPane.showInputDialog( + ">>> Update to " + obj + "[" + ind + + "] := " + val2); + + Type objt = obj.getType(); + if (objt == null) + { return "/* No type for: " + obj + " */"; } + + Type objet = objt.getElementType(); + String j7type = objt.getJava7(objet); + + if (ind != null) + { String indopt = ind.queryFormJava7(env,local); + String lexp = obj.queryFormJava7(env,local); + String wind = ind.wrap(indopt); + String wval = var.wrap(val2); + + if (objt.isMapType()) + { return "((" + j7type + ") " + lexp + ").put(" + wind + ", " + wval + ");"; } // map[ind] = val2 + else if (obj.isRef()) + { return lexp + "[" + indopt + " -1] = " + val2 + ";"; } + else if (Type.isSequenceType(objet) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // obj[ind] := + // MatrixLib.singleValueMatrix( + // Sequence{obj[ind]->size()}, var) + + Expression col = + new BinaryExpression("->at", obj, ind); + + SetExpression setexpr = + new SetExpression(true); + Expression uex = new UnaryExpression("->size", col); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "Ocl.addSequence(new ArrayList(), " + uex + ")"; + // String setocl = + // "(new SystemTypes.Set().add( " + + // uex.queryForm(env,local) + " )).getElements()"; + + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + BasicExpression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "Ocl", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + + return + BasicExpression.updateFormEqIndexJava7(obj,ind, + "Ocl.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, env, local); + } + else if (obj instanceof BasicExpression) + { Vector pars = new Vector(); + // setatpars.add(obj); + pars.add(ind); + pars.add(var); + Expression setatexpr = + BasicExpression.newFunctionBasicExpression("setAt", + obj,pars); + + return ((BasicExpression) obj).updateFormEqJava7(env, + "Ocl.setAt(" + lexp + ", " + indopt + ", " + wval + ")", + setatexpr, local); + } + else + { return "(" + lexp + ").set(" + indopt + " -1, " + val2 + ");"; } + } + + return "/* Error: null index */"; + } + // obj.updateFormEqJava7(env, String val2, Expression var, boolean local) + + public static String updateFormEqIndexCSharp(Expression obj, Expression ind, + String val2, Expression var, java.util.Map env, boolean local) + { // obj[ind] = val2 where obj is complex expression, + // either a sequence, reference or map, or + // itself an indexed expression + + Type objt = obj.getType(); + if (objt == null) + { return "/* No type for: " + obj + " */"; } + + Type objet = objt.getElementType(); + + if (ind != null) + { String indopt = ind.queryFormCSharp(env,local); + String lexp = obj.queryFormCSharp(env,local); + String wind = ind.wrapCSharp(indopt); + String wval = var.wrapCSharp(val2); + + if (ind.type != null && + "String".equals(ind.type.getName())) + { return "((Hashtable) " + lexp + ")[" + wind + "] = " + wval + ";"; } // map[ind] = val2 + else if (Type.isReferenceType(obj.type)) + { return lexp + "[" + indopt + "-1] = " + val2 + ";"; } + else if (Type.isSequenceType(objet) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // obj[ind] := + // MatrixLib.singleValueMatrix( + // Sequence{obj[ind]->size()}, var) + + Expression col = + new BinaryExpression("->at", obj, ind); + + SetExpression setexpr = + new SetExpression(true); + Expression uex = new UnaryExpression("->size", col); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "SystemTypes.addSet(new ArrayList(), " + + uex.queryFormCSharp(env,local) + " )"; + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + BasicExpression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "SystemTypes", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + return + BasicExpression.updateFormEqIndexCSharp(obj,ind, + "SystemTypes.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, env, local); + } + else + { return "((ArrayList) " + lexp + ")[" + indopt + " -1] = " + wval + ";"; } + } + return "/* Error: null index */"; + } + + public static String updateFormEqIndexCPP(Expression obj, Expression ind, + String val2, Expression var, java.util.Map env, boolean local) + { // (*obj)[ind] = val2 where obj is complex expression, + // either a sequence or map, or + // itself an indexed expression + + + if (ind != null) + { String indopt = ind.queryFormCPP(env,local); + String lexp = obj.queryFormCPP(env,local); + String wind = indopt; + String wval = var.queryFormCPP(env,local); + + if (ind.type != null && "String".equals(ind.type.getName())) + { return "(*" + lexp + ")[" + indopt + "] = " + wval + ";"; } + else if (obj.isRef()) + { return "(" + lexp + ")[" + indopt + " -1] = " + wval + ";"; } + else + { return "(*" + lexp + ")[" + indopt + " -1] = " + wval + ";"; } + } + + return "/* Error: null index in " + obj + "[index] := " + val2 + " */"; + } + + public String updateFormEq(java.util.Map env, + String val2, Expression var, boolean local) + { String cont = "Controller.inst()"; + + // System.out.println("^^^^^^^^^ Assignment " + this + " " + val2); + // System.out.println("^^^^^^^^^ Assignment " + umlkind + " " + objectRef); + + String datax = data; + if (objectRef != null) + { datax = objectRef.queryForm(env,local) + "." + data; } + // queryFormCPP ?? + + if (Type.isSequenceType(type) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // this := + // MatrixLib.singleValueMatrix( + // Sequence{this->size()}, var) + + SetExpression setexpr = + new SetExpression(true); + + Expression uex = new UnaryExpression("->size", this); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "(new SystemTypes.Set().add( " + + uex.queryForm(env,local) + " )).getElements()"; + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + Expression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "Set", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + return + this.updateFormEq(env, + "Set.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, local); + } + + + if ("subrange".equals(data) && parameters != null && + objectRef != null && + objectRef instanceof BasicExpression) + { // obj.subrange(a,b) := val2 for strings is same as + // obj := obj.subrange(1,a-1) + val2 + obj.subrange(b+1) + + Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + + Vector pars1 = new Vector(); + pars1.add(new BasicExpression(1)); + pars1.add(new BinaryExpression("-", par1, + new BasicExpression(1))); + + Expression rng1 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, pars1); + rng1.setType(objectRef.getType()); + rng1.setElementType(objectRef.getElementType()); + + + Expression rng2 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, + new BinaryExpression("+", par2, + new BasicExpression(1))); + rng2.setType(objectRef.getType()); + rng2.setElementType(objectRef.getElementType()); + + if (type != null && "String".equals(type.getName())) + { // objx := objx.subrange(1,par1x-1) + val2 + + // objx.subrange(par2x+1) + + Expression newvar = + new BinaryExpression("+", rng1, + new BinaryExpression("+", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryForm(env,local); + + return + ((BasicExpression) objectRef).updateFormEq( + env,newval2,newvar,local); + } + else if (type != null && + "Sequence".equals(type.getName())) + { // objx := objx.subrange(0,par1x-1) ^ val2 ^ + // objx.subrange(par2x + 1) + + Expression newvar = + new BinaryExpression("->union", rng1, + new BinaryExpression("->union", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryForm(env,local); + + return + ((BasicExpression) objectRef).updateFormEq( + env,newval2,newvar,local); + } + } + + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't assign to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (val2.equals("{}") || val2.equals("Set{}") || val2.equals("Sequence{}")) // delete the class extent + { String datas = classExtentQueryForm(env,local); + return "List _" + data + " = new Vector(); \n" + + " _" + data + ".addAll(" + datas + "); \n" + + " " + cont + ".killAll" + data + "(_" + data + ");\n"; + } + else + { return "{} /* can't assign to: " + data + " */"; } + } + + if (umlkind == VARIABLE) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + String wind = arrayIndex.wrap(indopt); + String wval = var.wrap(val2); + if ((arrayIndex.type != null && + "String".equals(arrayIndex.type.getName())) || + BasicExpression.isMapAccess(this)) + { return datax + ".put(" + wind + ", " + wval + ");"; } + // map[index] = val2 + else + { return datax + ".set((" + indopt + " -1), " + wval + ");"; } + } + return datax + " = " + val2 + ";"; + } + + String nme = ""; + if (entity != null) + { nme = entity.getName(); + if (entity.isBidirectionalRole(data)) + { local = false; } + } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + String wval = var.wrap(val2); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return data + ".put(" + ind + ", " + wval + ");"; } // for maps + return data + ".set((" + ind + " - 1), " + wval + ");"; + } + return data + " = " + val2 + ";"; + } + + if (entity != null && entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + String wval = var.wrap(val2); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return data + ".put(" + indopt + ", " + wval + ");"; } // for maps + return nme + ".set" + data + "((" + indopt + " -1), " + wval + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array index + + String varx = findEntityVariable(env); + + String target = ""; + if (varx != null && varx.equals("this")) + { System.err.println("!! WARNING: using self with non-local update " + this); + target = varx + ","; + } + else if (varx != null) + { target = varx + ","; } + + // data is a feature of the entity, non-local consequences of the update + if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cont + ".set" + data + "(" + target + ind + ", " + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified + return cont + ".set" + data + "(" + target + indopt + "," + val2 + ");"; + } + return cont + ".set" + data + "(" + target + val2 + ");"; + } // Really cont + ".set" ... in each case + } + else // objectRef != null + { String pre = objectRef.queryForm(env,local); + + if (objectRef instanceof UnaryExpression && + "!".equals(((UnaryExpression) objectRef).operator)) + { // !x.data := val is setdata(x[0],val) + + return cont + ".set" + data + "(" + pre + ", " + + val2 + ");"; + } + + if (entity.isClassScope(data)) + { if (arrayIndex != null) + { String ind1 = arrayIndex.queryForm(env,local); + String indopt = evaluateString("-",ind1,"1"); + return nme + ".set" + data + "(" + indopt + ", " + val2 + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // C[inds].data = val2 + { return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; } + else // C[ind].data = val2 + { return cont + ".set" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".setAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { // objectRef.umlkind != CLASSID + String cref = nme; + if (entity != null && entity.isInterface()) + { cref = nme + "." + nme + "Ops"; } + + { if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + if (isQualified()) + { return cref + ".setAll" + data + "(" + pre + "," + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return cref + ".setAll" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; + } + } + else // not objectRef.isMultiple() + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return pre + ".set" + data + "(" + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return pre + ".set" + data + "(" + indopt + "," + val2 + ");"; + } + return pre + ".set" + data + "(" + val2 + ");"; + } + else if (arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cont + ".set" + data + "(" + pre + "," + ind + "," + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); + return cont + ".set" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return cont + ".set" + data + "(" + pre + "," + val2 + ");"; + } + } + return "{} /* unrecognised update: " + this + " = " + val2 + " */"; + } // arrayIndex != null: setdata(var,arrayIndex,val) ? + + public String updateFormEqJava6(java.util.Map env, + String val2, Expression var, boolean local) + { String cont = "Controller.inst()"; + + // System.out.println("#### " + this + " := " + val2); + + if (Type.isSequenceType(type) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // this := + // MatrixLib.singleValueMatrix( + // Sequence{this->size()}, var) + + SetExpression setexpr = + new SetExpression(true); + + Expression uex = new UnaryExpression("->size", this); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "Set.addSequence(new ArrayList(), " + + uex.queryFormJava6(env,local) + " )"; + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + Expression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "Set", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + return + this.updateFormEqJava6(env, + "Set.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, local); + } + + + if ("subrange".equals(data) && parameters != null && + objectRef != null && + objectRef instanceof BasicExpression) + { // obj.subrange(a,b) := val2 for strings is same as + // obj := obj.subrange(1,a-1) + val2 + obj.subrange(b+1) + + Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + + Vector pars1 = new Vector(); + pars1.add(new BasicExpression(1)); + pars1.add(new BinaryExpression("-", par1, + new BasicExpression(1))); + + Expression rng1 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, pars1); + rng1.setType(objectRef.getType()); + rng1.setElementType(objectRef.getElementType()); + + + Expression rng2 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, + new BinaryExpression("+", par2, + new BasicExpression(1))); + rng2.setType(objectRef.getType()); + rng2.setElementType(objectRef.getElementType()); + + if (type != null && "String".equals(type.getName())) + { // objx := objx.subrange(1,par1x-1) + val2 + + // objx.subrange(par2x+1) + + Expression newvar = + new BinaryExpression("+", rng1, + new BinaryExpression("+", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryFormJava6(env,local); + + return + ((BasicExpression) objectRef).updateFormEqJava6( + env,newval2,newvar,local); + } + else if (type != null && + "Sequence".equals(type.getName())) + { // objx := objx.subrange(0,par1x-1) ^ val2 ^ + // objx.subrange(par2x + 1) + + Expression newvar = + new BinaryExpression("->union", rng1, + new BinaryExpression("->union", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryFormJava6(env,local); + + return + ((BasicExpression) objectRef).updateFormEqJava6( + env,newval2,newvar,local); + } + } + + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't assign to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (val2.equals("{}") || val2.equals("Set{}") || val2.equals("Sequence{}")) // delete the class extent + { String datas = classExtentQueryFormJava6(env,local); + return "ArrayList _" + data + " = new ArrayList(); \n" + + " _" + data + ".addAll(" + datas + "); \n" + + " " + cont + ".killAll" + data + "(_" + data + ");\n"; + } + else + { return "{} /* can't assign to: " + this + " */"; } + } + + if (umlkind == VARIABLE) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + String wind = arrayIndex.wrapJava6(indopt); + String wval = var.wrapJava6(val2); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return data + ".put(" + wind + ", " + wval + ");"; } // map[index] = val2 + else + { return data + ".set((" + indopt + " -1), " + wval + ");"; } + } + return data + " = " + val2 + ";"; + } // and map case. wrap val2 + + String nme = entity.getName(); + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + String wind = arrayIndex.wrapJava6(ind); + String wval = var.wrapJava6(val2); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return data + ".put(" + wind + ", " + wval + ");"; } + return data + ".set((" + ind + " - 1)," + wval + ");"; + } + return data + " = " + val2 + ";"; + } + + if (entity != null && entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = + arrayIndex.queryFormJava6(env,local); + // String wind = arrayIndex.wrapJava6(ind); + String wval = var.wrapJava6(val2); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return data + ".put(" + indopt + ", " + wval + ");"; } // for maps + return nme + ".set" + data + "((" + indopt + " -1), " + wval + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array + + String varx = findEntityVariable(env); + + String target = ""; + if (varx.equals("this")) + { System.err.println("!! WARNING: using self with non-local update " + this); + target = varx + ","; + } + else + { target = varx + ","; } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cont + ".set" + data + "(" + target + ind + ", " + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified + return cont + ".set" + data + "(" + target + indopt + "," + val2 + ");"; + } + return cont + ".set" + data + "(" + target + val2 + ");"; + } // Really cont + ".set" ... in each case + } + else // objectRef != null + { String pre = objectRef.queryFormJava6(env,local); + + if (objectRef instanceof UnaryExpression && + "!".equals(((UnaryExpression) objectRef).operator)) + { // !x.data := val is setdata(x[0],val) + + return cont + ".set" + data + "(" + pre + ", " + + val2 + ");"; + } + + if (entity != null && entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + String wval = var.wrapJava6(val2); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return nme + "." + data + ".put(" + indopt + ", " + wval + ");"; } // for maps + return nme + ".set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // C[inds].data = val2 + { return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; } + else // C[ind].data = val2 + { return cont + ".set" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".setAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { // objectRef.umlkind != CLASSID + String cref = nme; + if (entity.isInterface()) + { cref = nme + "." + nme + "Ops"; } + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cref + ".setAll" + data + "(" + pre + "," + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return cref + ".setAll" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; + } + else // not objectRef.isMultiple() + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return pre + ".set" + data + "(" + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return pre + ".set" + data + "(" + indopt + "," + val2 + ");"; + } + return cont + ".set" + data + "(" + pre + ", " + val2 + ");"; + } + else if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + if (isQualified()) + { return cont + ".set" + data + "(" + pre + "," + ind + "," + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); + return cont + ".set" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + // return cont + ".set" + data + "(" + pre + "," + val2 + ");"; + } + return cont + ".set" + data + "(" + pre + "," + val2 + ");"; + } + return "{} /* unrecognised update: " + this + " = " + val2 + " */"; + } // arrayIndex != null: setdata(var,arrayIndex,val) ? + + public String updateFormEqJava7(java.util.Map env, String val2, Expression var, boolean local) + { String cont = "Controller.inst()"; + + String datax = data; + if (objectRef != null) + { datax = objectRef.queryFormJava7(env,local) + "." + data; } + + if (Type.isSequenceType(type) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // this := + // MatrixLib.singleValueMatrix( + // Sequence{this->size()}, var) + + SetExpression setexpr = + new SetExpression(true); + + Expression uex = new UnaryExpression("->size", this); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "Ocl.addSequence(new ArrayList(), " + + uex.queryFormJava7(env,local) + ")"; + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + Expression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "Ocl", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + return + this.updateFormEqJava7(env, + "Ocl.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, local); + } + + + if ("subrange".equals(data) && parameters != null && + objectRef != null && + objectRef instanceof BasicExpression) + { // obj.subrange(a,b) := val2 for strings is same as + // obj := obj.subrange(1,a-1) + val2 + obj.subrange(b+1) + + Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + + Vector pars1 = new Vector(); + pars1.add(new BasicExpression(1)); + pars1.add(new BinaryExpression("-", par1, + new BasicExpression(1))); + + Expression rng1 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, pars1); + rng1.setType(objectRef.getType()); + rng1.setElementType(objectRef.getElementType()); + + + Expression rng2 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, + new BinaryExpression("+", par2, + new BasicExpression(1))); + rng2.setType(objectRef.getType()); + rng2.setElementType(objectRef.getElementType()); + + /* String objx = objectRef.queryFormJava7(env,local); + String lqf = ((BasicExpression) objectRef).leftQueryFormJava7(env,local); + String par1x = par1.queryFormJava7(env,local); + String par2x = par2.queryFormJava7(env,local); */ + + if (type != null && "String".equals(type.getName())) + { // objx := objx.subrange(1,par1x-1) + val2 + + // objx.subrange(par2x+1) + + Expression newvar = + new BinaryExpression("+", rng1, + new BinaryExpression("+", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryFormJava7(env,local); + + /* String res = lqf + " = (" + objx + ").substring(0," + par1x + "-1) + " + val2 + " + (" + objx + ").substring(" + par2x + ");\n"; + return res; */ + + return + ((BasicExpression) objectRef).updateFormEqJava7( + env,newval2,newvar,local); + } + else if (type != null && + "Sequence".equals(type.getName())) + { // objx := objx.subrange(0,par1x-1) ^ val2 ^ + // objx.subrange(par2x + 1) + + Expression newvar = + new BinaryExpression("->union", rng1, + new BinaryExpression("->union", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryFormJava7(env,local); + + return + ((BasicExpression) objectRef).updateFormEqJava7( + env,newval2,newvar,local); + } + } + + + // System.out.println("#### " + this + " := " + val2); + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't assign to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (val2.equals("{}") || + val2.equals("Set{}") || + val2.equals("Sequence{}")) // delete the class extent + { String datas = classExtentQueryFormJava7(env,local); + return "ArrayList<" + data + "> _" + data + " = new ArrayList<" + data + ">(); \n" + + " _" + data + ".addAll(" + datas + "); \n" + + " " + cont + ".killAll" + data + "(_" + data + ");\n"; + } + else + { return "{} /* can't assign to: " + this + " */"; } + } + + if (umlkind == VARIABLE) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + String wind = arrayIndex.wrap(indopt); + String wval = var.wrap(val2); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return data + ".put(" + wind + ", " + wval + ");"; } // map[index] = val2 + else + { wval = Type.convertDataValueJava7(val2, type, var.type); + return data + ".set((" + indopt + " -1), " + wval + ");"; + } + } + + + if (type != null && var.type == null) + { String cstype = type.getJava7(); + return datax + " = (" + cstype + ") (" + val2 + ");"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + datax + " = " + val2 + ";"; } + if ("String".equals(type.getName())) + { return " " + datax + " = \"\" + (" + val2 + ");"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + datax + " = Ocl.to" + cname + "(" + val2 + ");"; + } + + String cstype = type.getJava7(); + return " " + datax + " = (" + cstype + ") (" + val2 + ");"; + } + + return data + " = " + val2 + ";"; + } + + // String nme = entity.getName(); + if (entity != null && entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String wind = arrayIndex.wrap(ind); + String wval = + Type.convertDataValueJava7(val2, + type, var.type); + + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return data + ".put(" + wind + ", " + wval + ");"; } + return data + ".set((" + ind + " - 1)," + wval + ");"; + } + + if (type != null && var.type == null) + { String cstype = type.getJava7(); + return datax + " = (" + cstype + ") (" + val2 + ");"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + datax + " = " + val2 + ";"; } + if ("String".equals(type.getName())) + { return " " + datax + " = \"\" + (" + val2 + ");"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + datax + " = Ocl.to" + cname + "(" + val2 + ");"; + } + + String cstype = type.getJava7(); + return " " + datax + " = (" + cstype + ") (" + val2 + ");"; + } + + return data + " = " + val2 + ";"; + } + + if (entity != null && entity.isClassScope(data)) + { String nme = entity.getName(); + if (arrayIndex != null) + { String indopt = + arrayIndex.queryFormJava7(env,local); + // if ("String".equals(arrayIndex.type + "") || + // BasicExpression.isMapAccess(this)) + return nme + ".set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array + + String varx = findEntityVariable(env); + + String target = ""; + if (varx.equals("this")) + { System.err.println("!! WARNING: using self with non-local update " + this); + target = varx + ","; + } + else + { target = varx + ","; } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + String wval = + Type.convertDataValueJava7(val2, + type, var.type); + + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return cont + ".set" + data + "(" + target + ind + ", " + wval + ");"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified + return cont + ".set" + data + "(" + target + indopt + "," + wval + ");"; + } + + if (type != null && var.type == null) + { String cstype = type.getJava7(); + return cont + ".set" + data + "(" + target + " (" + cstype + ") (" + val2 + "));"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return cont + ".set" + data + "(" + target + val2 + ");"; } + if ("String".equals(type.getName())) + { return cont + ".set" + data + "(" + target + "\"\" + (" + val2 + "));"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return cont + ".set" + data + "(" + target + " Ocl.to" + cname + "(" + val2 + "));"; + } + String cstype = type.getJava7(); + return cont + ".set" + data + "(" + target + " (" + cstype + ") (" + val2 + "));"; + } + + return cont + ".set" + data + "(" + target + val2 + ");"; + } // Really cont + ".set" ... in each case + } + else // objectRef != null + { String pre = objectRef.queryFormJava7(env,local); + + if (entity != null && entity.isClassScope(data)) + { String nme = entity.getName(); + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return nme + ".set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // C[inds].data = val2 + { return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; } + else // C[ind].data = val2 + { return cont + ".set" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".setAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef instanceof UnaryExpression && + "!".equals(((UnaryExpression) objectRef).operator)) + { // !x.data := val is setdata(x[0],val) + + return cont + ".set" + data + "(" + pre + ", " + + val2 + ");"; + } + + if (entity != null && objectRef.isMultiple()) + { String nme = entity.getName(); + String cref = nme; + if (entity.isInterface()) + { cref = nme + "." + nme + "Ops"; } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified()) + { return cref + ".setAll" + data + "(" + pre + "," + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return cref + ".setAll" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return cref + ".setAll" + data + "(" + pre + ", " + val2 + ");"; + } + else // not objectRef.isMultiple() + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return pre + ".set" + data + "(" + ind + ", " + + val2 + ");"; + } + + String indopt = evaluateString("-",ind,"1"); + return pre + ".set" + data + "(" + indopt + ", " + val2 + ");"; + } + return pre + ".set" + data + "(" + val2 + ");"; + } + else if (arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this) + ) + { return cont + ".set" + data + "(" + pre + ", " + ind + ", " + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); + return cont + ".set" + data + "(" + pre + ", " + indopt + "," + + val2 + ");"; + } + + if (type != null && var.type == null) + { String cstype = type.getJava7(); + return cont + ".set" + data + "(" + pre + ", (" + cstype + ") (" + val2 + "));"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + cont + ".set" + data + "(" + pre + ", " + val2 + ");"; } + if ("String".equals(type.getName())) + { return " " + cont + ".set" + data + "(" + pre + ", \"\" + (" + val2 + "));"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + cont + ".set" + data + "(" + pre + ", Ocl.to" + cname + "(" + val2 + "));"; + } + String cstype = type.getJava7(); + return cont + ".set" + data + "(" + pre + ", (" + cstype + ") (" + val2 + "));"; + } + + return cont + ".set" + data + "(" + pre + ", " + val2 + ");"; + } + } + + return "{} /* unrecognised update: " + this + " = " + val2 + " */"; + } // arrayIndex != null: setdata(var,arrayIndex,val) ? + + public String updateFormEqCSharp(java.util.Map env, + String val2, Expression var, boolean local) + { String cont = "Controller.inst()"; + + // System.out.println(">>> Assignment " + this + " = " + val2); + + if (Type.isSequenceType(type) && + (var.isNumeric() || var.isString() || + var.isBoolean())) + { // this := + // MatrixLib.singleValueMatrix( + // Sequence{this->size()}, var) + + SetExpression setexpr = + new SetExpression(true); + + Expression uex = new UnaryExpression("->size", this); + uex.setType(new Type("int", null)); + setexpr.addElement(uex); + setexpr.setElementType(new Type("int", null)); + + String setocl = + "SystemTypes.addSet(new ArrayList(), " + + uex.queryFormCSharp(env,local) + " )"; + + Vector rangepars = new Vector(); + rangepars.add(setexpr); + rangepars.add(var); + + Expression scope = + BasicExpression.newStaticCallBasicExpression( + "singleValueMatrix", "SystemTypes", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(var.getType()); + scope.umlkind = QUERY; + + return + this.updateFormEqCSharp(env, + "SystemTypes.singleValueMatrix(" + setocl + ", " + val2 + ")", + scope, local); + } + + + + String datax = data; + + if (objectRef != null) + { datax = objectRef.queryFormCSharp(env,local) + "." + data; } + + if ("subrange".equals(data) && parameters != null && + objectRef != null && + objectRef instanceof BasicExpression) + { // obj.subrange(a,b) := val2 for strings is same as + // obj := obj.subrange(1,a-1) + val2 + obj.subrange(b+1) + + Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + + Vector pars1 = new Vector(); + pars1.add(new BasicExpression(1)); + pars1.add(new BinaryExpression("-", par1, + new BasicExpression(1))); + + Expression rng1 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, pars1); + rng1.setType(objectRef.getType()); + rng1.setElementType(objectRef.getElementType()); + + + Expression rng2 = + BasicExpression.newFunctionBasicExpression( + "subrange", objectRef, + new BinaryExpression("+", par2, + new BasicExpression(1))); + rng2.setType(objectRef.getType()); + rng2.setElementType(objectRef.getElementType()); + + /* String objx = objectRef.queryFormJava7(env,local); + String lqf = ((BasicExpression) objectRef).leftQueryFormJava7(env,local); + String par1x = par1.queryFormJava7(env,local); + String par2x = par2.queryFormJava7(env,local); */ + + if (type != null && "String".equals(type.getName())) + { // objx := objx.subrange(1,par1x-1) + val2 + + // objx.subrange(par2x+1) + + Expression newvar = + new BinaryExpression("+", rng1, + new BinaryExpression("+", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryFormCSharp(env,local); + + /* String res = lqf + " = (" + objx + ").substring(0," + par1x + "-1) + " + val2 + " + (" + objx + ").substring(" + par2x + ");\n"; + return res; */ + + return + ((BasicExpression) objectRef).updateFormEqCSharp( + env,newval2,newvar,local); + } + else if (type != null && + "Sequence".equals(type.getName())) + { // objx := objx.subrange(0,par1x-1) ^ val2 ^ + // objx.subrange(par2x + 1) + + Expression newvar = + new BinaryExpression("->union", rng1, + new BinaryExpression("->union", var, rng2)); + newvar.setType(objectRef.getType()); + newvar.setElementType(objectRef.getElementType()); + + String newval2 = newvar.queryFormCSharp(env,local); + + return + ((BasicExpression) objectRef).updateFormEqCSharp( + env,newval2,newvar,local); + } + } + + + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return " {} /* can't assign to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (val2.equals("{}") || val2.equals("Set{}") || val2.equals("Sequence{}")) // delete the class extent + { String datas = classExtentQueryFormCSharp(env,local); + return "ArrayList _" + data + " = new ArrayList(); \n" + + " _" + data + ".AddRange(" + datas + "); \n" + + " " + cont + ".killAll" + data + "(_" + data + ");\n"; + } + else + { return " {} /* can't assign to: " + data + " */"; } + } + + if (umlkind == VARIABLE) // assume objectRef == null + { // System.out.println(">>> Variable " + this); + + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + String wind = arrayIndex.wrapCSharp(indopt); + String wval = // var.wrapCSharp(val2); + Type.convertDataValueCSharp(val2, type, var.type); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return datax + "[" + wind + "] = " + wval + ";"; } // map[index] = val2 + else + { return datax + "[" + indopt + " -1] = " + wval + ";"; } + } + + if (type != null && var.type == null) + { String cstype = type.getCSharp(); + return datax + " = (" + cstype + ") (" + val2 + ");"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + datax + " = " + val2 + ";"; } + else if ("String".equals(type.getName())) + { return " " + datax + " = \"\" + (" + val2 + ");"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + datax + " = SystemTypes.to" + cname + "(" + val2 + ");"; + } + + String cstype = type.getCSharp(); + return " " + datax + " = (" + cstype + ") (" + val2 + ");"; + } + + return " " + datax + " = " + val2 + ";"; + } + + String nme = entity.getName(); + if (entity.isBidirectionalRole(data)) + { local = false; } + + // System.out.println(">>%%%%%%%%%%%%>> " + this + " objectref = " + objectRef + " " + data + " " + var + " " + val2); + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + String wind = arrayIndex.wrapCSharp(ind); + String wval = // var.wrapCSharp(val2); + Type.convertDataValueCSharp(val2, type, var.type); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return data + "[" + wind + "] = " + wval + ";"; } + return data + "[" + ind + " - 1] = " + val2 + ";"; + } + + if (type != null && var.type == null) + { String cstype = type.getCSharp(); + return data + " = (" + cstype + ") (" + val2 + ");"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return data + " = " + val2 + ";"; } + else if ("String".equals(type.getName())) + { return " " + datax + " = \"\" + (" + val2 + ");"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + datax + " = SystemTypes.to" + cname + "(" + val2 + ");"; + } + String cstype = type.getCSharp(); + return data + " = (" + cstype + ") (" + val2 + ");"; + } + + return data + " = " + val2 + ";"; + } + + if (entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return nme + ".set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array + + String varx = findEntityVariable(env); + + String target = ""; + if (varx.equals("this")) + { System.err.println("!! WARNING: using self with non-local update " + this); + target = varx + ","; + } + else + { target = varx + ","; } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + String wval = + Type.convertDataValueCSharp(val2, type, var.type); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return + // cont + ".set" + data + "(" + target + ind + ", " + val2 + ");"; + varx + ".set" + data + "(" + ind + ", " + wval + ");"; + } + String indopt = evaluateString("-",ind,"1"); // not for qualified + return cont + ".set" + data + "(" + target + indopt + "," + wval + ");"; + } + + if (type != null && var.type == null) + { String cstype = type.getCSharp(); + return cont + ".set" + data + "(" + target + " (" + cstype + ") (" + val2 + "));"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + cont + ".set" + data + "(" + target + val2 + ");"; } + else if ("String".equals(type.getName())) + { return " " + cont + ".set" + data + "(" + target + "\"\" + (" + val2 + "));"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + cont + ".set" + data + "(" + target + "SystemTypes.to" + cname + "(" + val2 + "));"; + } + String cstype = type.getCSharp(); + return " " + cont + ".set" + data + "(" + target + " (" + cstype + ") (" + val2 + "));"; + } + + return cont + ".set" + data + "(" + target + val2 + ");"; + } // Really cont + ".set" ... in each case + } + else // objectRef != null + { String pre = objectRef.queryFormCSharp(env,local); + + // System.out.println("**** Controller.inst().set" + data + "(" + pre + ", " + val2 + ")"); + + if (entity != null && entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = + arrayIndex.queryFormCSharp(env,local); + return nme + ".set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + ".set" + data + "(" + val2 + ");"; + } // and with array + + if (objectRef instanceof UnaryExpression && + "!".equals(((UnaryExpression) objectRef).operator)) + { return "(" + pre + ")." + data + " = " + val2 + ";"; } + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // C[inds].data = val2 + { return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; } + else // C[ind].data = val2 + { return cont + ".set" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "_s"; + return cref + ".setAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { String cref = nme; + if (entity != null && entity.isInterface()) + { cref = nme + "Ops"; } + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cref + ".setAll" + data + "(" + pre + "," + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return cref + ".setAll" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return cref + ".setAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + String wval = + Type.convertDataValueCSharp(val2, type, var.type); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return pre + ".set" + data + "(" + ind + "," + + wval + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return pre + ".set" + data + "(" + indopt + "," + wval + ");"; + } + return pre + ".set" + data + "(" + val2 + ");"; + } + else if (arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cont + ".set" + data + "(" + pre + "," + ind + "," + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); + return cont + ".set" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + + if (type != null && var.type == null) + { String cstype = type.getCSharp(); + return cont + ".set" + data + "(" + pre + ", (" + cstype + ") (" + val2 + "));"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + cont + ".set" + data + "(" + pre + ", " + val2 + ");"; } + else if ("String".equals(type.getName())) + { return " " + cont + ".set" + data + "(" + pre + ", \"\" + (" + val2 + "));"; } + else if ("String".equals(var.type.getName()) && + type.isNumeric()) + { String cname = Named.capitalise(type.getName()); + return " " + cont + ".set" + data + "(" + pre + ", SystemTypes.to" + cname + "(" + val2 + "));"; + } + String cstype = type.getCSharp(); + return cont + ".set" + data + "(" + pre + ", (" + cstype + ") (" + val2 + "));"; + } + + return cont + ".set" + data + "(" + pre + "," + val2 + ");"; + } + // return cont + ".set" + data + "(" + pre + "," + val2 + ");"; + } + + return " {} /* unrecognised update: " + this + " = " + val2 + " */"; + } // arrayIndex != null: setdata(var,arrayIndex,val) ? + + public String updateFormEqCPP(java.util.Map env, + String val2, boolean local) + { String cont = "Controller::inst->"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't assign to: " + data + " */"; } + + System.out.println("### Assignment: " + this + " := " + val2); + System.out.println("### " + this.umlkind + ", " + this.type); + + String datax = data; + if (objectRef != null) + { datax = objectRef.queryFormCPP(env,local) + "." + data; } + + String cetype = "void*"; + Type et = getElementType(); + if (et != null) + { cetype = et.getCPP(et.getElementType()); } + + if (umlkind == CLASSID && arrayIndex == null) + { if (val2.equals("{}") || val2.equals("Set{}") || val2.equals("Sequence{}")) // delete the class extent + { String datas = classExtentQueryFormCPP(env,local); + return "vector<" + cetype + ">* _" + data + " = new vector<" + cetype + ">(); \n" + + " _" + data + "->insert(_" + data + "->end(), " + datas + "->begin(), " + + datas + "->end()); \n" + + " " + cont + "killAll" + data + "(_" + data + ");\n"; + } + else + { return "{} /* can't assign to: " + data + " */"; } + } + + if (umlkind == VARIABLE) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + if ("String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return "(*" + datax + ")[" + indopt + "] = " + val2 + ";"; } // map[index] = val2 + else + { return "(*" + datax + ")[" + indopt + " -1] = " + val2 + ";"; } + } + + /* if (type != null && var.type == null) + { String cstype = type.getCPP(); + return datax + " = (" + cstype + ") (" + val2 + ");"; + } + else if (type != null && var.type != null) + { if (Type.isSpecialisedOrEqualType(var.type, type)) + { return " " + datax + " = " + val2 + ";"; } + String cstype = type.getCPP(); + return " " + datax + " = (" + cstype + ") (" + val2 + ");"; + } */ + + return datax + " = " + val2 + ";"; + } + + String nme = entity.getName(); + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return "(*" + data + ")[" + ind + "] = " + val2 + ";"; } + return "(*" + data + ")[" + ind + " - 1] = " + val2 + ";"; + } + return data + " = " + val2 + ";"; + } + + if (entity != null && entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + return nme + "::set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + "::set" + data + "(" + val2 + ");"; + } // and with array + + String var = findEntityVariable(env); + + String target = ""; + if (var.equals("this")) + { System.err.println("WARNING: using self with non-local update " + this); + target = var + ","; + } + else + { target = var + ","; } + + if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cont + "set" + data + "(" + target + ind + ", " + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); // not for qualified + return cont + "set" + data + "(" + target + indopt + "," + val2 + ");"; + } + return cont + "set" + data + "(" + target + val2 + ");"; + } // Really cont + ".set" ... in each case + } + else // objectRef != null + { String pre = objectRef.queryFormCPP(env,local); + + if (entity != null && entity.isClassScope(data)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + return nme + "::set" + data + "((" + indopt + " -1), " + val2 + ");"; + } + return nme + "::set" + data + "(" + val2 + ");"; + } // and with array + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // C[inds].data = val2 + { return cname + "::setAll" + data + "(" + pre + "," + val2 + ");"; } + else // C[ind].data = val2 + { return cont + "set" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "get" + cname.toLowerCase() + "_s()"; + return cname + "::setAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return nme + "::setAll" + data + "(" + pre + "," + ind + "," + + val2 + ");"; + } + String indopt = evaluateString("-",ind,"1"); + return nme + "::setAll" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return nme + "::setAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { if (local) + { if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return pre + "->set" + data + "(" + ind + "," + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); + return pre + "->set" + data + "(" + indopt + "," + val2 + ");"; + } + return pre + "->set" + data + "(" + val2 + ");"; + } + else if (arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + if (isQualified() || + "String".equals(arrayIndex.type + "") || + BasicExpression.isMapAccess(this)) + { return cont + "set" + data + "(" + pre + "," + ind + "," + val2 + ");"; } + String indopt = evaluateString("-",ind,"1"); + return cont + "set" + data + "(" + pre + "," + indopt + "," + + val2 + ");"; + } + return cont + "set" + data + "(" + pre + "," + val2 + ");"; + } + } + return "{} /* unrecognised update: " + this + " = " + val2 + " */"; + } // arrayIndex != null: setdata(var,arrayIndex,val) ? + + + private String updateFormIn(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + String nme = ""; + if (entity != null) + { nme = entity.getName(); } + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) // but no arrayIndex + { if (local && entity.hasFeature(val2)) // or is parameter of the op + { return val2 + " = new " + data + "();"; } + else if (entity.hasStereotype("external")) + { return data + " " + val2 + " = new " + data + "();"; } + else + { // return data + " " + val2 + " = Controller.inst().create" + data + "();"; + return data + " " + val2 + " = new " + data + "();\n " + + cont + ".add" + data + "(" + val2 + ");"; + } // also check completeness of post in such cases + } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).add(" + val2 + ");"; + } + return data + ".add(" + val2 + ");"; + } // wrap val2 + // case with arrayIndex: ((List) data.get(ind - 1)).add(val2) + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { return data + ".add(" + val2 + ");"; } + else + { return "{} /* can't add to single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + String qual = ""; + + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryForm(env,local) + ", "; + if (local) + { return var + ".add" + data + "(" + qual + val2 + ");"; } + else + { return cont + ".add" + data + "(" + var + "," + qual + val2 + ");"; } + } + + if (local) + { return data + ".add(" + val2 + ");"; } + // unordered and zero-one roles: check not in first + + return cont + ".add" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be an object + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryForm(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 : C[inds].data + { return cref + ".addAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 : C[ind].data + { return cont + ".add" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".addAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryForm(env,local) + ", "; } + + if (objectRef.isMultiple()) + { String cref = nme; + if (entity != null && entity.isInterface()) + { cref = nme + "." + nme + "Ops"; } + return cref + ".addAll" + data + "(" + pre + "," + qual + val2 + ");"; + } // use Set.union if unordered + else + { return cont + ".add" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised add: " + val2 + " : " + this + " */"; + } // Entity: generate unionAll etc ops + + private String updateFormInJava6(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + String nme = ""; + if (entity != null) + { nme = entity.getName(); } + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (local && entity.hasFeature(val2)) // or is parameter of the op + { return val2 + " = new " + data + "();"; } + else if (entity.hasStereotype("external")) + { return data + " " + val2 + " = new " + data + "();"; } + else + { // return data + " " + val2 + " = Controller.inst().create" + data + "();"; + return data + " " + val2 + " = new " + data + "();\n " + + cont + ".add" + data + "(" + val2 + ");"; + } // also check completeness of post in such cases + } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).add(" + val2 + ");"; + } + return data + ".add(" + val2 + ");"; + } // wrap val2 + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { return data + ".add(" + val2 + ");"; } + else + { return "{} /* can't add to single-valued attribute */"; } + } + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role */"; } + + String var = findEntityVariable(env); + String qual = ""; + + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormJava6(env,local) + ", "; + if (local) + { return var + ".add" + data + "(" + qual + val2 + ");"; } + else + { return cont + ".add" + data + "(" + var + "," + qual + val2 + ");"; } + } + + if (local) + { return data + ".add(" + val2 + ");"; } + // unordered roles: check not in first + + return cont + ".add" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be an object + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormJava6(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 : C[inds].data + { return cref + ".addAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 : C[ind].data + { return cont + ".add" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".addAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormJava6(env,local) + ", "; } + + if (objectRef.isMultiple()) + { String cref = nme; + if (entity != null && entity.isInterface()) + { cref = nme + "." + nme + "Ops"; } + return cref + ".addAll" + data + "(" + pre + "," + qual + val2 + ");"; + } // use Set.union if unordered + else + { return cont + ".add" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised add: " + val2 + " : " + this + " */"; + } // Entity: generate unionAll etc ops + + private String updateFormInJava7(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + String nme = ""; + if (entity != null) + { nme = entity.getName(); } + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (local && entity.hasFeature(val2)) // or is parameter of the op + { return val2 + " = new " + data + "();"; } + else if (entity.hasStereotype("external")) + { return data + " " + val2 + " = new " + data + "();"; } + else + { // return data + " " + val2 + " = Controller.inst().create" + data + "();"; + return data + " " + val2 + " = new " + data + "();\n " + + cont + ".add" + data + "(" + val2 + ");"; + } // also check completeness of post in such cases + } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + String j7type = elementType.getJava7(); + return "((" + j7type + ") " + data + ".get(" + indopt + " -1)).add(" + val2 + ");"; + } + return data + ".add(" + val2 + ");"; + } // wrap val2 + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { return data + ".add(" + val2 + ");"; } + else + { return "{} /* can't add to single-valued attribute */"; } + } + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role */"; } + + String var = findEntityVariable(env); + String qual = ""; + + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormJava7(env,local) + ", "; + if (local) + { return var + ".add" + data + "(" + qual + val2 + ");"; } + else + { return cont + ".add" + data + "(" + var + "," + qual + val2 + ");"; } + } + + if (local) + { return data + ".add(" + val2 + ");"; } + // unordered roles: check not in first + + return cont + ".add" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be an object + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormJava7(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 : C[inds].data + { return cref + ".addAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 : C[ind].data + { return cont + ".add" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".addAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormJava7(env,local) + ", "; } + + if (objectRef.isMultiple()) + { String cref = nme; + if (entity != null && entity.isInterface()) + { cref = nme + "." + nme + "Ops"; } + return cref + ".addAll" + data + "(" + pre + "," + qual + val2 + ");"; + } // use Set.union if unordered + else + { return cont + ".add" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised add: " + val2 + " : " + this + " */"; + } // Entity: generate unionAll etc ops + + private String updateFormInCSharp(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + String nme = ""; + if (entity != null) + { nme = entity.getName(); } + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (local && entity.hasFeature(val2)) // or is parameter of the op + { return val2 + " = new " + data + "();"; } + else if (entity.hasStereotype("external")) + { return data + " " + val2 + " = new " + data + "();"; } + else + { // return data + " " + val2 + " = Controller.inst().create" + data + "();"; + return data + " " + val2 + " = new " + data + "();\n " + + cont + ".add" + data + "(" + val2 + ");"; + } // also check completeness of post in such cases + } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return "((ArrayList) " + data + "[" + indopt + " -1]).Add(" + val2 + ");"; + } + return data + ".Add(" + val2 + ");"; + } // wrap val2 + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { return data + ".Add(" + val2 + ");"; } + else + { return "{} /* can't add to single-valued attribute */"; } + } + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + String qual = ""; + + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormCSharp(env,local) + ", "; + if (local) + { return var + ".add" + data + "(" + qual + val2 + ");"; } + else + { return cont + ".add" + data + "(" + var + "," + qual + val2 + ");"; } + } + + if (local) + { return data + ".Add(" + val2 + ");"; } + // unordered roles: check not in first + + return cont + ".add" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be an object + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormCSharp(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "Ops"; } + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 : C[inds].data + { return cref + ".addAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 : C[ind].data + { return cont + ".add" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "_s"; + return cref + ".addAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormCSharp(env,local) + ", "; } + + if (objectRef.isMultiple()) + { String cref = nme; + if (entity != null && entity.isInterface()) + { cref = nme + "Ops"; } + return cref + ".addAll" + data + "(" + pre + "," + qual + val2 + ");"; + } // use Set.union if unordered + else + { return cont + ".add" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised add: " + val2 + " : " + this + " */"; + } // Entity: generate unionAll etc ops + + private String updateFormInCPP(java.util.Map env, + String val2, boolean local) + { String cont = "Controller::inst->"; + + String nme = ""; + if (entity != null) + { nme = entity.getName(); } + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == CLASSID && arrayIndex == null) + { if (local && entity.hasFeature(val2)) // or is parameter of the op + { return val2 + " = new " + data + "();"; } + else if (entity.hasStereotype("external")) + { return data + "* " + val2 + " = new " + data + "();"; } + else + { return data + "* " + val2 + " = new " + data + "();\n " + + cont + "add" + data + "(" + val2 + ");"; + } // also check completeness of post in such cases + } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { String pre = data; + + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + pre = "((*" + data + ")[" + indopt + " -1])"; + } + + if (isOrdered() || isSequenceValued()) + { return "((vector) " + pre + ")->push_back(" + val2 + ");"; } + else + { return "((set) " + pre + ")->insert(" + val2 + ");"; } + } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (isOrdered() || isSequenceValued()) + { return data + "->push_back(" + val2 + ");"; } + else + { return data + "->insert(" + val2 + ");"; } + } + else + { return "{} /* can't add to single-valued attribute */"; } + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + String qual = ""; + + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormCPP(env,local) + ", "; + if (local) + { return var + "->add" + data + "(" + qual + val2 + ");"; } + else + { return cont + "add" + data + "(" + var + "," + qual + val2 + ");"; } + } + + if (local) + { if (isOrdered() || isSequenceValued()) + { return data + "->push_back(" + val2 + ");"; } + else + { return data + "->insert(" + val2 + ");"; } + } + return cont + "add" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be an object + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormCPP(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 : C[inds].data + { return cname + "::addAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 : C[ind].data + { return cont + "add" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "get" + cname.toLowerCase() + "_s()"; + return cname + "::addAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormCPP(env,local) + ", "; } + + if (objectRef.isMultiple()) + { return nme + "::addAll" + data + "(" + pre + "," + qual + val2 + ");"; } + // use Set.union if unordered -- implement addAll this way (Entity.java) + else + { return cont + "add" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised add: " + val2 + " : " + this + " */"; + } // Entity: generate unionAll etc ops + + private String updateFormNotin(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't remove from: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).remove(" + val2 + ");"; + } + return data + ".remove(" + val2 + ");"; + } + // wrap val2 if primitive; really removeAll + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".kill" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryForm(env,local) + ", "; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).remove(" + val2 + ");"; + } + return data + ".remove(" + val2 + ");"; + } + else + { return "{} /* can't remove from single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) // && not addOnly + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't remove from ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (local) + { return var + ".remove" + data + "(" + qual + val2 + ");"; } // Remove all copies + + return cont + ".remove" + data + "(" + var + "," + qual + val2 + ");"; + } + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemove(env,dataform,exp2,local,"="); + } + + String pre = objectRef.queryForm(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 /: C[inds].data + { return cref + ".removeAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 /: C[ind].data + { return cont + ".remove" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".removeAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".removeAll" + data + "(" + pre + "," + qual + val2 + ");"; + } + else + { return cont + ".remove" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised remove: " + this + "->excludes(" + val2 + ") */"; + } + + private String updateFormNotinJava6(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't remove from: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).remove(" + val2 + ");"; + } + return data + ".remove(" + val2 + ");"; + } + // wrap val2 if primitive; really removeAll + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".kill" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormJava6(env,local) + ", "; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).remove(" + val2 + ");"; + } + return data + ".remove(" + val2 + ");"; + } + else + { return "{} /* can't remove from single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) // && not addOnly + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't remove from ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (local) + { return var + ".remove" + data + "(" + qual + val2 + ");"; } // Remove all copies + + return cont + ".remove" + data + "(" + var + "," + qual + val2 + ");"; + } + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveJava6(env,dataform,exp2,local,"="); + } + + String pre = objectRef.queryFormJava6(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 /: C[inds].data + { return cref + ".removeAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 /: C[ind].data + { return cont + ".remove" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".removeAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String cref = ename; + if (entity.isInterface()) + { cref = ename + "." + ename + "Ops"; } + return cref + ".removeAll" + data + "(" + pre + "," + qual + val2 + ");"; + } + else + { return cont + ".remove" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised remove: " + this + "->excludes( " + val2 + ") */"; + } + + private String updateFormNotinJava7(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't remove from: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).remove(" + val2 + ");"; + } + return data + ".remove(" + val2 + ");"; + } + // wrap val2 if primitive; really removeAll + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".kill" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormJava7(env,local) + ", "; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).remove(" + val2 + ");"; + } + return data + ".remove(" + val2 + ");"; + } + else + { return "{} /* can't remove from single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) // && not addOnly + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't remove from ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (local) + { return var + ".remove" + data + "(" + qual + val2 + ");"; } // Remove all copies + + return cont + ".remove" + data + "(" + var + "," + qual + val2 + ");"; + } + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveJava7(env,dataform,exp2,local,"="); + } + + String pre = objectRef.queryFormJava7(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "." + cname + "Ops"; } + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 /: C[inds].data + { return cref + ".removeAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 /: C[ind].data + { return cont + ".remove" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "s"; + return cref + ".removeAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String cref = ename; + if (entity.isInterface()) + { cref = ename + "." + ename + "Ops"; } + return cref + ".removeAll" + data + "(" + pre + "," + qual + val2 + ");"; + } + else + { return cont + ".remove" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised remove: " + this + "->excludes( " + val2 + ") */"; + } + + private String updateFormNotinCSharp(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't remove from: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return "((ArrayList) " + data + "[" + indopt + " -1]).Remove(" + val2 + ");"; + } + return data + ".Remove(" + val2 + ");"; + } + // wrap val2 if primitive; really removeAll + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".kill" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormCSharp(env,local) + ", "; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return "((ArrayList) " + data + "[" + indopt + " -1]).Remove(" + val2 + ");"; + } + return data + ".Remove(" + val2 + ");"; + } + else + { return "{} /* can't remove from single-valued attribute: " + this + " */"; } + } + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't remove from ONE role */"; } + + String var = findEntityVariable(env); + + if (local) + { return var + ".remove" + data + "(" + qual + val2 + ");"; } // Remove all copies + + return cont + ".remove" + data + "(" + var + "," + qual + val2 + ");"; + } + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveCSharp(env,dataform,exp2,local,"="); + } + + String pre = objectRef.queryFormCSharp(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + String cref = cname; + if (objref.entity != null && objref.entity.isInterface()) + { cref = cname + "Ops"; } + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 /: C[inds].data + { return cref + ".removeAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 /: C[ind].data + { return cont + ".remove" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "." + cname.toLowerCase() + "_s"; + return cref + ".removeAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String cref = ename; + if (entity.isInterface()) + { cref = ename + "Ops"; } + return cref + ".removeAll" + data + "(" + pre + "," + qual + val2 + ");"; + } + else + { return cont + ".remove" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised remove: " + this + "->excludes(" + val2 + ") */"; + } + + private String updateFormNotinCPP(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller::inst->"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't remove from: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + String coll = "set"; + if (isOrdered() || isSequenceValued()) + { coll = "vector"; } + return "(" + data + "->at(" + indopt + " -1))->erase(" + val2 + ");"; + } + return data + "->erase(" + val2 + ");"; + } + // wrap val2 if primitive; really removeAll + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + "kill" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + String qual = ""; + if (isQualified() && arrayIndex != null) + { qual = arrayIndex.queryFormCPP(env,local) + ", "; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + String coll = "set"; + if (isOrdered() || isSequenceValued()) + { coll = "vector"; + return "(" + data + "->at(" + indopt + " -1)->erase(find(" + data + "->at(" + indopt + " -1)->begin(), " + data + "->at(" + indopt + " -1)->end(), " + val2 + ")));"; + } + return "(" + data + "->at(" + indopt + " -1))->erase(" + val2 + ");"; + } + + if (isOrdered() || isSequenceValued()) + { return + data + "->erase(find(" + data + "->begin(), " + data + "->end(), " + val2 + "));"; + } + return data + "->erase(" + val2 + ");"; + } + else + { return "{} /* can't remove from single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) // and not addOnly + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't remove from ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (local) + { return var + "->remove" + data + "(" + qual + val2 + ");"; } // Remove all copies + + return cont + "remove" + data + "(" + var + "," + qual + val2 + ");"; + } + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveCPP(env,dataform,exp2,local,"="); + } + + String pre = objectRef.queryFormCPP(env,local); + + if (objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression)) + { BasicExpression objref = (BasicExpression) objectRef; + String cname = objref.data; + if (objref.arrayIndex != null) + { if (objref.arrayIndex.isMultiple()) // val2 /: C[inds].data + { return cname + "::removeAll" + data + "(" + pre + "," + val2 + ");"; } + else // val2 /: C[ind].data + { return cont + "remove" + data + "(" + pre + "," + val2 + ");"; } + } + String cobjs = cont + "get" + cname.toLowerCase() + "_s()"; + return cname + "::removeAll" + data + "(" + cobjs + "," + val2 + ");"; + } + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + return ename + "::removeAll" + data + "(" + pre + "," + qual + val2 + ");"; + } + else + { return cont + "remove" + data + "(" + pre + "," + qual + val2 + ");"; } + } + return "{} /* unrecognised remove: " + this + "->excludes(" + val2 + ") */"; + } + + private String updateFormRemove(java.util.Map env, BasicExpression dataform, + Expression exp2, boolean local, String op) + { String cont = "Controller.inst()"; + + if (objectRef == null) + { Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryForm(env,local); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { if (entity.isBidirectionalRole(data)) + { local = false; } + + if (local) + { return "subtract" + data + "(" + rej + ");"; } + else + { String var = findEntityVariable(env); + return cont + ".subtract" + data + "(" + var + ", " + rej + ");"; + } + } + else if (umlkind == CLASSID) // eg: exp2 /: C.dataform + { return cont + ".killAll" + data + "(" + rej + ");"; } + else + { return "{} /* Invalid subtract */"; } + } + else + { if (umlkind == ROLE && multiplicity == ModelElement.ONE || + umlkind == ATTRIBUTE ) + { BasicExpression newdf; + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + if (dataform.objectRef == null) + { newdf = dataform; + newdf.objectRef = dataexp; + } + else + { BasicExpression dor = (BasicExpression) dataform.objectRef; + dor.setInnerObjectRef(dataexp); + // dor.objectRef = dataexp; + newdf = dataform; + } + return + ((BasicExpression) objectRef).updateFormRemove(env,newdf,exp2,local,op); + } + else if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { String pre = objectRef.queryForm(env,local); + Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryForm(env,local); + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + + return eref + ".subtractAll" + data + "(" + pre + "," + rej + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + rej + ");"; } + } + else + { return "{} /* Invalid subtract */"; } + } + } + + private String updateFormRemoveJava6(java.util.Map env, BasicExpression dataform, + Expression exp2, boolean local, String op) + { String cont = "Controller.inst()"; + + if (objectRef == null) + { Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormJava6(env,local); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { if (entity.isBidirectionalRole(data)) + { local = false; } + + if (local) + { return "subtract" + data + "(" + rej + ");"; } + else + { String var = findEntityVariable(env); + return cont + ".subtract" + data + "(" + var + ", " + rej + ");"; + } + } + else if (umlkind == CLASSID) // eg: exp2 /: C.dataform + { return cont + ".killAll" + data + "(" + rej + ");"; } + else + { return "{} /* Invalid subtract */"; } + } + else + { if (umlkind == ROLE && multiplicity == ModelElement.ONE || + umlkind == ATTRIBUTE ) + { BasicExpression newdf; + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + if (dataform.objectRef == null) + { newdf = dataform; + newdf.objectRef = dataexp; + } + else + { BasicExpression dor = (BasicExpression) dataform.objectRef; + dor.setInnerObjectRef(dataexp); + // dor.objectRef = dataexp; + newdf = dataform; + } + return + ((BasicExpression) objectRef).updateFormRemoveJava6(env,newdf,exp2,local,op); + } + else if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { String pre = objectRef.queryFormJava6(env,local); + Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormJava6(env,local); + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + + return eref + ".subtractAll" + data + "(" + pre + "," + rej + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + rej + ");"; } + } + else + { return "{} /* Invalid subtract */"; } + } + } + + private String updateFormRemoveJava7(java.util.Map env, BasicExpression dataform, + Expression exp2, boolean local, String op) + { String cont = "Controller.inst()"; + + if (objectRef == null) + { Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormJava7(env,local); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { if (entity.isBidirectionalRole(data)) + { local = false; } + + if (local) + { return "subtract" + data + "(" + rej + ");"; } + else + { String var = findEntityVariable(env); + return cont + ".subtract" + data + "(" + var + ", " + rej + ");"; + } + } + else if (umlkind == CLASSID) // eg: exp2 /: C.dataform + { return cont + ".killAll" + data + "(" + rej + ");"; } + else + { return "{} /* Invalid subtract */"; } + } + else + { if (umlkind == ROLE && multiplicity == ModelElement.ONE || + umlkind == ATTRIBUTE ) + { BasicExpression newdf; + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + if (dataform.objectRef == null) + { newdf = dataform; + newdf.objectRef = dataexp; + } + else + { BasicExpression dor = (BasicExpression) dataform.objectRef; + dor.setInnerObjectRef(dataexp); + // dor.objectRef = dataexp; + newdf = dataform; + } + return + ((BasicExpression) objectRef).updateFormRemoveJava7(env,newdf,exp2,local,op); + } + else if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { String pre = objectRef.queryFormJava7(env,local); + Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormJava7(env,local); + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + + return eref + ".subtractAll" + data + "(" + pre + "," + rej + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + rej + ");"; } + } + else + { return "{} /* Invalid subtract */"; } + } + } + + private String updateFormRemoveCSharp(java.util.Map env, BasicExpression dataform, + Expression exp2, boolean local, String op) + { String cont = "Controller.inst()"; + + if (objectRef == null) + { Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormCSharp(env,local); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { if (entity.isBidirectionalRole(data)) + { local = false; } + + if (local) + { return "subtract" + data + "(" + rej + ");"; } + else + { String var = findEntityVariable(env); + return cont + ".subtract" + data + "(" + var + ", " + rej + ");"; + } + } + else if (umlkind == CLASSID) // eg: exp2 /: C.dataform + { return cont + ".killAll" + data + "(" + rej + ");"; } + else + { return "{} /* Invalid subtract */"; } + } + else + { if (umlkind == ROLE && multiplicity == ModelElement.ONE || + umlkind == ATTRIBUTE ) + { BasicExpression newdf; + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + if (dataform.objectRef == null) + { newdf = dataform; + newdf.objectRef = dataexp; + } + else + { BasicExpression dor = (BasicExpression) dataform.objectRef; + dor.setInnerObjectRef(dataexp); + // dor.objectRef = dataexp; + newdf = dataform; + } + return + ((BasicExpression) objectRef).updateFormRemoveCSharp(env,newdf,exp2,local,op); + } + else if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { String pre = objectRef.queryFormCSharp(env,local); + Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormCSharp(env,local); + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity.isInterface()) + { eref = ename + "Ops"; } + + return eref + ".subtractAll" + data + "(" + pre + "," + rej + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + rej + ");"; } + } + else + { return "{} /* Invalid subtract */"; } + } + } + + private String updateFormRemoveCPP(java.util.Map env, BasicExpression dataform, + Expression exp2, boolean local, String op) + { String cont = "Controller::inst->"; + + if (objectRef == null) + { Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormCPP(env,local); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { if (entity.isBidirectionalRole(data)) + { local = false; } + + if (local) + { return "subtract" + data + "(" + rej + ");"; } + else + { String var = findEntityVariable(env); + return cont + "subtract" + data + "(" + var + ", " + rej + ");"; + } + } + else if (umlkind == CLASSID) // eg: exp2 /: C.dataform + { return cont + "killAll" + data + "(" + rej + ");"; } + else + { return "{} /* Invalid subtract */"; } + } + else + { if (umlkind == ROLE && multiplicity == ModelElement.ONE || + umlkind == ATTRIBUTE ) + { BasicExpression newdf; + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + if (dataform.objectRef == null) + { newdf = dataform; + newdf.objectRef = dataexp; + } + else + { BasicExpression dor = (BasicExpression) dataform.objectRef; + dor.setInnerObjectRef(dataexp); + // dor.objectRef = dataexp; + newdf = dataform; + } + return + ((BasicExpression) objectRef).updateFormRemoveCPP(env,newdf,exp2,local,op); + } + else if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { String pre = objectRef.queryFormCPP(env,local); + Expression selarg = new BinaryExpression(op,dataform,exp2); + Expression selexp = + new BinaryExpression("->select",this,selarg); + String rej = selexp.queryFormCPP(env,local); + + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + + return eref + "::subtractAll" + data + "(" + pre + "," + rej + ");"; + } + else + { return cont + "subtract" + data + "(" + pre + "," + rej + ");"; } + } + else + { return "{} /* Invalid subtract */"; } + } + } + + private String updateFormSubset(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).addAll(" + val2 + ");"; + } + return data + ".addAll(" + val2 + ");"; + } + + if (umlkind == CLASSID && arrayIndex == null) + { // System.out.println("Creation operation on " + data); + return cont + ".createAll" + data + "(" + val2 + ");"; + } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).addAll(" + val2 + ");"; + } + return data + ".addAll(" + val2 + ");"; + } + else + { return "{} /* can't add to single-valued attribute: " + this + " */"; } + } // case of index + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // or frozen + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + return cont + ".union" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".addAll(" + val2 + ");"; } + + return cont + ".union" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryForm(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".unionAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".union" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised union: " + val2 + " <: " + this + " */"; + } + + private String updateFormSubsetJava6(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).addAll(" + val2 + ");"; + } + return data + ".addAll(" + val2 + ");"; + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { // System.out.println("Creation operation on " + data); + return cont + ".createAll" + data + "(" + val2 + ");"; + } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).addAll(" + val2 + ");"; + } + return data + ".addAll(" + val2 + ");"; + } + else + { return "{} /* can't add to single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // or frozen + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + return cont + ".union" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".addAll(" + val2 + ");"; } + + return cont + ".union" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormJava6(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".unionAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".union" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised union: " + val2 + " <: " + this + " */"; + } + + private String updateFormSubsetJava7(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).addAll(" + val2 + ");"; + } + return data + ".addAll(" + val2 + ");"; + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { // System.out.println("Creation operation on " + data); + return cont + ".createAll" + data + "(" + val2 + ");"; + } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).addAll(" + val2 + ");"; + } + return data + ".addAll(" + val2 + ");"; + } + else + { return "{} /* can't add to single-valued attribute: " + this + " */"; } + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // or frozen + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + return cont + ".union" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".addAll(" + val2 + ");"; } + + return cont + ".union" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormJava7(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".unionAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".union" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised union: " + val2 + " <: " + this + " */"; + } + + private String updateFormSubsetCSharp(java.util.Map env, + String val2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + data + " */"; } + + if (umlkind == VARIABLE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return "((ArrayList) " + data + "[" + indopt + " -1]).AddRange(" + val2 + ");"; + } + return data + ".AddRange(" + val2 + ");"; + } + else + { return "{} /* can't add to single-valued variable: " + this + " */"; } + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { // System.out.println("Creation operation on " + data); + return cont + ".createAll" + data + "(" + val2 + ");"; + } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE) + { if (type != null && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return "((ArrayList) " + data + "[" + indopt + " -1]).AddRange(" + val2 + ");"; + } + return data + ".AddRange(" + val2 + ");"; + } + else + { return "{} /* can't add to single-valued attribute: " + this + " */"; } + } + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + return cont + ".union" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".AddRange(" + val2 + ");"; } + + return cont + ".union" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormCSharp(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "Ops"; } + return eref + ".unionAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".union" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised union: " + val2 + " <: " + this + " */"; + } + + private String updateFormSubsetCPP(java.util.Map env, + String val2, boolean local) + { String cont = "Controller::inst->"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP || prestate) + { return "{} /* can't add to: " + this + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { String pre = data; + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + String coll = "set"; + if (isOrdered()) { coll = "vector"; } + pre = "(" + data + "->at(" + indopt + " -1));"; + } + if (isOrdered()) + { return pre + "->insert(" + pre + "->end(), " + val2 + "->begin(), " + + val2 + "->end());"; + } + else + { return pre + "->insert(" + val2 + "->begin(), " + val2 + "->end());"; } + } // case of index. + + if (umlkind == CLASSID && arrayIndex == null) + { // System.out.println("Creation operation on " + data); + return cont + "createAll" + data + "(" + val2 + ");"; + } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE && Type.isCollectionType(type)) + { String pre = data; + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + String coll = "set"; + if (isOrdered()) { coll = "vector"; } + pre = "(" + data + "->at(" + indopt + " -1));"; + } + if (isOrdered()) + { return pre + "->insert(" + pre + "->end(), " + val2 + "->begin(), " + + val2 + "->end());"; + } + else + { return pre + "->insert(" + val2 + "->begin(), " + val2 + "->end());"; } + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't add to ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + return cont + "union" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) + { if (isOrdered()) + { return data + "->insert(" + data + "->end(), " + val2 + "->begin(), " + + val2 + "->end());"; + } + else + { return data + "->insert(" + val2 + "->begin(), " + val2 + "->end());"; } + } + return cont + "union" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { String pre = objectRef.queryFormCPP(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + return ename + "::unionAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + "union" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised union: " + val2 + " <: " + this + " */"; + } + + private String updateFormSubtract(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't subtract: " + this + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).removeAll(" + val2 + ");"; + } + return data + ".removeAll(" + val2 + ");"; + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".killAll" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryForm(env,local); + return "((List) " + data + ".get(" + indopt + " -1)).removeAll(" + val2 + ");"; + } + return data + ".removeAll(" + val2 + ");"; + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // or addOnly + { return "{} /* can't subtract ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryForm(env,local); + return cont + ".subtract" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".removeAll(" + val2 + ");"; } + + return cont + ".subtract" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemove(env,dataform,exp2,local,":"); + } + String pre = objectRef.queryForm(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".subtractAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised subtract: " + this + " - " + val2 + " */"; + } + + private String updateFormSubtractJava6(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't subtract: " + this + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).removeAll(" + val2 + ");"; + } + return data + ".removeAll(" + val2 + ");"; + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".killAll" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava6(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).removeAll(" + val2 + ");"; + } + return data + ".removeAll(" + val2 + ");"; + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // or addOnly + { return "{} /* can't subtract ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormJava6(env,local); + return cont + ".subtract" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".removeAll(" + val2 + ");"; } + + return cont + ".subtract" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveJava6(env,dataform,exp2,local,":"); + } + String pre = objectRef.queryFormJava6(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".subtractAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised subtract: " + this + " - " + val2 + " */"; + } + + private String updateFormSubtractJava7(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't subtract: " + this + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).removeAll(" + val2 + ");"; + } + return data + ".removeAll(" + val2 + ");"; + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".killAll" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormJava7(env,local); + return "((Collection) " + data + ".get(" + indopt + " -1)).removeAll(" + val2 + ");"; + } + return data + ".removeAll(" + val2 + ");"; + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // or addOnly + { return "{} /* can't subtract ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormJava7(env,local); + return cont + ".subtract" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + ".removeAll(" + val2 + ");"; } + + return cont + ".subtract" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveJava7(env,dataform,exp2,local,":"); + } + String pre = objectRef.queryFormJava7(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "." + ename + "Ops"; } + return eref + ".subtractAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised subtract: " + this + " - " + val2 + " */"; + } + + private String updateFormSubtractCSharp(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller.inst()"; + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't subtract: " + this + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return data + "[" + indopt + " -1] = SystemTypes.subtract((ArrayList) " + + data + "[" + indopt + " -1], " + val2 + ");"; + } + return data + " = SystemTypes.subtract(" + data + ", " + val2 + ");"; + } + // val2 must be a list + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + ".killAll" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE && Type.isCollectionType(type)) + { if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCSharp(env,local); + return data + "[" + indopt + " -1] = SystemTypes.subtract((ArrayList) " + data + "[" + indopt + " -1], " + val2 + ");"; + } + return data + " = SystemTypes.subtract(" + data + ", " + val2 + ");"; + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) // and not addOnly + { return "{} /* can't subtract ONE role: " + this + " */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormCSharp(env,local); + return cont + ".subtract" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) { return data + " = SystemTypes.subtract(" + data + ", " + val2 + ");"; } + + return cont + ".subtract" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveCSharp(env,dataform,exp2,local,":"); + } + String pre = objectRef.queryFormCSharp(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + String eref = ename; + if (entity != null && entity.isInterface()) + { eref = ename + "Ops"; } + return eref + ".subtractAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + ".subtract" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised subtract: " + this + " - " + val2 + " */"; + } + + private String updateFormSubtractCPP(java.util.Map env, + String val2, Expression exp2, boolean local) + { String cont = "Controller::inst->"; + Type et = getElementType(); + String cetype = "void*"; + if (et != null) { cetype = et.getCPP(); } + + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == QUERY || + umlkind == FUNCTION || umlkind == UPDATEOP || prestate) + { return "{} /* can't subtract: " + this + " */"; } + + if (umlkind == VARIABLE && Type.isCollectionType(type)) + { String pre = data; + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + pre = "(" + data + "->at(" + indopt + " -1));"; + } + return pre + " = UmlRsdsLib<" + cetype + ">::subtract(" + pre + ", " + val2 + ");"; + } + // case of index, and below. + + if (umlkind == CLASSID && arrayIndex == null) + { return cont + "killAll" + entity.getName() + "(" + val2 + ");"; } + + if (entity.isBidirectionalRole(data)) + { local = false; } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE && Type.isCollectionType(type)) + { String pre = data; + if (arrayIndex != null) + { String indopt = arrayIndex.queryFormCPP(env,local); + pre = "(" + data + "->at(" + indopt + " -1));"; + } + return pre + " = UmlRsdsLib<" + cetype + ">::subtract(" + pre + ", " + val2 + ");"; + } + + if (umlkind == ROLE) + { if (multiplicity == ModelElement.ONE) + { return "{} /* can't subtract ONE role */"; } + + String var = findEntityVariable(env); + + if (isQualified() && arrayIndex != null) + { String ind = arrayIndex.queryFormCPP(env,local); + return cont + "subtract" + data + "(" + var + ", " + ind + ", " + val2 + ");"; + } + + if (local) + { return data + " = UmlRsdsLib<" + cetype + ">::subtract(" + data + ", " + val2 + ");"; } + + return cont + "subtract" + data + "(" + var + "," + val2 + ");"; + } // no need to wrap -- val2 must be a list + } + else // objectRef != null, ROLE, != ONE assumed + { if (umlkind == ATTRIBUTE || umlkind == ROLE && multiplicity == ModelElement.ONE) + { BasicExpression dataform = (BasicExpression) clone(); + dataform.objectRef = null; + return + ((BasicExpression) objectRef).updateFormRemoveCPP(env,dataform,exp2,local,":"); + } + String pre = objectRef.queryFormCPP(env,local); + if (objectRef.isMultiple()) + { String ename = entity.getName(); + return ename + "::subtractAll" + data + "(" + pre + "," + val2 + ");"; + } + else + { return cont + "subtract" + data + "(" + pre + "," + val2 + ");"; } + } + return "{} /* unrecognised subtract: " + this + " - " + val2 + " */"; + } + + public BExpression bqueryForm(java.util.Map env) + { // assume expression already type-checked. true |-> TRUE, etc + BExpression res; + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { BExpression bind = arrayIndex.binvariantForm(env,true); + if (entity != null) + { Attribute pk = entity.getPrincipalKey(); + BExpression invpk = new BPostfixExpression("~", new BBasicExpression(pk + "")); + if (arrayIndex.isMultiple()) + { res = new BApplySetExpression(invpk,bind); } + else + { res = new BApplyExpression(invpk,bind); } + return res; + } + } + String es = data.toLowerCase() + "s"; + res = new BBasicExpression(es); + res.setMultiplicity(ModelElement.MANY); + res.setKind(umlkind); + return res; + } + + if (umlkind == VALUE || umlkind == VARIABLE || umlkind == CONSTANT) + { if (data.equals("self")) + { BExpression var = findBContextVariable(env,entity); + return var; + } + if (data.equals("true")) + { res = new BBasicExpression("TRUE"); } + else if (data.equals("false")) + { res = new BBasicExpression("FALSE"); } + else if (isSequence(data) || isSet(data)) + { Expression se = buildSetExpression(data); + BExpression seqf = se.bqueryForm(env); + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,true); + return new BApplyExpression(seqf,ind); + } + return seqf; + } + else if (isString(data)) + { BExpression bexp = new BBasicExpression(data); + bexp.setKind(umlkind); + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,true); + return new BApplyExpression(bexp,ind); + } + return bexp; + } + else if (isMultiple()) + { res = new BBasicExpression(data); } + else + { Vector vv = new Vector(); + BBasicExpression be = new BBasicExpression(data); + be.setKind(umlkind); + vv.add(be); + return new BSetExpression(vv); + } + res.setKind(umlkind); + return res; + } // makeBSet -- WHY???? + + if (umlkind == FUNCTION) + { BExpression pre = objectRef.bqueryForm(env); + // System.out.println(objectRef + " query form is: " + pre + " " + + // pre.setValued()); + String op; + if (data.equals("size")) + { op = "card"; + return new BUnaryExpression(op,pre.simplify()); + } + else if (data.equals("abs") || data.equals("sqr") || + data.equals("sqrt") || data.equals("max") || + data.equals("min")) + { op = data; + return new BUnaryExpression(op,pre.simplify()); + } // can be sets { xx | yy: pre & xx = f(yy) } + else if (data.equals("closure")) + { // System.out.println(entity + " " + objectRef + " " + objectRef.entity + + // env); + String rel = ((BasicExpression) objectRef).data; + // the relation being closured + if (((BasicExpression) objectRef).objectRef == null) + { BExpression var = findBContextVariable(env,objectRef.entity); + return new BUnaryExpression("closure(" + rel + ")",var); + } + BExpression objs = + ((BasicExpression) objectRef).objectRef.bqueryForm(env); + return new BUnaryExpression("closure(" + rel + ")",objs); + } + else if (data.equals("any")) + { BExpression arg = pre.simplify(); + arg.setBrackets(true); + return new BApplyExpression(arg,new BBasicExpression("1")); + } + else if (data.equals("subcollections")) + { return new BUnaryExpression("FIN",pre.simplify()); } + else if (data.equals("asSet")) + { if (objectRef.isOrderedB()) + { return new BUnaryExpression("ran",pre.simplify()); } + else + { return pre.simplify(); } + } + else if (data.equals("sum")) // Ignore toLower, toUpper + { BExpression xxbe = new BBasicExpression("x_x"); + BExpression pred = + new BBinaryExpression(":",xxbe,pre); + return new BSigmaExpression("x_x",pred,xxbe); + } + else if (data.equals("oclIsKindOf")) + { Expression par1 = (Expression) parameters.get(0); + String par1s = par1 + ""; + BExpression rightobjs = new BBasicExpression(par1s.toLowerCase() + "s"); + return new BBinaryExpression(":", pre, rightobjs); + } + else if (data.equals("oclAsType")) + { return pre; } + else // last, first, front, tail, sort, reverse + { return new BUnaryExpression(data,pre); } + } + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (umlkind == ATTRIBUTE) + { Attribute datt = entity.getDefinedAttribute(data); + if (datt == null || datt.isClassScope()) + { BExpression bres = new BBasicExpression(data); + bres.setKind(umlkind); + } // if array? + } + BExpression var = findBContextVariable(env,entity); + BApplySetExpression fapp = + new BApplySetExpression(data,var); + fapp.setMultiplicity(multiplicity); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { BExpression ufapp = new BUnaryExpression("union",fapp); + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,true); + return new BApplyExpression(ufapp,ind); + } // binvariantForm for array indexes + if (entity.getRole(data).isOrdered()) + { return new BUnaryExpression("ran",ufapp); } + else + { return ufapp; } + } + return fapp; + } + else if (umlkind == QUERY) + { Vector bpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + BExpression bpar = par.binvariantForm(env,true); + bpars.add(bpar); + } + } + return new BBasicExpression(data,bpars); + } // may have array index + } + else + { BExpression pre = objectRef.bqueryForm(env); + BApplySetExpression fapp = new BApplySetExpression(data,pre); + fapp.setMultiplicity(multiplicity); + + if (umlkind == ROLE && multiplicity != ModelElement.ONE) + { BExpression ufapp = new BUnaryExpression("union",fapp); + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,true); + return new BApplyExpression(ufapp,ind); + } // actually { sq(ind) | sq : ufapp } + if (entity.getRole(data) != null && entity.getRole(data).isOrdered()) + { return new BUnaryExpression("ran",ufapp); } + else + { return ufapp; } + } + if (umlkind == ATTRIBUTE) + { Attribute datt = entity.getDefinedAttribute(data); + if (datt == null || datt.isClassScope()) + { BExpression bres = new BBasicExpression(data); + bres.setKind(umlkind); + } // array case? + } + else if (umlkind == QUERY) + { Vector bpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + BExpression bpar = par.binvariantForm(env,true); + bpars.add(bpar); + } + } + Vector prepars = new Vector(); + prepars.add(pre); + BBasicExpression bres = + new BBasicExpression(data + "_" + entity,prepars); + bres.setKind(umlkind); + if (bpars.size() > 0) + { return new BApplyExpression(bres,bpars); } + else + { return bres; } + } // may have array index + + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,true); + return new BApplyExpression(fapp,ind); + } + + return fapp; + } // same as above if multiple + Vector vv = new Vector(); + BBasicExpression be = new BBasicExpression(data); + be.setKind(umlkind); + vv.add(be); + return new BSetExpression(vv); + } // query form of CLASS ident is lower case of it + "s". Set valued + + public BExpression bqueryForm() + { return bqueryForm(null); } + + public static BExpression findBContextVar(java.util.Map env, Entity e) + { BasicExpression exp = new BasicExpression(("" + e).toLowerCase() + "x"); + return exp.findBContextVariable(env,e); + } + + public BExpression findBContextVariable(java.util.Map env, Entity e) + { BExpression var; + if (env == null || e == null) + { var = new BBasicExpression(data); + var.setKind(umlkind); + } + else + { String nme = e.getName(); + var = (BExpression) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = e.searchForSubclass(env); } + if (var == null) + { var = e.searchForSuperclass(env); + if (var == null) + { System.err.println("!! Error: no variable for " + nme); + var = new BBasicExpression(nme.toLowerCase() + "x"); + } + else + { var = new BBinaryExpression("/\\", var, + new BBasicExpression(nme.toLowerCase() + "s")); + } + } + } + var.setKind(umlkind); + return var; + } + + public BStatement bupdateForm(java.util.Map env, + String operator, BExpression val2, boolean local) + { if (operator.equals("=")) + { return bEqupdateForm(env,val2,local); } + else if (operator.equals(":")) + { return bInupdateForm(env,val2,local); } + else if (operator.equals("/:")) + { return bNotinupdateForm(env,val2,local); } + else if (operator.equals("<:")) + { return bSubsetupdateForm(env,val2,local); } + else if (operator.equals("/<:")) + { return bSubtractupdateForm(env,val2,local); } + else + { return new BBasicStatement("skip"); } + } + + public BStatement bupdateForm(java.util.Map env, boolean local) + { String feat = ""; + String op = ""; + + System.out.println(">> B UPDATE FORM OF " + this + " " + isEvent); + + if (isEvent) // an operation of entity -- not allowed if local + { Vector oppars = new Vector(); + + if (data.charAt(0) == 's' && data.length() > 3) // set + { feat = data.substring(3,data.length()); + op = data.substring(0,3); + System.out.println("Feature == " + feat + " op = " + op); + } + else if (data.charAt(0) == 'a' && data.length() > 3) + { feat = data.substring(3,data.length()); + op = data.substring(0,3); + } + else if (data.charAt(0) == 'r' && data.length() > 6) // remove + { feat = data.substring(6,data.length()); + op = data.substring(0,6); + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression e = (Expression) parameters.get(i); + BExpression be = e.binvariantForm(env,local); + oppars.add(be); + } + } + Vector pars = new Vector(); + String ename = entity.getName(); + if (objectRef == null) + { BExpression var = (BExpression) env.get(ename); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclass(env); } + if (var == null) + { System.err.println("!! Error: No variable of " + ename); + var = new BBasicExpression(ename.toLowerCase() + "x"); + var.setKind(VARIABLE); + } + + BExpression pre1 = var.simplify(); + BExpression psimp = BExpression.unmakeSet(pre1); + pars.add(psimp); + pars.addAll(oppars); + + BStatement res; + if (psimp.setValued() && op != null && + op.equals("set") || op.equals("remove") || op.equals("add")) + { res = new BOperationCall(op + "All" + feat,pars); } + else + { res = new BOperationCall(data,pars); } + res.setWriteFrame(feat); + return res; + } + else if ("super".equals("" + objectRef)) + { System.out.println(">> Super entity: " + entity); + if (entity != null) // && entity.getSuperclass() != null) + { // Entity sup = entity.getSuperclass(); + BehaviouralFeature supop = entity.getOperation(data); + if (supop != null) + { Expression suppost = supop.getPost(); + return suppost.bupdateForm(env,local); + } + } + return new BBasicStatement("skip"); + } + else + { BExpression pre = objectRef.bqueryForm(env); // better to use binvariantForm + BExpression pre1 = pre.simplify(); + BExpression psimp = BExpression.unmakeSet(pre1); + pars.add(psimp); + pars.addAll(oppars); + + BStatement res; + if (psimp.setValued() && op != null && + op.equals("set") || op.equals("remove") || + op.equals("add")) + { res = new BOperationCall(op + "All" + feat,pars); } + else + { res = new BOperationCall(data,pars); } + res.setWriteFrame(feat); + return res; + } + } + else + { System.out.println("!! No update form for " + this + " " + isEvent); + return new BBasicStatement("skip"); + } // no sensible update form + } + // If objectRef is multiple may need setAll versions. + // also local versions + + public BStatement bEqupdateForm(java.util.Map env, + BExpression s, boolean local) + { BStatement res; + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP) + { System.out.println("Cannot update: " + this); + return new BBasicStatement("skip"); + } + if (prestate == true) + { System.out.println("Cannot update: " + this); + return new BBasicStatement("skip"); + } + if (umlkind == VARIABLE) + { if (data.equals("result")) + { BExpression be = new BBasicExpression(data); + be.setKind(VARIABLE); + res = new BAssignStatement(be,s); + res.setWriteFrame(data); + return res; + } + System.out.println("Cannot update: " + this); + return new BBasicStatement("skip"); + } + BExpression ind = null; + if (arrayIndex != null) + { ind = arrayIndex.binvariantForm(env,local); } // really bqueryForm! + + Association ast = entity.getDefinedRole(data); + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { String nme = entity.getName(); + BExpression var = (BExpression) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclass(env); } + if (var == null) // error + { var = entity.searchForSuperclass(env); + if (var == null) + { System.err.println("No range of values for " + nme); + var = new BBasicExpression(entity.getName().toLowerCase() + "x"); + } + else + { var = new BBinaryExpression("/\\",var, + new BBasicExpression(nme.toLowerCase() + "s")); + } + } + var.setKind(umlkind); + if (local) + { return constructLocalBOp("set",data,var.simplify(),s,ind,ast); } + return constructBOp("set",data,var.simplify(),s,ind); + } + } + else + { String nme = entity.getName(); + BExpression pre = objectRef.binvariantForm(env,local); + if (umlkind == ATTRIBUTE && entity.isClassScope(data)) + { pre = null; } // and for add, remove etc + else + { pre = pre.simplify(); } + if (local) + { return constructLocalBOp("set",data,pre,s,ind,ast); } + + return constructBOp("set",data,pre,s,ind); + } + return new BBasicStatement("skip"); + } + + public BStatement bInupdateForm(java.util.Map env, + BExpression s, boolean local) + { BStatement res; + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP) + { return new BBasicStatement("skip"); } + if (umlkind == CLASSID) + { String dvar = data.toLowerCase() + "x"; + String dvars = data.toLowerCase() + "s"; + String tname = data + "_OBJ"; + BExpression dexp = new BBasicExpression(dvar); + BExpression texp = new BBasicExpression(tname); + BExpression objs = new BBasicExpression(dvars); + BExpression mns = new BBinaryExpression("-",texp,objs); + BExpression exp = new BBinaryExpression(":",dexp,mns); + // BExpression s1 = BExpression.unSet(s); + // String snme = s1 + ""; + // BStatement assgn = + // constructLocalBOp("set",snme,null,dexp,null); + BStatement addst = + constructLocalBOp("add",dvars,null,dexp,null,null); + // BParallelStatement stat = new BParallelStatement(); + // stat.addStatement(assgn); + // stat.addStatement(addst); + + // if (local && entity.hasAttribute(snme)) + Vector vars = new Vector(); + vars.add(dvar); + // ANY snmex WHERE snmex : data.toUpperCase() - + // data.toLowerCase() + "s" THEN snme(datax) := snmex || + // datas := datas \/ {snmex} END + res = new BAnyStatement(vars,exp,addst); + return res; + } + if (umlkind == VARIABLE) + { if (data.equals("result")) // or lhs := lhs \/ rhs in all cases? + { BSetExpression rhs = new BSetExpression(); + rhs.addElement(s); + BExpression be = new BBasicExpression(data); + be.setKind(VARIABLE); + res = new BAssignStatement(be,rhs); + res.setWriteFrame(data); + return res; + } + return new BBasicStatement("skip"); + } + + Association ast = entity.getDefinedRole(data); + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { String nme = entity.getName(); + BExpression var = (BExpression) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclass(env); } + if (local) + { return constructLocalBOp("add",data,var.simplify(),s,null,ast); } + return constructBOp("add",data,var.simplify(),s,null); + } + } + else + { BExpression pre = objectRef.binvariantForm(env,local); + if (local) + { return constructLocalBOp("add",data,pre.simplify(),s,null,ast); } + return constructBOp("add",data,pre.simplify(),s,null); + } + return new BBasicStatement("skip"); + } + + public BStatement bNotinupdateForm(java.util.Map env, + BExpression s, boolean local) + { BStatement res; + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP) + { return new BBasicStatement("skip"); } + if (umlkind == VARIABLE) + { // if (data.equals("result")) + // { return "result := result - {" + s + "}"; } + return new BBasicStatement("skip"); + } + + Association ast = entity.getDefinedRole(data); + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { String nme = entity.getName(); + BExpression var = (BExpression) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclass(env); } + if (local) + { return constructLocalBOp("remove",data,var.simplify(),s,null,ast); } + return constructBOp("remove",data,var.simplify(),s,null); + } + } + else + { BExpression pre = objectRef.binvariantForm(env,local); + if (local) + { return constructLocalBOp("remove",data,pre.simplify(),s,null,ast); } + return constructBOp("remove",data,pre.simplify(),s,null); + } + return new BBasicStatement("skip"); + } + + public BStatement bSubsetupdateForm(java.util.Map env, + BExpression s, boolean local) + { BStatement res; + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP) + { return new BBasicStatement("skip"); } + if (umlkind == VARIABLE) + { if (data.equals("result")) + { BExpression be = new BBasicExpression(data); + res = new BAssignStatement(be,s); + res.setWriteFrame(data); + return res; + } + return new BBasicStatement("skip"); + } + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { String nme = entity.getName(); + BExpression var = (BExpression) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclass(env); } + + if (local) + { return constructLocalBOp("union",data,var.simplify(),s,null,null); } + return constructBOp("union",data,var.simplify(),s,null); + } + } + else + { BExpression pre = objectRef.binvariantForm(env,local); + if (local) + { return constructLocalBOp("union",data,pre.simplify(),s,null,null); } + return constructBOp("union",data,pre.simplify(),s,null); + } + return new BBasicStatement("skip"); + } + + public BStatement bSubtractupdateForm(java.util.Map env, + BExpression s, boolean local) + { BStatement res; + if (umlkind == VALUE || umlkind == CONSTANT || umlkind == FUNCTION || + umlkind == QUERY || umlkind == UPDATEOP) + { return new BBasicStatement("skip"); } + if (umlkind == VARIABLE) + { // if (data.equals("result")) + // { return "result := result - {" + s + "}"; } + return new BBasicStatement("skip"); + } + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { String nme = entity.getName(); + BExpression var = (BExpression) env.get(nme); + if (var == null) // because nme is superclass of ent: dom(env) + { var = entity.searchForSubclass(env); } + if (local) + { return constructLocalBOp("subtract",data,var.simplify(),s,null,null); } + return constructBOp("subtract",data,var.simplify(),s,null); + } + } + else + { BExpression pre = objectRef.binvariantForm(env,local); + if (local) + { return constructLocalBOp("subtract",data,pre.simplify(),s,null,null); } + return constructBOp("subtract",data,pre.simplify(),s,null); + } + return new BBasicStatement("skip"); + } + + private BStatement constructBOp(String op, String feat, + BExpression var, + BExpression val, BExpression ind) + { // System.out.println("Call: " + op + " " + var + " " + val + + // " " + var.setValued() + " " + val.setValued()); + BStatement res; + Vector params = new Vector(); + if (var == null) + { if (ind != null) + { params.add(ind); } + params.add(val); + res = new BOperationCall(op + feat,params); + res.setWriteFrame(feat); + return res; + } + else if (var instanceof BSetExpression) + { BSetExpression svar = (BSetExpression) var; + if (svar.isSingleton()) + { BExpression e = svar.getElement(0); + params.add(e); + if (ind != null) + { params.add(ind); } + params.add(val); + if (e.setValued()) + { res = new BOperationCall(op + "All" + feat,params); + res.setWriteFrame(feat); + return res; + } + res = new BOperationCall(op + feat,params); + res.setWriteFrame(feat); + return res; + } + } + params.add(var); + if (ind != null) + { params.add(ind); } + params.add(val); + // res = new BOperationCall(op + "All" + feat,params); + res = new BOperationCall(op + feat,params); + res.setWriteFrame(feat); + return res; + } + + public BStatement constructLocalBOp(String op,String f, + BExpression e, + BExpression v, BExpression ind, Association ast) + { BStatement res; + BExpression var = null; + if (e != null) + { var = BExpression.unmakeSet(e); } + if (var != null && var.setValued()) + { return buildLocalAllOp(op,f,var,v,ind); } // updates a set of objects at once + BExpression lhs; + if (var != null) + { lhs = new BApplyExpression(f,var); } + else + { lhs = new BBasicExpression(f); } + + lhs.setMultiplicity(multiplicity); + lhs.setKind(umlkind); + if (op.equals("set")) + { if (ind != null) + { lhs = new BApplyExpression(lhs,ind); } + res = new BAssignStatement(lhs,v); + res.setWriteFrame(f); + System.out.println("WRITE FRAME of " + res + " : " + f); + if (ast != null) + { String role1 = ast.getRole1(); + if (role1 != null && role1.length() > 0) + { // an inverse is needed + int card1 = ast.getCard1(); + int card2 = ast.getCard2(); + // role2 is data + BExpression invrhs = computeInverseBExpressionSet(ast,role1,data,card1,card2,var,v); + BExpression invlhs = new BBasicExpression(role1); + BStatement invstat = new BAssignStatement(invlhs,invrhs); + invstat.setWriteFrame(role1); + BParallelStatement body = new BParallelStatement(); + body.addStatement(res); + body.addStatement(invstat); + return body; + } + } + return res; + } + if (op.equals("add")) + { BSetExpression se = + new BSetExpression(); + if (v instanceof BSetExpression) + { se = (BSetExpression) v; } + else + { se.addElement(v); } + BExpression rhs; + if (ast != null && ast.isOrdered()) + { se.setOrdered(true); + rhs = new BBinaryExpression("^",lhs,se); + } + else + { rhs = new BBinaryExpression("\\/",lhs,se); } // different for sequences + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + if (ast != null) + { String role1 = ast.getRole1(); + if (role1 != null && role1.length() > 0) + { // an inverse is needed + int card1 = ast.getCard1(); + int card2 = ast.getCard2(); + // role2 is data + BStatement invstat = computeInverseBAdd(ast,role1,data,card1,card2,var,v); + BParallelStatement body = new BParallelStatement(); + body.addStatement(res); + body.addStatement(invstat); + return body; + } + } + return res; + } + if (op.equals("union")) + { BExpression rhs = + new BBinaryExpression("\\/",lhs,v); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + if (op.equals("subtract")) + { BExpression rhs = + new BBinaryExpression("-",lhs,v); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + if (op.equals("remove")) + { BSetExpression se = + new BSetExpression(); + if (v instanceof BSetExpression) + { se = (BSetExpression) v; } + else + { se.addElement(v); } + BExpression rhs; + if (ast != null && ast.isOrdered()) + { // { _ii_, _yy_ | #_jj_.(_jj_ : dom(f) & _yy_ = f(_jj_) & _ii_ = card(dom(f) \cap 1.._jj_) ) } + // where f = lhs |>> se + BBinaryExpression rresf = new BBinaryExpression("|>>",lhs,se); + Vector subparams = new Vector(); + subparams.add("_ii_"); + subparams.add("_yy_"); + BUnaryExpression domf = new BUnaryExpression("dom", rresf); + BBasicExpression jjbe = new BBasicExpression("_jj_"); + BBinaryExpression rge = new BBinaryExpression("..", new BBasicExpression("1"), jjbe); + BBinaryExpression intrsec = new BBinaryExpression("/\\", domf, rge); + BUnaryExpression cardintrsec = new BUnaryExpression("card", intrsec); + BBasicExpression iibe = new BBasicExpression("_ii_"); + BBinaryExpression iieq = new BBinaryExpression("=", iibe, cardintrsec); + BBinaryExpression jjindom = new BBinaryExpression(":", jjbe, domf); + BApplyExpression appf = new BApplyExpression(lhs, jjbe); + BBasicExpression yybe = new BBasicExpression("_yy_"); + BBinaryExpression yyeq = new BBinaryExpression("=", yybe, appf); + BBinaryExpression and1 = new BBinaryExpression("&", jjindom, yyeq); + BBinaryExpression and2 = new BBinaryExpression("&", and1, iieq); + BQuantifierExpression exists1 = new BQuantifierExpression("#", "_jj_", and2); + rhs = new BSetComprehension(subparams, exists1); + } + else + { rhs = + new BBinaryExpression("-",lhs,se); + } // DIFFERENT FOR SEQUENCES + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + if (ast != null) + { String role1 = ast.getRole1(); + if (role1 != null && role1.length() > 0) + { // an inverse is needed + int card1 = ast.getCard1(); + int card2 = ast.getCard2(); + // role2 is data + BStatement invstat = computeInverseBDel(ast,role1,data,card1,card2,var,v); + BParallelStatement body = new BParallelStatement(); + body.addStatement(res); + body.addStatement(invstat); + return body; + } + } + return res; + } + return new BBasicStatement("skip"); + } // deal with cases other than set. + + private BStatement buildLocalAllOp(String op,String f, + BExpression e, + BExpression v, BExpression ind) + { BStatement res; + BExpression lhs = new BBasicExpression(f); + if (op.equals("set")) // f := f <+ e * {v} + { if (ind != null) // f := f <+ { ee,sq | ee: e & sq = f(ee) <+ {ind |-> v}} + { BExpression maplet = new BBinaryExpression("|->",ind,v); + BSetExpression sem = new BSetExpression(); + sem.addElement(maplet); + String ee = Identifier.nextIdentifier("_ee"); + BExpression ex = new BBasicExpression(ee); + BExpression fapp = new BApplyExpression(f,ex); + BExpression upd = new BBinaryExpression("<+",fapp,sem); + String ss = Identifier.nextIdentifier("_xx"); + BExpression sq = new BBasicExpression(ss); + BExpression updeq = new BBinaryExpression("=",sq,upd); + BExpression inexp = new BBinaryExpression(":",ex,e); + BExpression pred = new BBinaryExpression("&",inexp,updeq); + Vector vars = new Vector(); + vars.add(ee); + vars.add(ss); + BExpression comp = new BSetComprehension(vars,e,pred); // e? + BExpression rhs = new BBinaryExpression("<+",lhs,comp); + return new BAssignStatement(lhs,rhs); + } + BSetExpression se = new BSetExpression(); + se.addElement(v); + BExpression prd = + new BBinaryExpression("*",e,se); + BExpression rhs = + new BBinaryExpression("<+",lhs,prd); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + if (op.equals("add")) // f := f <+ { ee,xx | ee : e & xx = f(ee) \/ {v} } + { BSetExpression se = new BSetExpression(); + se.addElement(v); + Vector vars = new Vector(); + String ee = Identifier.nextIdentifier("_ee"); + vars.add(ee); + String xx = Identifier.nextIdentifier("_xx"); + vars.add(xx); + BExpression be = new BBasicExpression(ee); + BExpression xe = new BBasicExpression(xx); + BExpression inexp = new BBinaryExpression(":",be,e); + BExpression fapp = + new BApplyExpression(f,be); + fapp.setMultiplicity(multiplicity); // f is data + BExpression un = + new BBinaryExpression("\\/",fapp,se); + BExpression pred = + new BBinaryExpression("=",xe,un); + pred = new BBinaryExpression("&",inexp,pred); + BExpression sc = + new BSetComprehension(vars,e,pred); + BExpression rhs = + new BBinaryExpression("<+",lhs,sc); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + if (op.equals("union")) // f := f <+ { ee,xx | ee : e & xx = f(ee) \/ v } + { Vector vars = new Vector(); + String ee = Identifier.nextIdentifier("_ee"); + vars.add(ee); + String xx = Identifier.nextIdentifier("_xx"); + vars.add(xx); + BExpression be = new BBasicExpression(ee); + BExpression xe = new BBasicExpression(xx); + BExpression fapp = + new BApplyExpression(f,be); + fapp.setMultiplicity(multiplicity); + BExpression inexp = new BBinaryExpression(":",be,e); + BExpression un = + new BBinaryExpression("\\/",fapp,v); + BExpression pred = + new BBinaryExpression("=",xe,un); + pred = new BBinaryExpression("&",inexp,pred); + + BExpression sc = + new BSetComprehension(vars,e,pred); + BExpression rhs = + new BBinaryExpression("<+",lhs,sc); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + if (op.equals("subtract")) // f := f <+ { ee,xx | ee : e & xx = f(ee) - v } + { Vector vars = new Vector(); + String ee = Identifier.nextIdentifier("_ee"); + vars.add(ee); + String xx = Identifier.nextIdentifier("_xx"); + vars.add(xx); + BExpression be = new BBasicExpression(ee); + BExpression xe = new BBasicExpression(xx); + BExpression inexp = new BBinaryExpression(":",be,e); + BExpression fapp = + new BApplyExpression(f,be); + fapp.setMultiplicity(multiplicity); // f is data + BExpression un = + new BBinaryExpression("-",fapp,v); + BExpression pred = + new BBinaryExpression("=",xe,un); + pred = new BBinaryExpression("&",inexp,pred); + BExpression sc = + new BSetComprehension(vars,e,pred); + BExpression rhs = + new BBinaryExpression("<+",lhs,sc); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + if (op.equals("remove")) // f := f <+ { ee,xx | ee : e & xx = f(ee) - {v} } + { BSetExpression se = new BSetExpression(); + se.addElement(v); + Vector vars = new Vector(); + String ee = Identifier.nextIdentifier("_ee"); + vars.add(ee); + String xx = Identifier.nextIdentifier("_xx"); + vars.add(xx); + BExpression be = new BBasicExpression(ee); + BExpression xe = new BBasicExpression(xx); + BExpression inexp = new BBinaryExpression(":",be,e); + BExpression fapp = + new BApplyExpression(f,be); + fapp.setMultiplicity(multiplicity); // f is data + BExpression un = + new BBinaryExpression("-",fapp,se); + BExpression pred = + new BBinaryExpression("=",xe,un); + pred = new BBinaryExpression("&",inexp,pred); + BExpression sc = + new BSetComprehension(vars,e,pred); + BExpression rhs = + new BBinaryExpression("<+",lhs,sc); + res = new BAssignStatement(lhs,rhs); + res.setWriteFrame(f); + return res; + } + return new BBasicStatement("skip"); + } + + public static BExpression computeInverseBExpressionSet(Association ast, String role1, String role2, + int card1, int card2, BExpression var, + BExpression val) + { BExpression role1be = new BBasicExpression(role1); + Entity e1 = ast.getEntity1(); + String e1name = e1.getName(); + String e1var = e1name.toLowerCase() + "_xx"; + Entity e2 = ast.getEntity2(); + String e2name = e2.getName(); + String e2var = e2name.toLowerCase() + "_xx"; + String e2s = e2name.toLowerCase() + "s"; + BExpression e2sbe = new BBasicExpression(e2s); + Vector e1xset = new Vector(); + e1xset.add(var); + BExpression e1xsetbe = new BSetExpression(e1xset,false); + + if (card2 == ModelElement.MANY) + { if (card1 == ModelElement.ONE) + { // role1 := (val <<| role1) \\/ val*{var} + BExpression rhs1 = new BBinaryExpression("<<|",val,role1be); + rhs1.setBrackets(true); + BExpression rhs2 = new BBinaryExpression("*",val,e1xsetbe); + BExpression invrhs = new BBinaryExpression("\\/",rhs1,rhs2); + return invrhs; + } + else + { Vector scompvars = new Vector(); + scompvars.add(e2var); + scompvars.add(e1var); + BExpression e2varbe = new BBasicExpression(e2var); + BExpression e1varbe = new BBasicExpression(e1var); + BExpression pred11 = new BBinaryExpression(":",e2varbe,val); + BExpression role1app = new BApplyExpression(role1,e2varbe); + BExpression role1add = new BBinaryExpression("\\/",role1app,e1xsetbe); + BExpression pred12 = new BBinaryExpression("=",e1varbe,role1add); + BExpression pred1 = new BBinaryExpression("&",pred11,pred12); + BExpression comp1 = new BSetComprehension(scompvars,pred1); + BExpression role1sub = new BBinaryExpression("-",role1app,e1xsetbe); + BExpression pred21 = new BBinaryExpression("/:",e2varbe,val); + BExpression pred22 = new BBinaryExpression(":",e2varbe,e2sbe); + BExpression pred2 = new BBinaryExpression("&",pred22,pred21); + BExpression pred23 = new BBinaryExpression("=",e1varbe,role1sub); + BExpression comp2 = new BSetComprehension(scompvars, + new BBinaryExpression("&",pred2,pred23)); + BExpression invrhs = new BBinaryExpression("\\/", comp1, comp2); + return invrhs; + } // role1 := { bxx,axx | bxx : val & axx = ar(bxx) - { ax } } \\/ ... + } + else if (card2 == ModelElement.ONE && card1 != ModelElement.ONE) + { // role1 := { bx |-> ar(bx) \\/ {ax} } \\/ { bb,aa | bb : bs & bb /= bx & aa : ar(bx) - { ax } } + Vector scompvars = new Vector(); + scompvars.add(e2var); + scompvars.add(e1var); + BExpression e2varbe = new BBasicExpression(e2var); + BExpression e1varbe = new BBasicExpression(e1var); + BExpression pred11 = new BBinaryExpression("=",e2varbe,val); + BExpression role1app = new BApplyExpression(role1,e2varbe); + BExpression role1add = new BBinaryExpression("\\/",role1app,e1xsetbe); + BExpression pred12 = new BBinaryExpression("=",e1varbe,role1add); + BExpression pred1 = new BBinaryExpression("&",pred11,pred12); + BExpression comp1 = new BSetComprehension(scompvars,pred1); + BExpression role1sub = new BBinaryExpression("-",role1app,e1xsetbe); + BExpression pred21 = new BBinaryExpression("/=",e2varbe,val); + BExpression pred22 = new BBinaryExpression(":",e2varbe,e2sbe); + BExpression pred2 = new BBinaryExpression("&",pred22,pred21); + BExpression pred23 = new BBinaryExpression("=",e1varbe,role1sub); + BExpression comp2 = new BSetComprehension(scompvars, + new BBinaryExpression("&",pred2,pred23)); + BExpression invrhs = new BBinaryExpression("\\/", comp1, comp2); + return invrhs; + } + return null; + } + + public BStatement computeInverseBAdd(Association ast, String role1, String role2, + int card1, int card2, BExpression var, + BExpression val) + { BExpression role1be = new BBasicExpression(role1); + String e1name = entity.getName(); + String e1var = e1name.toLowerCase() + "_xx"; + Entity e2 = ast.getEntity2(); + String e2name = e2.getName(); + String e2var = e2name.toLowerCase() + "_xx"; + String e2s = e2name.toLowerCase() + "s"; + BExpression e2sbe = new BBasicExpression(e2s); + Vector e1xset = new Vector(); + e1xset.add(var); + BExpression e1xsetbe = new BSetExpression(e1xset,false); + + if (card1 != ModelElement.ONE) + { BExpression invlhs = new BApplyExpression(role1,val); + Vector invvals = new Vector(); + invvals.add(var); + BSetExpression role1se = new BSetExpression(invvals,false); + BExpression invrhs = new BBinaryExpression("\\/",invlhs,role1se); + invrhs.setBrackets(true); + BStatement inversecode = new BAssignStatement(invlhs,invrhs); + inversecode.setWriteFrame(role1); + return inversecode; + } + else // role1(nmexbe) := cx + { BExpression invlhs = new BApplyExpression(role1,val); + BStatement inversecode = new BAssignStatement(invlhs,var); + inversecode.setWriteFrame(role1); + return inversecode; + } + } + + + public BStatement computeInverseBDel(Association ast, String role1, String role2, + int card1, int card2, BExpression var, + BExpression val) + { BExpression role1be = new BBasicExpression(role1); + String e1name = entity.getName(); + String e1var = e1name.toLowerCase() + "_xx"; + Entity e2 = ast.getEntity2(); + String e2name = e2.getName(); + String e2var = e2name.toLowerCase() + "_xx"; + String e2s = e2name.toLowerCase() + "s"; + BExpression e2sbe = new BBasicExpression(e2s); + Vector e1xset = new Vector(); + e1xset.add(var); + BExpression e1xsetbe = new BSetExpression(e1xset,false); + + if (card1 != ModelElement.ONE) + { BExpression invlhs = new BApplyExpression(role1,val); + Vector invvals = new Vector(); + invvals.add(var); + BSetExpression role1se = new BSetExpression(invvals,false); + BExpression invrhs = new BBinaryExpression("-",invlhs,role1se); + invrhs.setBrackets(true); + BStatement inversecode = new BAssignStatement(invlhs,invrhs); + inversecode.setWriteFrame(role1); + return inversecode; + } + else // role1 := role1 domain anti-restriction { nmexbe } + { Vector invvals = new Vector(); + invvals.add(val); + BSetExpression role1se = new BSetExpression(invvals,false); + + BExpression invrhs = new BBinaryExpression("<<|",role1se,role1be); + BStatement inversecode = new BAssignStatement(role1be,invrhs); + inversecode.setWriteFrame(role1); + return inversecode; + } + } + + + public BExpression binvariantForm(java.util.Map env, boolean local) + { BExpression res; + + if (umlkind == CLASSID) + { if (arrayIndex != null) + { BExpression bind = arrayIndex.binvariantForm(env,local); + if (entity != null) + { Attribute pk = entity.getPrincipalKey(); + BExpression invpk = new BPostfixExpression("~", new BBasicExpression(pk.getName())); + if (arrayIndex.isMultiple()) + { res = new BApplySetExpression(invpk,bind); } + else + { res = new BApplyExpression(invpk,bind); } + return res; + } + } + String es = data.toLowerCase() + "s"; + res = new BBasicExpression(es); + res.setMultiplicity(ModelElement.MANY); + return res; + } + + if (umlkind == VALUE) + { if (data.equals("true")) + { res = new BBasicExpression("TRUE"); } + else if (data.equals("false")) + { res = new BBasicExpression("FALSE"); } + else if (isSequence(data) || isSet(data)) + { Expression se = buildSetExpression(data); + BExpression seqf = se.binvariantForm(env,local); + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,local); + return new BApplyExpression(seqf,ind); + } + return seqf; + } + else if (isString(data)) + { BExpression bexp = new BBasicExpression(data); + if (arrayIndex != null) + { BExpression ind = arrayIndex.binvariantForm(env,local); + return new BApplyExpression(bexp,ind); + } + return bexp; + } + res = new BBasicExpression(data); + res.setKind(VALUE); + return res; + } + + + if (umlkind == VARIABLE || umlkind == CONSTANT) + { if (data.equals("self")) + { BExpression var = findBContextVariable(env,entity); + return var; + } + res = new BBasicExpression(data); + res.setKind(umlkind); + if (objectRef != null) + { BExpression obj = objectRef.binvariantForm(env,local); + if (objectRef.isMultiple()) + { BExpression res2 = new BApplySetExpression(res,obj); + return res2; + } + else + { return new BApplyExpression(res,obj); } + } + return res; + } + + if (umlkind == FUNCTION) + { if (objectRef == null) + { return null; } // invalid function + BExpression pre = objectRef.binvariantForm(env,local); + String op; + if (data.equals("size")) // also strings + { op = "card"; + return new BUnaryExpression(op,pre); + } + else if (data.equals("sqr")) + { return new BBinaryExpression("*",pre,pre); } + else if (data.equals("Sum")) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + BExpression low = par1.binvariantForm(env,local); + BExpression upp = par2.binvariantForm(env,local); + BExpression ind = par3.binvariantForm(env,local); + BExpression exp = par4.binvariantForm(env,local); + BExpression rang = new BBinaryExpression("..", low, upp); + BExpression pred = new BBinaryExpression(":", ind, rang); + return new BSigmaExpression(par3 + "", pred, exp); + } + else if (data.equals("Prd")) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + BExpression low = par1.binvariantForm(env,local); + BExpression upp = par2.binvariantForm(env,local); + BExpression ind = par3.binvariantForm(env,local); + BExpression exp = par4.binvariantForm(env,local); + BExpression rang = new BBinaryExpression("..", low, upp); + BExpression pred = new BBinaryExpression(":", ind, rang); + return new BPiExpression(par3 + "", pred, exp); + } + else if (data.equals("abs") || data.equals("log") || data.equals("sin") || + data.equals("cos") || data.equals("tan") || + data.equals("sqrt") || data.equals("max") || data.equals("floor") || + data.equals("min") || data.equals("exp") || data.equals("round") || + data.equals("ceil") || data.equals("asin") || data.equals("acos") || + data.equals("atan") || data.equals("sinh") || data.equals("cosh") || + data.equals("tanh") || data.equals("log10") || data.equals("cbrt")) + { op = data; + return new BUnaryExpression(op,pre); + } // for sets.func a set comprehension + else if (data.equals("closure")) + { if (objectRef instanceof BasicExpression) + { BasicExpression beref = (BasicExpression) objectRef; + String rel = beref.data; + // the relation being closured + BExpression closureexp = new BApplyExpression("closure", new BBasicExpression(rel)); + + if (beref.objectRef != null) + { BExpression objs = + beref.objectRef.binvariantForm(env,local); + return new BApplyExpression(closureexp,objs); + } + else + { BExpression var = findBContextVariable(env,objectRef.entity); + return new BApplyExpression(closureexp,var); + } + } + BExpression arg = objectRef.binvariantForm(env,local); + return new BUnaryExpression("closure",arg); + } + else if (data.equals("any")) + { pre.setBrackets(true); + return new BApplyExpression(pre,new BBasicExpression("1")); + } + else if (data.equals("subcollections")) + { return new BUnaryExpression("FIN",pre); } // But not if objectRef is ordered + else if (data.equals("asSet")) + { if (objectRef.isOrderedB()) + { return new BUnaryExpression("ran",pre); } // Only if objectRef is ordered + else + { return pre; } + } // asSequence??? + else if (data.equals("oclIsKindOf") && parameters != null && parameters.size() > 0) + { Expression par1 = (Expression) parameters.get(0); + String par1s = par1 + ""; + BExpression rightobjs = new BBasicExpression(par1s.toLowerCase() + "s"); + return new BBinaryExpression(":", pre, rightobjs); + } + else if (data.equals("oclAsType")) + { return pre; } + else if (data.equals("sum")) // sum + { String xx = Identifier.nextIdentifier("_xx"); + BExpression xxbe = new BBasicExpression(xx); + BExpression pred = + new BBinaryExpression(":",xxbe,pre); + return new BSigmaExpression(xx,pred,xxbe); + } + else if (data.equals("prd")) // product + { String xx = Identifier.nextIdentifier("_xx"); + BExpression xxbe = new BBasicExpression(xx); + BExpression pred = + new BBinaryExpression(":",xxbe,pre); + return new BPiExpression(xx,pred,xxbe); + } + else if (data.equals("reverse")) + { return new BUnaryExpression("rev",pre); } + else if (data.equals("indexOf")) + { if (parameters != null && parameters.size() > 0) + { BExpression ber = + ((Expression) parameters.get(0)).binvariantForm(env,local); + BSetExpression img = new BSetExpression(); + img.addElement(ber); + BExpression func = new BPostfixExpression("~",pre); + res = new BApplySetExpression(func,img); + res = new BUnaryExpression("min",res); + return res; + } + } + else if (data.equals("count")) + { if (parameters != null && parameters.size() > 0) + { BExpression ber = + ((Expression) parameters.get(0)).binvariantForm(env,local); + BSetExpression img = new BSetExpression(); + img.addElement(ber); + BExpression func = new BPostfixExpression("~",pre); + res = new BApplySetExpression(func,img); + res = new BUnaryExpression("card",res); + return res; + } + } + else if (data.equals("subrange")) + { if (parameters != null && parameters.size() > 1) + { BExpression bstart = + ((Expression) parameters.get(0)).binvariantForm(env,local); + BExpression bend = + ((Expression) parameters.get(1)).binvariantForm(env,local); + bstart.setBrackets(true); + bend.setBrackets(true); + if ("Integer".equals(objectRef + "")) + { return new BBinaryExpression("..", bstart, bend); } + + BBinaryExpression bstartminus1 = + new BBinaryExpression("-",bstart,new BBasicExpression("1")); + bstartminus1.setBrackets(true); + BBinaryExpression trimend = + new BBinaryExpression("/|\\",pre,bend); + trimend.setBrackets(true); + return new BBinaryExpression("\\|/",trimend,bstartminus1); + } + } + else if (data.equals("insertAt")) + { if (parameters != null && parameters.size() > 1) + { BExpression bpos = + ((Expression) parameters.get(0)).binvariantForm(env,local); + BExpression obj = + ((Expression) parameters.get(1)).binvariantForm(env,local); + BBinaryExpression bposminus1 = + new BBinaryExpression("-",bpos,new BBasicExpression("1")); + bposminus1.setBrackets(true); + BBinaryExpression trimend = + new BBinaryExpression("/|\\",pre,bposminus1); + trimend.setBrackets(true); + BSetExpression objseq = new BSetExpression(); + objseq.addElement(obj); + objseq.setOrdered(true); + BBinaryExpression trimstart = + new BBinaryExpression("\\|/",pre,bposminus1); + trimstart.setBrackets(true); + return new BBinaryExpression("^",trimend, + new BBinaryExpression("^",objseq,trimstart)); + } + } + + else // last, first, front, tail - 1st 2 not quite correct for strings + { return new BUnaryExpression(data,pre); } + } + + System.out.println("*** Binvar form: " + this + " (multiple = " + isMultiple() + " ordered = " + isOrderedB() + ")"); + + if (objectRef == null) + { if (umlkind == ATTRIBUTE || umlkind == ROLE) + { if (entity.isClassScope(data)) // local means a local par? + { if (arrayIndex != null) + { return new BApplyExpression(data, + arrayIndex.binvariantForm(env,local)); + } + return new BBasicExpression(data); + } + // String ename = entity.getName(); + BExpression var = findBContextVariable(env,entity); + res = new BApplyExpression(data,var); // Assume that var is single-valued + res.setMultiplicity(multiplicity); + if (arrayIndex != null) + { res.setBrackets(true); + res = new BApplyExpression(res, + arrayIndex.binvariantForm(env,local)); + } + res.setKind(umlkind); + return res; + } + else if (umlkind == QUERY) + { Vector bpars = new Vector(); + BExpression var = findBContextVariable(env,entity); + Vector prepars = new Vector(); + prepars.add(var); + BBasicExpression bres = new BBasicExpression(data + "_" + entity,prepars); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + BExpression bpar = par.binvariantForm(env,true); + bpars.add(bpar); + } + } + return new BApplyExpression(bres,bpars); + } // may have array index + } + else // objectRef != null + { BExpression obj = objectRef.binvariantForm(env,local); + if (entity != null && entity.isClassScope(data)) // local means a local par? + { if (arrayIndex != null) + { return new BApplyExpression(data, + arrayIndex.binvariantForm(env,local)); + } + return new BBasicExpression(data); + } // also for functions + if (umlkind == QUERY) + { Vector bpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + BExpression bpar = par.binvariantForm(env,true); + bpars.add(bpar); + } + } + Vector prepars = new Vector(); + prepars.add(obj); + BBasicExpression bres = new BBasicExpression(data + "_" + entity,prepars); + if (bpars.size() > 0) + { if (objectRef.isMultiple()) // { op(ex)(pars) | ex : obj } + { Vector vars = new Vector(); + String xx = Identifier.nextIdentifier("xx"); + BExpression xxbe = new BBasicExpression(xx); + Vector prepars1 = new Vector(); + prepars1.add(xxbe); + BBasicExpression bres1 = + new BBasicExpression(data + "_" + entity,prepars1); + vars.add(new BApplyExpression(bres1,bpars)); + BBinaryExpression pred1 = new BBinaryExpression(":",xxbe,obj); + + BExpression comp = new BSetComprehension(vars,pred1); + return comp; + } + else + { return new BApplyExpression(bres,bpars); } + } + else + { if (objectRef.isMultiple()) + { return new BApplySetExpression( + new BBasicExpression(data + "_" + entity),obj); + } + else + { return bres; } + } + } // may have array index. What about obj? + else if (objectRef.isMultiple()) + { if (isOrderedB()) // seq-role or 1-role/attribute applied to seq objectRef + { BExpression comp = new BBinaryExpression(";",obj, + new BBasicExpression(data)); + comp.setBrackets(true); + if (umlkind == ATTRIBUTE || multiplicity == ModelElement.ONE) + { res = comp; } + else // seq role applied to seq object Ref + { res = new BUnaryExpression("conc",comp); } + } + else // object ref is a set, or role is set-valued + { BApplySetExpression app = new BApplySetExpression(data,obj); + // app.setMultiplicity(ModelElement.MANY); + if (umlkind == ATTRIBUTE || multiplicity == ModelElement.ONE) + { res = app; } // object ref is a set + else if (objectRef.isOrderedB()) // role is a set + { BUnaryExpression ranobjref = new BUnaryExpression("ran", obj); + res = new BApplySetExpression(data,ranobjref); + } + else // role is a sequence, and applied to a set, to produce a set! + { BUnaryExpression unionexp = new BUnaryExpression("union", app); + res = new BUnaryExpression("ran", unionexp); + } + } + if (arrayIndex != null) // the current expression must be a sequence or string + { res = new BApplyExpression(res, + arrayIndex.binvariantForm(env,local)); + } + res.setKind(umlkind); + System.out.println("B INVARIANT FORM OF " + this + " IS " + res); + return res; + } + else + { BApplyExpression app = new BApplyExpression(data,obj); // not null? + app.setMultiplicity(multiplicity); + if (arrayIndex != null) + { app = new BApplyExpression(app, + arrayIndex.binvariantForm(env,local)); + } + app.setKind(umlkind); + return app; + } + } + res = new BBasicExpression(data); + res.setKind(umlkind); + System.out.println(">> B INVARIANT FORM OF " + this + " IS " + res); + + return res; // and setKind in all other cases, as well. + } + + public boolean isMultiple() + { // Multiple if objectRef or arrayIndex are multiple, or if + // a Set, Sequence or multi-valued role or variable. Otherwise not. + + if (arrayIndex == null) // depends only on data itself + { if (umlkind == ROLE && + multiplicity != ModelElement.ONE) + { return true; } + + if (umlkind == CLASSID) + { return true; } + + if (umlkind == VARIABLE) + { return Type.isCollectionType(type); } + + if (objectRef != null) + { if ("last".equals(data) || "first".equals(data) || + "max".equals(data) || "min".equals(data) || "any".equals(data)) + { Type argelemtype = objectRef.getElementType(); + return (argelemtype != null && argelemtype.isCollectionType()); + } + if (objectRef.isMultiple()) + { if (data.equals("size") || data.equals("Sum") || data.equals("Prd") || + data.equals("sum") || data.equals("prd") || + data.equals("count") || data.equals("indexOf") || data.equals("isDeleted")) + { return false; } + else if (entity != null && entity.isStaticFeature(data) && + objectRef.umlkind == CLASSID && (objectRef instanceof BasicExpression) && + ((BasicExpression) objectRef).arrayIndex == null) + { return type.isMultiple(); } + else + { return true; } + } + } + + if (umlkind == FUNCTION) + { if (data.equals("closure") || data.equals("asSet") || data.equals("subcollections") || + // data.equals("front") || data.equals("tail") || data.equals("reverse") || + data.equals("characters") || data.equals("sort")) + { return true; } // or object ref multiple + if (data.equals("size") || data.equals("max") || data.equals("min") || + data.equals("Sum") || data.equals("Prd") || + data.equals("sum") || data.equals("indexOf") || + data.equals("count") || data.equals("prd") || data.equals("isDeleted")) + { return false; } + if (data.equals("first") || data.equals("last") || data.equals("any")) + { return Type.isCollectionType(objectRef.elementType); } + } + + + if (type == null) + { System.out.println("!Warning: null type in: " + data); + // JOptionPane.showMessageDialog(null, "Null type in: " + this, + // "Error", JOptionPane.ERROR_MESSAGE); + return false; + } + + if (type.getName().equals("String")) + { return false; } + + if (type.getName().equals("Set") || + type.getName().equals("Sequence")) + { return true; } + + if (data.equals("front") || data.equals("tail")) + { return true; } // Must be a sequence + + if (multiplicity != ModelElement.ONE) + { return true; } + + return false; + } + else // arrayIndex != null + { if (isQualified()) + { return multiplicity != ModelElement.ONE; } + + if (Type.isCollectionType(elementType)) + { return true; } + + if (umlkind == CLASSID) + { return arrayIndex.isMultiple(); } + + return false; + } + } // arrayIndex != null: reduces cardinality to 1 or 0..1, unless it is also + // multiple + + + + public Expression createActionForm(final Vector sms) + { /* actionForm = this; */ + buildJavaForm(sms); + return this; // for multiples, is data(objectRef) ?? + } + + public Expression substitute(Expression oldE, + Expression newE) + { if (oldE == this) + { return newE; } + BasicExpression res = (BasicExpression) clone(); + if (objectRef != null) + { Expression newobref = objectRef.substitute(oldE,newE); + res.objectRef = newobref; + } + if (arrayIndex != null) + { Expression newind = arrayIndex.substitute(oldE,newE); + res.arrayIndex = newind; + } + if (parameters != null) + { Vector newpars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + newpars.add(par.substitute(oldE,newE)); + } + res.parameters = newpars; + } + + return res; + } + + public Expression substituteEq(final String oldVar, + final Expression newVal) + { if (toString().equals(oldVar)) + { return (Expression) newVal.clone(); } + + BasicExpression res = (BasicExpression) clone(); + + Expression newind = null; + if (arrayIndex != null) + { newind = arrayIndex.substituteEq(oldVar,newVal); + res.arrayIndex = newind; + } + + Vector newpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + newpars.add(par.substituteEq(oldVar,newVal)); + } + res.parameters = newpars; + } + + if (objectRef == null) + { if (prestate) + { return res; } + if (data.equals(oldVar)) + { Expression res1 = (Expression) newVal.clone(); + if (res1 instanceof BasicExpression) + { BasicExpression res1be = (BasicExpression) res1; + res1be.parameters = newpars; + res1be.arrayIndex = newind; + return res1be; + } // discards other updates + return res1; + } + return res; + } + + res.objectRef = + objectRef.substituteEq(oldVar,newVal); + + /* New, untested: */ + if (data.equals(oldVar)) + { if (newVal instanceof BasicExpression) + { BasicExpression newData = (BasicExpression) newVal.clone(); + if (newData.objectRef != null) + { newData.setInnerObjectRef(res.objectRef); + return newData; + } + else + { newData.objectRef = res.objectRef; + return newData; + } + } + } + return res; + } // again, not if prestate + + public Expression removeSlicedParameters( + BehaviouralFeature op, Vector fpars) + { // op(parameters) becomes op(pars) where + // pars are the parameters *not* in the range of + // the removed formal parameters fpars of op + // op is original version of + // operation before slicing. + + BasicExpression res = (BasicExpression) clone(); + + Expression newind = null; + if (arrayIndex != null) + { newind = arrayIndex.removeSlicedParameters(op,fpars); + res.arrayIndex = newind; + } + + Vector oldpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + oldpars.add(par.removeSlicedParameters(op,fpars)); + } + res.parameters = oldpars; + } + + if (objectRef == null) + { } + else + { res.objectRef = + objectRef.removeSlicedParameters(op,fpars); + } + + if (data.equals(op.getName()) && + (umlkind == QUERY || umlkind == UPDATEOP)) + { Vector newpars = new Vector(); + Vector oppars = op.getParameters(); + for (int i = 0; i < oppars.size(); i++) + { Attribute att = (Attribute) oppars.get(i); + if (fpars.contains(att.getName())) + { System.out.println("++ Removing parameter " + att); } + else + { newpars.add(oldpars.get(i)); } + } + res.parameters = newpars; + } + + return res; + } + + public Expression removePrestate() + { + BasicExpression res = (BasicExpression) clone(); + + res.prestate = false; + + if (arrayIndex != null) + { Expression newind = arrayIndex.removePrestate(); + res.arrayIndex = newind; + } + + Vector newpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + newpars.add(par.removePrestate()); + } + res.parameters = newpars; + } + + if (objectRef == null) + { } + else + { res.objectRef = + objectRef.removePrestate(); + } + + res.setType(type); + res.setElementType(elementType); + + return res; + } + + public Expression simplify(final Vector vars) + { return simplify(); } + + public Expression simplify() + { if (umlkind == FUNCTION) + { if (objectRef == null) + { return this; } + Expression ors = objectRef.simplify(); + + // many cases, eg, 2.sqr as 4, etc + + if (data.equals("last") && + (ors instanceof SetExpression)) + { SetExpression se = (SetExpression) ors; + return se.getLastElement(); + } + else if (data.equals("first") && + (ors instanceof SetExpression)) + { SetExpression se = (SetExpression) ors; + return se.getFirstElement(); + } + else if (data.equals("size") && + (ors instanceof SetExpression)) + { SetExpression se = (SetExpression) ors; + return new BasicExpression(se.size()); + } + else if (data.equals("subrange") && + ors instanceof BasicExpression && + ((BasicExpression) ors).objectRef != null && + ((BasicExpression) ors).data.equals("subrange")) + { // e.subrange(a,b).subrange(c,d) is + // e.subrange(a+c-1, a+d-1) + + BasicExpression objref = (BasicExpression) ors; + Expression a = (Expression) objref.parameters.get(0); + Expression c = (Expression) parameters.get(0); + Expression newA = + Expression.simplifyPlus(a, c); + Expression newAsimp = + Expression.simplifyMinus(newA, + new BasicExpression(1)); + Vector pars = new Vector(); + pars.add(newAsimp); + BasicExpression res = + newFunctionBasicExpression("subrange", + objref.objectRef, + pars); + if (parameters.size() > 1) + { Expression d = (Expression) parameters.get(1); + Expression newB = + Expression.simplifyPlus(a, d); + Expression newBsimp = + Expression.simplifyMinus(newB, new BasicExpression(1)); + pars.add(newBsimp); + } + return res; + } + + objectRef = ors; + return this; + } + + if (arrayIndex == null) { return this; } + + Expression ai = arrayIndex.simplify(); + if (isNumber("" + ai) && isString(data)) + { int i = Integer.parseInt("" + ai); + String ss = data.substring(i-1,i); + BasicExpression res = new BasicExpression("\"" + ss + "\""); + return res; + // and type check it? + } + if (isNumber("" + ai) && isSequence(data)) + { int i = Integer.parseInt("" + ai); + SetExpression se = (SetExpression) buildSetExpression(data); + Expression res = se.getElement(i-1); + return res; + // and type check it? + } + if (objectRef == null) + { return this; } + Expression ors = objectRef.simplify(); + objectRef = ors; + if (isNumber("" + ai) && (ors instanceof SetExpression)) + { int i = Integer.parseInt("" + ai); + Expression ob = ((SetExpression) ors).getElement(i-1); + BasicExpression res = new BasicExpression(data); + res.objectRef = ob; // and copy the object ref of ors? + return res; + } + arrayIndex = ai; + return this; + } + + public Vector getBaseEntityUses() + { Vector res = new Vector(); + if (objectRef == null) + { if (umlkind == ROLE || umlkind == QUERY || umlkind == ATTRIBUTE) + { if (entity != null) + { if (entity.isStaticFeature(data)) + { System.err.println("!! ERROR: Static feature should have class name objectref: " + this); } + // must have class name as objectRef + else + { res.add(entity); } + } + } + else if ("self".equals(data) && entity != null) + { res.add(entity); } + } + else + { res.addAll(objectRef.getBaseEntityUses()); } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.getBaseEntityUses()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = VectorUtil.union(res,par.getBaseEntityUses()); + } + } + + return res; + } // and recursively also for parameters of operation calls + + public boolean hasVariable(final String s) + { return toString().equals(s); } + + /* allVariablesUsedIn */ + public Vector getVariableUses() + { Vector res = new Vector(); // of Expression + + if (("Sum".equals(data) || "Prd".equals(data)) && + "Integer".equals(objectRef + "") && parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + res.addAll(par1.getVariableUses()); + res.addAll(par2.getVariableUses()); + Vector ss = par4.getVariableUses(); + Vector removals = new Vector(); + for (int i = 0; i < ss.size(); i++) + { Expression e1 = (Expression) ss.get(i); + if ((e1 + "").equals(par3 + "")) + { removals.add(e1); } + } + ss.removeAll(removals); + res.addAll(ss); + return res; + } + + if (umlkind == VARIABLE && parameters == null) // it is a true variable + { if (variable != null) + { res.add(new BasicExpression(variable)); } // ignoring arrayIndex + else + { res.add(this); } + } + + if (objectRef != null) + { res.addAll(objectRef.getVariableUses()); } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.getVariableUses()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.getVariableUses()); + } + } + + return res; + } + + public Vector allVariableNames() + { Vector res = new Vector(); // of String + + if (("Sum".equals(data) || "Prd".equals(data)) && + "Integer".equals(objectRef + "") && parameters != null && parameters.size() > 3) + { Expression par1 = (Expression) parameters.get(0); + Expression par2 = (Expression) parameters.get(1); + Expression par3 = (Expression) parameters.get(2); + Expression par4 = (Expression) parameters.get(3); + res.addAll(par1.allVariableNames()); + res.addAll(par2.allVariableNames()); + res.add(par3 + ""); + Vector ss = par4.allVariableNames(); + res.addAll(ss); + return res; + } + + if (umlkind == VARIABLE && parameters == null) // it is a true variable + { if (variable != null) + { res.add(variable + ""); } // ignoring arrayIndex + else + { res.add(this + ""); } + } + + if (objectRef != null) + { res.addAll(objectRef.allVariableNames()); } + + if (arrayIndex != null) + { res = VectorUtil.union(res,arrayIndex.allVariableNames()); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allVariableNames()); + } + } + + return res; + } + + public Vector getAssignedVariableUses() + { Vector res = new Vector(); + + if (umlkind == VARIABLE && parameters == null) // it is a true variable + { if (variable != null) + { res.add(new BasicExpression(variable)); } // ignoring arrayIndex + else + { res.add(this); } + } + + if (objectRef != null && (objectRef instanceof BasicExpression)) + { res.addAll(((BasicExpression) objectRef).getAssignedVariableUses()); } + + return res; + } + + public Vector getUses(String feature) + { Vector res = new Vector(); + if (data.equals(feature)) + { res.add(this); } + else if (objectRef != null) + { res = objectRef.getUses(feature); } + if (arrayIndex != null) + { res.addAll(arrayIndex.getUses(feature)); } + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.getUses(feature)); + } + } + + return res; + } // and from arrayIndex + + + public Vector allFeaturesUsedIn() + { Vector res = new Vector(); + if (umlkind == ATTRIBUTE || umlkind == ROLE) + { res.add(data); } + if (objectRef != null) + { res.addAll(objectRef.allFeaturesUsedIn()); } + if (arrayIndex != null) + { res.addAll(arrayIndex.allFeaturesUsedIn()); } + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allFeaturesUsedIn()); + } + } + return res; + } // and from arrayIndex + + public Vector allAttributesUsedIn() + { Vector res = new Vector(); + if ("self".equals(this + "")) + { return res; } + if ("super".equals(this + "")) + { return res; } + + if (umlkind == ATTRIBUTE || umlkind == ROLE) + { Vector path = getAttributePath(); + res.add(new Attribute(path)); + } + else if (objectRef != null) + { res.addAll(objectRef.allAttributesUsedIn()); } + + /* + if (arrayIndex != null) + { res.addAll(arrayIndex.allFeaturesUsedIn()); } + */ + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allAttributesUsedIn()); + } + } + + return res; + } // and from arrayIndex + + private Vector getAttributePath() + { Attribute att = new Attribute(this); + if (objectRef != null && (objectRef instanceof BasicExpression) && + !("self".equals(objectRef + ""))) + { Vector path = ((BasicExpression) objectRef).getAttributePath(); + path.add(att); + return path; + } + Vector res = new Vector(); + res.add(att); + return res; + } + + public Vector allOperationsUsedIn() + { Vector res = new Vector(); + if (umlkind == UPDATEOP || umlkind == QUERY || isEvent) + { res.add(entity + "::" + data); } + if (objectRef != null) + { res.addAll(objectRef.allOperationsUsedIn()); } + if (arrayIndex != null) + { res.addAll(arrayIndex.allOperationsUsedIn()); } + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allOperationsUsedIn()); + } + } + return res; + } + + public boolean isSelfCall(BehaviouralFeature bf) + { String nme = bf.getName(); + + if (isSelfCall(nme)) + { return true; } + + Entity owner = bf.getEntity(); + if (bf.isStatic() && owner != null) + { String ename = owner.getName(); + if (isSelfCall(ename,nme)) + { return true; } + } + + return false; + } + + public boolean isSelfCall(String nme) + { if (data.equals(nme) && + "self".equals(objectRef + "") && + (umlkind == UPDATEOP || umlkind == QUERY || + isEvent)) + { return true; } + return false; + } + + public boolean isSelfCall(String ename, String nme) + { if (data.equals(nme) && + ename.equals(objectRef + "") && + (umlkind == UPDATEOP || umlkind == QUERY || + isEvent)) + { return true; } + return false; + } + + public Vector equivalentsUsedIn() + { Vector res = new Vector(); + if ("equivalent".equals(data)) + // { res.add(entity + "::" + data); } + { res.add(objectRef); } + + if (objectRef != null) + { res.addAll(objectRef.equivalentsUsedIn()); } + if (arrayIndex != null) + { res.addAll(arrayIndex.equivalentsUsedIn()); } + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.equivalentsUsedIn()); + } + } + return res; + } // and from arrayIndex + + public Vector allValuesUsedIn() + { Vector res = new Vector(); + if (umlkind == VALUE) + { res.add(data); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allValuesUsedIn()); + } + } + + if (arrayIndex != null) + { res.addAll(arrayIndex.allValuesUsedIn()); } + + if (objectRef != null) + { res.addAll(objectRef.allValuesUsedIn()); } + + return res; + } + + public Vector allBinarySubexpressions() + { return new Vector(); } + + public Vector componentsUsedIn(final Vector sms) + { Vector res = new Vector(); + int cat = Statemachine.NONE; + Statemachine sm = null; + + for (int i = 0; i < sms.size(); i++) + { sm = (Statemachine) sms.get(i); + cat = sm.getCategory(data); + if (cat == Statemachine.STATEMACHINE || + cat == Statemachine.ATTRIBUTE || + cat == Statemachine.EVENT) + { res.add(sm); + return res; + } + } + return res; + } + + public Expression addPreForms(String var) + { Expression arrayInd = arrayIndex; + Expression objRef = objectRef; + BasicExpression res = (BasicExpression) clone(); + + if (arrayIndex != null) + { arrayInd = arrayIndex.addPreForms(var); } + + if (objectRef != null) + { if ((objectRef + "").equals(var)) + { res.prestate = true; } + else + { objRef = objectRef.addPreForms(var); } // and add to the parameters, etc + } + + if (parameters != null) + { Vector newpars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Expression newpar = par.addPreForms(var); + newpars.add(newpar); + } + res.parameters = newpars; + } + + res.objectRef = objRef; + res.arrayIndex = arrayInd; + return res; + } + + public Vector allReadFrame() + { return readFrame(); } + + public Vector readFrame() + { Vector res; + String ename = ""; + + // System.out.println("||| " + this + " is " + umlkind + " " + entity); + + if ("equivalent".equals(data) && objectRef != null) + { res = objectRef.readFrame(); + res.add("$IN::$trace"); + res.add("$Trace::target"); + return res; + } + + if (objectRef != null) + { res = objectRef.readFrame(); + Type t = objectRef.elementType; + if (t != null && t.entity != null) + { ename = t.entity.getName() + "::"; } + else if (entity != null) + { ename = entity.getName() + "::"; } + } + else + { res = new Vector(); } + + if (umlkind == ROLE || umlkind == ATTRIBUTE) + { if (ename.length() == 0 && entity != null) + { ename = entity + "::"; } + if (prestate) + { res.add(ename + data + "@pre"); } + else + { res.add(ename + data); } + } + else if (umlkind == CLASSID) + { if (prestate) + { res.add(data + "@pre"); } + else + { res.add(data); } + + if (entity != null) + { Vector allsubs = entity.getAllSubclasses(); + for (int j = 0; j < allsubs.size(); j++) + { String subent = ((Entity) allsubs.get(j)).getName(); + if (prestate) + { res.add(subent + "@pre"); } + else + { res.add(subent); } + } + } + } + else if (umlkind == QUERY || umlkind == UPDATEOP) + { if (entity != null) + { BehaviouralFeature op = + entity.getDefinedOperation(data,parameters); + if (op != null) + { res.addAll(op.getReadFrame()); } + } + } + + if (arrayIndex != null) + { res.addAll(arrayIndex.readFrame()); } + + if (parameters != null) + { for (int j = 0; j < parameters.size(); j++) + { Expression par = (Expression) parameters.get(j); + res.addAll(par.allReadFrame()); + } + } + + return res; + } + + public Vector wr(Vector assocs) + { Vector res = new Vector(); + String ename = ""; + + if (prestate) { return res; } + + if ("equivalent".equals(data)) + { res.add("$IN::$trace"); + res.add("$Trace::target"); + res.add("$Trace"); + return res; + } + + if (objectRef != null) + { Type t = objectRef.elementType; + if (t != null && t.entity != null) + { ename = t + "::"; } + else if (entity != null) + { ename = entity.getName() + "::"; } + } + + if (umlkind == ROLE || umlkind == ATTRIBUTE) + { if (ename.length() == 0) + { ename = entity + "::"; } + res.add(ename + data); + if (umlkind == ROLE && entity != null) // also add opposite end if there is one + { String opp = Association.getOppositeEnd(data, entity, assocs); + if (opp != null) + { res.add(opp); } + } + } + else if (umlkind == CLASSID) + { res.add(data); + /* if (entity != null) + { Vector allsubs = entity.getAllSuperclasses(); + for (int j = 0; j < allsubs.size(); j++) + { res.add(((Entity) allsubs.get(j)).getName()); } + } */ + } // and all superclasses + else if (umlkind == UPDATEOP && entity != null) + { BehaviouralFeature op = entity.getDefinedOperation(data,parameters); + if (op != null) + { res.addAll(op.getWriteFrame(assocs)); } + } + + return res; + } + + public String updatedData() + { // The affected item in a[i] := v + // or a.op(pars) + + String res = null; + String objname = ""; + + if (prestate) + { return res; } + + if ("equivalent".equals(data)) + { return res; } + + if (objectRef != null) + { objname = objectRef + ""; } + + if (umlkind == ROLE || umlkind == ATTRIBUTE || + umlkind == VARIABLE) + { return objname + data; } + else if (umlkind == CLASSID) + { return objname + data; } + else if (umlkind == UPDATEOP || umlkind == QUERY) + { // BehaviouralFeature op = entity.getDefinedOperation(data,parameters); + // if (op != null) + // { res.addAll(op.getWriteFrame(assocs)); } + return objname; + } + + return res; + } + + public Vector readData() + { // The index in a[i] := v + // or pars data in a.op(pars) + + Vector res = new Vector(); + + if (prestate) + { return res; } + + if ("equivalent".equals(data)) + { return res; } + + if (arrayIndex != null) + { res.addAll(arrayIndex.allReadData()); } + + // if (umlkind == ROLE || umlkind == ATTRIBUTE || + // umlkind == VARIABLE || + // umlkind == CLASSID) + // { return res; } + // else if (umlkind == UPDATEOP || umlkind == QUERY) + // { + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Vector parvars = par.allReadData(); + res = VectorUtil.union(res,parvars); + } + } + // } + + return res; + } + + public Vector readBasicExpressionData() + { // All read basic expressions including arguments + + Vector res = new Vector(); + + if (prestate) + { return res; } + + if ("equivalent".equals(data)) + { return res; } + + if (arrayIndex != null) + { res.addAll(arrayIndex.allReadBasicExpressionData()); } + + // if (umlkind == ROLE || umlkind == ATTRIBUTE || + // umlkind == VARIABLE || + // umlkind == CLASSID) + // { return res; } + // else if (umlkind == UPDATEOP || umlkind == QUERY) + // { + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Vector parvars = par.allReadBasicExpressionData(); + res = VectorUtil.union(res,parvars); + } + } + // } + + return res; + } + + public Vector allReadBasicExpressionData() + { // All read basic expressions including arguments + + Vector res = new Vector(); + + if (prestate) + { return res; } + + if ("equivalent".equals(data)) + { return res; } + + // if (arrayIndex != null) + // { res.addAll( + // arrayIndex.allReadBasicExpressionData()); } + + if (umlkind == ROLE || umlkind == ATTRIBUTE || + umlkind == VARIABLE || + umlkind == CLASSID) + { res.add(this); + return res; + } + else if (umlkind == UPDATEOP || umlkind == QUERY) + { res.add(this); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + Vector parvars = par.allReadBasicExpressionData(); + res = VectorUtil.union(res,parvars); + } + } + } + + return res; + } + + + public Expression excel2Ocl(Entity target, Vector entities, Vector qvars, Vector antes) + { if (umlkind == VALUE) + { return this; } + if (umlkind == ATTRIBUTE) + { // E.Att becomes ex.att, ex added to qvars if needed. + if (entity == null) + { return this; } // error + if (entity == target) + { String tvarname = target.getName().toLowerCase() + "x"; + BasicExpression tvar = new BasicExpression(target, tvarname); + BasicExpression owexp = (BasicExpression) clone(); + owexp.setObjectRef(tvar); + owexp.setType(elementType); + return owexp; + } + else + { String svarname = entity.getName().toLowerCase() + "x"; + BasicExpression svar = new BasicExpression(entity, svarname); + BasicExpression owexp = (BasicExpression) clone(); + owexp.setObjectRef(svar); + if (qvars.contains(svarname)) { } + else + { qvars.add(svarname); + BinaryExpression scop = new BinaryExpression(":", svar, new BasicExpression(entity)); + antes.add(scop); + } + owexp.setType(elementType); + return owexp; + } + } + else if (isReduceFunctionCall()) + { // F(pars) with pars expected to be sequences. + return convertExcelExpression(); + } + else + { return convertExcelExpression(target,entities,qvars,antes); } + } + + public Vector splitToCond0Cond1(Vector conds, Vector v1, Vector v2, Vector v3) + { Expression cond0 = (Expression) conds.get(0); + Expression cond1 = (Expression) conds.get(1); + Vector res = new Vector(); + + Expression c1 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c1); + + return res; + } + + + // The following turns x : e & P & l = g & Q into [x,P,l,Q] in allvars + public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vector lvars, Vector allvars, Vector allpreds) + { Expression cond0 = (Expression) conds.get(0); + Expression cond1 = (Expression) conds.get(1); + Vector res = new Vector(); + // System.out.println("Split conds on: " + this); + + Expression c1; + if (cond1 == null) + { c1 = this; } + else + { c1 = new BinaryExpression("&",cond1,this); } + res.add(cond0); + res.add(c1); + allvars.add(this); + allpreds.add(this); + // System.out.println("Added condition: " + this); + + return res; + } + + public Vector splitToTCondPost(Vector tvars, Vector conds) + { Expression cond0 = (Expression) conds.get(0); + Expression cond1 = (Expression) conds.get(1); + Vector res = new Vector(); + + Expression c1 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c1); + + return res; + } + + public Vector variablesUsedIn(final Vector vars) + { Vector res = new Vector(); + String s = toString(); + if (vars.contains(s)) + { res.add(s); } // eg, att, or sig1.sig + return res; + } + + public boolean selfConsistent(final Vector vars) + { return true; } + + public boolean conflictsWith(Expression e) + { return false; } + + public Maplet findSubexp(final String var) + { return new Maplet(null,this); } /* ???? */ + + public Expression filter(final Vector vars) + { return null; } /* ???? */ + + public Vector splitAnd(final Vector comps) + { Vector res = new Vector(); + res.add(clone()); + return res; + } + + public Vector splitOr(final Vector comps) + { Vector res = new Vector(); + res.add(clone()); + return res; + } + + public Expression expandMultiples(final Vector sms) + { return this; } // Case of event? + + public Expression removeExpression(final Expression e) + { if (equals(e)) + { return null; } + else + { return this; } + } + + public boolean implies(final Expression e) + { if (equalsString("false")) { return true; } + if (e.equalsString("true")) { return true; } + if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (be.operator.equals("=")) { return false; } + else if (be.operator.equals("&")) + { return (implies(be.left) && implies(be.right)); } + else if (be.operator.equals("or")) + { return (implies(be.left) || implies(be.right)); } + else { return false; } + } + else if (e instanceof BasicExpression) + { return equals(e); } + else { return false; } + } + + public boolean consistentWith(final Expression e) + { return subformulaOf(e); } /* Eg, event names */ + + public boolean subformulaOf(final Expression e) + { if (e instanceof BasicExpression) + { return equals(e); } + else if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (isEvent) + { return subformulaOf(be.left) || subformulaOf(be.right); } + else + { return false; } // v isn't a subformula of v = val + } + return false; + } + + public Expression computeNegation4succ(final Vector as) + { if (data.equals("true")) + { return new BasicExpression("false"); } + if (data.equals("false")) + { return new BasicExpression("true"); } + if (umlkind == Expression.UPDATEOP) + { return new BasicExpression("false"); } // unsatisfactory. + return new UnaryExpression("not",this); + } /* if name of an event, "or" of others -NO. */ + + public Vector computeNegation4ante(final Vector as) + { Vector res = new Vector(); + if (data.equals("true")) + { res.add(new BasicExpression("false")); } + if (data.equals("false")) + { res.add(new BasicExpression("true")); } + return res; + } + + public Expression computeNegation4succ() + { if (data.equals("true")) + { return new BasicExpression("false"); } + if (data.equals("false")) + { return new BasicExpression("true"); } + if (umlkind == Expression.UPDATEOP) + { return new BasicExpression("false"); } // unsatisfactory + return new UnaryExpression("not",this); + } /* if name of an event, "or" of others -NO. */ + + public Vector computeNegation4ante() + { Vector res = new Vector(); + if (data.equals("true")) + { res.add(new BasicExpression("false")); } + if (data.equals("false")) + { res.add(new BasicExpression("true")); } + res.add(new UnaryExpression("not",this)); // Added Jan 2016 + return res; + } + + + public DataDependency getDataItems() + { DataDependency res = new DataDependency(); + if (umlkind == ATTRIBUTE || umlkind == ROLE || + umlkind == VARIABLE || umlkind == CONSTANT) + { res.addSource(new BasicExpression(data)); } + if (objectRef != null) + { DataDependency dd = objectRef.getDataItems(); + res.union(dd); + } + if (arrayIndex != null) + { DataDependency dd2 = arrayIndex.getDataItems(); + res.union(dd2); + } + + return res; + } + + public DataDependency rhsDataDependency() // ???? + { DataDependency res = new DataDependency(); + if (kind == ATTRIBUTE || kind == ROLE) + { res.addTarget(this); } + else + { res.addSource(this); } + if (objectRef == null) + { return res; } + return res.union(objectRef.getDataItems()); + } // and the arrayindex + // target is the entity of first element of targets + // that is not the src. + + public Expression matchCondition(String op, String f, + Expression exbe) + { if (objectRef == null) + { if (data.equals(f)) + { return new BasicExpression("true"); } + else + { return new BasicExpression("false"); } + } // or in arrayRef + else if (objectRef.multiplicity == ModelElement.ONE) + { if (data.equals(f)) + { return new BinaryExpression("=",exbe,objectRef); } + else + { return objectRef.matchCondition(op,f,exbe); } + } + else + { if (data.equals(f)) + { return new BinaryExpression(":",exbe,objectRef); } + else + { return objectRef.matchCondition(op,f,exbe); } + } + } + + public Expression featureSetting(String var, String feat, Vector r) + { return null; } + + public boolean nakedUse(String f) // Ie, of form f.features + { if (data.equals(f)) + { if (objectRef != null) + { return false; } + return true; // parameters and object ref also should be naked if use f + } + else if (objectRef == null) + { return false; } + else if (objectRef instanceof BasicExpression) + { return ((BasicExpression) objectRef).nakedUse(f); } + else + { return false; } + } + + + /* public static void main(String[] args) + { Compiler2 comp = new Compiler2(); + comp.nospacelexicalanalysis("\"abc\"[2]"); + Expression e = comp.parse(); + System.out.println(e); + System.out.println(e.toZ3()); + Vector v = new Vector(); + System.out.println(e.typeCheck(v,v,v,v)); + // System.out.println(((BasicExpression) e).arrayIndex); + } */ + + public static void main(String[] args) + { // System.out.println(Math.log10(100)); + // System.out.println(Math.log(100)/Math.log(10)); + BasicExpression expr = new BasicExpression("x@100"); + System.out.println(expr); + BasicExpression expr1 = new BasicExpression("0xFFFFFFFFFFFFFFFFFFFF"); + System.out.println(expr1); + Vector t = new Vector(); + Vector e = new Vector(); + Vector v = new Vector(); + expr1.typeCheck(t,e,v); + System.out.println(">>> Type of " + expr1 + " is: " + expr1.type + " ( " + expr1.elementType + " )"); + + } + + public Expression simplifyOCL() + { // Replaces energy-expensive processing by simpler. + + Expression objR = objectRef; + if (objectRef != null) + { objR = objectRef.simplifyOCL(); } + + Expression arrInd = arrayIndex; + if (arrayIndex != null) + { arrInd = arrayIndex.simplifyOCL(); } + + Vector pars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + pars.add(par.simplifyOCL()); + } + } + else + { pars = parameters; } + + BasicExpression res = (BasicExpression) clone(); + res.objectRef = objR; + res.arrayIndex = arrInd; + res.parameters = pars; + return res; + } + + + + public Map energyUse(Map res, Vector rUses, Vector oUses) + { // Calls to OclType reflection operators and OclDatasource + // connect are red flags. + + if (objectRef != null) + { objectRef.energyUse(res,rUses,oUses); } + + if (arrayIndex != null) + { arrayIndex.energyUse(res,rUses,oUses); + if (arrayIndex.isCollectionValued()) + { rUses.add("!!! Expensive operation: implicit ->collect over index collection in: " + this); + int rscore = (int) res.get("red"); + res.set("red", rscore+1); + } + } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + par.energyUse(res,rUses,oUses); + } + } + + if (umlkind == VALUE) {} + else if (umlkind == UPDATEOP || + umlkind == QUERY) + { if ("OclProcess".equals(objectRef + "") && + "newOclProcess".equals(data)) + { rUses.add("!!! Expensive operation: Call of process/task creation: " + this); + int rscore = (int) res.get("red"); + res.set("red", rscore+1); + } + else if ("OclType".equals(objectRef + "") && + "loadExecutableObject".equals(data)) + { rUses.add("!!! Expensive operation: Runtime library loading: " + this); + int rscore = (int) res.get("red"); + res.set("red", rscore+1); + } + else if ("OclDatasource".equals(objectRef + "") && + "getConnection".equals(data)) + { rUses.add("!!! Expensive operation: Database/internet connection: " + this); + int rscore = (int) res.get("red"); + res.set("red", rscore+1); + } + else if ("OclType".equals(objectRef + "") && + ("getAttributeValue".equals(data) || + "setAttributeValue".equals(data) || + "hasAttribute".equals(data) || + "removeAttribute".equals(data))) + { rUses.add("!!! Reflection is expensive: " + this); + int rscore = (int) res.get("red"); + res.set("red", rscore+1); + } + } + + return res; + } + + public java.util.Map collectionOperatorUses(int level, + java.util.Map res, Vector vars) + { // level |-> [x.setAt(i,y), etc] + + if (data.equals("insertAt") || + data.equals("insertInto") || + data.equals("subrange") || + data.equals("setAt") || + data.equals("excludingSubrange") || + data.equals("setSubrange")) + { Vector opers = (Vector) res.get(level); + if (opers == null) + { opers = new Vector(); } + opers.add(this); + res.put(level, opers); + + Vector vuses = variablesUsedIn(vars); + if (level > 1 && vuses.size() == 0) + { JOptionPane.showInputDialog(">> The expression " + this + " is independent of the iterator variables " + vars + "\n" + + "Use Extract local variable to optimise."); + refactorELV = true; + } + + return res; + } + + if (arrayIndex != null) + { BasicExpression be = (BasicExpression) clone(); + be.arrayIndex = null; + BinaryExpression newbe = + new BinaryExpression("->at", be, arrayIndex); + Vector opers = (Vector) res.get(level); + if (opers == null) + { opers = new Vector(); } + opers.add(newbe); + res.put(level, opers); + return res; + } + + return res; + } // and in the parameters and object ref + + + public int syntacticComplexity() + { int res = 0; + + if (objectRef != null) + { res = objectRef.syntacticComplexity(); } + + if (arrayIndex != null) + { res = res + arrayIndex.syntacticComplexity(); } + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res = res + par.syntacticComplexity(); + } + } + + if (umlkind == VALUE) {} + else + // if (umlkind == ATTRIBUTE || umlkind == CLASSID || umlkind == UPDATEOP || + // umlkind == QUERY || umlkind == ROLE) + if (objectRef == null) + { return res + 1; } + else + { return res + 2; } + + // one for the "." and 1 for the data. + + return res; + } // and arrayIndex, parameters + + public int cyclomaticComplexity() + { return 1; } // a basic boolean predicate + + public void changedEntityName(String oldN, String newN) + { if (data.equals(oldN)) + { data = newN; } + if (type != null && oldN.equals(type.getName())) + { type.setName(newN); } + if (elementType != null && oldN.equals(elementType.getName())) + { elementType.setName(newN); } + if (objectRef != null) + { objectRef.changedEntityName(oldN, newN); } + if (arrayIndex != null) + { arrayIndex.changedEntityName(oldN, newN); } + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + par.changedEntityName(oldN, newN); + } + } + } + + public String cg(CGSpec cgs) + { String etext = (this + "").trim(); + Vector args = new Vector(); + Vector eargs = new Vector(); + Vector textrules = new Vector(); + + if (("displayString".equals(data) || + "displayint".equals(data) || + "displaylong".equals(data) || + "displaydouble".equals(data) || + "displayboolean".equals(data) || + "displaySequence".equals(data) || + "displaySet".equals(data) || + "displayMap".equals(data)) && + parameters != null && + parameters.size() == 1) + { Expression par1 = (Expression) parameters.get(0); + args.add(par1.cg(cgs)); + eargs.add(par1); + CGRule r = cgs.matchedBasicExpressionRule(this,etext,textrules); + if (r != null) + { System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + String res = r.applyRule(args,eargs,cgs); + return res; + } + } + + + if (umlkind == FUNCTION) + { // process as the corresponding unary or binary expression + if ("allInstances".equals(data)) + { args.add(objectRef + ""); + eargs.add(objectRef); + CGRule r = cgs.matchedBasicExpressionRule(this,etext,textrules); + if (r != null) + { // System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + String res = r.applyRule(args,eargs,cgs); + return res; + } + } + else if ("size".equals(data) || + "reverse".equals(data) || + "toLowerCase".equals(data) || + "toUpperCase".equals(data) || + "first".equals(data) || "last".equals(data) || + "front".equals(data) || "tail".equals(data)) + { // args.add(objectRef + ""); + // eargs.add(objectRef); + UnaryExpression uexp = new UnaryExpression(this); + System.out.println(">> Converted basic expression " + this + + " to UnaryExpression " + uexp); + return uexp.cg(cgs); + } + else if (parameters != null && parameters.size() == 0) + { UnaryExpression uexp = new UnaryExpression(this); + System.out.println(">> Converted basic expression " + this + + " to UnaryExpression " + uexp); + return uexp.cg(cgs); + } + else if (parameters != null && parameters.size() == 2) + { // case of x.insertAt(i,y) or s.subrange(x,y) + if ("Integer".equals(objectRef + "")) { } + else + { args.add(objectRef.cg(cgs)); + // eargs.add(objectRef); + } + args.add(((Expression) parameters.get(0)).cg(cgs)); + args.add(((Expression) parameters.get(1)).cg(cgs)); + eargs.add((Expression) parameters.get(0)); + eargs.add((Expression) parameters.get(1)); + CGRule r = cgs.matchedBasicExpressionRule(this,etext,textrules); + + if (r != null) + { System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + } + else if (parameters != null && parameters.size() == 3) + { // s.setSubrange(i,j,v) + args.add(objectRef.cg(cgs)); + args.add(((Expression) parameters.get(0)).cg(cgs)); + args.add(((Expression) parameters.get(1)).cg(cgs)); + args.add(((Expression) parameters.get(2)).cg(cgs)); + eargs.add(objectRef); + eargs.add((Expression) parameters.get(0)); + eargs.add((Expression) parameters.get(1)); + eargs.add((Expression) parameters.get(2)); + CGRule r = cgs.matchedBasicExpressionRule(this,etext,textrules); + + if (r != null) + { System.out.println(">> Matched basic expression rule: " + r + " to: " + etext + " with arguments= " + args); + + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + } + else if (parameters != null && parameters.size() == 4 && "Integer".equals(objectRef + "")) + { // Integer.Sum(a,b,i,e), Integer.Prd(a,b,i,e) + args.add(((Expression) parameters.get(0)).cg(cgs)); + args.add(((Expression) parameters.get(1)).cg(cgs)); + args.add(((Expression) parameters.get(2)).cg(cgs)); + args.add(((Expression) parameters.get(3)).cg(cgs)); + eargs.add((Expression) parameters.get(0)); + eargs.add((Expression) parameters.get(1)); + eargs.add((Expression) parameters.get(2)); + eargs.add((Expression) parameters.get(3)); + CGRule r = cgs.matchedBasicExpressionRule(this,etext,textrules); + + if (r != null) + { // System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + } + else if (parameters != null && parameters.size() == 1) + { BinaryExpression bexp = new BinaryExpression(this); + // System.out.println(">> Converted basic expression " + this + + // " to BinaryExpression " + bexp); + return bexp.cg(cgs); + } + // case of _1.pow(_2), _1.subrange(_2) etc + } + + + if (arrayIndex != null) // no parametrs + { BasicExpression arg = (BasicExpression) clone(); + arg.arrayIndex = null; + arg.parameters = null; + arg.elementType = type; + if (arrayIndex.type != null && arrayIndex.type.isInteger()) + { arg.type = new Type("Sequence", null); } + else + { arg.type = new Type("Map", null); } + + args.add(arg.cg(cgs)); // but need to retype it + args.add(arrayIndex.cg(cgs)); + eargs.add(arg); + eargs.add(arrayIndex); + } // assume parameters == null + else if (objectRef != null) + { args.add(objectRef.cg(cgs)); + eargs.add(objectRef); + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; // retype it + if (parameters != null) + { String pars = ""; + if (parameters.size() > 0) + { Expression p = (Expression) parameters.get(0); + Vector partail = new Vector(); + partail.addAll(parameters); + partail.remove(0); + pars = p.cgParameter(cgs,partail); + } + // args.add(pars); + // eargs.add(parameters); + + /* String parg = ""; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + String parstring = par.cg(cgs); + parg = parg + parstring; + if (i < parameters.size()-1) + { parg = parg + ","; } + // need special processig for parameters + } */ + dataexp.parameters = null; + + System.out.println(dataexp + " is static: " + dataexp.isStatic); + String dexcg = dataexp.cg(cgs); + System.out.println(dexcg); + System.out.println(); + + args.add(dataexp.cg(cgs)); + args.add(pars); + eargs.add(dataexp); + eargs.add(parameters); + } + else + { args.add(dataexp.cg(cgs)); + eargs.add(dataexp); + } + } + else if (parameters != null) + { String parg = ""; + // Set the formalParameter of each par to + // the corresponding attribute of the operation. + + if (parameters.size() > 0) + { Expression p = (Expression) parameters.get(0); + Vector partail = new Vector(); + partail.addAll(parameters); + partail.remove(0); + parg = p.cgParameter(cgs,partail); + } + args.add(data); + args.add(parg); + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + dataexp.parameters = null; // need to retype it + eargs.add(dataexp); + eargs.add(parameters); + } + else + { args.add(etext); + eargs.add(this); + } + // and cg of parameters + + textrules = new Vector(); + CGRule r = cgs.matchedBasicExpressionRule(this,etext,textrules); + + System.out.println(">>> Found basic expression rule: " + r + " for " + this + " args= " + args + + " eargs= " + eargs); + System.out.println(); + + if (r != null) + { if (textrules.size() > 0) + { CGRule tr = (CGRule) textrules.get(0); + System.out.println(">>> Applying text rule " + tr + " " + tr.variables); + if (tr.variables.size() == 2) // it is text_1(_2) + { BasicExpression rootexp = (BasicExpression) clone(); + rootexp.parameters = null; + String rootstring = rootexp + ""; + String prefix = ModelElement.longestCommonPrefix(rootstring,tr.lhs); + String remstring = + rootstring.substring( + prefix.length(), rootstring.length()); + Vector textargs = new Vector(); + textargs.add(remstring); + String parstring = ""; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parstring = parstring + par.cg(cgs); + if (i < parameters.size() - 1) + { parstring = parstring + ", "; } + } + textargs.add(parstring); + return tr.applyRule(textargs); + } + else if (tr.variables.size() == 1 && + tr.lhs.endsWith("_1()")) // it is text_1() + { BasicExpression rootexp = (BasicExpression) clone(); + rootexp.parameters = null; + String rootstring = rootexp + ""; + String prefix = ModelElement.longestCommonPrefix(rootstring,tr.lhs); + String remstring = rootstring.substring(prefix.length(), rootstring.length()); + Vector textargs = new Vector(); + textargs.add(remstring); + return tr.applyRule(textargs); + } + else if (tr.variables.size() == 1 && + tr.lhs.endsWith("(_1)")) // it is text(_1) + { Vector textargs = new Vector(); + String parstring = ""; + for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + parstring = parstring + par.cg(cgs); + if (i < parameters.size() - 1) + { parstring = parstring + ", "; } + } + textargs.add(parstring); + return tr.applyRule(textargs); + } + } + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + else + { r = cgs.matchedTextRule(etext); + if (r != null) + { System.out.println(">>> Found basic expression text rule: " + r + " for " + this); + return r.applyTextRule(etext); + } + } + return etext; + } + +} + diff --git a/version24/BasicState.class b/version24/BasicState.class new file mode 100644 index 0000000000000000000000000000000000000000..05e75c43388db21ef891e0fda598a35aec1dea29 GIT binary patch literal 708 zcma)3(P|Sx6g_vl$u{e1Yi!k~TC28_Y+K`lPew!(1tHdllt4g`$!2V~Y&H-lf=_~= ztv>iI3Sz*3AK*ucXVMjyJh`xQ@0@$)o^xk@{r>S2z-`>{;p2jbizPT%@wsqQ@ln94 zT`qaJ>|-8l9WNDC>n$^k)BQ%REpQ(WdRnm1j8nZk>UZ^U zPjwR_g(w-Mj7!y8?&P!Xp^i*L;Jr+gF*+42lF%~B=)Q^$*o8&E|K^3&ja4Ez!}{J~DAqZ&Q6Rw9IP(u46+Gr%CZ@DgDG2?Dv&Y}n=a5~{P%#GoGnK|)}jI$_b zC!VuUfs9)d6gs3An>KNoJpGI8ZinCDO)%dHw|2J2DBW>aa$PIz0C|s+d_Y-_uqww` dmyg(yPt-VvrA(>9XuUb%tfSAwmu&^-{{U%2kZ=G1 literal 0 HcmV?d00001 diff --git a/version24/Behaviour.class b/version24/Behaviour.class new file mode 100644 index 0000000000000000000000000000000000000000..367588370fcdad162fab2cc04a08e8034b107ad6 GIT binary patch literal 2232 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, "); + Vector pars = new Vector(); + while (stok.hasMoreTokens()) + { String par = stok.nextToken(); + Type tt = Type.getTypeFor(par,types,entities); + if (tt != null) + { pars.add(tt); } + else + { Entity entpar = new Entity(par); + tt = new Type(entpar); + pars.add(tt); + } + System.out.println(">> Added type parameter " + tt); + } + + typeParameters = pars; + } + + public void setTypeParameters(Vector pars) + { typeParameters = pars; } + + public boolean isGeneric() + { return typeParameters != null && + typeParameters.size() > 0; + } + + public String getCompleteName() + { String nme = getName(); + + if (typeParameters.size() > 0) + { String tp = ""; + for (int i = 0; i < typeParameters.size(); i++) + { tp = tp + + ((ModelElement) typeParameters.get(i)).getName(); + if (i < typeParameters.size()-1) + { tp = tp + ","; } + } + nme = nme + "<" + tp + ">"; + } + + return nme; + } + + public int getArity() + { if (parameters == null) + { return 0; } + return parameters.size(); + } + + public Object clone() + { Vector newpars = new Vector(); + if (parameters == null) { } + else + { for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + Attribute newpar = (Attribute) par.clone(); + newpars.add(newpar); + } + } + BehaviouralFeature res = new BehaviouralFeature(getName(), + newpars, query, resultType); + res.setElementType(elementType); + res.setStatechart(sm); + res.setActivity(activity); + res.setEntity(entity); + res.setInstanceScope(instanceScope); + res.setDerived(derived); + res.setOrdered(ordered); + res.setSorted(sorted); + res.setPre(pre); // I assume these + res.setPost(post); // should be copied, or cloned? + res.setBx(bx); + if (typeParameters != null) + { res.typeParameters = new Vector(); + res.typeParameters.addAll(typeParameters); + } // clone them. + + return res; + } // and copy the use case, readfr, etc? + + public BehaviouralFeature interfaceOperation() + { BehaviouralFeature res = (BehaviouralFeature) clone(); + res.activity = null; + res.setAbstract(true); + return res; + } + + public BehaviouralFeature addContainerReference( + BasicExpression ref, + String var, Vector excl) + { BehaviouralFeature res = new BehaviouralFeature(getName(), parameters, query, resultType); + res.setElementType(elementType); + res.setStatechart(sm); + res.setEntity(entity); + res.setInstanceScope(instanceScope); + res.setDerived(derived); + res.setOrdered(ordered); + res.setSorted(sorted); + res.setBx(bx); + + Vector newexcl = new Vector(); + newexcl.addAll(excl); + newexcl.add(getName()); + + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + newexcl.add(att.getName()); + } + } + + if (typeParameters != null) + { res.typeParameters = new Vector(); + res.typeParameters.addAll(typeParameters); + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + newexcl.add(tp.getName()); + } + } + + Expression newpre = null; + if (pre != null) + { newpre = pre.addContainerReference(ref,var,newexcl); } + else + { newpre = new BasicExpression(true); } + Expression newpost = null; + if (post != null) + { newpost = post.addContainerReference(ref,var,newexcl); } + else + { newpost = new BasicExpression(true); } + Statement newact = null; + if (activity != null) { + newact = activity.addContainerReference(ref,var,newexcl); + } + + res.setActivity(newact); + res.setPre(newpre); + res.setPost(newpost); + + return res; + } // and copy the use case, readfr, etc? + + public static BehaviouralFeature newConstructor(String ename, + Entity ent, Vector pars) + { BehaviouralFeature bf = new BehaviouralFeature("new" + ename); + bf.setParameters(pars); + Entity e = new Entity(ename); + + Type etype = new Type(e); + bf.setType(etype); + bf.setPostcondition(new BasicExpression(true)); + SequenceStatement code = new SequenceStatement(); + + BasicExpression res = + BasicExpression.newVariableBasicExpression( + "res", etype); + + CreationStatement cs = + new CreationStatement("res", etype); + // cs.setInstanceType(etype); + code.addStatement(cs); + + BasicExpression createCall = + new BasicExpression("create" + ename); + createCall.setUmlKind(Expression.UPDATEOP); + createCall.setParameters(new Vector()); + createCall.setIsEvent(); + createCall.setType(etype); + createCall.setStatic(true); + // createCall.entity = e; + + AssignStatement assgn = new AssignStatement(res,createCall); + code.addStatement(assgn); + + BasicExpression initialiseCall = + new BasicExpression("initialise"); + initialiseCall.setUmlKind(Expression.UPDATEOP); + initialiseCall.setIsEvent(); + Vector parNames = bf.getParameterExpressions(); + // System.out.println(">>=== " + pars + " " + parNames); + + initialiseCall.setParameters(parNames); + initialiseCall.setObjectRef(res); + InvocationStatement callInit = + new InvocationStatement(initialiseCall); + callInit.setParameters(parNames); + code.addStatement(callInit); + + // Add each instance _initialiseInstance() operation + // res._initialiseInstance() + if (ent != null) + { Vector allops = ent.getOperations(); + for (int i = 0; i < allops.size(); i++) + { BehaviouralFeature op = (BehaviouralFeature) allops.get(i); + String opname = op.getName(); + if (opname.startsWith("_initialiseInstance")) + { BasicExpression initialiseInstanceCall = + new BasicExpression(opname); + initialiseInstanceCall.setUmlKind(Expression.UPDATEOP); + initialiseInstanceCall.setIsEvent(); + initialiseInstanceCall.setParameters(new Vector()); + initialiseInstanceCall.setObjectRef(res); + InvocationStatement callInstInit = + new InvocationStatement(initialiseInstanceCall); + callInstInit.setParameters(new Vector()); + code.addStatement(callInstInit); + } + } + } + + ReturnStatement rs = new ReturnStatement(res); + code.addStatement(rs); + + code.setBrackets(true); + + bf.setActivity(code); + bf.setStatic(true); + + return bf; + } + + public static BehaviouralFeature newConstructor(String ename, + Entity ent, Vector pars, + Vector gpars) + { BehaviouralFeature bf = new BehaviouralFeature("new" + ename); + bf.setParameters(pars); + Entity e = new Entity(ename); + if (gpars != null) + { e.setTypeParameters(gpars); } + + Type etype = new Type(e); + bf.setType(etype); + + System.out.println(">> Generic parameters of " + bf + " are " + gpars); + + System.out.println(">> Return type of " + bf + " is " + e.getCompleteName()); + + bf.setPostcondition(new BasicExpression(true)); + SequenceStatement code = new SequenceStatement(); + + BasicExpression res = + BasicExpression.newVariableBasicExpression( + "res", etype); + + CreationStatement cs = + new CreationStatement("res", etype); + cs.setInstanceType(etype); + code.addStatement(cs); + + BasicExpression createCall = + new BasicExpression("create" + ename); + createCall.setUmlKind(Expression.UPDATEOP); + createCall.setParameters(new Vector()); + createCall.setIsEvent(); + createCall.setType(etype); + createCall.setStatic(true); + // createCall.entity = e; + + AssignStatement assgn = new AssignStatement(res,createCall); + code.addStatement(assgn); + + BasicExpression initialiseCall = + new BasicExpression("initialise"); + initialiseCall.setUmlKind(Expression.UPDATEOP); + initialiseCall.setIsEvent(); + Vector parNames = bf.getParameterExpressions(); + // System.out.println(">>=== " + pars + " " + parNames); + + initialiseCall.setParameters(parNames); + initialiseCall.setObjectRef(res); + InvocationStatement callInit = + new InvocationStatement(initialiseCall); + callInit.setParameters(parNames); + code.addStatement(callInit); + + // Add each instance _initialiseInstance() operation + // res._initialiseInstance() + Vector allops = ent.getOperations(); + for (int i = 0; i < allops.size(); i++) + { BehaviouralFeature op = (BehaviouralFeature) allops.get(i); + String opname = op.getName(); + if (opname.startsWith("_initialiseInstance")) + { BasicExpression initialiseInstanceCall = + new BasicExpression(opname); + initialiseInstanceCall.setUmlKind(Expression.UPDATEOP); + initialiseInstanceCall.setIsEvent(); + initialiseInstanceCall.setParameters(new Vector()); + initialiseInstanceCall.setObjectRef(res); + InvocationStatement callInstInit = + new InvocationStatement(initialiseInstanceCall); + callInstInit.setParameters(new Vector()); + code.addStatement(callInstInit); + } + } + + ReturnStatement rs = new ReturnStatement(res); + code.addStatement(rs); + + code.setBrackets(true); + + bf.setActivity(code); + bf.setStatic(true); + + return bf; + } + + public static BehaviouralFeature newStaticConstructor(String ename, Vector pars) + { BehaviouralFeature bf = new BehaviouralFeature("new" + ename); + bf.setParameters(pars); + Entity e = new Entity(ename); + Type etype = new Type(e); + bf.setType(etype); + bf.setPostcondition(new BasicExpression(true)); + SequenceStatement code = new SequenceStatement(); + + BasicExpression res = BasicExpression.newVariableBasicExpression("result", etype); + + CreationStatement cs = new CreationStatement("result", etype); + code.addStatement(cs); + + BasicExpression createCall = new BasicExpression("create" + ename); + createCall.setUmlKind(Expression.UPDATEOP); + createCall.setParameters(new Vector()); + createCall.setIsEvent(); + createCall.setType(etype); + createCall.setStatic(true); + // createCall.entity = e; + + AssignStatement assgn = new AssignStatement(res,createCall); + code.addStatement(assgn); + + for (int i = 0; i < pars.size(); i++) + { Attribute attr = (Attribute) pars.get(i); + BasicExpression lhs = new BasicExpression(attr); + lhs.setObjectRef(res); + BasicExpression rhs = new BasicExpression(attr); + AssignStatement assgnpar = + new AssignStatement(lhs,rhs); + code.addStatement(assgnpar); + } + + ReturnStatement rs = new ReturnStatement(res); + code.addStatement(rs); + + code.setBrackets(true); + + bf.setActivity(code); + bf.setStatic(true); + + return bf; + } + + public static BehaviouralFeature newStaticConstructor(Entity ent) + { String ename = ent.getName(); + BehaviouralFeature bf = new BehaviouralFeature("new" + ename); + bf.setParameters(new Vector()); + Type etype = new Type(ent); + bf.setType(etype); + bf.setPostcondition(new BasicExpression(true)); + SequenceStatement code = new SequenceStatement(); + + BasicExpression res = BasicExpression.newVariableBasicExpression("result", etype); + + CreationStatement cs = new CreationStatement("result", etype); + code.addStatement(cs); + + BasicExpression createCall = new BasicExpression("create" + ename); + createCall.setUmlKind(Expression.UPDATEOP); + createCall.setParameters(new Vector()); + createCall.setIsEvent(); + createCall.setType(etype); + createCall.setStatic(true); + // createCall.entity = e; + + AssignStatement assgn = new AssignStatement(res,createCall); + code.addStatement(assgn); + + Vector pars = ent.getAttributes(); + for (int i = 0; i < pars.size(); i++) + { Attribute attr = (Attribute) pars.get(i); + BasicExpression lhs = new BasicExpression(attr); + lhs.setObjectRef(res); + Expression rhs = attr.getInitialisation(); + if (rhs != null) + { AssignStatement assgnpar = + new AssignStatement(lhs,rhs); + code.addStatement(assgnpar); + } + } + + BasicExpression initialiseCall = + new BasicExpression("initialise"); + initialiseCall.setUmlKind(Expression.UPDATEOP); + initialiseCall.setIsEvent(); + // Vector parNames = bf.getParameterExpressions(); + // System.out.println(">>=== " + pars + " " + parNames); + + initialiseCall.setParameters(new Vector()); + initialiseCall.setObjectRef(res); + InvocationStatement callInit = + new InvocationStatement(initialiseCall); + // callInit.setParameters(parNames); + code.addStatement(callInit); + + ReturnStatement rs = new ReturnStatement(res); + code.addStatement(rs); + + code.setBrackets(true); + + bf.setActivity(code); + bf.setStatic(true); + + return bf; + } + + public static BehaviouralFeature newStaticConstructor(Entity ent, Vector pars, Vector exprs) + { String ename = ent.getName(); + BehaviouralFeature bf = new BehaviouralFeature("new" + ename); + bf.setParameters(pars); + Type etype = new Type(ent); + bf.setType(etype); + bf.setPostcondition(new BasicExpression(true)); + SequenceStatement code = new SequenceStatement(); + + BasicExpression res = BasicExpression.newVariableBasicExpression("result", etype); + + CreationStatement cs = new CreationStatement("result", etype); + code.addStatement(cs); + + BasicExpression createCall = new BasicExpression("create" + ename); + createCall.setUmlKind(Expression.UPDATEOP); + createCall.setParameters(new Vector()); + createCall.setIsEvent(); + createCall.setType(etype); + createCall.setStatic(true); + // createCall.entity = e; + + AssignStatement assgn = new AssignStatement(res,createCall); + code.addStatement(assgn); + + // Vector pars = ent.getAttributes(); + for (int i = 0; i < pars.size(); i++) + { Attribute attr = (Attribute) pars.get(i); + BasicExpression lhs = new BasicExpression(attr); + lhs.setObjectRef(res); + Expression rhs = (Expression) exprs.get(i); + if (rhs != null) + { AssignStatement assgnpar = + new AssignStatement(lhs,rhs); + code.addStatement(assgnpar); + } + } + + // BasicExpression initialiseCall = + // new BasicExpression("initialise"); + // initialiseCall.setUmlKind(Expression.UPDATEOP); + // initialiseCall.setIsEvent(); + // Vector parNames = bf.getParameterExpressions(); + // System.out.println(">>=== " + pars + " " + parNames); + + // initialiseCall.setParameters(new Vector()); + // initialiseCall.setObjectRef(res); + // InvocationStatement callInit = + // new InvocationStatement(initialiseCall); + // callInit.setParameters(parNames); + // code.addStatement(callInit); + + ReturnStatement rs = new ReturnStatement(res); + code.addStatement(rs); + + code.setBrackets(true); + + bf.setActivity(code); + bf.setStatic(true); + + return bf; + } + + public static BehaviouralFeature fromAttribute(Attribute att) + { BehaviouralFeature res = + new BehaviouralFeature(att.getName()); + res.parameters = att.getParameters(); + res.resultType = att.getInnerElementType(); + + System.out.println("==== Operation from attribute: " + res.display()); + + return res; + } + + public UseCase toUseCase() + { // usecase name : resultType + // { parameter ... assumptions ... postconditions } + + UseCase res = new UseCase(getName()); + res.addParameters(parameters); + res.setResultType(resultType); + res.setElementType(elementType); + if (pre != null) + { res.addPrecondition(pre); } + if (post != null) + { res.addPostcondition(post); } + res.setActivity(activity); + res.setTypeParameters(typeParameters); + + return res; + } // type parameters become those of the linked class + + public boolean isMutatable() + { if (isDerived()) + { return false; } + if (parameters == null || parameters.size() == 0) + { return false; } + if (resultType == null || "void".equals(resultType + "")) + { return false; } + return isQuery(); + } // At least one input parameter, and a result parameter + + public Vector getMutants() + { return myMutants; } + + public Vector getMutants(Vector allops) + { Vector res = new Vector(); + for (int i = 0; i < myMutants.size(); i++) + { BehaviouralFeature bf = (BehaviouralFeature) myMutants.get(i); + String nme = bf.getName(); + if (ModelElement.lookupByName(nme,allops) != null) + { res.add(bf); } + } + return res; + } // only mutants that actually are in the class + + + public Vector formMutantOperations(Vector posts) + { if (myMutants.size() > 0) + { return myMutants; } // cached result. + + Vector res = new Vector(); + String nme = getName(); + + for (int i = 0; i < posts.size(); i++) + { Expression postx = (Expression) posts.get(i); + BehaviouralFeature bfclone = (BehaviouralFeature) this.clone(); + bfclone.setName(nme + "_mutant_" + i); + bfclone.setPost(postx); + bfclone.setDerived(true); + res.add(bfclone); + } + + if ("true".equals(post + "") && activity != null) + { Vector statmuts = activity.singleMutants(); + res = new Vector(); + for (int i = 0; i < statmuts.size(); i++) + { Statement statmut = (Statement) statmuts.get(i); + BehaviouralFeature bfclone = (BehaviouralFeature) this.clone(); + bfclone.setName(nme + "_mutant_" + i); + bfclone.setActivity(statmut); + bfclone.setDerived(true); + res.add(bfclone); + } + } + + JOptionPane.showMessageDialog(null, "Mutant versions of " + getName() + " are: " + res, + "", JOptionPane.INFORMATION_MESSAGE); + + myMutants = new Vector(); + myMutants.addAll(res); + + return res; + } + + public Vector formMutantCalls(String ename, Vector mutants, Vector tests, Vector alltests, Vector testcalls) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCode(tst); + // parameterInitialisationCode(tvals); + + String javaType = resultType.getJava(); + + String call = javaType + " " + nme + "_result = _self." + this.toString() + ";\n"; + call = call + + " System.out.println(\"Test " + j + " of " + nme + " on \" + _self + \" result = \" + " + nme + "_result);\n"; + + // Should use " try {\n" + + String testcode = + " public static void " + nme + "_mutation_tests_" + j + "(" + ename + " _self, int[] _counts, int[] _totals)\n" + + " {\n" + + " " + code + "\n" + + " try {\n " + call + "\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self." + m.toString(); + testcode = testcode + + " try {\n" + + " " + javaType + " " + mname + "_result = " + mutantcall + ";\n" + + " if ((\"\" + " + nme + "_result).equals(\"\" + " + mname + "_result)) { _totals[" + j + "]++; } else\n" + + " { System.out.println(\"Test " + j + " of " + tsts + " detects " + nme + " mutant " + i + " of " + muts + "\");\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n" + + " } catch (Throwable _e) {\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n"; + } + testcode = testcode + " } catch (Throwable _e) { }\n }\n\n"; + + /* Should be: + " } catch (Throwable _e) { _e.printStackTrace(); }\n"; */ + + res.add(testcode); + + String testcall = " MutationTest." + nme + "_mutation_tests_" + j + "(_self,_counts,_totals);\n"; + testcalls.add(testcall); + } + } + return res; + } + + public Vector formMutantCallsCSharp(String ename, Vector mutants, Vector tests, Vector alltests, Vector testcalls) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCodeCSharp(tst); + // parameterInitialisationCode(tvals); + + String javaType = resultType.getCSharp(); + + String call = javaType + " " + nme + "_result = _self." + this.toString() + ";\n"; + if (this.isStatic()) + { call = javaType + " " + nme + "_result = " + ename + "." + this.toString() + ";\n"; } + call = call + + " Console.WriteLine(\"Test " + j + " of " + nme + " on \" + _self + \" result = \" + " + nme + "_result);\n"; + + // Should use " try {\n" + + String testcode = + " public static void " + nme + "_mutation_tests_" + j + "(" + ename + " _self, int[] _counts, int[] _totals)\n" + + " {\n" + + " " + code + "\n" + + " try {\n " + call + "\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self." + m.toString(); + if (this.isStatic()) + { mutantcall = ename + "." + m.toString(); } + + testcode = testcode + + " try {\n" + + " " + javaType + " " + mname + "_result = " + mutantcall + ";\n" + + " if ((\"\" + " + nme + "_result).Equals(\"\" + " + mname + "_result)) { _totals[" + j + "]++; } else\n" + + " { Console.WriteLine(\"Test " + j + " of " + tsts + " detects " + nme + " mutant " + i + " of " + muts + "\");\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n" + + " } catch { }\n"; + } + testcode = testcode + " } catch { }\n }\n\n"; + + res.add(testcode); + + String testcall = " MutationTest." + nme + "_mutation_tests_" + j + "(_self,_counts,_totals);\n"; + testcalls.add(testcall); + } + } + return res; + } + + public Vector formMutantCallsCPP(String ename, Vector mutants, Vector tests, Vector alltests, Vector testcalls) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCodeCPP(tst); + // parameterInitialisationCode(tvals); + + String javaType = resultType.getCPP(); + + String call = javaType + " " + nme + "_result = _self->" + this.toString() + ";\n"; + if (this.isStatic()) + { call = javaType + " " + nme + "_result = " + ename + "::" + this.toString() + ";\n"; } + call = call + + " cout << \"Test \" << " + j + " << \" of " + nme + " on \" << _self << \" result = \" << " + nme + "_result << endl;\n"; + + // Should use " try {\n" + + String testcode = + " static void " + nme + "_mutation_tests_" + j + "(" + ename + "* _self, int _counts[], int _totals[])\n" + + " {\n" + + " " + code + "\n" + + " try {\n " + call + "\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self->" + m.toString(); + if (this.isStatic()) + { mutantcall = ename + "::" + m.toString(); } + + testcode = testcode + + " try {\n" + + " " + javaType + " " + mname + "_result = " + mutantcall + ";\n" + + " if (" + nme + "_result == " + mname + "_result) { _totals[" + j + "]++; } else\n" + + " { cout << \"Test \" << " + j + " << \" of \" << " + tsts + " << \" detects " + nme + " mutant \" << " + i + " << \" of \" << " + muts + " << endl;\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n" + + " } catch (...) { }\n"; + } + testcode = testcode + " } catch (...) { }\n }\n\n"; + + res.add(testcode); + + String testcall = " MutationTest::" + nme + "_mutation_tests_" + j + "(_self,_counts,_totals);\n"; + testcalls.add(testcall); + } + } + return res; + } + + public Vector formMutantCallsJava6(Vector mutants, Vector tests, Vector alltests) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCodeJava6(tst); + // parameterInitialisationCode(tvals); + + String java6Type = resultType.getJava6(); + + String call = java6Type + " " + nme + "_result = _self." + this.toString() + ";\n"; + call = call + + " System.out.println(\"Test " + j + " of " + nme + " on \" + _self + \" result = \" + " + nme + "_result);\n"; + + String testcode = " try {\n" + + " " + code + "\n" + + " " + call + "\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self." + m.toString(); + testcode = testcode + + " " + java6Type + " " + mname + "_result = " + mutantcall + ";\n" + + " if ((\"\" + " + nme + "_result).equals(\"\" + " + mname + "_result)) { _totals[" + j + "]++; } else\n" + + " { System.out.println(\"Test " + j + " of " + tsts + " detects " + nme + " mutant " + i + " of " + muts + "\");\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n"; + } + testcode = testcode + + " } catch (Throwable _e) { _e.printStackTrace(); }\n"; + res.add(testcode); + } + } + return res; + } + + public Vector formMutantCallsJava7(Vector mutants, Vector tests, Vector alltests) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCodeJava7(tst); + // parameterInitialisationCode(tvals); + + String java7Type = resultType.getJava7(); + + String call = java7Type + " " + nme + "_result = _self." + this.toString() + ";\n"; + call = call + + " System.out.println(\"Test " + j + " of " + nme + " on \" + _self + \" result = \" + " + nme + "_result);\n"; + + String testcode = " try {\n" + + " " + code + "\n" + + " " + call + "\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self." + m.toString(); + testcode = testcode + + " " + java7Type + " " + mname + "_result = " + mutantcall + ";\n" + + " if ((\"\" + " + nme + "_result).equals(\"\" + " + mname + "_result)) { _totals[" + j + "]++; } else\n" + + " { System.out.println(\"Test " + j + " of " + tsts + " detects " + nme + " mutant " + i + " of " + muts + "\");\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n"; + } + testcode = testcode + + " } catch (Throwable _e) { _e.printStackTrace(); }\n"; + res.add(testcode); + } + } + return res; + } + + public Vector formMutantCallsJava8(Vector mutants, Vector tests, Vector alltests) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCodeJava8(tst); + // parameterInitialisationCode(tvals); + + String java8Type = resultType.getJava8(); + + String call = java8Type + " " + nme + "_result = _self." + this.toString() + ";\n"; + call = call + + " System.out.println(\"Test " + j + " of " + nme + " on \" + _self + \" result = \" + " + nme + "_result);\n"; + + String testcode = " try {\n" + + " " + code + "\n" + + " " + call + "\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self." + m.toString(); + testcode = testcode + + " " + java8Type + " " + mname + "_result = " + mutantcall + ";\n" + + " if ((\"\" + " + nme + "_result).equals(\"\" + " + mname + "_result)) { _totals[" + j + "]++; } else\n" + + " { System.out.println(\"Test " + j + " of " + tsts + " detects " + nme + " mutant " + i + " of " + muts + "\");\n" + + " _counts[" + j + "]++; \n" + + " _totals[" + j + "]++;\n" + + " }\n"; + } + testcode = testcode + + " } catch (Throwable _e) { _e.printStackTrace(); }\n"; + res.add(testcode); + } + } + return res; + } + + public Vector formMutantCallsPython( + String ename, Vector mutants, Vector tests, + Vector alltests, Vector testcalls) + { // for each m : mutants, t : tests, set up a call to + // m(t.values) + + String nme = getName(); + Vector res = new Vector(); + + if (resultType != null && !("void".equals(resultType + ""))) + { int tsts = alltests.size(); + int muts = mutants.size(); + + for (int j = 0; j < tsts; j++) + { Vector tst = (Vector) alltests.get(j); + // String tvals = (String) tst.get(1); + String code = parInitCodePython(tst); + // parameterInitialisationCode(tvals); + + // String javaType = resultType.getCSharp(); + + String call = " " + nme + "_result = _self." + this.toString() + "\n"; + if (this.isStatic()) + { call = " " + nme + "_result = app." + ename + "." + this.toString() + "\n"; } + call = call + + " print(\"Test " + j + " of " + nme + " on \" + str(_self) + \" result = \" + str(" + nme + "_result))\n"; + + // Should use " try {\n" + + String testcode = + " def " + nme + "_mutation_tests_" + j + "(_self, _counts, _totals) :\n" + + " pass\n" + + code + "\n" + + " try :\n" + + call + + " except:\n" + + " print(\"Unable to execute " + nme + "\")\n" + + " return\n\n"; + + for (int i = 0; i < muts; i++) + { BehaviouralFeature m = (BehaviouralFeature) mutants.get(i); + String mname = m.getName(); + String mutantcall = "_self." + m.toString(); + if (this.isStatic()) + { mutantcall = "app." + ename + "." + m.toString(); } + + testcode = testcode + + " try :\n" + + " " + mname + "_result = " + mutantcall + ";\n" + + " if str(" + nme + "_result) == str(" + mname + "_result) :\n" + + " _totals[" + j + "] = _totals[" + j + "] + 1\n" + + " else :\n" + + " print(\"Test " + j + " of " + tsts + " detects " + nme + " mutant " + i + " of " + muts + "\")\n" + + " _counts[" + j + "] = _counts[" + j + "] + 1\n" + + " _totals[" + j + "] = _totals[" + j + "] + 1\n" + + " except :\n" + + " pass\n\n"; + } + + res.add(testcode); + + String testcall = " MutationTest." + nme + "_mutation_tests_" + j + "(_self,_counts,_totals)\n"; + testcalls.add(testcall); + } + } + return res; + } + + + public String parametersString() + { String res = ""; + if (parameters == null) + { return res; } + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + res = res + att.getName() + " : " + att.getType(); + if (i < parameters.size()-1) + { res = res + ","; } + } + return res; + } + + + public boolean hasParameter(String nme) + { Attribute att = (Attribute) ModelElement.lookupByName(nme,parameters); + if (att != null) + { return true; } + return false; + } + + public String parameterInitialisationCode(String strs) + { String res = ""; + int st = strs.indexOf("parameters"); + if (st >= 0) + { String data = strs.substring(st,strs.length()); + res = data.substring(11,data.length()); + int eqind = res.indexOf("="); + if (eqind >= 0) + { String par = res.substring(0,eqind).trim(); + String val = res.substring(eqind+2,res.length()).trim(); + + int next = val.indexOf("parameters"); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { res = " " + att.getType() + " " + par + " = "; } + else // it is a feature of the object + { res = " _self." + par + " = "; } + + String value = val; + if (att != null && att.isEntity()) + { Type atttype = att.getType(); + Entity attent = atttype.getEntity(); + String attentname = attent.getName(); + String es = attentname.toLowerCase() + "s"; + value = "(" + attentname + ") Controller.inst()." + es + ".get(0)"; + } + + if (next < 0) + { return res + value + ";"; } + String remainder = val.substring(next,val.length()); + + if (att != null && att.isEntity()) { } + else + { value = val.substring(0,next).trim(); } + + return res + value + ";\n" + + parameterInitialisationCode(remainder); + } + else + { eqind = res.indexOf(":"); + // else look for ":" in the case of collection pars + // val : parameters.par + + if (eqind >= 0) + { String val = res.substring(0,eqind).trim(); + String par = res.substring(eqind+12,res.length()).trim(); + + int rnext = val.indexOf(":"); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { res = " " + att.getType() + " " + par + " = new " + att.getType().getJava() + "();\n" + + " " + par + ".add(" + val + ")"; } + else // it is a feature of the object + { res = " _self." + par + ".add(" + val + ")"; } + + if (rnext < 0) + { return res + ";"; } + String remainder = val.substring(rnext,val.length()); + String value = val.substring(0,rnext).trim(); + return res + value + ";\n" + + parameterInitialisationCode(remainder); + } + } + } + return res; + } + + public String parInitCode(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + leafent.getName() + " " + par + " " + rem + "\n"; + } + else + { res = res + " " + atttype.getJava() + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self." + par + " " + rem + "\n"; } + } + } + return res; + } + + public String parInitCodeCSharp(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + leafent.getName() + " " + par + " " + rem + "\n"; + } + else + { res = res + " " + atttype.getCSharp() + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self." + par + " " + rem + "\n"; } + } + } + return res; + } + + public String parInitCodeCPP(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + leafent.getName() + "* " + par + " " + rem + "\n"; + } + else + { res = res + " " + atttype.getCPP() + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self->" + par + " " + rem + "\n"; } + } + } + return res; + } + + public String parInitCodeJava6(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + leafent.getName() + " " + par + " " + rem + "\n"; + } + else + { res = res + " " + atttype.getJava6() + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self." + par + " " + rem + "\n"; } + } + } + return res; + } + + public String parInitCodeJava7(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + leafent.getName() + " " + par + " " + rem + "\n"; + } + else + { res = res + " " + atttype.getJava7() + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self." + par + " " + rem + "\n"; } + } + } + return res; + } + + public String parInitCodeJava8(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = (Attribute) ModelElement.lookupByName(par,parameters); + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + leafent.getName() + " " + par + " " + rem + "\n"; + } + else + { res = res + " " + atttype.getJava8() + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self." + par + " " + rem + "\n"; } + } + } + return res; + } + + public String parInitCodePython(Vector v) + { String res = ""; + for (int i = 0; i < v.size(); i++) + { String assign = (String) v.get(i); + int eqindex = assign.indexOf("="); + if (eqindex >= 0) + { String par = assign.substring(0,eqindex).trim(); + String rem = + assign.substring(eqindex,assign.length()); + + // if a parameter, give it a declaration + Attribute att = + (Attribute) ModelElement.lookupByName(par,parameters); + + if (att != null) + { Type atttype = att.getType(); + + if (atttype.isAbstractEntity()) + { Entity absent = atttype.getEntity(); + Entity leafent = absent.firstLeafSubclass(); + res = res + " " + par + " " + rem + "\n"; + } + else + { res = res + " " + par + " " + rem + "\n"; } + } + else // it is a feature of the object + { res = res + " _self." + par + " " + rem + "\n"; } + } + } + return res; + } + + + public void defineParameters(Entity inPars, Entity outPars) + { // parameters = new Vector(); + if (inPars != null) + { parameters.addAll(inPars.getAttributes()); } + + if (outPars != null) + { Vector outparams = outPars.getAttributes(); + if (outparams.size() > 0) + { Attribute res = (Attribute) outparams.get(0); + resultType = res.getType(); + } + } + } + + public void addParameters(Vector atts) + { for (int i = 0; i < atts.size(); i++) + { Attribute par = (Attribute) atts.get(i); + if (hasParameter(par.getName())) { } + else + { parameters.add(par); } + } + } + + + public void addParameter(Attribute att) + { if (att == null) + { return; } + + if (hasParameter(att.getName())) { } + else + { parameters.add(att); } + } + + public void addFirstParameter(Attribute att) + { if (att == null) + { return; } + + if (hasParameter(att.getName())) { } + else + { parameters.add(0,att); } + } + + public void addTypeParameter(Type t) + { if (typeParameters.contains(t)) { } + else + { typeParameters.add(t); } + } + + public void removeParameters(Vector atts) + { parameters.removeAll(atts); } + + + public Vector getTypeParameters() + { return typeParameters; } + + public void setStatechart(Statemachine s) + { sm = s; } + + public void setActivity(Statement st) + { activity = st; } + + public void setActivity(Vector stats) + { if (stats == null || stats.size() == 0) + { activity = new InvocationStatement("skip"); } + else if (stats.size() == 1) + { activity = (Statement) stats.get(0); } + else + { activity = new SequenceStatement(stats); } + } + + public boolean hasResult() + { if (resultType != null && + !("void".equals(resultType + ""))) + { return true; } + return false; + } + + public boolean hasResultType() + { return hasResult(); } + + public void setResultType(Type t) + { resultType = t; } + + public boolean hasReturnVariable() + { if (resultType == null) + { return false; } + if ("void".equals(resultType + "")) + { return false; } + return true; + } + + public boolean hasReturnValue() + { if (resultType == null) + { return false; } + if ("void".equals(resultType + "")) + { return false; } + return true; + } + + public Type getFunctionType() + { Type res; + if (resultType != null) + { res = resultType; } + else + { res = new Type("void", null); } + if (parameters == null || parameters.size() == 0) + { Type ftype = new Type("Function", null); + ftype.setElementType(res); + ftype.setKeyType(res); + return ftype; + } + + for (int i = parameters.size()-1; i >= 0; i--) + { Attribute par = (Attribute) parameters.get(i); + Type ptype = par.getType(); + Type ftype = new Type("Function", null); + ftype.setElementType(res); + ftype.setKeyType(ptype); + res = ftype; + } + + return res; + } + + public static Type buildFunctionType(Vector pars) + { Type res = new Type("OclAny", null); + if (pars == null || pars.size() == 0) + { Type ftype = new Type("Function", null); + ftype.setElementType(res); + ftype.setKeyType(new Type("void", null)); + return ftype; + } + + for (int i = pars.size()-1; i >= 0; i--) + { Attribute par = (Attribute) pars.get(i); + Type ptype = par.getType(); + Type ftype = new Type("Function", null); + ftype.setElementType(res); + ftype.setKeyType(ptype); + res = ftype; + } + + return res; + } + + public boolean isZeroArgument() + { return parameters.size() == 0; } + + public Statement extendBehaviour() + { // System.out.println(">>> Operation activity = " + activity); + + if (activity == null) + { return new SequenceStatement(); } + + // Vector newparams = new Vector(); + // newparams.addAll(parameters); + + java.util.Map env = new java.util.HashMap(); + + Statement stat = activity.generateDesign(env,false); + + if (hasResult()) + { if (Statement.hasResultDeclaration(stat)) + { return stat; } + + Attribute att = new Attribute("result",resultType,ModelElement.INTERNAL); + att.setElementType(elementType); + // newparams.add(att); + + // System.out.println(">>> Enhanced activity = " + stat); Vector contexts = new Vector(); + // newparams.addAll(ownedAttribute); + + Statement newstat = new SequenceStatement(); + // ReturnStatement returnstat = null; + CreationStatement cres = new CreationStatement(resultType + "", "result"); + cres.setInstanceType(resultType); + if (elementType != null) + { cres.setElementType(elementType); } + ((SequenceStatement) newstat).addStatement(cres); + // returnstat = new ReturnStatement(new BasicExpression(att)); + + ((SequenceStatement) newstat).addStatement(stat); + + // if (returnstat != null) + // { ((SequenceStatement) newstat).addStatement(returnstat); } + + // JOptionPane.showMessageDialog(null, "Result declaration: result : " + resultType + "(" + elementType + ")", + // "", JOptionPane.INFORMATION_MESSAGE); + + // newstat.typeCheck(types,entities,contexts,newparams); + return newstat; + } + return new SequenceStatement(); + } + + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + args.add(getName()); + Vector eargs = new Vector(); + eargs.add(this); + + String typePar = ""; + if (typeParameters != null && typeParameters.size() > 0) + { Type tp = (Type) typeParameters.get(0); + typePar = tp.getName(); + args.add(typePar); + eargs.add(tp); + } + + String pars = ""; + if (parameters == null) {} + else if (parameters.size() == 0) {} + else + { Attribute p = (Attribute) parameters.get(0); + Vector partail = new Vector(); + partail.addAll(parameters); + partail.remove(0); + pars = p.cgParameter(cgs,partail); + } + args.add(pars); + eargs.add(parameters); + + if (resultType != null) + { args.add(resultType.cg(cgs)); + eargs.add(resultType); + } + else + { Type rt = new Type("void",null); + args.add(rt.cg(cgs)); + eargs.add(rt); + } + + if (pre != null) + { args.add(pre.cg(cgs)); + eargs.add(pre); + } + else + { BasicExpression pr = new BasicExpression(true); + args.add(pr.cg(cgs)); + eargs.add(pr); + } + + if (post != null) + { args.add(post.cg(cgs)); + eargs.add(post); + } + else + { BasicExpression pst = new BasicExpression(true); + args.add(pst.cg(cgs)); + eargs.add(pst); + } + + if (activity != null) + { if (hasResult()) + { Statement newact = extendBehaviour(); + String actres = newact.cg(cgs); + args.add(actres); + eargs.add(newact); + } + else + { String actres = activity.cg(cgs); + // System.out.println(">>> Activity result: " + actres); + args.add(actres); + eargs.add(activity); + } + } + else + { Statement nullstat = new SequenceStatement(); + args.add(nullstat.cg(cgs)); + eargs.add(nullstat); + } + // only one Operation rule? + // maybe for static/cached + + CGRule r = cgs.matchedOperationRule(this,etext); + if (r != null) + { System.out.println(">>> Matched operation rule: " + r + " with args " + args); + return r.applyRule(args,eargs,cgs); + } + + System.out.println("!!! No matching rule for operation " + getName()); + + return etext; + } + + + public Vector testCases(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + // We are only interested in those that are *read* + // by the operation - its readFrame. + // And not frozen attributes. + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCases("parameters", lowerBounds, + upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + public Vector testCasesCSharp(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + // We are only interested in those that are *read* + // by the operation - its readFrame. + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCasesCSharp( + "parameters", lowerBounds, upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + public Vector testCasesCPP(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + // We are only interested in those that are *read* + // by the operation - its readFrame. + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCasesCPP( + "parameters", lowerBounds, upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + public Vector testCasesPython(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + // We are only interested in those that are *read* + // by the operation - its readFrame. + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCasesPython( + "parameters", lowerBounds, upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + public Vector testCasesJava6(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + // System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + // System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + // System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCasesJava6("parameters", + lowerBounds, upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + public Vector testCasesJava7(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + // System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + // System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + // System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCasesJava7("parameters", + lowerBounds, upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + public Vector testCasesJava8(Vector opTests) + { Vector allattributes = getParameters(); + Vector preattributes = new Vector(); + preattributes.addAll(allattributes); + if (entity != null) + { preattributes.addAll(entity.getLocalFeatures()); } + + String nme = getName(); + Vector res = new Vector(); + Vector allOpTests = new Vector(); + + if (preattributes == null || preattributes.size() == 0) + { res.add("-- no test for operation " + nme + "\n"); + return res; + } + + java.util.Map upperBounds = new java.util.HashMap(); + java.util.Map lowerBounds = new java.util.HashMap(); + + Vector test0 = new Vector(); + test0.add(nme); + test0.add("-- tests for operation " + nme + "\n"); + res.add(test0); + + Expression pre = precondition(); + if (pre != null) + { Vector bounds = new Vector(); + java.util.Map aBounds = new java.util.HashMap(); + pre.getParameterBounds(preattributes,bounds,aBounds); + + + identifyUpperBounds(allattributes,aBounds,upperBounds); + identifyLowerBounds(allattributes,aBounds,lowerBounds); + // System.out.println(".>> Parameter bounds for operation " + nme + " : " + aBounds); + // System.out.println(".>> Upper bounds map for operation " + nme + " : " + upperBounds); + // System.out.println(".>> Lower bounds map for operation " + nme + " : " + lowerBounds); + } + + for (int i = 0; i < allattributes.size(); i++) + { Vector newres = new Vector(); + Vector attoptests = new Vector(); + Attribute att = (Attribute) allattributes.get(i); + + if (att.isFrozen()) { continue; } + + Vector testassignments = + att.testCasesJava8("parameters", + lowerBounds, upperBounds, attoptests); + allOpTests.add(attoptests); + + for (int j = 0; j < res.size(); j++) + { Vector oldtest = (Vector) res.get(j); + String tst = (String) oldtest.get(1); + for (int k = 0; k < testassignments.size(); k++) + { String kstr = (String) testassignments.get(k); + if (kstr.length() > 0) + { String newtst = tst + "\n" + kstr; + Vector optest = new Vector(); + optest.add(nme); + optest.add(newtst); + newres.add(optest); + } + } + } + res.clear(); + res.addAll(newres); + } + + opTests.addAll(flattenTests(allOpTests)); + // System.out.println(">>> Flattened tests = " + opTests); + + return res; + } + + private Vector flattenTests(Vector opTests) + { Vector newOpTests = new Vector(); + if (opTests.size() > 0) + { Vector ptests = (Vector) opTests.get(0); + for (int j = 0; j < ptests.size(); j++) + { String ptest = (String) ptests.get(j); + Vector tailopTests = new Vector(); + tailopTests.addAll(opTests); + tailopTests.remove(0); + Vector tailtests = flattenTests(tailopTests); + for (int k = 0; k < tailtests.size(); k++) + { Vector tailtest = (Vector) tailtests.get(k); + Vector newtest = new Vector(); + newtest.add(ptest); + newtest.addAll(tailtest); + newOpTests.add(newtest); + } + } + return newOpTests; + } + else + { newOpTests.add(new Vector()); + return newOpTests; + } + } + + private void identifyUpperBounds(Vector atts, java.util.Map boundConstraints, java.util.Map upperBounds) + { for (int i = 0; i < atts.size(); i++) + { Attribute att = (Attribute) atts.get(i); + String aname = att.getName(); + Vector bpreds = (Vector) boundConstraints.get(aname); + if (bpreds != null) + { for (int j = 0; j < bpreds.size(); j++) + { BinaryExpression pred = (BinaryExpression) bpreds.get(j); + Expression ubound = pred.getUpperBound(aname); + if (ubound != null) + { upperBounds.put(aname,ubound); } + } + } + } + } + + private void identifyLowerBounds(Vector atts, java.util.Map boundConstraints, java.util.Map lowerBounds) + { for (int i = 0; i < atts.size(); i++) + { Attribute att = (Attribute) atts.get(i); + String aname = att.getName(); + Vector bpreds = (Vector) boundConstraints.get(aname); + if (bpreds != null) + { for (int j = 0; j < bpreds.size(); j++) + { BinaryExpression pred = (BinaryExpression) bpreds.get(j); + Expression lbound = pred.getLowerBound(aname); + if (lbound != null) + { lowerBounds.put(aname,lbound); } + } + } + } + } + + public Vector getReadFrame() + { if (readfr != null) { return readfr; } // to avoid recursion + readfr = new Vector(); + Vector res = new Vector(); + // subtract each params name: + if (post != null) + { res.addAll(post.readFrame()); } + if (activity != null) + { res.addAll(activity.readFrame()); } + + for (int p = 0; p < parameters.size(); p++) + { String par = "" + parameters.get(p); + res.remove(par); + } + // System.out.println("Invocation " + this + " READ FRAME= " + res); + readfr = res; + return res; + } + + public Vector getWriteFrame(Vector assocs) + { if (writefr != null) { return writefr; } // to avoid recursion + writefr = new Vector(); + Vector res = new Vector(); + if (post != null) + { res.addAll(post.wr(assocs)); } + if (activity != null) + { res.addAll(activity.writeFrame()); } + + // subtract each params name: + for (int p = 0; p < parameters.size(); p++) + { String par = "" + parameters.get(p); + res.remove(par); + } + + // System.out.println("Invocation " + this + " WRITE FRAME= " + res); + writefr = res; + return res; + } + + public Statemachine getSm() + { return sm; } + + public Statement getActivity() + { return activity; } + + public boolean isClassScope() + { return !instanceScope; } + + public boolean isCached() + { if (hasStereotype("cached")) + { return true; } + return false; + } + + public void setCached(boolean b) + { if (b) + { addStereotype("cached"); } + else + { removeStereotype("cached"); } + } + + public void setInstanceScope(boolean b) + { if (b) + { removeStereotype("static"); + instanceScope = true; + } + else + { addStereotype("static"); // ?? + instanceScope = false; + } + } + + public void setStatic(boolean b) + { if (b) + { addStereotype("static"); + instanceScope = false; + } + else + { removeStereotype("static"); // ?? + instanceScope = true; + } + } + + public void setQuery(boolean q) + { query = q; + if (query) { addStereotype("query"); } + else { removeStereotype("query"); } + } + + public void setVarArgStereotype(Vector pars) + { if (pars.size() > 0) + { Attribute va = (Attribute) pars.get(pars.size()-1); + if ("par_varg_sq".equals(va.getName()) && + va.isSequence()) + { addStereotype("vararg"); } + } + } + + public void setVarArgStereotype() + { setVarArgStereotype(parameters); } + + + public boolean isVarArg() + { return hasStereotype("vararg"); } + + public void setDerived(boolean d) + { derived = d; } + + public boolean isDerived() + { return derived; } + + public BehaviouralFeature mergeOperation(Entity e, BehaviouralFeature eop) + { // Assume that both are instanceScope + + BehaviouralFeature res = null; + Type newt = null; + boolean isquery = false; + Vector newpars = new Vector(); + Expression newpost = null; + Expression newpre = null; + + if (resultType == null) + { if (eop.resultType == null) {} + else + { newt = eop.resultType; } + } + else + { if (eop.resultType == null) + { newt = resultType; } + else + { newt = resultType.mergeType(eop.resultType); + if (newt == null) + { return null; } + } + } + // parameters also must match + if (parameters.size() > eop.parameters.size()) + { newpars = parameters; } + else + { parameters = eop.parameters; } + // take the union of them. + + if (query && eop.query) + { isquery = true; } + + if ((pre + "").equals(eop.pre + "")) + { newpre = pre; } + else + { newpre = Expression.simplify("&",pre,eop.pre,null); } + + if ((post + "").equals(eop.post + "")) + { newpost = post; } + else + { newpost = Expression.simplify("or",post,eop.post,null); } + + res = + new BehaviouralFeature(getName(),newpars,isquery,newt); + res.setEntity(e); + res.setPre(newpre); + res.setPost(newpost); + return res; + } // also set elementType + + public void setEntity(Entity ent) + { entity = ent; } + + public Entity getEntity() + { return entity; } + + public void setOwner(Entity ent) + { entity = ent; } + + public Entity getOwner() + { return entity; } + + public void setUseCase(UseCase uc) + { useCase = uc; } + + public UseCase getUseCase() + { return useCase; } + + public String getEntityName() + { if (entity == null) { return ""; } + return entity.getName(); + } + + public void setPre(Expression p) + { pre = p; } + + public void addPrecondition(Object obj) + { if (obj != null) + { Expression pp = new BasicExpression("\"" + obj + "\""); + pre = Expression.simplifyAnd(pre,pp); + } + } + + + public void setPost(Expression p) + { post = p; } + + public void addPostcondition(Object obj) + { if (obj != null) + { Expression pp = new BasicExpression("\"" + obj + "\""); + post = Expression.simplifyAnd(post,pp); + } + } + + public void addActivity(Object obj) + { Statement newstat = new ImplicitInvocationStatement("\"" + obj + "\""); + + if (activity == null) + { activity = newstat; } + else if (activity instanceof SequenceStatement) + { ((SequenceStatement) activity).addStatement(newstat); } + else + { SequenceStatement res = new SequenceStatement(); + res.addStatement(activity); + res.addStatement(newstat); + activity = res; + } + } + + + + public void setPrecondition(Expression p) + { pre = p; } + + public Expression precondition() + { return pre; } + + public Expression postcondition() + { return post; } + + public void setPostcondition(Expression p) + { post = p; } + + public void setOrdered(boolean ord) + { ordered = ord; } + + public void setSorted(boolean ord) + { sorted = ord; } + + public void setText(String line) + { text = line; } + + public void clearText() + { text = ""; } + + public boolean hasText() + { return text != null && text.length() > 0; } + + public void addBPre(Expression e) + { if (bpre == null) + { bpre = e; } + else + { bpre = Expression.simplifyAnd(bpre,e); } + } + + public void addPost(Expression e) + { if (post == null) + { post = e; } + else + { post = Expression.simplifyAnd(post,e); } + } + + public boolean isDefinedinSuperclass() + { if (entity == null) + { return false; } + Entity sup = entity.getSuperclass(); + if (sup == null) + { return false; } + BehaviouralFeature sop = sup.getDefinedOperation(name); + if (sop == null) + { return false; } + return true; + } + + public boolean isQuery() + { return query; } // invariants/postconditions for this op should have + // result in succ as only updated feature + + public boolean isUpdate() + { return query == false; } + + public boolean isGenerator() + { return hasStereotype("generator"); } + + public static boolean isStatic0(ModelElement mm) + { if (mm instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) mm; + if (bf.isStatic()) { } + else + { return false; } + if (bf.parameters != null && + bf.parameters.size() == 0) + { return true; } + return false; + } + return false; + } + + public static boolean isStaticN(ModelElement mm) + { if (mm instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) mm; + if (bf.isStatic()) { } + else + { return false; } + if (bf.parameters != null && + bf.parameters.size() > 0) + { return true; } + return false; + } + return false; + } + + public static boolean isQuery0(ModelElement mm) + { if (mm instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) mm; + if (bf.query) { } + else + { return false; } + if (bf.parameters != null && + bf.parameters.size() == 0) + { return true; } + return false; + } + return false; + } + + public static boolean isQueryN(ModelElement mm) + { if (mm instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) mm; + if (bf.query) { } + else + { return false; } + if (bf.parameters != null && + bf.parameters.size() > 0) + { return true; } + return false; + } + return false; + } + + public static boolean isUpdate0(ModelElement mm) + { if (mm instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) mm; + if (bf.query) + { return false; } + + if (bf.parameters != null && + bf.parameters.size() == 0) + { return true; } + } + return false; + } + + public static boolean isUpdateN(ModelElement mm) + { if (mm instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) mm; + if (bf.query) + { return false; } + + if (bf.parameters != null && + bf.parameters.size() > 0) + { return true; } + } + return false; + } + + public void setAbstract(boolean ab) + { if (ab) + { addStereotype("abstract"); } + else + { removeStereotype("abstract"); } + } + + public boolean isAbstract() + { return hasStereotype("abstract"); } + + public boolean isSequential() + { return hasStereotype("sequential"); } + + public boolean isStatic() + { return hasStereotype("static"); } + + public boolean isUnsafe() + { return hasStereotype("unsafe"); } + + public boolean isVirtual(Entity ent) + { // if same op is in ent & ent superclass or ent subclass + if (ent.isInterface() || ent.isAbstract()) + { return true; } + + if (ent.isActive() && "run".equals(name)) + { return true; } + + String sig = getSignature(); + if (ent != null) + { Entity esup = ent.getSuperclass(); + if (esup != null) + { BehaviouralFeature bf = esup.getOperationBySignature(sig); + if (bf != null) + { return true; } + } + + for (int j = 0; j < ent.getInterfaces().size(); j++) + { Entity intf = (Entity) ent.getInterfaces().get(j); + BehaviouralFeature bfintf = + intf.getOperationBySignature(sig); + if (bfintf != null) + { return true; } + } + + Vector subs = ent.getSubclasses(); + for (int i = 0; i < subs.size(); i++) + { Entity sub = (Entity) subs.get(i); + BehaviouralFeature bfsub = + sub.getOperationBySignature(sig); + if (bfsub != null) + { return true; } + } + } + return false; + } + + public boolean isFinal() + { return hasStereotype("final"); } + + public boolean isOrdered() + { return ordered; } + + public boolean isSorted() + { return sorted; } + + public boolean isSingleValued() + { if (resultType != null && !("".equals(resultType)) && + !("void".equals(resultType))) + { if (Type.isCollectionType(resultType)) + { return false; } + return true; + } + return false; + } + + public Vector getParameters() + { return parameters; } + + public Attribute getParameter(int i) + { return (Attribute) parameters.get(i); } + + public void setParameters(Vector pars) + { parameters = pars; } + + public void setParameters(java.util.Map vartypes) + { parameters = new Vector(); + java.util.Set keys = vartypes.keySet(); + Vector keyvect = new Vector(); + keyvect.addAll(keys); + for (int i = 0; i < keyvect.size(); i++) + { String key = (String) keyvect.get(i); + if (vartypes.get(key) instanceof Attribute) + { parameters.add(vartypes.get(key)); } + else if (vartypes.get(key) instanceof Type) + { Type vtype = (Type) vartypes.get(key); + if (key != null && vtype != null) + { Attribute att = new Attribute(key,vtype,ModelElement.INTERNAL); + parameters.add(att); + } + } // and avoid duplicates + } + } + + public void setParameters(java.util.Map vartypes, java.util.Map velemtypes) + { parameters = new Vector(); + java.util.Set keys = vartypes.keySet(); + Vector keyvect = new Vector(); + keyvect.addAll(keys); + for (int i = 0; i < keyvect.size(); i++) + { String key = (String) keyvect.get(i); + Type vtype = (Type) vartypes.get(key); + Type vetype = (Type) velemtypes.get(key); + if (key != null && vtype != null) + { Attribute att = new Attribute(key,vtype,ModelElement.INTERNAL); + att.setElementType(vetype); + parameters.add(att); + } // and avoid duplicates + } + } + + public Vector parameterEntities() + { Vector res = new Vector(); + if (parameters == null) + { return res; } + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + Type typ = par.getType(); + if (typ != null && typ.isEntity()) + { res.add(typ.getEntity()); } + } + + return res; + } + + public boolean usesOnlyParameterAttributes(Vector attrs) + { // Each attr : attrs has name starting with a parameter name + // and not with self. + + for (int i = 0; i < attrs.size(); i++) + { Attribute attr = (Attribute) attrs.get(i); + String nme = attr.getName(); + + if (nme.startsWith("self.")) + { return false; } + + boolean found = false; + for (int j = 0; j < parameters.size(); j++) + { Attribute par = (Attribute) parameters.get(j); + if (nme.startsWith(par.getName() + ".")) + { found = true; + break; + } + } + + if (!found) + { return false; } + } + + return true; + } + + public void setElementType(Type et) + { elementType = et; } + // and set the elementType of the resultType. + + public Type getResultType() + { if (resultType == null) { return null; } + return (Type) resultType.clone(); + } + + public Type getReturnType() + { if (resultType == null) + { return new Type("void", null); } + return (Type) resultType.clone(); + } + + public Attribute getResultParameter() + { if (resultType == null) + { return null; } + + if (resultType.getName().equals("void")) + { return null; } + + Attribute resultVar = + new Attribute("result", resultType, ModelElement.INTERNAL); + resultVar.setElementType(elementType); + return resultVar; + } + + public Type getType() + { if (resultType == null) + { return new Type("void",null); } + return (Type) resultType.clone(); + } + + public Type getElementType() + { if (elementType == null) { return null; } + return (Type) elementType.clone(); + } + + public Expression getPre() + { return pre; } + + public Expression getPost() + { return post; } + + public Expression definedness(Vector arguments) + { // pre & (pre => def(post)) + Expression res; + if (defcond != null) + { return substituteParameters(defcond, arguments); } + else if (post != null) + { if (pre != null) + { defcond = (Expression) pre.clone(); + Expression defpost = post.definedness(); + Expression imp = new BinaryExpression("=>", defcond, defpost); + imp.setBrackets(true); + res = new BinaryExpression("&", defcond, imp); + } + else + { defcond = new BasicExpression(true); + res = post.definedness(); + } + } + else + { res = new BasicExpression(true); } + defcond = res; + + // JOptionPane.showMessageDialog(null, "Definedness obligation for " + getName() + " is:\n" + res, + // "Internal consistency condition", JOptionPane.INFORMATION_MESSAGE); + System.out.println("***> Definedness obligation for " + getName() + " is:\n" + res); + + if (activity != null) + { Vector calls = + Statement.getOperationCalls(activity); + Vector returns = + Statement.getReturnValues(activity); + + String selfexpr = toString(); + String selfexpr1 = selfexpr; + + if (instanceScope == false && entity != null) + { selfexpr1 = entity.getName() + "." + selfexpr; } + + + if (VectorUtil.containsEqualString(selfexpr, calls) || + VectorUtil.containsEqualString(selfexpr1, calls)) + { + System.out.println("!! Warning: possible infinite recursion: " + + selfexpr + " is in calls of activity: " + calls); + } + + if (VectorUtil.containsEqualString(selfexpr, returns) || + VectorUtil.containsEqualString(selfexpr1, returns)) + { + System.out.println("!! Warning: possible infinite recursion: " + + selfexpr + " is in returned values: " + returns); + } + + Expression def = activity.definedness(); + System.out.println(">> Activity definedness: " + def); + } + + return substituteParameters(res, arguments); + } + + public Expression determinate(Vector arguments) + { // (pre => det(post)) + if (detcond != null) + { return substituteParameters(detcond, arguments); } + else + { detcond = new BasicExpression(true); + Expression imp = null; + if (post != null) + { Expression detpost = post.determinate(); + if (pre != null) + { imp = new BinaryExpression("=>", pre, detpost); + imp.setBrackets(true); + } + else + { imp = detpost; } + } + else + { imp = new BasicExpression(true); } + + // JOptionPane.showMessageDialog(null, "Determinacy obligation for " + getName() + " is:\n" + imp, + // "Internal consistency condition", JOptionPane.INFORMATION_MESSAGE); + System.out.println("***> Determinacy obligation for " + getName() + " is:\n" + imp); + detcond = imp; + return substituteParameters(imp, arguments); + } + } + + public boolean parametersMatch(Vector pars) + { if (pars == null || parameters == null) + { return false; } + + System.out.println(">>> For operation " + name + " actual parameters are " + pars + " formal parameters are " + parameters); + + if (pars.size() == parameters.size()) + { return true; } + + return false; + } // and check the types + + public boolean parametersSupset(Vector pars) + { if (pars == null || parameters == null) + { return false; } + + if (pars.size() < parameters.size()) + { return true; } + + return false; + } // and check the types + + public boolean parameterMatch(Vector pars) + { if (pars == null || parameters == null) + { return false; } + if (pars.size() != parameters.size()) + { return false; } + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + Expression arg = (Expression) pars.get(i); + if (par.getType() == null || + Type.isVacuousType(par.getType())) { } + else if (par.getType().equals(arg.getType())) { } + else if (Type.isSubType(arg.getType(), par.getType())) { } // = or a subtype + else + { return false; } + } + + return false; + } // and check the types + + public void setFormalParameters(Vector pars) + { if (pars == null || parameters == null) + { return; } + + Vector extrapars = new Vector(); + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + Type pt = par.getType(); + + if (i < pars.size()) + { Expression arg = (Expression) pars.get(i); + arg.formalParameter = par; + } + else + { Expression nullInit = + Type.nullInitialValueExpression(pt); + nullInit.formalParameter = par; + extrapars.add(nullInit); + } + } + + pars.addAll(extrapars); + } // Used in code generation, eg., for Swift. + + public Expression substituteParameters(Expression e, Vector arguments) + { if (e == null) + { return new BasicExpression(true); } + Expression res = (Expression) e.clone(); + if (parameters == null) { return res; } + for (int i = 0; i < parameters.size(); i++) + { if (i < arguments.size()) + { Expression arg = (Expression) arguments.get(i); + Attribute par = (Attribute) parameters.get(i); + res = res.substituteEq(par.getName(), arg); + } + } + return res; + } + + public Expression substituteParametersPre(Vector arguments) + { if (pre == null) + { return new BasicExpression(true); } + Expression res = (Expression) pre.clone(); + if (parameters == null) { return res; } + for (int i = 0; i < parameters.size(); i++) + { if (i < arguments.size()) + { Expression arg = (Expression) arguments.get(i); + Attribute par = (Attribute) parameters.get(i); + res = res.substituteEq(par.getName(), arg); + } + } + return res; + } + + public Expression substituteParametersPost(Vector arguments) + { if (post == null) + { return new BasicExpression(true); } + Expression res = (Expression) post.clone(); + for (int i = 0; i < parameters.size(); i++) + { if (i < arguments.size()) + { Expression arg = (Expression) arguments.get(i); + Attribute par = (Attribute) parameters.get(i); + res = res.substituteEq(par.getName(), arg); + } + } + return res; + } + + public void substituteEq(String oldName, Expression newExpr) + { if (pre != null) + { Expression newpre = pre.substituteEq(oldName, newExpr); + this.setPre(newpre); + } + + if (post != null) + { Expression newpost = + post.substituteEq(oldName, newExpr); + this.setPost(newpost); + } + + if (activity != null) + { Statement newact = + activity.substituteEq(oldName, newExpr); + this.setActivity(newact); + } + } + + public void removeEntityParameter(Entity ent) + { if (parameters == null) + { return; } + + Vector removed = new Vector(); + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + + Type typ = par.getType(); + if (typ != null && typ.isEntity() && + ent == typ.getEntity()) + { removed.add(par); + BasicExpression selfexpr = + new BasicExpression("self"); + if (entity != null) + { selfexpr.setType(new Type(entity)); } + selfexpr.setUmlKind(Expression.VARIABLE); + + this.substituteEq(par.getName(), selfexpr); + } + + parameters.removeAll(removed); + return; + } + } + + public Vector checkParameterNames() + { Vector unusedVars = new Vector(); + + if (parameters == null) + { return unusedVars; } + + Vector pnames = new Vector(); + + int UVA = 0; + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pname = par.getName(); + + if (pnames.contains(pname)) + { System.err.println("!! ERROR: duplicated parameter name: " + pname + " in operation " + getName()); } + else + { pnames.add(pname); } + + if (Character.isLowerCase(pname.charAt(0))) { } + else + { System.err.println("! Warning: parameter names should start with a lower case letter: " + pname); } + + if (Entity.strictEntityName(pname)) { } + else + { System.err.println("! Warning: parameter names should be alphanumeric: " + pname); } + + if (pname.length() > 40) + { System.err.println("! Warning: parameter names should not be longer than 40 characters: " + pname); } + + + if (activity == null && post != null) + { Vector puses = post.getUses(pname); + if (puses.size() == 0) + { System.err.println("!! Code smell (UVA): parameter " + pname + " is unused in operation " + getName() + " postcondition."); + UVA++; + unusedVars.add(par); + } + } + + if (activity != null) + { Vector actuses = activity.getUses(pname); + if (actuses.size() == 0) + { System.err.println("!! Code smell (UVA): parameter " + pname + " is unused in operation " + getName() + " activity."); + UVA++; + unusedVars.add(par); + } + } + } + + if (UVA > 0) + { System.out.println("!!! UVA (parameters) = " + UVA + " for operation " + name); + System.out.println("!! Unused parameters: " + unusedVars); + System.out.println(); + } + + return unusedVars; + } + + public void removeUnusedParameters() + { Vector unusedVars = checkParameterNames(); + parameters.removeAll(unusedVars); + } + + + public void splitIntoSegments() + { if (activity == null) + { return; } + + String nme = getName(); // not considering generics + + if (activity instanceof SequenceStatement) + { SequenceStatement code = (SequenceStatement) activity; + Vector segments = code.segments(); + + System.out.println(">>> Segments: " + segments); + + // A segment is a viable operation if it writes only + // attributes or its own local variables (not + // parameters). Its parameters are all variables of + // this which are read in the segment. + + // Create new operation bf and set + // residue to self.bf(...) + // Otherwise, add segment code to unprocessed and + // try again with the preceding segment + unprocessed + + Vector residue = new Vector(); + Vector unprocessed = new Vector(); + + for (int i = segments.size() - 1; i >= 1; i--) + { Vector seg = (Vector) segments.get(i); + Vector completeseg = new Vector(); + completeseg.addAll(seg); + completeseg.addAll(unprocessed); + + SequenceStatement sseg = + new SequenceStatement(completeseg); + Vector wrs = sseg.writeFrame(); + // Vector rds = sseg.readFrame(); + + Vector unused = new Vector(); + Vector actuses = sseg.getVariableUses(unused); + actuses = ModelElement.removeExpressionByName("skip", actuses); + + System.out.println(">%%> Variables used in " + completeseg + " are: " + actuses); + System.out.println(">%%> Variables written in " + completeseg + " are: " + wrs); + System.out.println(">%%> Declared and unused variables of " + completeseg + " are " + unused); + + // if wrs disjoint from actuses it is ok. Parameters + // are actuses. + + Vector rems = + ModelElement.removeExpressionsByName(wrs, actuses); + + if (rems.size() == actuses.size()) + { System.out.println(">%%> Valid segment. Creating new operation for it."); + unprocessed = new Vector(); + + Vector pars = new Vector(); + Vector pnames = new Vector(); + for (int j = 0; j < actuses.size(); j++) + { Expression use = (Expression) actuses.get(j); + if (pnames.contains(use + "")) { } + else + { Attribute att = new Attribute(use); + pars.add(att); + pnames.add(use + ""); + } + } + + String newopname = Identifier.nextIdentifier(nme + "_segment_"); + BehaviouralFeature bf = + new BehaviouralFeature( + newopname, pars, query, resultType); + bf.setEntity(entity); + bf.setPost(new BasicExpression(true)); + bf.setComments("Derived from " + nme + " by Split operation refactoring"); + + if (residue.size() > 0) + { sseg.addStatements(residue); } + residue = new Vector(); + bf.setActivity(sseg); + entity.addOperation(bf); + if (resultType == null || + "void".equals(resultType + "")) + { + InvocationStatement callbf = + new InvocationStatement("self", bf); + residue.add(callbf); + } + else + { BasicExpression selfbe = + new BasicExpression(entity, "self"); + BasicExpression val = + BasicExpression.newCallBasicExpression( + bf,selfbe,pars); + ReturnStatement ret = + new ReturnStatement(val); + residue.add(ret); + } + } + else + { System.out.println(">%%> Invalid segment. Cannot split operation."); + Vector oldunprocessed = new Vector(); + oldunprocessed.addAll(completeseg); + unprocessed = oldunprocessed; + // residue = new Vector(); + } + } + + Vector seg = (Vector) segments.get(0); + if (unprocessed.size() == 0 && residue.size() > 0) + { seg.addAll(residue); + setActivity(new SequenceStatement(seg)); + } + else if (residue.size() > 0) + { seg.addAll(unprocessed); + seg.addAll(residue); + setActivity(new SequenceStatement(seg)); + } + } + } + + public static Vector allAttributesUsedIn(Entity ent, Vector ops) + { Vector res = new Vector(); + + for (int i = 0; i < ops.size(); i++) + { String op = (String) ops.get(i); + BehaviouralFeature bf = ent.getOperation(op); + if (bf != null) + { Vector attrs = bf.allAttributesUsedIn(); + res = VectorUtil.union(res,attrs); + } + } + return res; + } + + public Vector allAttributesUsedIn() + { Vector res = new Vector(); + if (activity != null) + { res = activity.allAttributesUsedIn(); } + else if (post != null) + { res = post.allAttributesUsedIn(); } + return res; + } + + public boolean checkVariableUse() + { Vector unused = new Vector(); + + if (activity != null) + { Vector wrf = activity.writeFrame(); + + System.out.println(">>> Parameters or variables " + wrf + " are written in " + getName() + " activity."); + + Vector actuses = activity.getVariableUses(unused); + actuses = ModelElement.removeExpressionByName("skip", actuses); + + System.out.println(">>> Parameters or non-local variables " + actuses + " are used in " + getName() + " activity."); + + Vector attrs = activity.allAttributesUsedIn(); + + System.out.println(">>> Attributes " + attrs + " are used in " + getName() + " activity."); + System.out.println(); + + if (unused.size() > 0) + { System.out.println("!! Parameters or non-local variables " + unused + " are declared but not used in " + getName() + " activity."); + System.out.println("!!! UVA (local variables) = " + unused.size() + " for operation " + name); + return true; + } + + System.out.println(); + } + + // Should be subset of parameters + visible data features + // getDeclaredVariables() -- any extra in here are UVA. + return false; + } + + + + private void typeCheckParameters(Vector pars, Vector types, Vector entities) + { for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + Type newtype = Type.typeCheck(partype,types,entities); + par.setType(newtype); + System.out.println(">> parameter " + par.getName() + + " has type " + newtype); + } + } + + private void typeInferenceParameters(Vector pars, Vector types, Vector entities) + { for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null && + partype.isAliasType()) + { partype = partype.getActualType(); } + Type newtype = Type.typeCheck(partype,types,entities); + par.setType(newtype); + par.setElementType(newtype.getElementType()); + System.out.println(">> parameter " + par.getName() + + " has type " + newtype); + } + } + + public Vector allTypeParameterEntities(Entity ent) + { Vector localEntities = new Vector(); + + if (typeParameters != null) + { for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + if (tp.isEntity()) + { localEntities.add(tp.getEntity()); } + } + } + + if (ent != null) + { Vector etpars = ent.getTypeParameters(); + if (etpars != null) + { for (int i = 0; i < etpars.size(); i++) + { Type tp = (Type) etpars.get(i); + if (tp.isEntity()) + { localEntities.add(tp.getEntity()); } + } + } + } + + return localEntities; + } + + public Vector allTypeParameterEntities() + { Vector localEntities = allTypeParameterEntities(entity); + + System.out.println(">>> All local entities for " + name + " are " + localEntities); + + return localEntities; + } + + public boolean typeCheck(Vector types, Vector entities) + { // System.err.println("ERROR -- calling wrong type-check for " + name); + + Vector localEntities = allTypeParameterEntities(); + + localEntities.addAll(entities); + + Vector contexts = new Vector(); + if (entity != null && instanceScope) + { contexts.add(entity); } + else if (entity != null && !instanceScope) + { localEntities.add(0,entity); } + + Vector env = new Vector(); + typeCheckParameters(parameters,types,localEntities); + env.addAll(parameters); + + if (resultType != null && !("void".equals(resultType + ""))) + { Attribute resultVar = getResultParameter(); + if (resultVar != null) + { env.add(resultVar); } + } + + if (pre != null) + { pre.typeCheck(types,localEntities,contexts,env); } + + boolean res = false; + + if (post != null) + { res = post.typeCheck( + types,localEntities,contexts,env); + } + + if (activity != null) + { System.out.println(">>> Type-checking activity " + activity); + res = activity.typeCheck( + types,localEntities,contexts,env); + } + + // System.out.println(">>> Parameters = " + parameters); + + return res; + } // and the activity? + // could deduce type and element type of result. + + public boolean typeInference(Vector types, Vector entities, + java.util.Map vartypes) + { java.util.Map localvartypes = new java.util.HashMap(); + localvartypes.putAll(vartypes); + + Vector localEntities = allTypeParameterEntities(); + + localEntities.addAll(entities); + + Vector contexts = new Vector(); + if (entity != null && instanceScope) + { contexts.add(entity); } + else if (entity != null && !instanceScope) + { localEntities.add(0,entity); } + + Vector env = new Vector(); + typeInferenceParameters(parameters,types,localEntities); + env.addAll(parameters); + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + localvartypes.put(par.getName(), par.getType()); + } + + if (resultType != null && !("void".equals(resultType + ""))) + { Attribute resultVar = getResultParameter(); + if (resultVar != null) + { env.add(resultVar); + localvartypes.put("result", resultType); + } + } + + if (pre != null) + { pre.typeCheck(types,localEntities,contexts,env); } + + boolean res = false; + + if (post != null) + { res = post.typeCheck( + types,localEntities,contexts,env); + } + + if (activity != null) + { System.out.println(">>> Type inference for activity " + activity); + res = activity.typeInference( + types,localEntities,contexts,env,localvartypes); + } + + System.out.println(">>> Typed variables = " + + localvartypes); + + Type rtype = (Type) localvartypes.get("result"); + if ((resultType == null || + "OclAny".equals(resultType + "")) && + rtype != null) + { resultType = rtype; } + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + Type newpartype = + (Type) localvartypes.get(par.getName()); + if (Type.isVacuousType(par.getType()) && + newpartype != null) + { par.setType(newpartype); } + } + + return res; + } + + public boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector env) + { Vector contexts1 = new Vector(); + if (entity != null && instanceScope) + { if (contexts.contains(entity)) { } + else + { contexts1.add(entity); } + } + contexts1.addAll(contexts); + + + // System.err.println("Type-check for " + name + " WITH " + env1 + " " + contexts1); + + Vector localEntities = allTypeParameterEntities(); + + localEntities.addAll(entities); + if (entity != null && !instanceScope) + { localEntities.add(0,entity); } + // The static context. + + typeCheckParameters(parameters,types,localEntities); + + Vector env1 = new Vector(); + env1.addAll(parameters); + env1.addAll(env); + + if (pre != null) + { pre.typeCheck(types,localEntities,contexts1,env1); } + + boolean res = false; + + if (post != null) + { res = post.typeCheck( + types,localEntities,contexts1,env1); + } + + if (activity != null) + { res = activity.typeCheck( + types,localEntities,contexts1,env1); + } + + return res; + } + + public static Vector reconstructParameters( + String pars, Vector types, Vector entities) + { return reconstructParameters(null, + pars," ,:",types,entities); + } + + public static Vector reconstructParameters(Entity ent, + String pars, Vector types, Vector entities) + { return reconstructParameters(ent, + pars," ,:",types,entities); + } + + public static Vector reconstructParameters(Entity ent, + String pars, String seps, + Vector types, Vector entities) + { Vector parvals = new Vector(); + Vector res = new Vector(); + StringTokenizer st = new StringTokenizer(pars,seps); + while (st.hasMoreTokens()) + { parvals.add(st.nextToken()); } + + Vector localEntities = new Vector(); + if (ent != null) + { localEntities.addAll(ent.typeParameterEntities()); } + localEntities.addAll(entities); + + for (int i = 0; i < parvals.size() - 1; i = i + 2) + { String var = (String) parvals.get(i); + String typ = (String) parvals.get(i+1); // could be Set(T), etc + + Type elemType = null; + + if (typ != null) + { int bind = typ.indexOf("("); + if (bind > 0) // a set, sequence or map type + { int cind = typ.indexOf(","); + if (cind > 0) + { String xparam = typ.substring(cind+1, typ.length() - 1); + elemType = Type.getTypeFor(xparam,types,localEntities); + } + else + { String tparam = typ.substring(bind+1,typ.length() - 1); + elemType = Type.getTypeFor(tparam,types,localEntities); + } + } + } + + Type t = Type.getTypeFor(typ,types,localEntities); + + if (t == null) // must be standard type or an entity + { System.err.println("!! ERROR: Invalid type name: " + typ); + JOptionPane.showMessageDialog(null, "ERROR: Invalid type for parameter: " + typ, + "Type error", JOptionPane.ERROR_MESSAGE); + } + else + { Attribute att = new Attribute(var,t,ModelElement.INTERNAL); + att.setElementType(elemType); + t.setElementType(elemType); + res.add(att); + System.out.println(">>> Parameter " + var + " type " + t); + } + } + return res; + } + + public String getParList() + { String res = ""; + + if (parameters == null) + { return res; } + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + res = res + att.getName() + " " + att.getType() + " "; + } + return res; + } + + public String getSignature() + { String res = getName(); + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getName(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + res = res + genPars + "("; + + if (parameters == null) + { return res + ")"; } + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + res = res + att.getName() + ": " + att.getType(); + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res + ")"; + } + + public String getTypeSignature() + { String res = getName(); + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getName(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + res = res + genPars + "("; + + if (parameters == null) + { return res + ")"; } + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + res = res + att.getType(); + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res + ")"; + } + + public Vector getParameterNames() + { Vector res = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + res.add(att.getName()); + } + return res; + } + + public Vector getParameterExpressions() + { Vector res = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + Expression expr = new BasicExpression(att); + expr.formalParameter = att; + res.add(expr); + } + return res; + } + + public Vector allVariableNames() + { Vector res = getParameterNames(); + if (activity != null) + { Vector vars = Statement.getLocalDeclarations(activity); + for (int i = 0; i < vars.size(); i++) + { CreationStatement cs = (CreationStatement) vars.get(i); + res.add(cs.getDeclaredVariable()); + } + Vector vs = activity.allVariableNames(); + res = VectorUtil.union(res, vs); + } + return res; + } + + public String getJavaParameterDec() + { String res = ""; + // System.out.println("PARAMETERS = " + parameters); + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + Type typ = att.getType(); + if (typ == null) + { System.err.println("!! ERROR: null type for parameter " + att); + JOptionPane.showMessageDialog(null, "ERROR: Invalid type for parameter: " + att, + "Type error", JOptionPane.ERROR_MESSAGE); + typ = new Type("void",null); + } + res = res + typ.getJava() + " " + attnme; + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res; + } + + public String getJava6ParameterDec() + { String res = ""; + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + Type typ = att.getType(); + if (typ == null) + { System.err.println("!! ERROR: null type for parameter " + att); + JOptionPane.showMessageDialog(null, "ERROR: Invalid type for parameter: " + att, + "Type error", JOptionPane.ERROR_MESSAGE); + typ = new Type("void",null); + } + res = res + typ.getJava6() + " " + attnme; + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res; + } + + public String getJava7ParameterDec() + { String res = ""; + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + Type typ = att.getType(); + if (typ == null) + { System.err.println("!! ERROR: null type for parameter " + att); + // JOptionPane.showMessageDialog(null, "ERROR: Invalid type for parameter: " + att, + // "Type error", JOptionPane.ERROR_MESSAGE); + typ = new Type("void",null); + } + res = res + typ.getJava7(att.getElementType()) + " " + attnme; + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res; + } + + public String getCSharpParameterDec() + { String res = ""; + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + Type typ = att.getType(); + if (typ == null) + { System.err.println("!! ERROR: null type for parameter " + att); + JOptionPane.showMessageDialog(null, "ERROR: Invalid type for parameter: " + att, + "Type error", JOptionPane.ERROR_MESSAGE); + typ = new Type("void",null); + } + res = res + typ.getCSharp() + " " + attnme; + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res; + } + + public String getCPPParameterDec() + { String res = ""; + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + Type typ = att.getType(); + if (typ == null) + { System.err.println("!! ERROR: null type for parameter " + att); + JOptionPane.showMessageDialog(null, "ERROR: Invalid type for parameter: " + att, + "Type error", JOptionPane.ERROR_MESSAGE); + typ = new Type("void",null); + } + res = res + typ.getCPP(att.getElementType()) + " " + attnme; + if (i < parameters.size() - 1) + { res = res + ","; } + } + return res; + } + + private String parcats() + { // Assumes all parameters are primitive/strings + String res = ""; + if (parameters.size() == 1) + { Attribute p = (Attribute) parameters.get(0); + return Expression.wrap(p.getType(), p.getName()); + } + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String par1 = par.getName(); + if (i < parameters.size() - 1) + { res = res + par1 + " + \", \" + "; } + else + { res = res + par1; } + } + return res; + } // works for Java + + private String parcatsJava6() + { // Assumes all parameters are primitive/strings + String res = ""; + if (parameters.size() == 1) + { Attribute p = (Attribute) parameters.get(0); + return Expression.wrapJava6(p.getType(), p.getName()); + } + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String par1 = par.getName(); + if (i < parameters.size() - 1) + { res = res + par1 + " + \", \" + "; } + else + { res = res + par1; } + } + return res; + } // works for Java6 + + private String parcatsCSharp() + { // Assumes all parameters are primitive/strings + String res = ""; + if (parameters.size() >= 1) + { Attribute p = (Attribute) parameters.get(0); + res = res + p.getName(); + } + for (int i = 1; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String par1 = par.getName(); + res = res + " + \", \" + " + par1; + } + return res; + } + + public BExpression getBParameterDec() + { BExpression res = null; + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + BExpression attbe = new BBasicExpression(att.getName()); + BExpression typebe = + new BBasicExpression(att.getType().generateB(att.getElementType())); + BExpression conj = new BBinaryExpression(":",attbe,typebe); + if (res == null) + { res = conj; } + else + { res = new BBinaryExpression("&",res,conj); } + } + return res; + } + + public BExpression getBCall() + { // call of query op, assumed instance scope + + String opname = getName(); + if (entity == null) + { opname = opname + "_"; } + else + { opname = opname + "_" + entity.getName(); } + String res = opname; + + String ex = entity.getName().toLowerCase() + "x"; + Vector epars = new Vector(); + epars.add(new BBasicExpression(ex)); + + if (parameters.size() == 0) + { return new BBasicExpression(opname,epars); } + + Vector pars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getName(); + pars.add(new BBasicExpression(dec)); + } + return new BApplyExpression(new BBasicExpression(opname,epars),pars); + } + + public BExpression getBFunctionDec() + { // opname_E : es --> (parT --> resultT) + BExpression res = null; + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + BExpression typebe = + new BBasicExpression(att.getType().generateB(att.getElementType())); + if (res == null) + { res = typebe; } + else + { res = new BBinaryExpression("*",res,typebe); } + } // what if empty? + + BExpression ftype; + if (resultType != null) // for Set/Sequence need elementType + { String rT = resultType.generateB(elementType); + if (res == null) + { ftype = new BBasicExpression(rT); } + else + { ftype = new BBinaryExpression("-->",res, + new BBasicExpression(rT)); + ftype.setBrackets(true); + } + } + else + { System.err.println("ERROR: Undefined return type of operation " + this); + ftype = null; + return null; + } + + String opname = getName(); + if (entity == null) // also if static + { opname = opname + "_"; + return new BBinaryExpression(":",new BBasicExpression(opname),ftype); + } + else + { opname = opname + "_" + entity.getName(); + String ename = entity.getName(); + String es = ename.toLowerCase() + "s"; + BExpression esbe = new BBasicExpression(es); + return new BBinaryExpression(":",new BBasicExpression(opname), + new BBinaryExpression("-->",esbe,ftype)); + } + } + + private String parameterList() + { String res = ""; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ", "; } + res = res + dec; + } + return res; + } + + + public String toString() + { String res = getName(); + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getName(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ","; } + } + genPars = genPars + ">"; + } + + res = res + genPars + "("; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ","; } + res = res + dec; + } + res = res + ")"; + return res; + } + + public String display() // what about guards? + { String res = ""; + if (isSequential()) + { res = res + "synchronized "; } + if (isAbstract()) + { res = res + "abstract "; } + if (isFinal()) + { res = res + "final "; } + if (instanceScope) { } + else + { res = res + "static "; } + if (isQuery()) + { res = res + "query "; } + + res = res + getSignature(); + + if (resultType != null) + { res = res + ": " + resultType; } + // if ("Set".equals(resultType + "") || "Sequence".equals(resultType + "")) + // { res = res + "(" + elementType + ")"; } + res = res + "\n"; + if (pre != null) + { res = res + "pre: " + pre + "\n"; } + if (post != null) + { res = res + "post: " + post + "\n"; } + if (activity != null) + { res = res + "activity: " + activity + "\n"; } + if (hasText()) + { res = res + "text:\n"; + res = res + text + "\n"; + } + return res; + } + + public String displayForUC() // what about guards? + { String res = ""; + + res = res + getSignature(); + + if (resultType != null) + { res = res + " : " + resultType; } + res = res + "\n\r"; + if (pre != null) + { res = res + "pre: " + pre + "\n\r"; } + else + { res = res + "pre: true\n\r"; } + + if (post != null) + { res = res + "post: " + post + "\n\r"; } + else + { res = res + "post: true\n\r"; } + return res; + } + + public Vector equivalentsUsedIn() + { Vector res = new Vector(); + if (pre != null) + { res.addAll(pre.equivalentsUsedIn()); } + if (post != null) + { res.addAll(post.equivalentsUsedIn()); } + if (activity != null) + { res.addAll(activity.equivalentsUsedIn()); } + return res; + } + + public void simplifyOCL() + { if (pre != null) + { pre = pre.simplifyOCL(); } + if (post != null) + { post = post.simplifyOCL(); } + if (activity != null) + { activity = activity.optimiseOCL(); } + } + + public Map energyAnalysis(Vector redUses, Vector amberUses) + { // Scan the postcondition/activity for energy expensive + // expressions/code + + Map res = new Map(); + res.set("red", 0); + res.set("amber", 0); + + java.util.Map clones = new java.util.HashMap(); + java.util.Map defs = new java.util.HashMap(); + + if (post != null) + { res = post.energyUse(res, redUses, amberUses); + + // System.out.println(res); + // System.out.println(redUses); + // System.out.println(amberUses); + + post.findClones(clones, defs, null, name); + if (clones.size() > 0) + { java.util.Set actualClones = new java.util.HashSet(); + + for (Object key : clones.keySet()) + { java.util.List occs = + (java.util.List) clones.get(key); + if (occs.size() > 1) + { actualClones.add(key); } + } + + if (actualClones.size() > 0) + { redUses.add("!!! Cloned expressions could be repeated evaluations: " + actualClones + "\n" + + ">>> Use Extract Local Variable refactoring"); + int rscore = (int) res.get("red"); + rscore = rscore + actualClones.size(); + res.set("red", rscore); + } + } // In a postcondition they usually are repeats. + } + + clones = new java.util.HashMap(); + defs = new java.util.HashMap(); + + if (activity != null) + { res = activity.energyUse(res, redUses, amberUses); + + // System.out.println(res); + // System.out.println(redUses); + // System.out.println(amberUses); + + activity.findClones(clones, defs, null, name); + if (clones.size() > 0) + { java.util.Set actualClones = new java.util.HashSet(); + + for (Object key : clones.keySet()) + { java.util.List occs = + (java.util.List) clones.get(key); + if (occs.size() > 1) + { actualClones.add(key); } + } + + if (actualClones.size() > 0) + { amberUses.add("!! Cloned expressions could be repeated evaluations: " + actualClones + "\n" + + ">>> Use Extract Local Variable refactoring"); + int ascore = (int) res.get("amber"); + ascore = ascore + actualClones.size(); + res.set("amber", ascore); + } + } // In a postcondition they usually are repeats. + } + + Vector unusedVars = checkParameterNames(); + if (unusedVars.size() > 0) + { amberUses.add("!! Unused parameters: " + unusedVars + "\n" + + ">>> Use remove unused parameters refactoring"); + int ascore = (int) res.get("amber"); + ascore = ascore + unusedVars.size(); + res.set("amber", ascore); + } + + return res; + } + + public void collectionOperatorUses(int level, + java.util.Map res, + Vector vars) + { // Scan the postcondition/activity for energy expensive + // expressions/code + + if (post != null) + { post.collectionOperatorUses(level, res, vars); } + + if (activity != null) + { activity.collectionOperatorUses(level, res, vars); } + + } // and activity + + public int displayMeasures(PrintWriter out) + { String res = ""; + String nme = getName(); + if (entity != null) + { nme = entity.getName() + "::" + nme; } + else if (useCase != null) + { nme = useCase.getName() + "::" + nme; } + + int pars = parameters.size(); + + if (resultType != null) + { pars++; } + + out.println("*** Number of parameters of operation " + nme + " = " + pars); + if (pars > TestParameters.numberOfParametersLimit) + { System.err.println("!!! Code smell (EPL): too many parameters (" + pars + ") for " + nme); + System.err.println(">>> Recommend refactoring by introducing value object for parameters or splitting operation into parts"); + } + + int complexity = 0; + int cyc = 0; + + if (pre != null) + { complexity = complexity + pre.syntacticComplexity(); } + if (post != null) + { complexity = complexity + post.syntacticComplexity(); + cyc = post.cyclomaticComplexity(); + } + + out.println("*** Postcondition cyclomatic complexity = " + cyc); + + if (activity != null) + { cyc = activity.cyclomaticComplexity(); + out.println("*** Activity cyclomatic complexity = " + cyc); + + int acomp = activity.syntacticComplexity(); + out.println("*** Activity syntactic complexity = " + acomp); + if (acomp > TestParameters.operationSizeLimit) + { System.err.println("!!! Code smell (EOS): too high activity complexity (" + acomp + ") for " + nme); + System.err.println(">>> Recommend refactoring by splitting operation"); + } + else if (acomp > TestParameters.operationSizeWarning) + { System.err.println("*** Warning: high activity complexity (" + acomp + ") for " + nme); } + complexity = complexity + acomp; + } + + out.println("*** Total complexity of operation " + nme + " = " + complexity); + out.println(); + if (cyc > TestParameters.cyclomaticComplexityLimit) + { System.err.println("!!! Code smell (CC): high cyclomatic complexity (" + cyc + ") for " + nme); + System.err.println(">>> Recommend refactoring by splitting operation"); + } + + if (complexity > TestParameters.operationSizeLimit) + { System.err.println("!!! Code smell (EHS): too high complexity (" + complexity + ") for " + nme); + System.err.println(">>> Recommend refactoring by splitting operation"); + } + else if (complexity > TestParameters.operationSizeWarning) + { System.err.println("*** Warning: high complexity (" + complexity + ") for " + nme); } + + + return complexity; + } + + public java.util.Map dataDependencies() + { java.util.Map res = new java.util.HashMap(); + + if (activity != null && + entity != null) + { String nme = getName(); + Vector allvars = new Vector(); + for (int i = 0; i < parameters.size(); i++) + { Attribute parx = (Attribute) parameters.get(i); + allvars.add(parx.getName()); + } + + Vector attrs = entity.getAttributes(); + for (int i = 0; i < attrs.size(); i++) + { Attribute attx = (Attribute) attrs.get(i); + allvars.add(attx.getName()); + } + + Vector opvars = activity.getVariableUses(); + + Map localdeps = new Map(); + Map dataLineages = new Map(); + + Vector postvars = new Vector(); + postvars.add("result"); + Vector deps = activity.dataDependents( + allvars,postvars); + System.out.println(); + System.out.println(">***> result is derived from:\n " + deps); + + // res.put("result", deps); + + + for (int i = 0; i < attrs.size(); i++) + { Attribute attx = (Attribute) attrs.get(i); + String aname = attx.getName(); + Vector avs = new Vector(); + avs.add(aname); + Vector adeps = + activity.dataDependents(allvars, avs, localdeps, + dataLineages); + System.out.println(">***> " + aname + " is derived from " + adeps); + res.put(aname, adeps); + /* for (int j = 0; j < adeps.size(); j++) + { String adepsource = "" + adeps.get(j); + if (aname.equals(adepsource)) { } + else + { localdeps.add_pair(adepsource, aname); } + } */ + } + + Vector seenvars = new Vector(); + seenvars.add("skip"); + + for (int i = 0; i < opvars.size(); i++) + { String vname = "" + opvars.get(i); + if (seenvars.contains(vname)) + { continue; } + Vector vvs = new Vector(); + vvs.add(vname); + Vector vdeps = + activity.dataDependents(allvars, vvs, localdeps, + dataLineages); + System.out.println(">***> " + vname + " is derived from " + vdeps); + System.out.println(); + seenvars.add(vname); + /* for (int j = 0; j < vdeps.size(); j++) + { String vdepsource = "" + vdeps.get(j); + if (vname.equals(vdepsource)) { } + else + { localdeps.add_pair(vdepsource, vname); } + } */ + } + + System.out.println(); + System.out.println(">***> Data dependencies for " + nme + " are:\n" + localdeps); + + System.out.println(); + System.out.println(">***> Data lineages for " + nme + " are:\n" + dataLineages); + + System.out.println(); + } + + return res; + } + + public int syntacticComplexity() + { + int complexity = 0; + + if (pre != null) + { complexity = complexity + pre.syntacticComplexity(); } + if (post != null) + { complexity = complexity + post.syntacticComplexity(); } + + if (activity != null) + { complexity = complexity + activity.syntacticComplexity(); } + + return complexity; + } + + public int cyclomaticComplexity() + { String res = ""; + String nme = getName(); + if (entity != null) + { nme = entity.getName() + "::" + nme; } + else if (useCase != null) + { nme = useCase.getName() + "::" + nme; } + + int pars = parameters.size(); + + if (resultType != null) + { pars++; } + + System.out.println("*** Number of parameters of operation " + nme + " = " + pars); + if (pars > 10) + { System.err.println("!!! Code smell (EPL): too many parameters (" + pars + ") for " + nme); } + + int complexity = 0; + int cyc = 0; + + if (pre != null) + { complexity = complexity + pre.syntacticComplexity(); } + if (post != null) + { complexity = complexity + post.syntacticComplexity(); + cyc = post.cyclomaticComplexity(); + } + + System.out.println("*** Postcondition cyclomatic complexity = " + cyc); + + if (activity != null) + { cyc = activity.cyclomaticComplexity(); + complexity = complexity + cyc; + System.out.println("*** Activity cyclomatic complexity = " + cyc); + } + + System.out.println("*** Total complexity of operation " + nme + " = " + complexity); + System.out.println(); + if (cyc > 10) + { System.err.println("!!! Code smell (CC): high cyclomatic complexity (" + cyc + ") for " + nme); } + if (complexity > 100) + { System.err.println("!!! Code smell (EHS): too high complexity (" + complexity + ") for " + nme); } + + return cyc; + } + + public int epl() + { return parameters.size(); } // plus variables introduced in post or activity. + + public int cc() + { int res = 0; + + if (post != null) + { res = post.cyclomaticComplexity(); } + + if (activity != null) + { res = res + activity.cyclomaticComplexity(); } + + return res; + } + + public void findClones(java.util.Map clones) + { String nme = getName(); + if (entity != null) + { nme = entity.getName() + "::" + nme; } + else if (useCase != null) + { nme = useCase.getName() + "::" + nme; } + + if (pre != null) + { pre.findClones(clones,null, nme); } + if (post != null) + { post.findClones(clones,null, nme); } + if (activity != null) + { activity.findClones(clones, null, nme); } + } + + public void findClones(java.util.Map clones, + java.util.Map cloneDefinitions) + { String nme = getName(); + if (entity != null) + { nme = entity.getName() + "::" + nme; } + else if (useCase != null) + { nme = useCase.getName() + "::" + nme; } + + if (pre != null) + { pre.findClones(clones, cloneDefinitions, null, nme); } + if (post != null) + { post.findClones(clones, cloneDefinitions, null, nme); } + if (activity != null) + { activity.findClones(clones, cloneDefinitions, + null, nme); + } + } + + public void findMagicNumbers(java.util.Map mgns) + { String nme = getName(); + if (entity != null) + { nme = entity.getName() + "::" + nme; } + else if (useCase != null) + { nme = useCase.getName() + "::" + nme; } + + if (pre != null) + { pre.findMagicNumbers(mgns, nme, nme); } + if (post != null) + { post.findMagicNumbers(mgns, nme, nme); } + if (activity != null) + { activity.findMagicNumbers(mgns, null, nme); } + } + + public void generateMamba(PrintWriter out, CGSpec cgs) + { String nme = getName(); + + String rt = "null"; + if (resultType != null) + { rt = resultType.getCSharp(); } + + String fdef = this.cg(cgs); + String actualDef = CGSpec.replaceActualNewlines(fdef); + + out.println(" {"); + out.println(" \"Name\": \"" + nme + "\","); + out.println(" \"Description\": \"\","); + out.println(" \"Syntax\": \"\","); + out.println(" \"Text\": \"" + actualDef + "\","); + out.println(" \"BaseInfo\": \"\","); + out.println(" \"IsStatic\": " + isStatic() + ","); + out.println(" \"IsInherited\": false,"); + out.println(" \"IsExternal\": false,"); + out.println(" \"ReturnDataType\": \"" + rt + "\","); + out.println(" \"Parameters\": [],"); + out.println(" \"RuleType\": 0,"); + out.println(" \"EventName\": \"\","); + out.println(" \"ApplyToAttribute\": \"\""); + out.print(" }"); + } + + public void generateJava(PrintWriter out) + { out.print(toString()); } + + public void generateCSharp(PrintWriter out) + { out.print(toString()); } + + public String genQueryCode(Entity ent, Vector cons) + { String res = " public "; + if (isSequential()) + { res = res + "synchronized "; } + if (isAbstract()) + { res = res + "abstract "; } // so comment out code + if (isClassScope() || isStatic()) + { res = res + "static "; } + + if (resultType == null || "void".equals(resultType + "")) + { JOptionPane.showMessageDialog(null, + "ERROR: null result type for query operation: " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + return ""; + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + res = res + genPars + resultType.getJava() + + " " + getName() + "("; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getType().getJava() + + " " + par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ", "; } + res = res + dec; + } + + if (isAbstract()) + { res = res + ");\n\n"; + return res; + } + + res = res + ")\n"; + res = res + " { " + resultType.getJava() + " " + + " result = " + resultType.getDefault() + + ";\n"; + + for (int j = 0; j < cons.size(); j++) + { Constraint con = (Constraint) cons.get(j); + if (con.getEvent() != null && + con.getEvent().equals(this)) + res = res + " " + + con.queryOperation(ent) + "\n"; + } + + res = res + " return result;\n"; + res = res + " }\n\n"; + return res; + } + + public String genQueryCodeJava6(Entity ent, Vector cons) + { String res = " public "; + if (isSequential()) + { res = res + "synchronized "; } + if (isAbstract()) + { res = res + "abstract "; } // so comment out code + if (isClassScope() || isStatic()) + { res = res + "static "; } + + if (resultType == null || "void".equals(resultType + "")) + { JOptionPane.showMessageDialog(null, "ERROR: null result type for: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return ""; + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava6(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + + res = res + genPars + resultType.getJava6() + + " " + getName() + "("; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getType().getJava6() + + " " + par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ", "; } + res = res + dec; + } + + if (isAbstract()) + { res = res + ");\n\n"; + return res; + } + res = res + ")\n"; + res = res + " { " + resultType.getJava6() + " " + + " result = " + resultType.getDefaultJava6() + + ";\n"; + + for (int j = 0; j < cons.size(); j++) + { Constraint con = (Constraint) cons.get(j); + if (con.getEvent() != null && + con.getEvent().equals(this)) + res = res + " " + + con.queryOperationJava6(ent) + "\n"; // Java6 version + } + res = res + " return result;\n"; + res = res + " }\n\n"; + return res; + } + + public String genQueryCodeJava7(Entity ent, Vector cons) + { String res = "public "; + if (isSequential()) + { res = res + "synchronized "; } + if (isAbstract()) + { res = res + "abstract "; } // so comment out code + if (isClassScope() || isStatic()) + { res = res + "static "; } + + if (resultType == null || "void".equals(resultType + "")) + { JOptionPane.showMessageDialog(null, + "ERROR: null result type of query operation: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return ""; + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava7(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + + + res = res + genPars + resultType.getJava7(elementType) + + " " + getName() + "("; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getType().getJava7(par.getElementType()) + + " " + par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ", "; } + res = res + dec; + } + + if (isAbstract()) + { res = res + ");\n\n"; + return res; + } + + res = res + ")\n"; + res = res + " { " + resultType.getJava7(elementType) + " " + + " result = " + resultType.getDefaultJava7() + ";\n"; + + for (int j = 0; j < cons.size(); j++) + { Constraint con = (Constraint) cons.get(j); + if (con.getEvent() != null && + con.getEvent().equals(this)) + res = res + " " + + con.queryOperationJava7(ent) + "\n"; // Java6 version + } + res = res + " return result;\n"; + res = res + " }\n\n"; + return res; + } + + public String genQueryCodeCSharp(Entity ent, Vector cons) + { String res = " public "; + if (isUnsafe()) + { res = res + "unsafe "; } + // if (isSequential()) + // { res = res + "synchronized "; } + if (isAbstract()) + { res = res + "abstract "; } // so comment out code + if (isClassScope() || isStatic()) + { res = res + "static "; } + + if (resultType == null || "void".equals(resultType + "")) + { JOptionPane.showMessageDialog(null, "ERROR: null result type for: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return ""; + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getCSharp(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + res = res + resultType.getCSharp() + + " " + getName() + genPars + "("; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getType().getCSharp() + + " " + par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ", "; } + res = res + dec; + } + + if (isAbstract()) + { res = res + ");\n\n"; + return res; + } + + res = res + ")\n"; + res = res + " { " + resultType.getCSharp() + " " + + " result = " + resultType.getDefaultCSharp() + + ";\n"; + for (int j = 0; j < cons.size(); j++) + { Constraint con = (Constraint) cons.get(j); + if (con.getEvent() != null && + con.getEvent().equals(this)) + res = res + " " + + con.queryOperationCSharp(ent) + "\n"; // CSharp version + } + res = res + " return result;\n"; + res = res + " }\n\n"; + return res; + } + + public String genQueryCodeCPP(Entity ent, Vector cons) + { String res = ""; + // " public "; + // if (isSequential()) + // { res = res + "synchronized "; } + // if (isAbstract()) + // { res = res + "abstract "; } // so comment out code + // if (isClassScope() || isStatic()) + // { res = res + "static "; } + + if (resultType == null || "void".equals(resultType + "")) + { JOptionPane.showMessageDialog(null, "ERROR: null result type for: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return ""; + } + + String ename = ""; + String eTypePars = ""; + Vector etpars = new Vector(); + String gpars = ent.typeParameterTextCPP(); + + if (ent == null) + { ent = entity; } + + Vector context = new Vector(); + if (ent != null) + { ename = ent.getName(); + context.add(ent); + if (ent.hasTypeParameters()) + { etpars.addAll(ent.getTypeParameters()); + for (int i = 0; i < etpars.size(); i++) + { Type etp = (Type) etpars.get(i); + eTypePars = eTypePars + etp.getName(); + if (i < etpars.size() - 1) + { eTypePars = eTypePars + ", "; } + } + } + } + + String opGenPars = ""; + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { etpars.addAll(typeParameters); + opGenPars = "template<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + opGenPars = opGenPars + " class " + tp.getName(); + if (i < typeParameters.size() - 1) + { opGenPars = opGenPars + ", "; } + } + opGenPars = opGenPars + "> "; + } + + if (etpars.size() > 0) + { genPars = "template<"; + for (int i = 0; i < etpars.size(); i++) + { Type tp = (Type) etpars.get(i); + genPars = genPars + " class " + tp.getName(); + if (i < etpars.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + String exname = ename; + if (eTypePars.length() > 0) + { exname = ename + "<" + eTypePars + ">"; } + + String header = ""; + if (etpars.size() > 0) + { header = " " + genPars + "\n"; } + + // if (entity != null) + // { ename = entity.getName() + "::"; } + // else if (ent != null) + // { ename = ent.getName() + "::"; } + + res = res + header; + res = res + resultType.getCPP(getElementType()) + + " " + exname + "::" + getName() + "("; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String dec = par.getType().getCPP(par.getElementType()) + + " " + par.getName(); + if (i < parameters.size() - 1) + { dec = dec + ", "; } + res = res + dec; + } + + if (isAbstract()) + { res = res + ");\n\n"; + return res; + } + res = res + ")\n"; + res = res + " { " + resultType.getCPP(getElementType()) + " " + + " result = " + resultType.getDefaultCPP(elementType) + + ";\n"; + + for (int j = 0; j < cons.size(); j++) + { Constraint con = (Constraint) cons.get(j); + if (con.getEvent() != null && + con.getEvent().equals(this)) + res = res + " " + + con.queryOperationCPP(ent) + "\n"; // CPP version + } + res = res + " return result;\n"; + res = res + " }\n\n"; + return res; + } + + public String getParameterisedName() + { String res = getName(); + if (typeParameters != null && typeParameters.size() > 0) + { res = res + "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + res = res + tp.getName(); + if (i < typeParameters.size() - 1) + { res = res + ","; } + } + res = res + ">"; + } + return res; + } + + public void saveData(PrintWriter out) + { if (derived) { return; } + out.println("Operation:"); + out.println(getParameterisedName()); + if (useCase != null) + { out.println("null " + useCase.getName()); } + else + { out.println(entity); } + + if (resultType == null) + { out.println("void"); } + else + { out.println(resultType); } + /* String rtname = resultType.getName(); + if (rtname.equals("Set") || rtname.equals("Sequence")) + { out.println(rtname + "(" + elementType + ")"); } + else + { out.println(rtname); } + } */ + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pnme = par.getName(); + // String tnme = par.getType().getName(); + // String elemt = ""; + // if ("Set".equals(tnme) || "Sequence".equals(tnme)) + // { if (par.getElementType() != null) + // { elemt = "(" + par.getElementType() + ")"; } + // } + out.print(pnme + " " + par.getType() + " "); + } + out.println(); + + String ss = ""; + for (int i = 0; i < stereotypes.size(); i++) + { ss = ss + " " + stereotypes.get(i); } + out.println(ss); + out.println(pre); + out.println(post); + out.println(""); + out.println(""); + } // multiple pre, post, and stereotypes, and the operation text + + public void saveKM3(PrintWriter out) + { if (derived) { return; } + + if (isStatic()) + { out.print(" static operation "); } + else + { out.print(" operation "); } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getName(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + out.print(getName() + genPars + "("); + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pnme = par.getName(); + out.print(pnme + " : " + par.getType() + " "); + if (i < parameters.size() - 1) + { out.print(", "); } + } + out.print(") : "); + + if (resultType == null) + { out.println("void"); } + else + { out.println(resultType); } + + if (pre != null) + { out.println(" pre: " + pre); } + else + { out.println(" pre: true"); } + + if (activity != null) + { out.println(" post: " + post); + out.println(" activity: " + activity + ";"); + } + else + { out.println(" post: " + post + ";"); } + + out.println(""); + } + + public String getKM3() + { // if (derived) { return ""; } + String res = ""; + + if (isQuery()) + { res = " query "; } + else + { res = " operation "; } + + if (isStatic()) + { res = " static" + res; } + else + { res = " " + res; } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getName(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + res = res + getName() + genPars + "("; + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pnme = par.getName(); + res = res + pnme + " : " + par.getType() + " "; + if (i < parameters.size() - 1) + { res = res + ", "; } + } + res = res + ") : "; + + if (resultType == null) + { res = res + "void\n"; } + else + { res = res + resultType + "\n"; } + + if (pre != null) + { res = res + " pre: " + pre + "\n"; } + else + { res = res + " pre: true\n"; } + + if (activity != null) + { res = res + " post: " + post + "\n"; + res = res + " activity: " + activity + ";\n"; + } + else + { res = res + " post: " + post + ";\n"; } + res = res + "\n"; + return res; + } + + public String toAST() + { if (derived) { return ""; } + String result = "(OclOperation "; + String res = ""; + + if (isQuery()) + { res = " query "; } + else + { res = " operation "; } + + if (isStatic()) + { res = " static" + res; } + + String tpars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { Type tp = (Type) typeParameters.get(0); + tpars = " < " + tp.getName() + " > "; + } + + res = res + getName() + tpars + " ( "; + + if (parameters != null && parameters.size() > 0) + { res = res + " (OclParameterList "; + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pnme = par.toASTParameter(); + res = res + pnme; + if (i < parameters.size() - 1) + { res = res + " , "; } + } + res = res + " ) "; + } + res = res + " ) : "; + + if (resultType == null) + { res = res + "void "; } + else + { res = res + resultType.toAST() + " "; } + + if (pre != null) + { res = res + "pre: " + pre.toAST() + " "; } + else + { res = res + "pre: true "; } + + if (activity != null) + { res = res + "post: " + post.toAST() + " "; + res = res + "activity: " + activity.toAST() + " "; + } + else + { res = res + "post: " + post.toAST() + " "; } + return result + res + ")"; + } + + + /* SaveTextModel */ + public String saveModelData(PrintWriter out, Entity ent, Vector entities, Vector types) + { if (stereotypes.contains("auxiliary")) + { return ""; } // but derived ops are usually recorded. + + String nme = getName(); + String opid = Identifier.nextIdentifier("operation_"); + out.println(opid + " : Operation"); + out.println(opid + ".name = \"" + nme + "\""); + Vector cntxt = new Vector(); + Vector env = new Vector(); + env.addAll(parameters); + + if (useCase != null) + { out.println(opid + ".useCase = " + useCase.getName()); } + else if (entity != null) + { out.println(opid + ".owner = " + entity); + // out.println(opid + " : " + entity + ".ownedOperation"); + cntxt.add(entity); + } + + if (isQuery()) + { out.println(opid + ".isQuery = true"); } + else + { out.println(opid + ".isQuery = false"); } + + if (isAbstract()) + { out.println(opid + ".isAbstract = true"); } + else + { out.println(opid + ".isAbstract = false"); } + + if (isStatic()) + { out.println(opid + ".isStatic = true"); } + else + { out.println(opid + ".isStatic = false"); } + + if (isCached()) + { out.println(opid + ".isCached = true"); } + else + { out.println(opid + ".isCached = false"); } + + if (resultType == null) + { out.println(opid + ".type = void"); + out.println(opid + ".elementType = void"); + } + else + { String rtname = resultType.getName(); + String typeid = resultType.getUMLModelName(out); + out.println(opid + ".type = " + typeid); + if (rtname.equals("Set") || rtname.equals("Sequence") || + rtname.equals("Ref") || + rtname.equals("Map") || rtname.equals("Function") ) + { if (elementType == null) + { System.err.println("! Warning!: No element type for " + this); + out.println(opid + ".elementType = void"); + } + else + { String elemtid = elementType.getUMLModelName(out); + out.println(opid + ".elementType = " + elemtid); + } + } + else + { out.println(opid + ".elementType = " + typeid); } + } + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pid = par.saveModelData(out); + // String pnme = par.getName(); + out.println(pid + " : " + opid + ".parameters"); + } + + // And typeParameters + + for (int i = 0; i < stereotypes.size(); i++) + { out.println("\"" + stereotypes.get(i) + "\" : " + opid + ".stereotypes"); } + + String preid; + if (pre != null) + { preid = pre.saveModelData(out); } + else + { preid = "true"; } + String postid; + if (post != null) + { postid = post.saveModelData(out); } + else + { postid = "true"; } + out.println(opid + ".precondition = " + preid); + out.println(opid + ".postcondition = " + postid); + + // System.out.println(">> Operation " + getName() + " activity is: " + activity); + + Vector localentities = new Vector(); + if (typeParameters != null && typeParameters.size() > 0) + { for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + if (tp.isEntity()) + { localentities.add(tp.getEntity()); } + } + } + localentities.addAll(entities); + + if (activity == null) + { Statement des = generateDesign(ent, localentities, types); + des.typeCheck(types,localentities,cntxt,env); + String desid = des.saveModelData(out, ent); + out.println(opid + ".activity = " + desid); + System.out.println(">> Operation " + getName() + " derived activity is: " + des); + } + else // if (activity != null) + { Statement newstat = activity; + if (hasResult() && + !Statement.hasResultDeclaration(activity)) + { // Add a var result : resultType + Attribute att = new Attribute("result",resultType,ModelElement.INTERNAL); + att.setElementType(elementType); + newstat = new SequenceStatement(); + CreationStatement cres = new CreationStatement(resultType + "", "result"); + cres.setInstanceType(resultType); + cres.setElementType(elementType); + ((SequenceStatement) newstat).addStatement(cres); + ((SequenceStatement) newstat).addStatement(activity); + } + String actid = newstat.saveModelData(out, ent); + out.println(opid + ".activity = " + actid); + } + + return opid; + } // multiple pre, post, and stereotypes, and the operation text + + public String saveAsUSEData() + { if (derived) { return ""; } + + String res = getName() + "("; + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pnme = par.getName(); + String tnme = par.getType().getUMLName(); + String elemt = ""; + if ("Set".equals(tnme) || "Sequence".equals(tnme)) + { if (par.getElementType() != null) + { elemt = "(" + par.getElementType().getUMLName() + ")"; } + } + res = res + pnme + " : " + tnme + elemt; + if (i < parameters.size() - 1) { res = res + ", "; } + } + res = res + ") "; + + if (resultType != null) + { String rtname = resultType.getName(); + if (rtname.equals("Set") || rtname.equals("Sequence")) + { if (elementType != null) + { res = res + " : " + resultType.getUMLName() + "(" + elementType.getUMLName() + ")"; } + else + { res = res + " : " + resultType.getUMLName() + "()"; } + } + else + { res = res + " : " + resultType.getUMLName(); } + } + res = res + "\n"; + + java.util.Map env = new java.util.HashMap(); + + if (pre == null) + { pre = new BasicExpression("true"); } + + if (post == null) + { post = new BasicExpression("true"); } + + res = res + "pre pre1:\n " + pre.toOcl(env,true) + "\n"; + res = res + "post post1:\n " + post.toOcl(env,true); + res = res + "\n\n"; + return res; + } // multiple pre, post, and stereotypes + + public String saveAsPlantUML() + { if (derived) { return ""; } + + String res = ""; + + if (instanceScope) + { if (isAbstract()) + { res = res + "{abstract} "; } + } + else + { res = res + "{static} "; } + + res = res + getName() + "("; + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + String pnme = par.getName(); + String tnme = par.getType().getUMLName(); + String elemt = ""; + if ("Set".equals(tnme) || "Sequence".equals(tnme)) + { if (par.getElementType() != null) + { elemt = "(" + par.getElementType().getUMLName() + ")"; } + } + res = res + pnme + " : " + tnme + elemt; + if (i < parameters.size() - 1) { res = res + ", "; } + } + res = res + ") "; + + if (resultType != null) + { String rtname = resultType.getName(); + if (rtname.equals("Set") || rtname.equals("Sequence")) + { if (elementType != null) + { res = res + " : " + resultType.getUMLName() + "(" + elementType.getUMLName() + ")"; } + else + { res = res + " : " + resultType.getUMLName() + "()"; } + } + else + { res = res + " : " + resultType.getUMLName(); } + } + res = res + "\n"; + + /* java.util.Map env = new java.util.HashMap(); + + if (pre == null) + { pre = new BasicExpression("true"); } + + if (post == null) + { post = new BasicExpression("true"); } + + res = res + "pre pre1:\n " + pre.toOcl(env,true) + "\n"; + res = res + "post post1:\n " + post.toOcl(env,true); + res = res + "\n\n"; */ + + return res; + } // multiple pre, post, and stereotypes + + public static Expression wpc(Expression pst, String op, String feat, + String val) + { // calculates [opfeat(val)]pst + Expression res = pst; + BasicExpression valbe = new BasicExpression(val); + if (op.equals("set")) + { // System.out.println(valbe + " multiplicity is: " + valbe.isMultiple()); + res = pst.substituteEq(feat,valbe); + } + else if (op.equals("add")) + { SetExpression se = new SetExpression(); + se.addElement(valbe); + Expression featbe = new BasicExpression(feat); + res = pst.substituteEq(feat,new BinaryExpression("\\/",featbe,se)); + } + else if (op.equals("remove")) + { SetExpression se = new SetExpression(); + se.addElement(valbe); + Expression featbe = new BasicExpression(feat); + res = pst.substituteEq(feat,new BinaryExpression("-",featbe,se)); + } + else if (op.equals("union")) + { Expression featbe = new BasicExpression(feat); + res = pst.substituteEq(feat,new BinaryExpression("\\/",featbe,valbe)); + } + else if (op.equals("subtract")) + { Expression featbe = new BasicExpression(feat); + res = pst.substituteEq(feat,new BinaryExpression("-",featbe,valbe)); + } + + return res; + } + + /* + public static Expression wpc(Expression post, Vector uses, Expression exbe, + String op, String feat, + BasicExpression valbe) + { if (uses.size() == 0) { return post; } + Expression nextpost = post; + + if (op.equals("set")) + { nextpost = post.substituteEq(feat,valbe); } + else if (op.equals("add")) // replace feat by feat \/ { valbe } for add, etc + { Expression featbe = new BasicExpression(feat); + SetExpression setexp = new SetExpression(); + setexp.addElement(valbe); + nextpost = post.substituteEq(feat,new BinaryExpression("\\/",featbe,setexp)); + } + else if (op.equals("remove")) // replace feat by feat - { valbe } + { Expression featbe = new BasicExpression(feat); + SetExpression setexp = new SetExpression(); + setexp.addElement(valbe); + nextpost = post.substituteEq(feat,new BinaryExpression("-",featbe,setexp)); + } // do these ONCE only + return wpc0(nextpost,uses,exbe,op,feat,valbe); + } */ + + // Not checked, may need to be updated + public static Expression wpc(Expression post, Vector uses, Expression exbe, + String op, String feat, boolean ord, + BasicExpression valbe) + { if (uses.size() == 0) { return post; } + Expression pre = post; + BasicExpression use = (BasicExpression) uses.get(0); + + if (use.objectRef == null || use.objectRef.umlkind == Expression.CLASSID) + { if (op.equals("set")) + { pre = post.substitute(use,valbe); } // use is just feat + else if (op.equals("add")) // replace feat by feat \/ { valbe } for add, etc + { Expression featbe = (BasicExpression) use.clone(); + // new BasicExpression(feat); + SetExpression setexp = new SetExpression(); + setexp.addElement(valbe); + Expression repl; + if (ord) + { setexp.setOrdered(true); + repl = new BinaryExpression("^",featbe,setexp); + } + else + { repl = new BinaryExpression("\\/",featbe,setexp); } + + repl.setBrackets(true); + pre = post.substitute(use,repl); + } + else if (op.equals("remove")) // replace feat by feat - { valbe } + { Expression featbe = new BasicExpression(feat); + SetExpression setexp = new SetExpression(); + setexp.addElement(valbe); + Expression repl = new BinaryExpression("-",featbe,setexp); + repl.setBrackets(true); + pre = post.substitute(use,repl); + } // do these ONCE only + else if (op.equals("union")) + { Expression featbe = (BasicExpression) use.clone(); + // new BasicExpression(feat); + Expression repl; + if (ord) + { repl = new BinaryExpression("^",featbe,valbe); } + else + { repl = new BinaryExpression("\\/",featbe,valbe); } + repl.setBrackets(true); + pre = post.substitute(use,repl); + } + else if (op.equals("subtract")) // replace feat by feat - valbe + { Expression featbe = new BasicExpression(feat); + Expression repl = new BinaryExpression("-",featbe,valbe); + repl.setBrackets(true); + pre = post.substitute(use,repl); + } // do these ONCE only + + // Expression selfeq = + // new BinaryExpression("=",new BasicExpression("self"), + // exbe); + // pre = Expression.simplifyImp(selfeq,pre); + uses.remove(0); + return wpc(pre,uses,exbe,op,feat,ord,valbe); + } + + if (use.objectRef.umlkind == Expression.VARIABLE) + { pre = pre.substitute(use,valbe); + pre = pre.substituteEq(use.objectRef.toString(),exbe); + // Expression neq = new BinaryExpression("/=",exbe,use.objectRef); + // Expression pre2 = new BinaryExpression("&",neq,pre); + // pre = new BinaryExpression("or",pre1,pre2); + // pre.setBrackets(true); + // Only if set? + } + else if (!use.objectRef.isMultiple()) + { Expression pre0 = pre.substitute(use,valbe); // also in above case? + BinaryExpression eq = + new BinaryExpression("=",exbe,use.objectRef); + pre = Expression.simplify("=>",eq,pre0,new Vector()); + // Expression neq = new BinaryExpression("/=",exbe,use.objectRef); + // Expression pre2 = new BinaryExpression("&",neq,pre); + // pre = new BinaryExpression("or",pre1,pre2); + // pre.setBrackets(true); + } + else if (use.objectRef.isMultiple()) // objs.f + { if (op.equals("set")) + { if (ord && use.objectRef.isOrdered()) + { // just objs.(f <+ { ex |-> value }) + BasicExpression fbe = + new BasicExpression(feat); + Expression maplet = new BinaryExpression("|->",exbe,valbe); + + SetExpression se = new SetExpression(); + se.addElement(maplet); + BinaryExpression oplus = new BinaryExpression("<+",fbe,se); + oplus.setBrackets(true); + oplus.objectRef = use.objectRef; + pre = pre.substitute(use,oplus); + } + else + { SetExpression se = new SetExpression(); + se.addElement(exbe); + Expression newobjs = + new BinaryExpression("-",use.objectRef,se); + newobjs.setBrackets(true); + BasicExpression fbe = + new BasicExpression(feat); + fbe.setObjectRef(newobjs); + if (use.umlkind == Expression.ATTRIBUTE || + use.multiplicity == ModelElement.ONE) + { // replace objs.f by (objs - {ex}).f \/ {value} + SetExpression vse = new SetExpression(); + vse.addElement(valbe); + Expression repl = + new BinaryExpression("\\/",fbe,vse); + repl.setBrackets(true); + pre = pre.substitute(use,repl); + // and implied by exbe: objs + } + else if (use.umlkind == Expression.ROLE && + use.multiplicity != ModelElement.ONE) + { Expression repl = + new BinaryExpression("\\/",fbe,valbe); + repl.setBrackets(true); + pre = pre.substitute(use,repl); + } + } + Expression exin = new BinaryExpression(":",exbe,use.objectRef); // : ran ? + pre = Expression.simplifyImp(exin,pre); + uses.remove(0); + return wpc(pre,uses,exbe,op,feat,ord,valbe); + } + else if (op.equals("add")) + { if (ord && use.objectRef.isOrdered()) + { // just objs.(f <+ { ex |-> f(ex) ^ [value] }) + BasicExpression fbe1 = + new BasicExpression(feat); + BasicExpression fbe = + new BasicExpression(feat); + + BasicExpression exbe1 = (BasicExpression) exbe.clone(); + exbe1.objectRef = fbe1; // f(ex) + SetExpression sq = new SetExpression(); + sq.setOrdered(true); + sq.addElement(valbe); // [val] + Expression cat = new BinaryExpression("^",exbe1,sq); + + Expression maplet = new BinaryExpression("|->",exbe,cat); + + SetExpression se = new SetExpression(); + se.addElement(maplet); + BinaryExpression oplus = new BinaryExpression("<+",fbe,se); + oplus.setBrackets(true); + oplus.objectRef = use.objectRef; + pre = pre.substitute(use,oplus); + } + else + { SetExpression vse = new SetExpression(); + vse.addElement(valbe); + Expression repl = + new BinaryExpression("\\/",use,vse); + repl.setBrackets(true); + pre = pre.substitute(use,repl); + } + } // exbe: objs for pre + else if (op.equals("union")) + { Expression repl = + new BinaryExpression("\\/",use,valbe); + repl.setBrackets(true); + pre = pre.substitute(use,repl); + } // exbe: objs for pre + else if (op.equals("remove")) + { SetExpression se = new SetExpression(); + se.addElement(exbe); + Expression newobjs = // (objs - {ex}).f + new BinaryExpression("-",use.objectRef,se); + newobjs.setBrackets(true); + BasicExpression fbe = + new BasicExpression(feat); + fbe.setObjectRef(newobjs); + SetExpression vse = new SetExpression(); + vse.addElement(valbe); // { value } + BasicExpression fbe2 = new BasicExpression(feat); + fbe2.setObjectRef(exbe); // ex.f + Expression minus = + new BinaryExpression("-",fbe2,vse); + minus.setBrackets(true); + Expression repl = + new BinaryExpression("\\/",fbe,minus); + repl.setBrackets(true); + pre = pre.substitute(use,repl); + } + else if (op.equals("subtract")) + { SetExpression se = new SetExpression(); + se.addElement(exbe); + Expression newobjs = // (objs - {ex}).f + new BinaryExpression("-",use.objectRef,se); + newobjs.setBrackets(true); + BasicExpression fbe = + new BasicExpression(feat); + fbe.setObjectRef(newobjs); + BasicExpression fbe2 = new BasicExpression(feat); + fbe2.setObjectRef(exbe); // ex.f + Expression minus = + new BinaryExpression("-",fbe2,valbe); + minus.setBrackets(true); + Expression repl = + new BinaryExpression("\\/",fbe,minus); + repl.setBrackets(true); + pre = pre.substitute(use,repl); + } // union, subtract? + + Expression inexp = new BinaryExpression(":",exbe,use.objectRef); + pre = new BinaryExpression("=>",inexp,pre); + } // or exbe /: objs & this + uses.remove(0); + return wpc(pre,uses,exbe,op,feat,ord,valbe); + } + + public Statement generateDesign(Entity ent, Vector entities, Vector types) + { Statement res = new SequenceStatement(); + Vector localEntities = allTypeParameterEntities(ent); + localEntities.addAll(entities); + + String name = getName(); + String ename = ""; + Vector context = new Vector(); + if (ent != null) + { context.add(ent); + ename = ent.getName(); + } + + String ex = ename.toLowerCase() + "x"; // very messy to do this + java.util.Map env0 = new java.util.HashMap(); + String pars = getJavaParameterDec(); + + // String header = + + if ("run".equals(name) && ent != null && ent.isActive()) + { if (ent.isInterface()) + { return res; } + + if (sm != null) + { Statement rc = sm.runCode(); + // add run_state : T to ent, and the type. + rc.typeCheck(types,localEntities,context,new Vector()); + return rc; + } // should be rc.updateForm(env0,true) + else if (activity != null) + { activity.typeCheck(types,localEntities,context,new Vector()); + return activity; + } + + return res; + } + + + if (sm != null) + { Statement cde = sm.getMethodJava(); // sequential code + return cde; + } + else if (activity != null) + { Vector env1 = new Vector(); + env1.addAll(parameters); + activity.typeCheck(types, + localEntities,context,env1); + + System.out.println(">>> Activity of " + name + " is: " + activity); + + return activity; + } + + + Vector atts = new Vector(); + ReturnStatement rets = null; + + String resT = "void"; + if (post == null) + { return res; } // or use the SM if one exists + // if ("true".equals(post + "")) + // { return res; } + + if (resultType != null && + !("void".equals(resultType.getName()))) + { resT = resultType + ""; + Attribute r = new Attribute("result", resultType, ModelElement.INTERNAL); + r.setElementType(elementType); + atts.add(r); + BasicExpression rbe = new BasicExpression(r); + CreationStatement cs = + new CreationStatement(resT, "result"); + cs.setType(resultType); + cs.setElementType(elementType); + // Expression init = resultType.getDefaultValueExpression(elementType); + // AssignStatement initialise = new AssignStatement(rbe, init); + ((SequenceStatement) res).addStatement(cs); + // ((SequenceStatement) res).addStatement(initialise); + rets = new ReturnStatement(rbe); + } + + if (ent != null && ent.isInterface()) + { return res; } + + atts.addAll(parameters); + + if (query && isNoRecursion()) + { Vector cases = Expression.caselist(post); + + // System.out.println(">>> Caselist = " + cases); + + Statement qstat = + designQueryList(cases, resT, env0, + types, localEntities, atts); + + // System.out.println(">>> qstat for no recursion = " + qstat); + + qstat.setBrackets(true); + WhileStatement ws = + new WhileStatement(new BasicExpression(true), qstat); + return ws; + } + else if (query) + { Vector cases = Expression.caselist(post); + + // System.out.println(">>> Caselist = " + cases); + + Statement qstat = + designQueryList(cases, resT, env0, + types, localEntities, atts); + + // System.out.println(">>> qstat = " + qstat); + + ((SequenceStatement) res).addStatement(qstat); + ((SequenceStatement) res).addStatement(rets); + return res; + } + else + { Statement stat; + if (bx) + { stat = post.statLC(env0,true); } + else + { stat = post.generateDesign(env0, true); } + + ((SequenceStatement) res).addStatement(stat); + if (resultType != null && !("void".equals(resultType.getName()))) + { ((SequenceStatement) res).addStatement(rets); } + + return res; + } // if no return + + // return res; + + // { return buildQueryOp(ent,name,resultType,resT,entities,types); } + // else + // { return buildUpdateOp(ent,name,resultType,resT,entities,types); } + } // ignore return type for update ops for now. + + + // For the entity operation: ent == entity normally + public String getOperationCode(Entity ent, Vector entities, Vector types) + { String name = getName(); + String ename = ""; + Vector context = new Vector(); + if (ent != null) + { context.add(ent); + ename = ent.getName(); + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + + String ex = ename.toLowerCase() + "x"; // very messy to do this + java.util.Map env0 = new java.util.HashMap(); + String pars = getJavaParameterDec(); + + // String header = + + String textcode = ""; + if (hasText()) + { textcode = text + "\n"; } + + + if ("run".equals(name) && ent != null && ent.isActive()) + { if (ent.isInterface()) + { return " public void run();\n"; } + + String res = " public void run()\n { "; + if (sm != null) + { Statement rc = sm.runCode(); + // add run_state : T to ent, and the type. + rc.typeCheck(types,entities,context,new Vector()); + return res + rc.toStringJava() + " }\n\n"; + } // should be rc.updateForm(env0,true) + res = res + textcode; + return res + " }\n\n"; + } + + + if (sm != null) + { Statement cde = sm.getMethodJava(); // sequential code + if (cde != null) + { Vector localatts = new Vector(); + localatts.addAll(sm.getAttributes()); + String res = ""; + Type tp = getResultType(); + String ts = "void"; + String statc = ""; + + if (tp != null) + { ts = tp.getJava(); } + + if (isClassScope() || isStatic()) + { statc = "static "; } + + res = " public " + statc + genPars + ts + " " + name + "(" + pars + ")\n { "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (ent.isInterface()) + { return " public " + genPars + ts + " " + name + "(" + pars + ");\n"; } + + if (tp != null && !"void".equals(ts)) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + cde.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + cde.updateForm(env0,true,types,entities,localatts) + "\n }"; + } // cde.updateForm(env0,true) + } + else if (activity != null) + { Vector localatts = new Vector(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ename,ex); } // or "this" if not static ?? + String res = ""; + + Type tp = getResultType(); + String ts = "void"; + + String header = ""; + + if (tp != null) + { ts = tp.getJava(); } + + if (ent != null && ent.isInterface()) + { return " public " + genPars + ts + " " + name + "(" + pars + ");\n"; } + + if (isSequential()) + { header = header + "synchronized "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + res = " public " + header + genPars + ts + " " + name + "(" + pars + ")\n { "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (tp != null && !"void".equals(ts)) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + + Vector preterms = activity.allPreTerms(); // But some should be within the activity + if (preterms.size() > 0) + { Statement newpost = (Statement) activity.clone(); + // System.out.println("PRE terms: " + preterms); + Vector processed = new Vector(); + String newdecs = ""; + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + // check if the preterm is valid and skip if not. + Type typ = preterm.getType(); + // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.queryForm(env0,true); + // classqueryForm; you want to remove the @pre + + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || + preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); } + else + { actualtyp = new Type("Set",null); } + actualtyp.setElementType(preterm.getElementType()); + actualtyp.setSorted(preterm.isSorted()); + + if (preterm.umlkind == Expression.CLASSID && preterm.arrayIndex == null) + { pretermqf = "Controller.inst()." + pretermqf.toLowerCase() + "s"; } + newdec = actualtyp.getJava() + " " + pre_var + " = new Vector();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } // Use this strategy also below and in Statement.java + else + { actualtyp = typ; + newdec = actualtyp.getJava() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + // System.out.println("$$$ PRE variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType + " FOR " + preterm); + + Attribute preatt = + new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + preatt.setElementType(preterm.elementType); + localatts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + newdecs + newpost.updateForm(env0,false,types,entities,localatts) + "\n }\n"; + } // updateForm(, true)? + activity.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + activity.updateForm(env0,false,types,entities,localatts) + "\n }\n"; + } + + String resT = "void"; + if (post == null) + { return ""; } // or use the SM if one exists + if (resultType != null) + { resT = resultType.getJava(); } + + if (ent != null && ent.isInterface()) + { return " public " + genPars + resT + " " + name + "(" + pars + ");\n"; } + + if (query) + { return buildQueryOp(ent,name,resultType,resT,entities,types); } + else + { return buildUpdateOp(ent,name,resultType,resT,entities,types); } + } // ignore return type for update ops for now. + + public String getOperationCodeJava6(Entity ent, Vector entities, Vector types) + { String name = getName(); + Vector context = new Vector(); + String ename = ""; + if (ent != null) + { context.add(ent); + ename = ent.getName(); + } + String ex = ename.toLowerCase() + "x"; + java.util.Map env0 = new java.util.HashMap(); + String pars = getJava6ParameterDec(); + + String textcode = ""; + if (hasText()) + { textcode = text + "\n"; } + + + if ("run".equals(name) && ent != null && ent.isActive()) + { if (ent.isInterface()) + { return " public void run();\n"; } + + String res = " public void run()\n { "; + if (sm != null) + { Statement rc = sm.runCode(); + // add run_state : T to ent, and the type. + rc.typeCheck(types,entities,context,new Vector()); + return res + rc.updateFormJava6(env0,true) + " }\n\n"; + } + res = res + textcode; + return res + " }\n\n"; + } + + + if (sm != null) + { Statement cde = sm.getSequentialCode(); // sequential code + if (cde != null) + { Vector localatts = new Vector(); + localatts.addAll(sm.getAttributes()); + String res = ""; + Type tp = getResultType(); + + String ts = "void"; + if (tp != null) + { ts = tp.getJava6(); } + + String statc = ""; + if (isClassScope() || isStatic()) + { statc = "static "; } + + + res = " public " + statc + ts + " " + name + "(" + pars + ")\n{ "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (ent != null && ent.isInterface()) + { return " public " + ts + " " + name + "(" + pars + ");\n"; } + + if (tp != null && !"void".equals(ts)) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + cde.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + cde.updateFormJava6(env0,true) + "\n }"; + } + } + else if (activity != null) + { Vector localatts = new Vector(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ename,ex); } // or "this" if not static ?? + String res = ""; + + Type tp = getResultType(); + String ts = "void"; + + String header = ""; + + if (tp != null) + { ts = tp.getJava6(); } + + if (ent != null && ent.isInterface()) + { return " public " + ts + " " + name + "(" + pars + ");\n"; } + + if (isSequential()) + { header = header + "synchronized "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + res = " public " + header + ts + " " + name + "(" + pars + ")\n { "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (tp != null && !("void".equals(ts))) + { res = res + ts + " result;\n"; } + + localatts.addAll(parameters); + Vector preterms = activity.allPreTerms(); + if (preterms.size() > 0) + { Statement newpost = (Statement) activity.clone(); + // System.out.println("Pre terms: " + preterms); + Vector processed = new Vector(); + String newdecs = ""; + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.classqueryFormJava6(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || + preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); + newdec = "ArrayList " + pre_var + " = new ArrayList();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + else + { actualtyp = new Type("Set",null); + newdec = "HashSet " + pre_var + " = new HashSet();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + actualtyp.setElementType(preterm.getElementType()); + actualtyp.setSorted(preterm.isSorted()); + } + else + { actualtyp = typ; + newdec = actualtyp.getJava6() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + + Attribute preatt = + new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + preatt.setElementType(preterm.elementType); + localatts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + newdecs + newpost.updateFormJava6(env0,false) + "\n }\n"; + } // updateForm(, true)? + activity.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + activity.updateFormJava6(env0,false) + "\n }\n"; + } + + String resT = "void"; + if (post == null) + { return ""; } // or use the SM if one exists + if (resultType != null) + { resT = resultType.getJava6(); } + + if (ent != null && ent.isInterface()) + { return " public " + resT + " " + name + "(" + pars + ");\n"; } + + if (query) + { return buildQueryOpJava6(ent,name,resultType,resT,entities,types); } + else + { return buildUpdateOpJava6(ent,name,resultType,resT,entities,types); } + } // ignore return type for update ops for now. + + public String getOperationCodeJava7(Entity ent, Vector entities, Vector types) + { String name = getName(); + Vector context = new Vector(); + String ename = ""; + String completeename = ""; + + if (ent != null) + { context.add(ent); + ename = ent.getName(); + completeename = ent.getCompleteName(); + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + + String ex = ename.toLowerCase() + "x"; + java.util.Map env0 = new java.util.HashMap(); + String pars = getJava7ParameterDec(); + + String textcode = ""; + if (hasText()) + { textcode = text + "\n"; } + + + if ("run".equals(name) && ent != null && ent.isActive()) + { if (ent.isInterface()) + { return " public void run();\n"; } + + String res = " public void run()\n { "; + res = res + ename + " " + ex + " = this;\n "; + if (sm != null) + { Statement rc = sm.runCode(); + // add run_state : T to ent, and the type. + rc.typeCheck(types,entities,context,new Vector()); + return res + rc.updateFormJava7(env0,true) + " }\n\n"; + } + else if (activity != null) + { Vector latts = new Vector(); + activity.typeCheck(types,entities,context,latts); + + return res + + activity.updateFormJava7(env0,false) + "\n }\n\n"; + } + res = res + textcode; + return res + " }\n\n"; + } + + + if (sm != null) + { Statement cde = sm.getSequentialCode(); // sequential code + if (cde != null) + { Vector localatts = new Vector(); + localatts.addAll(sm.getAttributes()); + String res = ""; + Type tp = getResultType(); + + String ts = "void"; + if (tp != null) + { ts = tp.getJava7(elementType); } + + String statc = ""; + if (isClassScope() || isStatic()) + { statc = "static "; } + + + res = " public " + statc + ts + " " + name + "(" + pars + ")\n{ "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (ent != null && ent.isInterface()) + { return " public " + ts + " " + name + "(" + pars + ");\n"; } + + if (tp != null && !"void".equals(ts)) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + cde.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + " " + ex + " = this;\n "; } + return res + cde.updateFormJava7(env0,true) + "\n }"; + } + } + else if (activity != null) + { Vector localatts = new Vector(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ename,ex); } // or "this" if not static ?? + String res = ""; + + Type tp = getResultType(); + String ts = "void"; + + String header = ""; + + if (tp != null) + { ts = tp.getJava7(elementType); } + + if (ent != null && ent.isInterface()) + { return " public " + ts + " " + name + "(" + pars + ");\n"; } + + if (isSequential()) + { header = header + "synchronized "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + res = " public " + header + ts + " " + name + "(" + pars + ")\n { "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (tp != null & !"void".equals(ts)) + { res = res + ts + " result;\n"; } + + localatts.addAll(parameters); + Vector preterms = activity.allPreTerms(); + if (preterms.size() > 0) + { Statement newpost = (Statement) activity.clone(); + // System.out.println(">>> Pre terms: " + preterms); + Vector processed = new Vector(); + String newdecs = ""; + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.classqueryFormJava7(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || + preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); + actualtyp.setElementType(preterm.getElementType()); + String jType = actualtyp.getJava7(preterm.getElementType()); + newdec = " " + jType + " " + pre_var + " = new " + jType + "();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + else + { actualtyp = new Type("Set",null); + actualtyp.setElementType(preterm.getElementType()); + + String jType = actualtyp.getJava7(preterm.getElementType()); + newdec = " " + jType + " " + pre_var + " = new " + jType + "();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + + actualtyp.setSorted(preterm.isSorted()); + prebe.setSorted(preterm.isSorted()); + System.out.println(">> Type of " + preterm + " = " + preterm.type + " { " + preterm.isSorted() + " }"); + } + else + { actualtyp = typ; + newdec = actualtyp.getJava7(preterm.elementType) + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + System.out.println(">> Pre variable " + prebe + " type= " + actualtyp + + " elemtype= " + prebe.elementType); + + Attribute preatt = + new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + preatt.setElementType(preterm.elementType); + localatts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + " " + completeename + " " + ex + " = this;\n "; } + return res + newdecs + newpost.updateFormJava7(env0,false) + "\n }\n"; + } // updateForm(, true)? + + activity.typeCheck(types,entities,context,localatts); + + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + " " + completeename + " " + ex + " = this;\n "; } + return res + activity.updateFormJava7(env0,false) + "\n }\n"; + } + + // System.out.println("JAVA 7 OPERATION CODE: "); + + String resT = "void"; + if (post == null) + { return ""; } // or use the SM if one exists + if (resultType != null) + { resT = resultType.getJava7(elementType); } + + if (ent != null && ent.isInterface()) + { return " public " + resT + " " + name + "(" + pars + ");\n"; } + + if (query) + { return buildQueryOpJava7(ent,name,resultType,resT,entities,types); } + else + { return buildUpdateOpJava7(ent,name,resultType,resT,entities,types); } + } // ignore return type for update ops for now. + + public String getOperationCodeCSharp(Entity ent, Vector entities, Vector types) + { String name = getName(); + Vector context = new Vector(); + String ename = ""; + String epars = ""; + + if (ent != null) + { context.add(ent); + ename = ent.getName(); + epars = ent.typeParameterTextCSharp(); + } + + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getCSharp(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + + String ex = ename.toLowerCase() + "x"; + java.util.Map env0 = new java.util.HashMap(); + String pars = getCSharpParameterDec(); + + String textcode = ""; + if (hasText()) + { textcode = text + "\n"; } + + /* if ("run".equals(name) && ent.isActive()) + { if (ent != null && ent.isInterface()) + { return " public void run();\n"; } + + String res = " public void run()\n { "; + if (sm != null) + { Statement rc = sm.runCode(); + // add run_state : T to ent, and the type. + rc.typeCheck(types,entities,context,new Vector()); + return res + rc.toStringJava() + " }\n\n"; + } + return res + " }\n\n"; + } */ + + + if (sm != null) + { Statement cde = sm.getSequentialCode(); // sequential code + if (cde != null) + { Vector localatts = new Vector(); + localatts.addAll(sm.getAttributes()); + String res = ""; + Type tp = getResultType(); + String ts = "void"; + if (tp != null) + { ts = tp.getCSharp(); } + + String statc = ""; + if (ent == null || isClassScope() || isStatic()) + { statc = "static "; } + + res = " public " + statc + ts + " " + name + genPars + "(" + pars + ")\n{ "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (ent != null && ent.isInterface()) + { return " public " + ts + " " + name + genPars + "(" + pars + ");\n"; } + + if (tp != null && !("void".equals(ts))) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + cde.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + epars + " " + ex + " = this;\n "; } + return res + cde.updateFormCSharp(env0,true) + "\n }"; + } + } + else + if (activity != null) + { Vector localatts = new Vector(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ename,ex); } // or "this" if not static ?? + String res = ""; + + Type tp = getResultType(); + String ts = "void"; + + String header = ""; + + if (tp != null) + { ts = tp.getCSharp(); } + + if (ent != null && ent.isInterface()) + { return " public " + ts + " " + name + genPars + "(" + pars + ");\n"; } + + // if (isSequential()) + // { header = header + "synchronized "; } + if (isUnsafe()) + { header = header + "unsafe "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "sealed "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + res = " public " + header + ts + " " + name + genPars + "(" + pars + ")\n { "; + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (Statement.hasResultDeclaration(activity)) + { } + else if (tp != null && !("void".equals(ts))) + { res = res + ts + " result;\n"; } + + + localatts.addAll(parameters); + Vector preterms = activity.allPreTerms(); + if (preterms.size() > 0) + { Statement newpost = (Statement) activity.clone(); + // System.out.println("Pre terms: " + preterms); + Vector processed = new Vector(); + String newdecs = ""; + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.classqueryFormCSharp(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); } + else + { actualtyp = new Type("Set",null); } + actualtyp.setElementType(preterm.getElementType()); + newdec = actualtyp.getCSharp() + " " + pre_var + " = new ArrayList();\n" + + " " + pre_var + ".AddRange(" + pretermqf + ");\n"; + } + else + { actualtyp = typ; + newdec = actualtyp.getCSharp() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + + Attribute preatt = + new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + preatt.setElementType(preterm.elementType); + localatts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + epars + " " + ex + " = this;\n "; } + return res + newdecs + newpost.updateFormCSharp(env0,false) + "\n }\n"; + } // updateForm(, true)? + activity.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + epars + " " + ex + " = this;\n "; } + return res + activity.updateFormCSharp(env0,false) + "\n }\n"; + } + + String resT = "void"; + if (post == null) + { return ""; } // or use the SM if one exists + if (resultType != null) + { resT = resultType.getCSharp(); } + + if (ent != null && ent.isInterface()) + { return " public " + resT + " " + name + genPars + "(" + pars + ");\n"; } + + if (query) + { return buildQueryOpCSharp(ent,name,resultType,resT,entities,types); } + else + { return buildUpdateOpCSharp(ent,name,resultType,resT,entities,types); } + } // ignore return type for update ops for now. + + // Operation for entity: + public String getOperationCodeCPP(Entity ent, Vector entities, Vector types, Vector decs) + { String name = getName(); + Vector context = new Vector(); + + String gpars = ent.typeParameterTextCPP(); + + String ename = ""; + String eTypePars = ""; + Vector etpars = new Vector(); + + if (ent != null) + { ename = ent.getName(); + context.add(ent); + if (ent.hasTypeParameters()) + { etpars.addAll(ent.getTypeParameters()); + for (int i = 0; i < etpars.size(); i++) + { Type etp = (Type) etpars.get(i); + eTypePars = eTypePars + etp.getName(); + if (i < etpars.size() - 1) + { eTypePars = eTypePars + ", "; } + } + } + } + + String ex = ename.toLowerCase() + "x"; + java.util.Map env0 = new java.util.HashMap(); + String pars = getCPPParameterDec(); + + String textcode = ""; + if (hasText()) + { textcode = text + "\n"; } + + String opGenPars = ""; + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { etpars.addAll(typeParameters); + opGenPars = " template<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + opGenPars = opGenPars + " class " + tp.getName(); + if (i < typeParameters.size() - 1) + { opGenPars = opGenPars + ", "; } + } + opGenPars = opGenPars + " >\n"; + } + + if (etpars.size() > 0) + { genPars = "template<"; + for (int i = 0; i < etpars.size(); i++) + { Type tp = (Type) etpars.get(i); + genPars = genPars + " class " + tp.getName(); + if (i < etpars.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + String exname = ename; + if (eTypePars.length() > 0) + { exname = ename + "<" + eTypePars + ">"; } + + String header = ""; + if (etpars.size() > 0) + { header = " " + genPars + "\n"; } + + + /* if ("run".equals(name) && ent.isActive()) + { if (ent.isInterface()) + { return " public void run();\n"; } + + String res = " public void run()\n { "; + if (sm != null) + { Statement rc = sm.runCode(); + // add run_state : T to ent, and the type. + rc.typeCheck(types,entities,context,new Vector()); + return res + rc.toStringJava() + " }\n\n"; + } + return res + " }\n\n"; + } */ + + String isstatic = ""; + if (isClassScope() || isStatic()) + { isstatic = "static "; } + else if (isVirtual(ent)) + { isstatic = "virtual "; } + + if (sm != null) + { Statement cde = sm.getSequentialCode(); // sequential code + if (cde != null) + { Vector localatts = new Vector(); + localatts.addAll(sm.getAttributes()); + String res = ""; + Type tp = getResultType(); + String ts = "void"; + if (tp != null) + { ts = tp.getCPP(elementType); } + res = header + " " + ts + " " + exname + "::" + name + "(" + pars + ")\n { "; + decs.add(opGenPars + " " + isstatic + ts + " " + name + "(" + pars + ");\n"); + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + // if (ent.isInterface()) + // { return " public " + ts + " " + name + "(" + pars + ");\n"; } + + // if (Statement.hasResultDeclaration(activity)) + // { } + // else + if (tp != null && !("void".equals(ts))) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + cde.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + "* " + ex + " = this;\n "; } + return res + cde.updateFormCPP(env0,true) + "\n }"; + } + } + else + if (activity != null) + { Vector localatts = new Vector(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ename,ex); } // or "this" if not static ?? + String res = ""; + + Type tp = getResultType(); + String ts = "void"; + + // String header = ""; + + Type elemT = getElementType(); + if (tp != null) + { ts = tp.getCPP(elemT); } + + String cet = "void*"; + if (elemT != null) + { cet = elemT.getCPP(elemT.getElementType()); } + + // if (ent.isInterface()) + // { return " public " + ts + " " + name + "(" + pars + ");\n"; } + + // if (isSequential()) + // { header = header + "synchronized "; } + // if (isAbstract()) + // { header = header + "abstract "; } + // if (isFinal()) + // { header = header + "sealed "; } + + + res = header + " " + ts + " " + exname + "::" + name + "(" + pars + ")\n { "; + decs.add(opGenPars + " " + isstatic + ts + " " + name + "(" + pars + ");\n"); + + if (comments != null) + { res = res + "/* " + comments + " */\n "; } + + if (Statement.hasResultDeclaration(activity)) + { } + else if (tp != null && !("void".equals(ts))) + { res = res + ts + " result;\n"; } + localatts.addAll(parameters); + Vector preterms = activity.allPreTerms(); + if (preterms.size() > 0) + { Statement newpost = (Statement) activity.clone(); + // System.out.println("Pre terms: " + preterms); + Vector processed = new Vector(); + String newdecs = ""; + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.classqueryFormCPP(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { Type pelemT = preterm.getElementType(); + String pcet = "void*"; + if (pelemT != null) + { pcet = pelemT.getCPP(pelemT.getElementType()); } + + if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); + newdec = "vector<" + pcet + ">* " + pre_var + " = new vector<" + pcet + ">();\n" + + " " + pre_var + "->insert(" + pre_var + "->end(), " + + pretermqf + "->begin(), " + + pretermqf + "->end());\n"; + } + else + { actualtyp = new Type("Set",null); + newdec = "std::set<" + pcet + ">* " + pre_var + " = new std::set<" + pcet + ">();\n" + + " " + pre_var + "->insert(" + pretermqf + "->begin(), " + + pretermqf + "->end());\n"; + } + actualtyp.setElementType(pelemT); + } + else + { actualtyp = typ; + newdec = actualtyp.getCPP() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + + Attribute preatt = + new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + preatt.setElementType(preterm.elementType); + localatts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + "* " + ex + " = this;\n "; } + return res + newdecs + newpost.updateFormCPP(env0,false) + "\n }\n"; + } // updateForm(, true)? + activity.typeCheck(types,entities,context,localatts); + if (ent == null || isClassScope() || isStatic()) { } + else + { res = res + ename + "* " + ex + " = this;\n "; } + return res + activity.updateFormCPP(env0,false) + "\n }\n"; + } + + String resT = "void"; + if (post == null) + { return ""; } // or use the SM if one exists + if (resultType != null) + { resT = resultType.getCPP(getElementType()); } + + // if (ent.isInterface()) + // { return " public " + resT + " " + name + "(" + pars + ");\n"; } + + if (query) + { return buildQueryOpCPP(ent,name,resultType,resT,entities,types,decs); } + else + { return buildUpdateOpCPP(ent,name,resultType,resT,entities,types,decs); } + } // ignore return type for update ops for now. + + public String typeParameterList() + { String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + return genPars; + } + + public String typeParameterListJava6() + { String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava6(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + return genPars; + } + + public String typeParameterListJava7() + { String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = " <"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getJava7(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + return genPars; + } + + public String buildQueryOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { if (resultType == null || "void".equals(resT)) + { System.err.println("ERROR: No result type for " + opname); + return ""; + } + + String genPars = typeParameterList(); + + /* Scope scope = post.resultScope(); + BinaryExpression rscope = null; + if (scope == null) // no range, must assign result + { System.err.println("WARNING: No scope for result of " + opname); } + else + { rscope = scope.resultScope; } */ + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } // But for static should only find static features + + String preheader = ""; + + String javaPars = getJavaParameterDec(); + String header = " public "; + if (isSequential()) + { header = header + "synchronized "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + + String statc = ""; + + if (isClassScope() || isStatic()) + { header = header + "static "; + statc = "static"; + } + + if (isAbstract()) + { header = header + genPars + resT + " " + + opname + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + genPars + resT + " " + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + // This should not carry over to inner static scopes, eg., in a ->select + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.preconditionExpression(); + preheader = " if (" + npre.queryForm(env0,true) + + ") { return result; } \n "; + } + } + + // Expression q0 = post.removeExpression(rscope); + // Expression q = null; + // if (q0 != null) + // { q = q0.substituteEq("result",rxbe); } + + header = header + " " + resT + " result = " + resultType.getDefault() + ";\n"; + header = header + preheader; + + String querycases = buildQueryCases(post,"",resT,env0,types,entities,atts); + + System.out.println(">> Query cases for " + post + " are: " + querycases); + System.out.println(); + + if (ent != null && isCached() && parameters.size() == 0 && instanceScope) + { ent.addAux(" private static java.util.Map " + opname + "_cache = new java.util.HashMap();\n"); + String wresult = Expression.wrap(resultType, "result"); + return header + + " Object _cached_result = " + opname + "_cache.get(this);\n" + + " if (_cached_result != null)\n" + + " { result = " + Expression.unwrap("_cached_result", resultType) + "; \n" + + " return result; \n" + + " }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache.put(this, " + wresult + ");\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + if (ent != null && isCached() && parameters.size() >= 1) + { ent.addAux(" private " + statc + " java.util.Map " + opname + "_cache = new java.util.HashMap();\n"); + // Attribute par = (Attribute) parameters.get(0); + // String par1 = par.getName(); + String wpar1 = parcats(); // Expression.wrap(par.getType(), par1); + String wresult = Expression.wrap(resultType, "result"); + return header + + " Object _cached_result = " + opname + "_cache.get(" + wpar1 + ");\n" + + " if (_cached_result != null)\n" + + " { result = " + Expression.unwrap("_cached_result", resultType) + "; \n" + + " return result; \n" + + " }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache.put(" + wpar1 + ", " + wresult + ");\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + + return header + " \n" + querycases + " return result;\n }\n"; + + /* if (isEqScope(rscope)) + { rscope.typeCheck(types,entities,atts); // not resultx though + Expression test = null; + // if (q instanceof BinaryExpression) + // { BinaryExpression qbe = (BinaryExpression) q; + // if (qbe.operator.equals("=>")) + // { test = qbe.left; } + // } + String body = Association.genEventCode(env0,test,rscope,true); + return header + " " + body + "\n" + + " return result;\n }"; + } + if (isInScope(rscope)) + { header = header + " " + resT + " result;\n"; + header = header + preheader; + header = header + " Vector " + rs + " = " + + getRange(rscope,env0) + ";\n"; + header = header + " for (int i = 0; i < " + + rs + ".size(); i++)\n"; + header = header + " { " + resT + " " + rx + + " = (" + resT + ") " + rs + ".get(i);\n"; + Expression newpost = + new BinaryExpression("=", + new BasicExpression("result"),rxbe); + newpost.typeCheck(types,entities,context,atts); + if (q != null) + { q.typeCheck(types,entities,context,atts); } + String body = Association.genEventCode(env0,q, + newpost,true); + return header + " " + body + " }\n" + + " return result;\n }"; + } + if (isSubScope(rscope)) + { Type elemT = getElementType(rscope); + if (elemT == null) { return ""; } + String jelemT = elemT.getJava(); + header = header + " " + resT + " result = new Vector();\n"; + header = header + preheader; + header = header + " Vector " + rs + " = " + + getRange(rscope,env0) + ";\n"; + header = header + " for (int i = 0; i < " + + rs + ".size(); i++)\n"; + header = header + " { " + jelemT + " " + rx + + " = (" + jelemT + ") " + rs + ".get(i);\n"; + Expression newpost = + new BinaryExpression(":",rxbe,new BasicExpression("result")); + + newpost.typeCheck(types,entities,context,atts); + if (q != null) + { q.typeCheck(types,entities,context,atts); } + String body = Association.genEventCode(env0,q, + newpost,true); + return header + " " + body + " }\n" + + " return result;\n }"; + } + return ""; */ + } + + public String buildQueryOpJava6(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { if (resultType == null || "void".equals(resT)) + { System.err.println("ERROR: No result type for " + opname); + return ""; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } // But for static should only find static features + + String preheader = ""; + + // String rx = "resultx"; + // Expression rxbe = new BasicExpression(rx); + String javaPars = getJava6ParameterDec(); + String header = " public "; + if (isSequential()) + { header = header + "synchronized "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + + String statc = ""; + + if (isClassScope() || isStatic()) + { header = header + "static "; + statc = "static"; + } + + String genPars = typeParameterListJava6(); + + if (isAbstract()) + { header = header + genPars + resT + " " + + opname + "(" + javaPars + ");\n\n"; + return header; + } + + + header = header + genPars + resT + " " + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + // Attribute resultxatt = new Attribute(rx,t,ModelElement.INTERNAL); + // resultxatt.setElementType(elementType); + atts.add(resultatt); + // atts.add(resultxatt); + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.preconditionExpression(); + preheader = " if (" + npre.queryFormJava6(env0,true) + + ") { return result; } \n "; + } + } + + // Expression q0 = post.removeExpression(rscope); + // Expression q = null; + // if (q0 != null) + // { q = q0.substituteEq("result",rxbe); } + + header = header + " " + resT + " result = " + resultType.getDefaultJava6() + ";\n"; + header = header + preheader; + + String querycases = buildQueryCasesJava6(post,"",resT,env0,types,entities,atts); + + if (ent != null && isCached() && parameters.size() == 0 && instanceScope) + { ent.addAux(" private static java.util.Map " + opname + "_cache = new java.util.HashMap();\n"); + String wresult = Expression.wrapJava6(resultType, "result"); + return header + + " Object _cached_result = " + opname + "_cache.get(this);\n" + + " if (_cached_result != null)\n" + + " { result = " + Expression.unwrapJava6("_cached_result", resultType) + "; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache.put(this, " + wresult + ");\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + if (ent != null && isCached() && parameters.size() >= 1) + { ent.addAux(" private " + statc + " java.util.Map " + opname + "_cache = new java.util.HashMap();\n"); + // Attribute par = (Attribute) parameters.get(0); + // String par1 = par.getName(); + String wpar1 = parcatsJava6(); + // Expression.wrap(par.getType(), par1); + String wresult = Expression.wrapJava6(resultType, "result"); + return header + + " Object _cached_result = " + opname + "_cache.get(" + wpar1 + ");\n" + + " if (_cached_result != null)\n" + + " { result = " + Expression.unwrapJava6("_cached_result", resultType) + "; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache.put(" + wpar1 + ", " + wresult + ");\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + return header + " \n" + querycases + " \n" + + " return result;\n }\n"; + } + + public String buildQueryOpJava7(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { + if (resultType == null || "void".equals(resultType + "")) + { System.err.println("ERROR: No result type for " + opname); + return ""; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } // But for static should only find static features + + String preheader = ""; + + // String rx = "resultx"; + // Expression rxbe = new BasicExpression(rx); + String javaPars = getJava7ParameterDec(); + String header = " public "; + if (isSequential()) + { header = header + "synchronized "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + + String statc = ""; + + if (isClassScope() || isStatic()) + { header = header + "static "; + statc = "static"; + } + + String genPars = typeParameterListJava7(); + + if (isAbstract()) + { header = header + genPars + resT + " " + + opname + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + genPars + resT + " " + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + // Attribute resultxatt = new Attribute(rx,t,ModelElement.INTERNAL); + // resultxatt.setElementType(elementType); + atts.add(resultatt); + // atts.add(resultxatt); + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.preconditionExpression(); + preheader = " if (" + npre.queryFormJava7(env0,true) + + ") { return result; } \n "; + } + } + + header = header + " " + resT + " result = " + resultType.getDefaultJava7() + ";\n"; + header = header + preheader; + + String querycases = buildQueryCasesJava7(post,"",resT,env0,types,entities,atts); + + if (ent != null && isCached() && parameters.size() == 0 && instanceScope) + { ent.addAux(" private static java.util.Map " + opname + "_cache = new java.util.HashMap();\n"); + String wresult = Expression.wrap(resultType, "result"); + return header + + " Object _cached_result = " + opname + "_cache.get(this);\n" + + " if (_cached_result != null)\n" + + " { result = " + Expression.unwrap("_cached_result", resultType) + "; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache.put(this, " + wresult + ");\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + if (ent != null && isCached() && parameters.size() >= 1) + { ent.addAux(" private " + statc + " java.util.Map " + opname + "_cache = new java.util.HashMap();\n"); + // Attribute par = (Attribute) parameters.get(0); + // String par1 = par.getName(); + String wpar1 = parcats(); // Expression.wrap(par.getType(), par1); + String wresult = Expression.wrap(resultType, "result"); + return header + + " Object _cached_result = " + opname + "_cache.get(" + wpar1 + ");\n" + + " if (_cached_result != null)\n" + + " { result = " + Expression.unwrap("_cached_result", resultType) + "; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache.put(" + wpar1 + ", " + wresult + ");\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + return header + " \n" + querycases + " \n" + + " return result;\n }\n"; + } + + public String typeParameterListCSharp() + { String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { genPars = "<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + genPars = genPars + tp.getCSharp(); + if (i < typeParameters.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + return genPars; + } + + public String buildQueryOpCSharp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { if (resultType == null || "void".equals(resultType + "")) + { System.err.println("ERROR: No result type for " + opname); + return ""; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } // But for static should only find static features + + String preheader = ""; + + // String rx = "resultx"; + // Expression rxbe = new BasicExpression(rx); + String javaPars = getCSharpParameterDec(); + String header = " public "; + // if (isSequential()) + // { header = header + "synchronized "; } + + if (isUnsafe()) + { header = header + "unsafe "; } + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "sealed "; } + String statc = ""; + + if (isClassScope() || isStatic()) + { header = header + "static "; + statc = "static"; + } + + String genPars = typeParameterListCSharp(); + + if (isAbstract()) + { header = header + resT + " " + + opname + genPars + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + resT + " " + + opname + genPars + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + // Attribute resultxatt = new Attribute(rx,t,ModelElement.INTERNAL); + // resultxatt.setElementType(elementType); + atts.add(resultatt); + // atts.add(resultxatt); + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.preconditionExpression(); + preheader = " if (" + npre.queryFormCSharp(env0,true) + + ") { return result; } \n "; + } + } + + // Expression q0 = post.removeExpression(rscope); + // Expression q = null; + // if (q0 != null) + // { q = q0.substituteEq("result",rxbe); } + + header = header + " " + resT + " result = " + resultType.getDefaultCSharp() + ";\n"; + header = header + preheader; + + String querycases = buildQueryCasesCSharp(post,"",resT,env0,types,entities,atts); + + if (ent != null && isCached() && parameters.size() == 0 && instanceScope) + { ent.addAux(" private static Hashtable " + opname + "_cache = new Hashtable();\n"); + String wresult = "result"; // Expression.wrap(resultType, "result"); + String tcsh = resultType.getCSharp(); + return header + + " object _cached_result = " + opname + "_cache[this];\n" + + " if (_cached_result != null)\n" + + " { result = (" + tcsh + ") _cached_result; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache[this] = " + wresult + ";\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + if (ent != null && isCached() && parameters.size() >= 1) + { ent.addAux(" private " + statc + " Hashtable " + opname + "_cache = new Hashtable();\n"); + // Attribute par = (Attribute) parameters.get(0); + // String par1 = par.getName(); + String wpar1 = parcatsCSharp(); // par1; // Expression.wrap(par.getType(), par1); + String wresult = "result"; // Expression.wrap(resultType, "result"); + String tcsh = resultType.getCSharp(); + return header + + " object _cached_result = " + opname + "_cache[" + wpar1 + "];\n" + + " if (_cached_result != null)\n" + + " { result = (" + tcsh + ") _cached_result; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache[" + wpar1 + "] = " + wresult + ";\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + return header + " \n " + querycases + " \n" + + " return result;\n }\n"; + } + + public String buildQueryOpCPP(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, Vector decs) + { if (resultType == null || "void".equals(resultType + "")) + { System.err.println("ERROR: No result type for " + opname); + return ""; + } + + String gpars = ent.typeParameterTextCPP(); + + String ename = ""; + String eTypePars = ""; + Vector etpars = new Vector(); + + Vector context = new Vector(); + if (ent != null) + { ename = ent.getName(); + context.add(ent); + if (ent.hasTypeParameters()) + { etpars.addAll(ent.getTypeParameters()); + for (int i = 0; i < etpars.size(); i++) + { Type etp = (Type) etpars.get(i); + eTypePars = eTypePars + etp.getName(); + if (i < etpars.size() - 1) + { eTypePars = eTypePars + ", "; } + } + } + } + + String preheader = ""; + + // String rx = "resultx"; + // Expression rxbe = new BasicExpression(rx); + String javaPars = getCPPParameterDec(); + String header = " "; + // if (isSequential()) + // { header = header + "synchronized "; } + // if (isAbstract()) + // { header = header + "abstract "; } + // if (isFinal()) + // { header = header + "sealed "; } + + String isstatic = ""; + if (isClassScope() || isStatic()) + { isstatic = "static "; } + else if (isVirtual(ent)) + { isstatic = "virtual "; } + + // if (isAbstract()) + // { header = header + resT + " " + + // opname + "(" + javaPars + ");\n\n"; + // return header; + // } + + String opGenPars = ""; + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { etpars.addAll(typeParameters); + opGenPars = " template<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + opGenPars = opGenPars + " class " + tp.getName(); + if (i < typeParameters.size() - 1) + { opGenPars = opGenPars + ", "; } + } + opGenPars = opGenPars + ">\n"; + } + + if (etpars.size() > 0) + { genPars = "template<"; + for (int i = 0; i < etpars.size(); i++) + { Type tp = (Type) etpars.get(i); + genPars = genPars + " class " + tp.getName(); + if (i < etpars.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + String exname = ename; + if (eTypePars.length() > 0) + { exname = ename + "<" + eTypePars + ">"; } + + + if (etpars.size() > 0) + { header = " " + genPars + "\n"; } + header = header + " " + resT + " " + exname + "::" + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + String opdec = ""; + if (typeParameters.size() > 0) + { opdec = opGenPars; } + opdec = opdec + + " " + isstatic + resT + " " + opname + "(" + javaPars + ");\n"; + + decs.add(opdec); + + java.util.Map env0 = new java.util.HashMap(); + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ename,"this"); } + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + // Attribute resultxatt = new Attribute(rx,t,ModelElement.INTERNAL); + // resultxatt.setElementType(elementType); + atts.add(resultatt); + // atts.add(resultxatt); + + String et = "void*"; + if (elementType != null) + { et = elementType.getCPP(elementType.getElementType()); } + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.preconditionExpression(); + preheader = " if (" + npre.queryFormCPP(env0,true) + + ") { return result; } \n "; + } + } + + // Expression q0 = post.removeExpression(rscope); + // Expression q = null; + // if (q0 != null) + // { q = q0.substituteEq("result",rxbe); } + + header = header + " " + resT + " result = " + resultType.getDefaultCPP(elementType) + ";\n"; + header = header + preheader; + + + String querycases = buildQueryCasesCPP(post,"",resT,env0,types,entities,atts); + + if (ent != null && isCached() && parameters.size() == 0 && instanceScope) + { String etype = "void*"; + if (elementType != null) + { etype = elementType.getCPP(); } + String tcsh = resultType.getCPP(etype); + + ent.addAux(" static map<" + ename + "*," + tcsh + "> " + opname + "_cache;\n"); + ent.addPrivateAux(" map<" + ename + "*," + tcsh + "> " + ename + "::" + opname + "_cache;\n"); + + String wresult = "result"; // Expression.wrap(resultType, "result"); + return header + + " map<" + ename + "*," + tcsh + ">::iterator _cached_pos = " + opname + "_cache.find(this);\n" + + " if (_cached_pos != " + opname + "_cache.end())\n" + + " { result = " + opname + "_cache[this]; }\n" + + " else \n" + + " { " + querycases + "\n" + + " (" + opname + "_cache*)[this] = " + wresult + ";\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + /* General caching for more than 1 parameter is not possible in C++ */ + + if (ent != null && isCached() && parameters.size() == 1 && instanceScope) + { String etype = "void*"; + if (elementType != null) + { etype = elementType.getCPP(elementType.getElementType()); } + String tcsh = resultType.getCPP(etype); + Attribute par = (Attribute) parameters.get(0); + String par1 = par.getName(); + String ptyp = par.getType().getCPP(); // must be primitive or String + // String wpar1 = parcatsCSharp(); + ent.addAux(" map<" + ptyp + "," + tcsh + "> " + opname + "_cache;\n"); + String wresult = "result"; + return header + + " map<" + ptyp + "," + tcsh + ">::iterator _cached_pos = " + opname + "_cache.find(" + par1 + ");\n" + + " if (_cached_pos != " + opname + "_cache.end())\n" + + " { result = " + opname + "_cache[" + par1 + "]; }\n" + + " else \n" + + " { " + querycases + "\n" + + " " + opname + "_cache[" + par1 + "] = " + wresult + ";\n" + + " }\n" + + " return result;\n" + + " }\n"; + } + + return header + querycases + " \n" + + " return result;\n }\n"; + + } + + public Statement designQueryList(Vector postconds, + String resT, + java.util.Map env0, + Vector types, + Vector entities, + Vector atts) + { if (postconds.size() == 0) + { return new SequenceStatement(); } + + Expression postcond = (Expression) postconds.get(0); + Statement fst = designBasicCase(postcond,resT, + env0,types,entities,atts); + if (postconds.size() == 1) + { return fst; } + + Vector ptail = new Vector(); + ptail.addAll(postconds); + ptail.remove(0); + + if ((postcond instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) postcond).operator)) + { Expression next = (Expression) postconds.get(1); + + if ((next instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) next).operator)) + { Statement elsepart = + designQueryList(ptail,resT, + env0,types,entities,atts); + if (fst instanceof ConditionalStatement) + { ((ConditionalStatement) fst).setElse(elsepart); + // Statement.combineIfStatements(fst,elsepart); + return fst; + } + else + { SequenceStatement res = new SequenceStatement(); + res.addStatement(fst); res.addStatement(elsepart); + return res; + } + } + else + { Statement stat = + designQueryList(ptail,resT, + env0,types,entities,atts); + SequenceStatement res = new SequenceStatement(); + res.addStatement(fst); res.addStatement(stat); + return res; + } + } + else + { Statement stat = + designQueryList(ptail,resT, + env0,types,entities,atts); + SequenceStatement res = new SequenceStatement(); + res.addStatement(fst); + res.addStatement(stat); + return res; + } // sequencing of fst and ptail + } + + /* if (postcond instanceof BinaryExpression) + { BinaryExpression pst = (BinaryExpression) postcond; + if ("&".equals(pst.operator)) + { Statement fst = designQueryCases(pst.left, resT, env0, types, entities, atts); + Statement scnd = designQueryCases(pst.right, resT, env0, types, entities, atts); + if ((pst.left instanceof BinaryExpression) && "=>".equals(((BinaryExpression) pst.left).operator)) + { IfStatement res = new IfStatement(fst, scnd); + return res; + } + else + { SequenceStatement ss = new SequenceStatement(); + ss.addStatement(fst); + ss.addStatement(scnd); + return ss; + } + } + else if ("=>".equals(pst.operator)) + { Statement body = designQueryCases(pst.right, resT, env0, types, entities, atts); + IfStatement res = new IfStatement(pst.left, body); + return res; + } + } + return designBasicCase(postcond, resT, env0, types, entities, atts); + } */ + + private Statement designBasicCase(Expression pst, + String resT, java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (pst instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) pst; + if ("=>".equals(be.operator)) + { Expression test = be.left; + + Constraint virtualCon = new Constraint(test,be.right); + + Vector pars = new Vector(); + pars.addAll(getParameters()); + Vector lvars = new Vector(); + virtualCon.secondaryVariables(lvars,pars); + + Vector allvars = new Vector(); + Vector allpreds = new Vector(); + Vector qvars1 = new Vector(); + Vector lvars1 = new Vector(); + Vector pars1 = ModelElement.getNames(pars); + Vector v0 = new Vector(); + BasicExpression betrue = new BasicExpression(true); + v0.add(betrue); + v0.add(betrue.clone()); + Vector splitante = + test.splitToCond0Cond1Pred(v0,pars1,qvars1, + lvars1,allvars,allpreds); + // System.out.println(">>> Quantified local = " + qvars1 + " Let local = " + lvars1 + " All: " + allvars); + + Expression ante1 = (Expression) splitante.get(0); + Expression ante2 = (Expression) splitante.get(1); + + // System.out.println(">>> Variable quantifiers: " + ante1); + // System.out.println(">>> Assumptions: " + ante2); + + Statement ifpart = + // new ImplicitInvocationStatement(be.right); + designBasicCase(be.right, resT, env0, + types, entities, atts); + + if (qvars1.size() > 0 || lvars1.size() > 0) + // allvars.size() > 0) + { Statement forloop = + virtualCon.q2LoopsPred( + allvars,qvars1,lvars1,ifpart); + return forloop; + } + + Statement cs = new ConditionalStatement(test, ifpart); + System.out.println(); + System.out.println(">-->> code for branch " + be); + System.out.println(">-->> is: " + cs); + return cs; + } // But may be let definitions and local variables in test. + else if ("=".equals(be.operator)) + { Expression beleft = be.left; + if (isNoRecursion() && + "result".equals(be.left + "")) + { + if (be.right.isSelfCall(this)) + { // recursive call to operation, replace by + // parameter assignements and continue + ContinueStatement ctn = new ContinueStatement(); + Statement assgns = + parameterAssignments(be.right); + if (assgns == null) + { return ctn; } + else + { SequenceStatement ss = new SequenceStatement(); + ss.addStatements((SequenceStatement) assgns); + ss.addStatement(ctn); + ss.setBrackets(true); + return ss; + } + } + else + { Statement retr = + new ReturnStatement(be.right); + return retr; + } + } + else if (env0.containsValue(be.left + "") || + "result".equals(be.left + "") || + ModelElement.getNames( + parameters).contains(be.left + "")) + { return new AssignStatement(be.left, be.right); } + // or attribute of ent + else if (entity != null && + entity.hasFeature(be.left + "")) + { return new AssignStatement(be.left, be.right); } + else // declare it + { Type t = be.left.getType(); + /* JOptionPane.showMessageDialog(null, + "Declaring new local variable " + be.left + " : " + t + " in:\n" + this, + "Implicit variable declaration", + JOptionPane.INFORMATION_MESSAGE); */ + if (t == null) + { t = new Type("OclAny", null); } + CreationStatement cs = + new CreationStatement(t.getJava(), be.left + ""); + cs.setInstanceType(t); + cs.setElementType(t.getElementType()); + cs.setFrozen(true); // it must be a constant + AssignStatement ast = new AssignStatement(be.left, be.right); + SequenceStatement sst = new SequenceStatement(); + sst.addStatement(cs); + sst.addStatement(ast); + return sst; + } + } + } + return pst.generateDesign(env0, true); + } + + // assume it is a conjunction of implications + private String buildQueryList(Vector postconds, String header,String resT, + java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (postconds.size() == 0) + { return ""; } + + Expression postcond = (Expression) postconds.get(0); + String fst = buildQueryCases(postcond,header,resT, + env0,types,entities,atts) + " "; + if (postconds.size() == 1) + { return fst; } + Vector ptail = new Vector(); + ptail.addAll(postconds); + ptail.remove(0); + + if ((postcond instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) postcond).operator)) + { fst = fst + " else\n "; + Expression next = (Expression) postconds.get(1); + + if ((next instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) next).operator)) + { return buildQueryList(ptail,fst,resT, + env0,types,entities,atts) + " "; + } + else + { fst = fst + " { "; + return buildQueryList(ptail,fst,resT, + env0,types,entities,atts) + "\n } "; + } + } + else + { return buildQueryList(ptail,fst,resT, + env0,types,entities,atts) + " "; + } // sequencing of fst and ptail + } + + // assume it is a conjunction of implications + private String buildQueryCases(Expression postcond, String header, String resT, + java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (postcond instanceof BinaryExpression) + { BinaryExpression pst = (BinaryExpression) postcond; + if ("&".equals(pst.operator)) // and left right both have => as top operator + { String fst = buildQueryCases(pst.left,header,resT, + env0,types,entities,atts) + " "; + if ((pst.left instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.left).operator)) + { fst = fst + " else\n "; + if ((pst.right instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.right).operator)) + { return buildQueryCases(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + else + { fst = fst + " { "; + return buildQueryCases(pst.right,fst,resT, + env0,types,entities,atts) + "\n } "; + } + } + else + { return buildQueryCases(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + } + + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if ("=>".equals(pst.operator)) + { Expression test = pst.left; + test.typeCheck(types,entities,context,atts); + String qf = test.queryForm(env0,true); + // System.out.println(">>-->> " + test + " QUERY FORM= " + qf); + + Constraint virtualCon = new Constraint(test,pst.right); + + Vector pars = new Vector(); + pars.addAll(getParameters()); + Vector lvars = new Vector(); + virtualCon.secondaryVariables(lvars,pars); + + Vector allvars = new Vector(); + Vector allpreds = new Vector(); + + Vector qvars1 = new Vector(); + Vector lvars1 = new Vector(); + Vector pars1 = ModelElement.getNames(pars); + Vector v0 = new Vector(); + BasicExpression betrue = new BasicExpression(true); + v0.add(betrue); + v0.add(betrue.clone()); + Vector splitante = test.splitToCond0Cond1Pred(v0,pars1,qvars1,lvars1,allvars,allpreds); + System.out.println(); + System.out.println(">>> Operation " + getName() + " case parameters = " + + pars1 + " Quantified local = " + + qvars1 + " Let local = " + lvars1 + " All: " + allvars); + + Expression ante1 = (Expression) splitante.get(0); + Expression ante2 = (Expression) splitante.get(1); + + // System.out.println(">>> Operation " + getName() + " case variable quantifiers: " + ante1); + // System.out.println(">>> Operation " + getName() + " case assumptions: " + ante2); + // System.out.println(); + + if (qvars1.size() > 0 || lvars1.size() > 0) + { Statement ifpart = new ImplicitInvocationStatement(pst.right); + // designBasicCase(pst.right, resT, env0, types, entities, atts); + Statement forloop = virtualCon.q2LoopsPred(allvars,qvars1,lvars1,ifpart); + // System.out.println(">>> Actual code= " + forloop); + String res = header + forloop.updateForm(env0,true,types,entities,atts); + // System.out.println(">-->> code for branch " + pst); + // System.out.println(">-->> is: " + res); + return res; + } + + header = header + " if (" + qf + ") \n { "; + String body = buildQueryCases(pst.right,header,resT, + env0,types,entities,atts); + String res = body + " \n }"; + // System.out.println(">-->> code for branch " + pst); + // System.out.println(">-->> is: " + res); + return res; + } + + if ("or".equals(pst.operator)) + { return buildQueryCases(pst.left,header,resT,env0,types,entities,atts); } + else + { return header + basicQueryCase(pst,resT,env0,types,entities,atts); } + } + else if (postcond instanceof ConditionalExpression) + { return header + basicQueryCase(postcond,resT,env0,types,entities,atts); } + return header; + } + + private String buildQueryCasesJava6(Expression postcond, String header,String resT, + java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (postcond instanceof BinaryExpression) + { BinaryExpression pst = (BinaryExpression) postcond; + if ("&".equals(pst.operator)) + { String fst = buildQueryCasesJava6(pst.left,header,resT, + env0,types,entities,atts) + " "; + if ((pst.left instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.left).operator)) + { fst = fst + " else\n "; + if ((pst.right instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.right).operator)) + { return buildQueryCasesJava6(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + else + { fst = fst + " { "; + return buildQueryCasesJava6(pst.right,fst,resT, + env0,types,entities,atts) + "\n } "; + } + } + else + { return buildQueryCasesJava6(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + } + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if ("=>".equals(pst.operator)) + { Expression test = pst.left; + test.typeCheck(types,entities,context,atts); + String qf = test.queryFormJava6(env0,true); + // System.out.println(test + " QUERY FORM= " + qf); + + header = header + " if (" + qf + ") \n { "; + String body = buildQueryCasesJava6(pst.right,header,resT, + env0,types,entities,atts); + return body + " \n }"; + } + if ("or".equals(pst.operator)) + { return buildQueryCasesJava6(pst.left,header,resT,env0,types,entities,atts); } + else + { return header + basicQueryCaseJava6(pst,resT,env0,types,entities,atts); } + } + else if (postcond instanceof ConditionalExpression) + { return header + basicQueryCaseJava6(postcond,resT,env0,types,entities,atts); } + return header; + } + + private String buildQueryCasesJava7(Expression postcond, String header,String resT, + java.util.Map env0, + Vector types, Vector entities, Vector atts) + { // System.out.println("JAVA7 QUERY CASES"); + if (postcond instanceof BinaryExpression) + { BinaryExpression pst = (BinaryExpression) postcond; + if ("&".equals(pst.operator)) + { String fst = buildQueryCasesJava7(pst.left,header,resT, + env0,types,entities,atts) + " "; + if ((pst.left instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.left).operator)) + { fst = fst + " else\n "; + if ((pst.right instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.right).operator)) + { return buildQueryCasesJava7(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + else + { fst = fst + " { "; + return buildQueryCasesJava7(pst.right,fst,resT, + env0,types,entities,atts) + "\n } "; + } + } + else + { return buildQueryCasesJava7(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + } + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if ("=>".equals(pst.operator)) + { Expression test = pst.left; + test.typeCheck(types,entities,context,atts); + String qf = test.queryFormJava7(env0,true); + // System.out.println(test + " QUERY FORM= " + qf); + + header = header + " if (" + qf + ") \n { "; + String body = buildQueryCasesJava7(pst.right,header,resT, + env0,types,entities,atts); + return body + " \n }"; + } + if ("or".equals(pst.operator)) + { return buildQueryCasesJava7(pst.left,header,resT,env0,types,entities,atts); } + else + { return header + basicQueryCaseJava7(pst,resT,env0,types,entities,atts); } + } + else if (postcond instanceof ConditionalExpression) + { return header + basicQueryCaseJava7(postcond,resT,env0,types,entities,atts); } + return header; + } + + private String buildQueryCasesCSharp(Expression postcond, String header, String resT, + java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (postcond instanceof BinaryExpression) + { BinaryExpression pst = (BinaryExpression) postcond; + if ("&".equals(pst.operator)) + { String fst = buildQueryCasesCSharp(pst.left,header,resT, + env0,types,entities,atts) + " "; + if ((pst.left instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.left).operator)) + { fst = fst + " else\n "; + if ((pst.right instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.right).operator)) + { return buildQueryCasesCSharp(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + else + { fst = fst + " { "; + return buildQueryCasesCSharp(pst.right,fst,resT, + env0,types,entities,atts) + "\n } "; + } + } + else + { return buildQueryCasesCSharp(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + } + + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if ("=>".equals(pst.operator)) + { Expression test = pst.left; + test.typeCheck(types,entities,context,atts); + String qf = test.queryFormCSharp(env0,true); + // System.out.println(test + " QUERY FORM= " + qf); + + header = header + " if (" + qf + ") \n { "; + String body = buildQueryCasesCSharp(pst.right,header,resT, + env0,types,entities,atts); + return body + " \n }"; + } + if ("or".equals(pst.operator)) + { return buildQueryCasesCSharp(pst.left,header,resT,env0,types,entities,atts); } + else + { return header + basicQueryCaseCSharp(pst,resT,env0,types,entities,atts); } + } + else if (postcond instanceof ConditionalExpression) + { return header + basicQueryCaseCSharp(postcond,resT,env0,types,entities,atts); } + return header; + } + + private String buildQueryCasesCPP(Expression postcond, String header,String resT, + java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (postcond instanceof BinaryExpression) + { BinaryExpression pst = (BinaryExpression) postcond; + if ("&".equals(pst.operator)) + { String fst = buildQueryCasesCPP(pst.left,header,resT, + env0,types,entities,atts) + " "; + if ((pst.left instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.left).operator)) + { fst = fst + " else\n "; + if ((pst.right instanceof BinaryExpression) && + "=>".equals(((BinaryExpression) pst.right).operator)) + { return buildQueryCasesCPP(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + else + { fst = fst + " { "; + return buildQueryCasesCPP(pst.right,fst,resT, + env0,types,entities,atts) + "\n } "; + } + } + else + { return buildQueryCasesCPP(pst.right,fst,resT, + env0,types,entities,atts) + " "; + } + } + + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if ("=>".equals(pst.operator)) + { Expression test = pst.left; + test.typeCheck(types,entities,context,atts); + String qf = test.queryFormCPP(env0,true); + // System.out.println(test + " QUERY FORM= " + qf); + + header = header + " if (" + qf + ") \n { "; + String body = buildQueryCasesCPP(pst.right,header,resT, + env0,types,entities,atts); + return body + " \n }"; + } + + if ("or".equals(pst.operator)) + { return buildQueryCasesCPP(pst.left,header,resT,env0,types,entities,atts); } + else + { return header + basicQueryCaseCPP(pst,resT,env0,types,entities,atts); } + } + else if (postcond instanceof ConditionalExpression) + { return header + basicQueryCaseCPP(postcond,resT,env0,types,entities,atts); } + + return header; + } + + + + private String basicQueryCase(Expression pst,String resT, java.util.Map env0, + Vector types, Vector entities, Vector atts) + { // Scope scope = pst.resultScope(); + + // if (scope == null) + if (pst instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) pst; + if ("=".equals(be.operator)) + { Expression beleft = be.left; + if (env0.containsValue(be.left + "") || "result".equals(be.left + "") || + ModelElement.getNames(parameters).contains(be.left + "")) + { return " " + pst.updateForm(env0,true) + "\n"; } // or attribute of ent + else if (entity != null && entity.hasFeature(be.left + "")) + { return " " + pst.updateForm(env0,true) + "\n"; } + else // declare it + { Type t = be.right.getType(); + System.out.println(">>> Declaring new local variable " + be.left + + " in:\n" + this); + // JOptionPane.showMessageDialog(null, + // "Declaring new local variable " + be.left + " in:\n" + this, + // "Implicit variable declaration", JOptionPane.INFORMATION_MESSAGE); + return " final " + t.getJava() + " " + pst.updateForm(env0,true) + " \n "; + } + } + else if ("&".equals(be.operator)) + { String fst = basicQueryCase(be.left, resT, env0, types, entities, atts); + return fst + basicQueryCase(be.right, resT, env0, types, entities, atts); + } + } + return " " + pst.updateForm(env0,true) + "\n "; + + /* BinaryExpression rscope = scope.resultScope; + String op = scope.scopeKind; + String rx = "resultx"; + Expression rxbe = new BasicExpression(rx); + String rs = "results"; + + Expression q0 = pst.removeExpression(rscope); + Expression q = null; + if (q0 != null) + { q = q0.substituteEq("result",rxbe); } + // What is the point of this??? + + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if (op.equals("eq")) + { rscope.typeCheck(types,entities,context,atts); // not resultx though + Expression test = null; + + // if (q instanceof BinaryExpression) + // { BinaryExpression qbe = (BinaryExpression) q; + // if (qbe.operator.equals("=>")) + // { test = qbe.left; } + // } + String body = Association.genEventCode(env0,test,rscope,true); + return " " + body + "\n"; + // + " return result;\n "; + } + if (op.equals("in")) + { String res = " Vector " + rs + " = new Vector();\n" + + " " + rs + ".addAll(" + getRange(rscope,env0) + ");\n"; + res = res + " for (int i = 0; i < " + rs + ".size(); i++)\n"; + res = res + " { " + resT + " " + rx + " = (" + resT + ") " + rs + ".get(i);\n"; + Expression newpost = + new BinaryExpression("=", new BasicExpression("result"), rxbe); + newpost.typeCheck(types,entities,context,atts); + if (q != null) + { q.typeCheck(types,entities,context,atts); } + String body = Association.genEventCode(env0,q, + newpost,true); + return res + " " + body + " }\n" + + " return result;\n "; + } + if (op.equals("subset")) + { Type elemT = getElementType(rscope); + if (elemT == null) { return ""; } + String jelemT = elemT.getJava(); + header = header + " " + resT + " result = new Vector();\n"; + header = header + preheader; + header = header + " Vector " + rs + " = " + + getRange(rscope,env0) + ";\n"; + header = header + " for (int i = 0; i < " + + rs + ".size(); i++)\n"; + header = header + " { " + jelemT + " " + rx + + " = (" + jelemT + ") " + rs + ".get(i);\n"; + Expression newpost = + new BinaryExpression(":",rxbe,new BasicExpression("result")); + + newpost.typeCheck(types,entities,context,atts); + if (q != null) + { q.typeCheck(types,entities,context,atts); } + String body = Association.genEventCode(env0,q, + newpost,true); + return header + " " + body + " }\n" + + " return result;\n }"; + } + if (op.equals("array")) + { BasicExpression arr = (BasicExpression) scope.arrayExp.clone(); + arr.arrayIndex = null; + Expression teste = rscope.substituteEq("result",rxbe); + arr.typeCheck(types,entities,context,atts); + teste.typeCheck(types,entities,context,atts); + String e = arr.queryForm(env0,true); + String test = teste.queryForm(env0,true); + String loop = + " result = 0;\n" + + " for (int resultx = 1; resultx <= " + e + ".size(); resultx++)\n" + + " { if (" + test + ") \n" + + " { result = resultx; \n" + + " return result; \n" + + " } \n" + + " }\n"; + return " " + loop + " return result;\n"; + } + return ""; */ + } + + private String basicQueryCaseJava6(Expression pst,String resT, java.util.Map env0, + Vector types, Vector entities, Vector atts) + { Scope scope = pst.resultScope(); + + if (pst instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) pst; + if ("=".equals(be.operator)) + { Expression beleft = be.left; + if (env0.containsValue(be.left + "") || "result".equals(be.left + "") || + ModelElement.getNames(parameters).contains(be.left + "")) + { return " " + pst.updateFormJava6(env0,true) + "\n"; } // or attribute of ent + else if (entity != null && entity.hasFeature(be.left + "")) + { return " " + pst.updateFormJava6(env0,true) + "\n"; } + else // declare it + { Type t = be.right.getType(); + /* JOptionPane.showMessageDialog(null, + "Declaring new local variable " + be.left + " in:\n" + this, + "Implicit variable declaration", JOptionPane.INFORMATION_MESSAGE); */ + + return " final " + t.getJava6() + " " + pst.updateFormJava6(env0,true) + " \n "; + } + } + } + return " " + pst.updateFormJava6(env0,true); + } + + private String basicQueryCaseJava7(Expression pst,String resT, java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (pst instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) pst; + if ("=".equals(be.operator)) + { Expression beleft = be.left; + if (env0.containsValue(be.left + "") || + "result".equals(be.left + "") || + ModelElement.getNames(parameters).contains(be.left + "")) + { return " " + pst.updateFormJava7(env0,true) + "\n"; } // or attribute of ent + else if (entity != null && entity.hasFeature(be.left + "")) + { return " " + pst.updateFormJava7(env0,true) + "\n"; } + else // declare it + { Type t = be.right.getType(); + /* JOptionPane.showMessageDialog(null, + "Declaring new local variable " + be.left + " : " + t + " in:\n" + this, + "Implicit variable declaration", JOptionPane.INFORMATION_MESSAGE); */ + + return " final " + t.getJava7(t.getElementType()) + " " + pst.updateFormJava7(env0,true) + " \n "; + } + } + } + return " " + pst.updateFormJava7(env0,true); + } + + private String basicQueryCaseCSharp(Expression pst,String resT, java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (pst instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) pst; + if ("=".equals(be.operator)) + { Expression beleft = be.left; + if (env0.containsValue(be.left + "") || "result".equals(be.left + "") || + ModelElement.getNames(parameters).contains(be.left + "")) + { return " " + pst.updateFormCSharp(env0,true); } // or attribute of ent + else if (entity != null && entity.hasFeature(be.left + "")) + { return " " + pst.updateFormCSharp(env0,true); } + else // declare it + { Type t = be.left.getType(); + /* JOptionPane.showMessageDialog(null, + "Declaring new local variable " + be.left + " in:\n" + this, + "Implicit variable declaration", JOptionPane.INFORMATION_MESSAGE); */ + + return " " + t.getCSharp() + " " + pst.updateFormCSharp(env0,true) + " \n "; + } + } + } + return " " + pst.updateFormCSharp(env0,true); + } + + private String basicQueryCaseCPP(Expression pst,String resT, java.util.Map env0, + Vector types, Vector entities, Vector atts) + { if (pst instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) pst; + if ("=".equals(be.operator)) + { Expression beleft = be.left; + if (env0.containsValue(be.left + "") || "result".equals(be.left + "") || + ModelElement.getNames(parameters).contains(be.left + "")) + { return " " + pst.updateFormCPP(env0,true); } // or attribute of ent + else if (entity != null && entity.hasFeature(be.left + "")) + { return " " + pst.updateFormCPP(env0,true); } + else // declare it + { Type t = be.left.getType(); + /* JOptionPane.showMessageDialog(null, + "Declaring new local variable " + be.left + " in:\n" + this, + "Implicit variable declaration", JOptionPane.INFORMATION_MESSAGE); */ + + return " " + t.getCPP(t.getElementType()) + " " + pst.updateFormCPP(env0,true) + " \n "; + } + } + } + return " " + pst.updateFormCPP(env0,true); + } + + + // Controller version of the operation -- only for instance operations. Should be + // for static also? + + public String getGlobalOperationCode(Entity ent,Vector entities, Vector types, + Vector constraints) + { String name = getName(); + String resT = "void"; + if (resultType != null) + { resT = resultType.getJava(); } + if (post == null) + { return ""; } + if (query) + { return buildGlobalQueryOp(ent,name,resultType,resT, + entities,types); + } + else // including for abstract ones + { return buildGlobalUpdateOp(ent,name,resultType,resT, + entities,types,constraints); + } + } // ignore return type for update ops for now. + + public String getGlobalOperationCodeJava6(Entity ent,Vector entities, Vector types, + Vector constraints) + { String name = getName(); + String resT = "void"; + if (resultType != null) + { resT = resultType.getJava6(); } + if (post == null) + { return ""; } + if (query) + { return buildGlobalQueryOpJava6(ent,name,resultType,resT, + entities,types); + } + else // including for abstract ones + { return buildGlobalUpdateOpJava6(ent,name,resultType,resT, + entities,types,constraints); + } + } // ignore return type for update ops for now. + + public String getGlobalOperationCodeJava7(Entity ent,Vector entities, Vector types, + Vector constraints) + { String name = getName(); + String resT = "void"; + if (resultType != null) + { resT = resultType.getJava7(elementType); } // may need the wrapper type down below. + if (post == null) + { return ""; } + if (query) + { return buildGlobalQueryOpJava7(ent,name,resultType,resT, + entities,types); + } + else // including for abstract ones + { return buildGlobalUpdateOpJava7(ent,name,resultType,resT, + entities,types,constraints); + } + } // ignore return type for update ops for now. + + + // Controller version of the operation + public String getGlobalOperationCodeCSharp(Entity ent,Vector entities, Vector types, + Vector constraints) + { // if (!instanceScope) { return ""; } + + if (isUnsafe()) { return ""; } + + String name = getName(); + String resT = "void"; + if (resultType != null) + { resT = resultType.getCSharp(); } + if (post == null) + { return ""; } + if (query) + { return buildGlobalQueryOpCSharp(ent,name,resultType,resT, + entities,types); + } + else // including for abstract ones + { return buildGlobalUpdateOpCSharp(ent,name,resultType,resT, + entities,types,constraints); + } + } // ignore return type for update ops for now. + + // Controller version of the operation + public String getGlobalOperationCodeCPP(Entity ent,Vector entities, Vector types, + Vector constraints, Vector declarations) + { if (!instanceScope) { return ""; } + + String name = getName(); + String resT = "void"; + if (resultType != null) + { resT = resultType.getCPP(getElementType()); } + if (post == null) + { return ""; } + if (query) + { return buildGlobalQueryOpCPP(ent,name,resultType,resT,declarations, + entities,types); + } + else // including for abstract ones + { return buildGlobalUpdateOpCPP(ent,name,resultType,resT,declarations, + entities,types,constraints); + } + } // ignore return type for update ops for now. + + + public String buildUpdateOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { String preheader = ""; + String javaPars = getJavaParameterDec(); + + // System.out.println(">>> Building update op for " + opname + " : " + t + " >> " + resT); + + String header = " public "; + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + String genPars = typeParameterList(); + + if (isAbstract()) + { header = header + genPars + resT + " " + + opname + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + genPars + resT + " " + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = new Vector(); + atts.addAll(parameters); + + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + " " + resT + " result = " + resultType.getDefault() + ";\n"; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.computeNegation4succ(); + Expression npre1 = npre.removePrestate(); + preheader = " // if (" + npre1.queryForm(env0,true) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + + Expression newpost = (Expression) post.clone(); + Vector preterms = post.allPreTerms(); + // System.out.println("Pre terms: " + preterms); + // substitute these by new variables pre_var in post, copy types/multiplicities + // of preterm variables. Have initial assignments pre_var = var.queryForm(); + // for each. Can optimise by ignoring vars not on any lhs + + Vector processed = new Vector(); + + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.queryForm(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); } + else + { actualtyp = new Type("Set",null); } + actualtyp.setElementType(preterm.getElementType()); + + if (preterm.umlkind == Expression.CLASSID && preterm.arrayIndex == null) + { pretermqf = "Controller.inst()." + pretermqf.toLowerCase() + "s"; } + newdec = actualtyp.getJava() + " " + pre_var + " = new Vector();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + else + { actualtyp = typ; + newdec = actualtyp.getJava() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + Attribute preatt = new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + // System.out.println("****** PRE variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType + " VALUE= " + pretermqf); + preatt.setElementType(preterm.elementType); + atts.add(preatt); + newpost = // newpost.substitute(preterm,prebe); + newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,atts); + String body = Association.genEventCode(env0,null,newpost,false); + if (returning.length() > 0) + { body = body + "\n return" + returning + ";\n"; } + + String res = header + newdecs + preheader + body + "\n" + " }"; + return res; + } + + public String buildUpdateOpJava6(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { String preheader = ""; + String javaPars = getJava6ParameterDec(); + + String header = " public "; + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + String genPars = typeParameterListJava6(); + + if (isAbstract()) + { header = header + genPars + resT + " " + + opname + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + genPars + resT + " " + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = new Vector(); + atts.addAll(parameters); + + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + " " + resT + " result = " + resultType.getDefaultJava6() + ";\n"; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.computeNegation4succ(); + Expression npre1 = npre.removePrestate(); + + preheader = " // if (" + npre1.queryFormJava6(env0,true) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + + Expression newpost = (Expression) post.clone(); + Vector preterms = post.allPreTerms(); + // System.out.println("Pre terms: " + preterms); + // substitute these by new variables pre_var in post, copy types/multiplicities + // of preterm variables. Have initial assignments pre_var = var.queryForm(); + // for each. Can optimise by ignoring vars not on any lhs + + Vector processed = new Vector(); + + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.queryFormJava6(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + // System.out.println(">>> Preterm " + preterm + " type = " + typ); + // System.out.println(">>> isOrdered: " + preterm.isOrdered() + " isMultiple: " + preterm.isMultiple() + " isSequenceValued: " + preterm.isSequenceValued()); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence", null); } + else + { actualtyp = new Type("Set",null); } + actualtyp.setElementType(preterm.getElementType()); + + + + if (preterm.umlkind == Expression.CLASSID && preterm.arrayIndex == null) + { pretermqf = "Controller.inst()." + pretermqf.toLowerCase() + "s"; } + String j6type = actualtyp.getJava6(); + newdec = j6type + " " + pre_var + " = new " + j6type + "();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + else + { actualtyp = typ; + newdec = actualtyp.getJava6() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + Attribute preatt = new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + preatt.setElementType(preterm.elementType); + atts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,atts); + String body = Association.genEventCodeJava6(env0,null,newpost,false); + if (returning.length() > 0) + { body = body + "\n return" + returning + ";\n"; } + + String res = header + newdecs + preheader + body + "\n" + " }"; + return res; + } + + public String buildUpdateOpJava7(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { String preheader = ""; + String javaPars = getJava7ParameterDec(); + + String header = " public "; + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + String genPars = typeParameterListJava7(); + + if (isAbstract()) + { header = header + genPars + resT + " " + + opname + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + genPars + resT + " " + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = new Vector(); + atts.addAll(parameters); + + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + " " + resT + " result = " + resultType.getDefaultJava7() + ";\n"; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.computeNegation4succ(); + Expression npre1 = npre.removePrestate(); + + preheader = " // if (" + npre1.queryFormJava7(env0,true) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + + Expression newpost = (Expression) post.clone(); + Vector preterms = post.allPreTerms(); + // System.out.println("Pre terms: " + preterms); + // substitute these by new variables pre_var in post, copy types/multiplicities + // of preterm variables. Have initial assignments pre_var = var.queryForm(); + // for each. Can optimise by ignoring vars not on any lhs + + Vector processed = new Vector(); + + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.queryFormJava7(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + prebe.setUmlKind(Expression.VARIABLE); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence", null); } + else + { actualtyp = new Type("Set",null); } + actualtyp.setElementType(preterm.getElementType()); + + if (preterm.umlkind == Expression.CLASSID && preterm.arrayIndex == null) + { pretermqf = "Controller.inst()." + pretermqf.toLowerCase() + "s"; } + + actualtyp.setSorted(preterm.isSorted()); + prebe.setSorted(preterm.isSorted()); + // System.out.println(">> Type of " + preterm + " = " + preterm.type + " { " + preterm.isSorted() + " }"); + + String j7type = + actualtyp.getJava7(preterm.elementType); + newdec = j7type + " " + pre_var + " = new " + j7type + "();\n" + + " " + pre_var + ".addAll(" + pretermqf + ");\n"; + } + else + { actualtyp = typ; + newdec = actualtyp.getJava7(preterm.elementType) + " " + pre_var + " = " + pretermqf + ";\n"; + } + + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + Attribute preatt = new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + preatt.setElementType(preterm.elementType); + atts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,atts); + String body = Association.genEventCodeJava7(env0,null,newpost,false); + if (returning.length() > 0) + { body = body + "\n return" + returning + ";\n"; } + + String res = header + newdecs + preheader + body + "\n" + " }"; + return res; + } + + + public String buildUpdateOpCSharp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { String preheader = ""; + String javaPars = getCSharpParameterDec(); + + String header = " public "; + + if (isUnsafe()) + { header = header + "unsafe "; } + + if (isAbstract()) + { header = header + "abstract "; } + if (isFinal()) + { header = header + "sealed "; } + if (isClassScope() || isStatic()) + { header = header + "static "; } + + String genPars = typeParameterListCSharp(); + + if (isAbstract()) + { header = header + resT + " " + + opname + genPars + "(" + javaPars + ");\n\n"; + return header; + } + + header = header + resT + " " + + opname + genPars + + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + java.util.Map env0 = new java.util.HashMap(); + + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = new Vector(); + atts.addAll(parameters); + + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + " " + resT + " result = " + resultType.getDefaultCSharp() + ";\n"; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.computeNegation4succ(); + Expression npre1 = npre.removePrestate(); + + preheader = " // if (" + npre1.queryFormCSharp(env0,true) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + + Expression newpost = (Expression) post.clone(); + Vector preterms = post.allPreTerms(); + // System.out.println("Pre terms: " + preterms); + // substitute these by new variables pre_var in post, copy types/multiplicities + // of preterm variables. Have initial assignments pre_var = var.queryForm(); + // for each. Can optimise by ignoring vars not on any lhs + + Vector processed = new Vector(); + + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.queryFormCSharp(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + if (preterm.isMultiple()) + { if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); } + else + { actualtyp = new Type("Set",null); } + actualtyp.setElementType(preterm.getElementType()); + + if (preterm.umlkind == Expression.CLASSID && preterm.arrayIndex == null) + { pretermqf = "Controller.inst().get" + pretermqf.toLowerCase() + "_s()"; } + newdec = actualtyp.getCSharp() + " " + pre_var + " = new ArrayList();\n" + + " " + pre_var + ".AddRange(" + pretermqf + ");\n"; + } + else + { actualtyp = typ; + newdec = actualtyp.getCSharp() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + Attribute preatt = new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + preatt.setElementType(preterm.elementType); + atts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,atts); + String body = Association.genEventCodeCSharp(env0,null,newpost,false); + if (returning.length() > 0) + { body = body + "\n return" + returning + ";\n"; } + + String res = header + newdecs + preheader + body + "\n" + " }"; + return res; + } + + public String buildUpdateOpCPP(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, Vector decs) + { String preheader = ""; + String javaPars = getCPPParameterDec(); + + String ename = ""; + String eTypePars = ""; + Vector etpars = new Vector(); + + String gpars = ent.typeParameterTextCPP(); + + Vector context = new Vector(); + if (ent != null) + { ename = ent.getName(); + context.add(ent); + if (ent.hasTypeParameters()) + { etpars.addAll(ent.getTypeParameters()); + for (int i = 0; i < etpars.size(); i++) + { Type etp = (Type) etpars.get(i); + eTypePars = eTypePars + etp.getName(); + if (i < etpars.size() - 1) + { eTypePars = eTypePars + ", "; } + } + } + } + + String header = ""; + // if (isAbstract()) + // { header = header + "abstract "; } + // if (isFinal()) + // { header = header + "sealed "; } + + String isstatic = ""; + if (isClassScope() || isStatic()) + { isstatic = "static "; } + else if (isVirtual(ent)) + { isstatic = "virtual "; } + + // if (isAbstract()) + // { header = header + resT + " " + + // opname + "(" + javaPars + ");\n\n"; + // return header; + // } + + String opGenPars = ""; + String genPars = ""; + if (typeParameters != null && typeParameters.size() > 0) + { etpars.addAll(typeParameters); + opGenPars = " template<"; + for (int i = 0; i < typeParameters.size(); i++) + { Type tp = (Type) typeParameters.get(i); + opGenPars = opGenPars + " class " + tp.getName(); + if (i < typeParameters.size() - 1) + { opGenPars = opGenPars + ", "; } + } + opGenPars = opGenPars + ">\n"; + } + + if (etpars.size() > 0) + { genPars = "template<"; + for (int i = 0; i < etpars.size(); i++) + { Type tp = (Type) etpars.get(i); + genPars = genPars + " class " + tp.getName(); + if (i < etpars.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + "> "; + } + + String exname = ename; + if (eTypePars.length() > 0) + { exname = ename + "<" + eTypePars + ">"; } + + + if (etpars.size() > 0) + { header = " " + genPars + "\n"; } + header = header + " " + resT + " " + exname + "::" + + opname + "(" + javaPars + ")\n { "; + + if (comments != null) + { header = header + "/* " + comments + " */\n "; } + + decs.add(opGenPars + " " + isstatic + resT + " " + opname + "(" + javaPars + ");\n"); + + java.util.Map env0 = new java.util.HashMap(); + + if (ent == null || isClassScope() || isStatic()) { } + else + { env0.put(ent.getName(),"this"); } + + Vector atts = new Vector(); + atts.addAll(parameters); + + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String et = "void*"; + if (elementType != null) + { et = elementType.getCPP(elementType.getElementType()); } + + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + " " + resT + " result = " + resultType.getDefaultCPP(elementType) + ";\n"; + returning = " result"; + } + + if (pre != null) + { pre.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre)) { } + else + { Expression npre = pre.computeNegation4succ(); + Expression npre1 = npre.removePrestate(); + + preheader = " // if (" + npre1.queryFormCPP(env0,true) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + + Expression newpost = (Expression) post.clone(); + Vector preterms = post.allPreTerms(); + // System.out.println("Pre terms: " + preterms); + // substitute these by new variables pre_var in post, copy types/multiplicities + // of preterm variables. Have initial assignments pre_var = var.queryForm(); + // for each. Can optimise by ignoring vars not on any lhs + + Vector processed = new Vector(); + + for (int i = 0; i < preterms.size(); i++) + { BasicExpression preterm = (BasicExpression) preterms.get(i); + if (processed.contains(preterm)) { continue; } + + Type typ = preterm.getType(); // but actual type may be list if multiple + Type actualtyp; + String newdec = ""; + String pre_var = Identifier.nextIdentifier("pre_" + preterm.data); + String pretermqf = preterm.queryFormCPP(env0,true); + BasicExpression prebe = new BasicExpression(pre_var); + + Type preET = preterm.getElementType(); + String pcet = "void*"; + if (preET != null) + { pcet = preET.getCPP(preET.getElementType()); } + + if (preterm.isMultiple()) + { if (preterm.umlkind == Expression.CLASSID && preterm.arrayIndex == null) + { pretermqf = "Controller::inst->get" + pretermqf.toLowerCase() + "_s()"; } + if (preterm.isOrdered() || preterm.isSequenceValued()) + { actualtyp = new Type("Sequence",null); + newdec = " vector<" + pcet + ">* " + pre_var + " = new vector<" + pcet + ">();\n" + + " " + pre_var + "->insert(" + pre_var + "->end(), " + + pretermqf + "->begin(), " + + pretermqf + "->end());\n"; + } + else + { actualtyp = new Type("Set",null); + newdec = " std::set<" + pcet + ">* " + pre_var + " = new std::set<" + pcet + ">();\n" + + " " + pre_var + "->insert(" + pretermqf + "->begin(), " + + pretermqf + "->end());\n"; + } + actualtyp.setElementType(preET); + } + else + { actualtyp = typ; + newdec = actualtyp.getCPP() + " " + pre_var + " = " + pretermqf + ";\n"; + } + newdecs = newdecs + " " + newdec; + prebe.type = actualtyp; + prebe.elementType = preterm.elementType; + Attribute preatt = new Attribute(pre_var,actualtyp,ModelElement.INTERNAL); + // System.out.println("Pre variable " + prebe + " type= " + actualtyp + + // " elemtype= " + prebe.elementType); + preatt.setElementType(preterm.elementType); + atts.add(preatt); + newpost = newpost.substituteEq("" + preterm,prebe); + processed.add(preterm); + } // substitute(preterm,prebe) more appropriate + + newpost.typeCheck(types,entities,context,atts); + String body = Association.genEventCodeCPP(env0,null,newpost,false); + if (returning.length() > 0) + { body = body + "\n return" + returning + ";\n"; } + + String res = header + newdecs + preheader + body + "\n" + " }"; + return res; + } + + + public String buildGlobalUpdateOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, + Vector constraints) + { String preheader = ""; + if (ent == null) { return ""; } + + String javaPars = getJavaParameterDec(); + String parlist = parameterList(); + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (!instanceScope) + { if (resT == null || resT.equals("void")) + { return " public static void " + opname + "(" + javaPars + ")\n" + + " { " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + return " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "List " + ex + "s"; + } + else + { java2Pars = "List " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + String retT = resT; + if (resT == null) + { retT = "void"; } + + String header2 = header + " List All" + ename + + opname + "(" + java2Pars + ")\n { "; + + header = header + retT + " " + + opname + "(" + javaPars + ")\n { "; + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) + { header2 = header2 + "\n List result = new Vector();\n "; + retT = "void"; + } + else + { header = header + "\n " + resT + " result = " + resultType.getDefault() + ";\n "; + header2 = header2 + "\n List result = new Vector();\n "; + returning = " result"; + } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " // if (!(" + pre1.queryForm(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + String body = " " + ex + "." + call + ";"; + String endbody = ""; + header2 = header2 + " for (int _i = 0; _i < " + exs + ".size(); _i++)\n" + + " { " + ename + " " + ex + " = (" + ename + ") " + exs + ".get(_i);\n"; + + if (parlist.length() > 0) + { parlist = "," + parlist; } + + String newitem = opname + "(" + ex + parlist + ")"; + + if ("List".equals(resT)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } // NOT addAll + else if (resT == null || resT.equals("void")) + { header2 = header2 + " " + newitem + ";\n"; } + else if (resultType.isPrimitive()) + { newitem = Expression.wrap(resultType,newitem); + header2 = header2 + " result.add(" + newitem + ");\n"; + } + else + { header2 = header2 + " result.add(" + newitem + ");\n"; } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + if (resT == null || resT.equals("void")) + { } + else + { body = " result = " + body; + endbody = " return result;"; + } + + for (int i = 0; i < constraints.size(); i++) + { Constraint cc = (Constraint) constraints.get(i); + Constraint ccnew = cc.matchesOp(opname, this); + if (ccnew != null) + { Vector contx = new Vector(); + if (ccnew.getOwner() != null) + { contx.add(ccnew.getOwner()); } + boolean ok = ccnew.typeCheck(types,entities,contx); + if (ok) + { String upd = ccnew.globalUpdateOp(ent,false); + body = body + "\n " + upd; + } + } + } + + // if (isDefinedinSuperclass()) + // { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; } + String gop = header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; + if (derived) + { return gop; } + return gop + header2; + } + + public String buildGlobalUpdateOpJava6(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, + Vector constraints) + { String preheader = ""; + String javaPars = getJava6ParameterDec(); + String parlist = parameterList(); + + if (ent == null) { return ""; } + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + String retT = resT; + if (resT == null) + { retT = "void"; } + + if (!instanceScope) + { if (resT == null || resT.equals("void")) + { return " public static void " + opname + "(" + javaPars + ")\n" + + " { " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + return " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "Collection " + ex + "s"; + } + else + { java2Pars = "Collection " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + String header2 = header + " ArrayList All" + ename + + opname + "(" + java2Pars + ")\n { "; + + header = header + retT + " " + + opname + "(" + javaPars + ")\n { "; + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) + { header2 = header2 + "\n ArrayList result = new ArrayList();\n "; } + else + { header = header + "\n " + resT + " result = " + resultType.getDefaultJava6() + ";\n "; + header2 = header2 + "\n ArrayList result = new ArrayList();\n "; + returning = " result"; + } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " // if (!(" + pre1.queryFormJava6(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + String body = " " + ex + "." + call + ";"; + String endbody = ""; + header2 = header2 + " for (Object _i : " + exs + ")\n" + + " { " + ename + " " + ex + " = (" + ename + ") _i;\n"; + + if (parlist.length() > 0) + { parlist = "," + parlist; } + + String newitem = opname + "(" + ex + parlist + ")"; + + if (resultType != null && Type.isMapType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } + else if (resultType != null && + Type.isCollectionType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } // NOT addAll + else if (resT == null || resT.equals("void")) + { header2 = header2 + " " + newitem + ";\n"; } + else if (resultType.isPrimitive()) + { newitem = Expression.wrap(resultType,newitem); + header2 = header2 + " result.add(" + newitem + ");\n"; + } + else + { header2 = header2 + " result.add(" + newitem + ");\n"; } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + if (resT == null || resT.equals("void")) + { } + else + { body = " result = " + body; + endbody = " return result;"; + } + + for (int i = 0; i < constraints.size(); i++) + { Constraint cc = (Constraint) constraints.get(i); + Constraint ccnew = cc.matchesOp(opname, this); + if (ccnew != null) + { Vector contx = new Vector(); + if (ccnew.getOwner() != null) + { contx.add(ccnew.getOwner()); } + boolean ok = ccnew.typeCheck(types,entities,contx); + if (ok) + { String upd = ccnew.globalUpdateOpJava6(ent,false); + body = body + "\n " + upd; + } + } + } + + // if (isDefinedinSuperclass()) + // { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; } + String gop = header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; + if (derived) + { return gop; } + return gop + header2; + } + + public String buildGlobalUpdateOpJava7(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, + Vector constraints) + { String preheader = ""; + String javaPars = getJava7ParameterDec(); + String parlist = parameterList(); + + if (ent == null) { return ""; } + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (!instanceScope) + { if (resT == null || resT.equals("void")) + { return " public static void " + opname + "(" + javaPars + ")\n" + + " { " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + return " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + Type allrestype = new Type("Sequence", null); + allrestype.setElementType(resultType); + String alltype = allrestype.getJava7(resultType); + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "Collection<" + ename + "> " + ex + "s"; + } + else + { java2Pars = "Collection<" + ename + "> " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + String retT = resT; + String header2 = header; + if (resT == null || resT.equals("void")) + { header2 = header2 + " ArrayList All" + ename + + opname + "(" + java2Pars + ")\n { "; + retT = "void"; + } + else + { header2 = header2 + " " + alltype + " All" + ename + + opname + "(" + java2Pars + ")\n { "; + } + + header = header + retT + " " + + opname + "(" + javaPars + ")\n { "; + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) + { header2 = header2 + "\n ArrayList result = new ArrayList();\n "; } + else + { header = header + "\n " + resT + " result = " + resultType.getDefaultJava7() + ";\n "; + header2 = header2 + "\n " + alltype + " result = new " + alltype + "();\n "; + returning = " result"; + } // wrapper types needed for primitive. + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " // if (!(" + pre1.queryFormJava7(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + String body = " " + ex + "." + call + ";"; + String endbody = ""; + header2 = header2 + " for (Object _i : " + exs + ")\n" + + " { " + ename + " " + ex + " = (" + ename + ") _i;\n"; + + if (parlist.length() > 0) + { parlist = "," + parlist; } + + String newitem = opname + "(" + ex + parlist + ")"; + + if (resultType != null && Type.isMapType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } + else if (resultType != null && + Type.isCollectionType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } // NOT addAll + else if (resT == null || resT.equals("void")) + { header2 = header2 + " " + newitem + ";\n"; } + else if (resultType.isPrimitive()) + { newitem = Expression.wrap(resultType,newitem); + header2 = header2 + " result.add(" + newitem + ");\n"; + } + else + { header2 = header2 + " result.add(" + newitem + ");\n"; } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + if (resT == null || resT.equals("void")) + { } + else + { body = " result = " + body; + endbody = " return result;"; + } + + for (int i = 0; i < constraints.size(); i++) + { Constraint cc = (Constraint) constraints.get(i); + Constraint ccnew = cc.matchesOp(opname, this); + if (ccnew != null) + { Vector contx = new Vector(); + if (ccnew.getOwner() != null) + { contx.add(ccnew.getOwner()); } + boolean ok = ccnew.typeCheck(types,entities,contx); + if (ok) + { String upd = ccnew.globalUpdateOpJava7(ent,false); + body = body + "\n " + upd; + } + } + } + + // if (isDefinedinSuperclass()) + // { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; } + String gop = header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; + if (derived) + { return gop; } + return gop + header2; + } + + public String buildGlobalUpdateOpCSharp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, + Vector constraints) + { String preheader = ""; + String javaPars = getCSharpParameterDec(); + String parlist = parameterList(); + + if (ent == null) { return ""; } + + String genPars = csharpGenericParameters(ent); + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "sealed "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(ArrayList exs, pars) + String java2Pars = ""; // For All version of op + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + String retT = resT; + if (resT == null) + { retT = "void"; } + + if (!instanceScope) + { if (resT == null || resT.equals("void")) + { return " public static void " + opname + genPars + "(" + javaPars + ")\n" + + " { " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + return " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "ArrayList " + ex + "s"; + } + else + { java2Pars = "ArrayList " + exs + "," + javaPars; + javaPars = ename + genPars + " " + ex + "," + javaPars; + } + + String header2 = header + " ArrayList All" + ename + + opname + "(" + java2Pars + ")\n { "; + + header = header + retT + " " + + opname + "(" + javaPars + ")\n { "; + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resT == null || resT.equals("void")) + { header2 = header2 + "\n ArrayList result = new ArrayList();\n "; } + else + { header = header + "\n " + resT + " result = " + resultType.getDefaultCSharp() + ";\n "; + header2 = header2 + "\n ArrayList result = new ArrayList();\n "; + returning = " result"; + } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " // if (!(" + pre1.queryFormCSharp(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + String body = " " + ex + "." + call + ";"; + String endbody = ""; + header2 = header2 + " for (int _i = 0; _i < " + exs + ".Count; _i++)\n" + + " { " + ename + genPars + " " + ex + " = (" + ename + genPars + ") " + exs + "[_i];\n"; + + if (parlist.length() > 0) + { parlist = "," + parlist; } + + String newitem = opname + "(" + ex + parlist + ")"; + + if (resultType != null && Type.isMapType(resultType)) + { header2 = header2 + " result.Add(" + newitem + ");\n"; } + else if (resultType != null && Type.isCollectionType(resultType)) + { header2 = header2 + " result.AddRange(" + newitem + ");\n"; } + else if (resT == null || resT.equals("void")) + { header2 = header2 + " " + newitem + ";\n"; } + else if (resultType.isPrimitive()) + { // newitem = Expression.wrap(resultType,newitem); + header2 = header2 + " result.Add(" + newitem + ");\n"; + } + else + { header2 = header2 + " result.Add(" + newitem + ");\n"; } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + if (resT == null || resT.equals("void")) + { } + else + { body = " result = " + body; + endbody = " return result;"; + } + + for (int i = 0; i < constraints.size(); i++) + { Constraint cc = (Constraint) constraints.get(i); + Constraint ccnew = cc.matchesOp(opname, this); + if (ccnew != null) + { Vector contx = new Vector(); + if (ccnew.getOwner() != null) + { contx.add(ccnew.getOwner()); } + boolean ok = ccnew.typeCheck(types,entities,contx); + if (ok) + { String upd = ccnew.globalUpdateOpCSharp(ent,false); + body = body + "\n " + upd; + } + } + } + + // if (isDefinedinSuperclass()) + // { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; } + + String gop = header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; + if (derived) + { return gop; } + return gop + header2; + } // if derived, omit the All global one. + + public String buildGlobalUpdateOpCPP(Entity ent, String opname, + Type t, String resT, Vector declarations, + Vector entities, Vector types, + Vector constraints) + { String preheader = ""; + String javaPars = getCPPParameterDec(); + + if (ent == null) { return ""; } + + String gpars = ent.typeParameterTextCPP(); + + String header = " "; + // if (isAbstract()) + // { header = header + "abstract "; } + // if (isFinal()) + // { header = header + "sealed "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(ArrayList exs, pars) + String java2Pars = ""; // For All version of op + String java3Pars = ""; + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (javaPars.equals("")) + { javaPars = ename + gpars + "* " + ex; + java2Pars = "vector<" + ename + gpars + "*>* " + exs; + java3Pars = "std::set<" + ename + gpars + "*>* " + exs; + } + else + { java2Pars = "vector<" + ename + gpars + "*>* " + exs + ", " + javaPars; + javaPars = ename + gpars + "* " + ex + ", " + javaPars; + java3Pars = "std::set<" + ename + gpars + "*>* " + exs + ", " + javaPars; + } + + String et = "void*"; + if (elementType != null) + { et = elementType.getCPP(elementType.getElementType()); } + + String allrest = "vector*"; + if ("void".equals(resultType + "")) + { allrest = "vector*"; } + else if (resultType != null) + { allrest = "vector<" + resT + ">*"; } + + String header2 = header + " " + allrest + " Controller::All" + ename + + opname + "(" + java2Pars + ")\n { "; + String header3 = header + " " + allrest + " Controller::All" + ename + + opname + "(" + java3Pars + ")\n { "; + + if (derived) { } + else + { declarations.add(" " + allrest + " All" + ename + opname + "(" + java2Pars + ");"); + declarations.add(" " + allrest + " All" + ename + opname + "(" + java3Pars + ");"); + } + + String retT = resT; + if (resT == null) + { retT = "void"; } + + header = header + retT + " Controller::" + + opname + "(" + javaPars + ")\n { "; + declarations.add(retT + " " + opname + "(" + javaPars + ");"); + + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + resultatt.setElementType(elementType); + atts.add(resultatt); + + String returning = ""; + if (resultType == null || resT.equals("void")) + { header2 = header2 + "\n vector* result = new vector();\n "; + header3 = header3 + "\n vector* result = new vector();\n "; + } + else + { header = header + "\n " + resT + " result = " + resultType.getDefaultCPP(elementType) + ";\n "; + header2 = header2 + "\n vector<" + resT + ">* result = new vector<" + resT + ">();\n "; + header3 = header3 + "\n vector<" + resT + ">* result = new vector<" + resT + ">();\n "; + returning = " result"; + } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " // if (!(" + pre1.queryFormCPP(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + String body = " " + ex + "->" + call + ";"; + String endbody = ""; + header2 = header2 + " for (int _i = 0; _i < " + exs + "->size(); _i++)\n" + + " { " + ename + gpars + "* " + ex + " = (*" + exs + ")[_i];\n"; + header3 = header3 + " for (std::set<" + ename + gpars + "*>::iterator _i = " + exs + "->begin(); _i != " + exs + "->end(); _i++)\n" + + " { " + ename + gpars + "* " + ex + " = *_i;\n"; + + String parlist = parameterList(); + if (parlist.length() > 0) + { parlist = "," + parlist; } + + String newitem = opname + "(" + ex + parlist + ")"; + + if (resultType != null && Type.isMapType(resultType)) + { header2 = header2 + " result->push_back(" + newitem + ");\n"; + header3 = header3 + " result->push_back(" + newitem + ");\n"; + } + else if (resultType != null && + Type.isCollectionType(resultType)) + { header2 = header2 + " result->insert(result->end(), " + newitem + "->begin(), " + + newitem + "->end());\n"; + header3 = header3 + " result->insert(result->end(), " + newitem + "->begin(), " + + newitem + "->end());\n"; + } + else if (resultType == null || resT.equals("void")) + { header2 = header2 + " " + newitem + ";\n"; + header3 = header3 + " " + newitem + ";\n"; + } + else + { header2 = header2 + " result->push_back(" + newitem + ");\n"; + header3 = header3 + " result->push_back(" + newitem + ");\n"; + } + + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + header3 = header3 + " }\n" + " return result; \n" + " }\n\n"; + + if (resultType == null || resT.equals("void")) + { } + else + { body = " result = " + body; + endbody = " return result;"; + } + + for (int i = 0; i < constraints.size(); i++) + { Constraint cc = (Constraint) constraints.get(i); + Constraint ccnew = cc.matchesOp(opname, this); + if (ccnew != null) + { Vector contx = new Vector(); + if (ccnew.getOwner() != null) + { contx.add(ccnew.getOwner()); } + boolean ok = ccnew.typeCheck(types,entities,contx); + if (ok) + { String upd = ccnew.globalUpdateOpCPP(ent,false); + body = body + "\n " + upd; + } + } + } + + // if (isDefinedinSuperclass()) + // { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; } + if (derived) + { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n"; } + else + { return header + newdecs + preheader + body + "\n " + endbody + " }\n\n" + header2 + header3; } + } + + + public String buildGlobalQueryOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { // if (isDefinedinSuperclass()) + // { return ""; } + if (ent == null) { return ""; } + + String preheader = ""; + String javaPars = getJavaParameterDec(); + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + String parlist = parameterList(); + + if (!instanceScope) + { return ""; // " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + // " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "List " + exs; + } + else + { java2Pars = "List " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + String header2 = header + " List All" + ename + + opname + "(" + java2Pars + ")\n { "; + + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + atts.add(resultatt); + String returning = ""; + String retT = resT; + if (resT == null || resT.equals("void")) + { retT = "void"; } + else + { header = header + "\n " + resT + " result = " + resultType.getDefault() + ";\n "; + header2 = header2 + "\n List result = new Vector();\n "; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " if (!(" + pre1.queryForm(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + header2 = header2 + " for (int _i = 0; _i < " + exs + ".size(); _i++)\n" + + " { " + ename + " " + ex + " = (" + ename + ") " + exs + ".get(_i);\n"; + + // if (parlist.length() > 0) + // { parlist = "," + parlist; } + + String newitem = ex + "." + opname + "(" + parlist + ")"; + + if ("List".equals(resT)) + { header2 = header2 + + " if (" + newitem + " != null)\n" + + " { result.addAll(" + newitem + "); }\n"; + } // NOT addAll + else + { // header2 = header2 + + // " if (" + newitem + " != null) \n"; + if (t != null && t.isPrimitive()) + { newitem = Expression.wrap(resultType,newitem); } + header2 = header2 + + " result.add(" + newitem + ");\n"; + } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + return header2; + } + + public String buildGlobalQueryOpJava6(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { if (derived) + { return ""; } + if (ent == null) { return ""; } + + String preheader = ""; + String javaPars = getJava6ParameterDec(); + String parlist = parameterList(); + + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + + if (!instanceScope) + { return ""; // " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + // " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "Collection " + exs; + } + else + { java2Pars = "Collection " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + + + String header2 = header + " ArrayList All" + ename + + opname + "(" + java2Pars + ")\n { "; + + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + atts.add(resultatt); + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + "\n " + resT + " result = " + resultType.getDefaultJava6() + ";\n "; + header2 = header2 + "\n ArrayList result = new ArrayList();\n "; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " if (!(" + pre1.queryFormJava6(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + header2 = header2 + " for (Object _i : " + exs + ")\n" + + " { " + ename + " " + ex + " = (" + ename + ") _i;\n"; + + // if (parlist.length() > 0) + // { parlist = "," + parlist; } + + String newitem = ex + "." + opname + "(" + parlist + ")"; + + if (resultType != null && + Type.isMapType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } + else if (resultType != null && + Type.isCollectionType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } // NOT addAll + else + { if (t != null && t.isPrimitive()) + { newitem = Expression.wrap(resultType,newitem); } + header2 = header2 + " result.add(" + newitem + ");\n"; + } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + return header2; + } + + public String buildGlobalQueryOpJava7(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { if (derived) + { return ""; } + if (ent == null) { return ""; } + + String preheader = ""; + String javaPars = getJava7ParameterDec(); + String parlist = parameterList(); + + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "final "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + + if (!instanceScope) + { return ""; // " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + // " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "Collection<" + ename + "> " + exs; + } + else + { java2Pars = "Collection<" + ename + "> " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + Type allrestype = new Type("Sequence", null); + allrestype.setElementType(resultType); + String alltype = allrestype.getJava7(resultType); + + String header2 = header; + if (resT == null || resT.equals("void")) + { header2 = header2 + " ArrayList All" + ename + + opname + "(" + java2Pars + ")\n { "; + } // not valid case + else + { header2 = header2 + " " + alltype + " All" + ename + + opname + "(" + java2Pars + ")\n { "; + } + + + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + atts.add(resultatt); + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { header = header + "\n " + resT + " result = " + resultType.getDefaultJava7() + ";\n "; + header2 = header2 + "\n " + alltype + " result = new " + alltype + "();\n "; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " if (!(" + pre1.queryFormJava7(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + header2 = header2 + " for (Object _i : " + exs + ")\n" + + " { " + ename + " " + ex + " = (" + ename + ") _i;\n"; + + // if (parlist.length() > 0) + // { parlist = "," + parlist; } + + String newitem = ex + "." + opname + "(" + parlist + ")"; + + if (resultType != null && + Type.isMapType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } + else if (resultType != null && + Type.isCollectionType(resultType)) + { header2 = header2 + " result.add(" + newitem + ");\n"; } // NOT addAll + else + { if (t != null && t.isPrimitive()) + { newitem = Expression.wrap(resultType,newitem); } + header2 = header2 + " result.add(" + newitem + ");\n"; + } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + return header2; + } + + public String csharpGenericParameters(Entity ent) + { String genPars = ""; + Vector alltypePars = new Vector(); + alltypePars.addAll(ent.getTypeParameters()); + if (typeParameters != null) + { alltypePars.addAll(typeParameters); } + if (alltypePars.size() > 0) + { genPars = "<"; + for (int i = 0; i < alltypePars.size(); i++) + { Type tp = (Type) alltypePars.get(i); + genPars = genPars + tp.getCSharp(); + if (i < alltypePars.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + return genPars; + } + + public String buildGlobalQueryOpCSharp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { // if (isDefinedinSuperclass()) + // { return ""; } + if (ent == null || derived) { return ""; } + + String preheader = ""; + String javaPars = getCSharpParameterDec(); + + String genPars = ""; + Vector alltypePars = new Vector(); + alltypePars.addAll(ent.getTypeParameters()); + if (typeParameters != null) + { alltypePars.addAll(typeParameters); } + if (alltypePars.size() > 0) + { genPars = "<"; + for (int i = 0; i < alltypePars.size(); i++) + { Type tp = (Type) alltypePars.get(i); + genPars = genPars + tp.getCSharp(); + if (i < alltypePars.size() - 1) + { genPars = genPars + ", "; } + } + genPars = genPars + ">"; + } + + String header = " public "; + // if (isAbstract()) + // { header = header + "abstract "; } + if (isFinal()) + { header = header + "sealed "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + String parlist = parameterList(); + + if (!instanceScope) + { return ""; // " public static " + resT + " " + opname + "(" + javaPars + ")\n" + + // " { return " + ename + "." + opname + "(" + parlist + "); }\n\n"; + } + + if (javaPars.equals("")) + { javaPars = ename + " " + ex; + java2Pars = "ArrayList " + exs; + } + else + { java2Pars = "ArrayList " + exs + "," + javaPars; + javaPars = ename + " " + ex + "," + javaPars; + } + + String header2 = header + " ArrayList All" + ename + + opname + "(" + java2Pars + ")\n { "; + + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + atts.add(resultatt); + String returning = ""; + if (resT == null || resT.equals("void")) { } + else + { // header = header + "\n " + resT + " result = " + resultType.getDefaultCSharp() + ";\n "; + header2 = header2 + "\n ArrayList result = new ArrayList();\n "; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " if (!(" + pre1.queryFormCSharp(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + header2 = header2 + " for (int _i = 0; _i < " + exs + ".Count; _i++)\n" + + " { " + ename + genPars + " " + ex + " = (" + ename + genPars + ") " + exs + "[_i];\n"; + + // if (parlist.length() > 0) + // { parlist = "," + parlist; } + + String newitem = ex + "." + opname + "(" + parlist + ")"; + + if (resultType != null && + Type.isMapType(resultType)) + { header2 = header2 + " result.Add(" + newitem + ");\n"; } + else if ("ArrayList".equals(resT)) + { header2 = header2 + " result.AddRange(" + newitem + ");\n"; } + else + { // if (t.isPrimitive()) + // { newitem = Expression.wrap(resultType,newitem); } + header2 = header2 + " result.Add(" + newitem + ");\n"; + } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + + return header2; + } + + public String buildGlobalQueryOpCPP(Entity ent, String opname, + Type t, String resT, Vector declarations, + Vector entities, Vector types) + { if (derived) { return ""; } + if (ent == null) { return ""; } + + // if (isDefinedinSuperclass()) + // { return ""; } + String preheader = ""; + String javaPars = getCPPParameterDec(); + + String header = " "; + // if (isAbstract()) + // { header = header + "abstract "; } + // if (isFinal()) + // { header = header + "sealed "; } + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + String exs = ex + "s"; // For All version of op: op(List exs, pars) + String java2Pars = ""; // For All version of op + String java3Pars = ""; // For All version of op + + if (javaPars.equals("")) + { javaPars = ename + "* " + ex; + java2Pars = "vector<" + ename + "*>* " + exs; + java3Pars = "std::set<" + ename + "*>* " + exs; + } + else + { java2Pars = "vector<" + ename + "*>* " + exs + "," + javaPars; + java3Pars = "std::set<" + ename + "*>* " + exs + "," + javaPars; + javaPars = ename + "* " + ex + "," + javaPars; + } + + String restype = ""; + if (resultType == null || resT.equals("void")) + { restype = "vector"; } + else + { restype = "vector<" + resT + ">"; } + + String et = "void*"; + if (elementType != null) + { et = elementType.getCPP(elementType.getElementType()); } + + String header2 = header + " " + restype + "* Controller::All" + ename + + opname + "(" + java2Pars + ")\n { "; + String header3 = header + " " + restype + "* Controller::All" + ename + + opname + "(" + java3Pars + ")\n { "; + // and add header to the declarations + declarations.add(restype + "* All" + ename + opname + "(" + java2Pars + ");"); + declarations.add(restype + "* All" + ename + opname + "(" + java3Pars + ");"); + + java.util.Map env0 = new java.util.HashMap(); + env0.put(ename,ex); + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + atts.add(resultatt); + + String returning = ""; + if (resultType == null || resT.equals("void")) + { header2 = header2 + "\n vector* result = new vector();\n "; + header3 = header3 + "\n vector* result = new vector();\n "; + } + else + { header2 = header2 + "\n vector<" + resT + ">* result = new vector<" + resT + ">();\n "; + header3 = header3 + "\n vector<" + resT + ">* result = new vector<" + resT + ">();\n "; + returning = " result"; + } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (pre != null) + { Expression pre1 = pre.substituteEq("self",new BasicExpression(ex)); + pre1.typeCheck(types,entities,context,atts); + if ("true".equals("" + pre1)) { } + else + { preheader = " if (!(" + pre1.queryFormCPP(env0,false) + + ")) { return" + returning + "; } \n "; + } + } + + String newdecs = ""; + String call = toString(); + + header2 = header2 + " for (int _i = 0; _i < " + exs + "->size(); _i++)\n" + + " { " + ename + "* " + ex + " = (*" + exs + ")[_i];\n"; + header3 = header3 + " for (std::set<" + ename + "*>::iterator _i = " + exs + "->begin(); _i != " + exs + "->end(); _i++)\n" + + " { " + ename + "* " + ex + " = *_i;\n"; + + String parlist = parameterList(); + // if (parlist.length() > 0) + // { parlist = "," + parlist; } + + String newitem = ex + "->" + opname + "(" + parlist + ")"; + + if (resultType != null) + /* && Type.isCollectionType(resultType)) + { header2 = header2 + " result->insert(result->end(), " + newitem + "->begin(), " + + newitem + "->end());\n"; + header3 = header3 + " result->insert(result->end(), " + newitem + "->begin(), " + + newitem + "->end());\n"; + } + else */ + { header2 = header2 + " result->push_back(" + newitem + ");\n"; + header3 = header3 + " result->push_back(" + newitem + ");\n"; + } + + header2 = header2 + " }\n" + " return result; \n" + " }\n\n"; + header3 = header3 + " }\n" + " return result; \n" + " }\n\n"; + + return header2 + header3; + } + + // Use the statemachine? + public BOp getBOperationCode(Entity ent,Vector entities, Vector types) + { String name = getName(); + String resT = null; + if (post == null) + { return null; } + if (resultType != null) + { resT = resultType.generateB(); } + if (query) + { BOp op = buildBQueryOp(ent,name,resultType,resT,entities,types); + if (op != null) + { op.setSignature(getSignature()); } + return op; + } + else + { BOp op = buildBUpdateOp(ent,name,resultType,resT,entities,types); + if (op != null) + { op.setSignature(getSignature()); } + return op; + } + } // no pre? + + public BOp getGlobalBOperationCode(Entity ent,Vector entities, Vector types, + Vector constraints) + { String name = getName(); + String resT = null; + if (resultType != null) + { resT = resultType.generateB(); } + if (post == null || query || isAbstract()) + { return null; } + else + { return buildGlobalBUpdateOp(ent,name,resultType,resT, + entities,types,constraints); + } + } // ignore return type for update ops for now. + + public BOp buildBQueryOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { String rx = "resultx"; + Expression rxbe = new BasicExpression(rx); + BExpression rxbbe = new BBasicExpression(rx); + boolean norange = false; + + + Scope scope = post.resultScope(); + BinaryExpression rscope = null; + if (scope == null) // no range, must assign result + { System.err.println("ERROR: No scope for result of " + opname); + // ANY resultx WHERE resultx: resultType & Post[resultx/result] + // THEN result := resultx END + // return null; + Expression resTbe = new BasicExpression(resT); + rscope = new BinaryExpression(":",rxbe,resTbe); + norange = true; + // post = new BinaryExpression("&",post,rscope); + } + else + { rscope = scope.resultScope; } + + BExpression returnbe = new BBasicExpression("result"); + java.util.Map env0 = new java.util.HashMap(); + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + BExpression exbe = new BBasicExpression(ex); + if (instanceScope) + { env0.put(ename,exbe); } + String es = ename.toLowerCase() + "s"; + BExpression esbe = new BBasicExpression(es); + + Expression presb = new BasicExpression("true"); + if (pre != null) + { presb = pre.substituteEq("self",new BasicExpression(ex)); } + + BExpression pre0 = getBParameterDec(); + BExpression pre1 = + BBinaryExpression.simplify("&",pre0,presb.binvariantForm(env0,false),true); + BExpression inst = new BBinaryExpression(":",exbe,esbe); + if (instanceScope) + { pre1 = BBinaryExpression.simplify("&",inst,pre1,false); } + // Only for instance scope ops + Vector atts = (Vector) parameters.clone(); + Attribute resultatt = new Attribute("result",t,ModelElement.INTERNAL); + Attribute resultxatt = new Attribute(rx,t,ModelElement.INTERNAL); + resultatt.setEntity(ent); // seems like a good idea + resultxatt.setEntity(ent); + atts.add(resultatt); + atts.add(resultxatt); + + Vector pars = getParameterNames(); + if (instanceScope) + { pars.add(0,ex); } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + if (isInScope(rscope) || isSubScope(rscope) || + (scope != null && scope.scopeKind.equals("array"))) + { Expression newpost = post.substituteEq("result",rxbe); + + newpost.typeCheck(types,entities,context,atts); + BExpression pred = newpost.binvariantForm(env0,false); + if (norange) + { pred = new BBinaryExpression("&", + new BBinaryExpression(":",rxbbe,new BBasicExpression(resT)), + pred); + } + else if (scope != null && scope.scopeKind.equals("array")) + { BasicExpression arr = (BasicExpression) scope.arrayExp.clone(); + arr.arrayIndex = null; + BExpression barr = arr.binvariantForm(env0,false); + pred = new BBinaryExpression("&", + new BBinaryExpression(":",rxbbe,new BUnaryExpression("dom",barr)), + pred); + } + Vector var = new Vector(); + var.add(rx); + BStatement assign = new BAssignStatement(returnbe,rxbbe); + BStatement body = new BAnyStatement(var,pred,assign); + return new BOp(opname,"result",pars,pre1,body); + } + if (isEqScope(rscope)) + { /* Expression returnval = returnValue(rscope); + returnval.typeCheck(types,entities,atts); + BStatement body = + new BAssignStatement(returnbe,returnval.binvariantForm(env0,false)); + body.setWriteFrame("result"); + + if (post instanceof BinaryExpression) + { BinaryExpression postbe = (BinaryExpression) post; + if (postbe.operator.equals("=>")) + { Expression cond = postbe.left; + cond.typeCheck(types,entities,atts); + BStatement code = new BIfStatement(cond.binvariantForm(env0,false),body, + null); + return new BOp(opname,"result",pars,pre1,code); + } + } // if a conjunction, use separateUpdates(statements) + */ + BStatement body = buildBUpdateCode(rscope,env0,types,entities,atts); + return new BOp(opname,"result",pars,pre1,body); + } + return null; // result := (opname_ename(ex))(pars) + } + + private BStatement buildBQueryCases(Expression pst, java.util.Map env, + Vector types, Vector entities, Vector atts) + { Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if (pst instanceof BinaryExpression) + { BinaryExpression bepst = (BinaryExpression) pst; + String op = bepst.operator; + + if (op.equals("=")) + { BExpression returnbe = new BBasicExpression("result"); + Scope scope = bepst.resultScope(); + Expression returnval = returnValue(scope.resultScope); + returnval.typeCheck(types,entities,context,atts); + BStatement body = + new BAssignStatement(returnbe,returnval.binvariantForm(env,false)); + body.setWriteFrame("result"); + return body; + } + if (op.equals("=>")) + { BStatement body = buildBUpdateCode(bepst.right, env, types, entities, atts); + Expression cond = bepst.left; + cond.typeCheck(types,entities,context,atts); + BStatement code = new BIfStatement(cond.binvariantForm(env,false),body, + null); + code.setWriteFrame("result"); + return code; + } + if (op.equals("&")) + { Vector res = new Vector(); + BStatement code1 = buildBQueryCases(bepst.left, env,types,entities,atts); + BStatement code2 = buildBQueryCases(bepst.right, env,types,entities,atts); + if ((code1 instanceof BIfStatement) && (code2 instanceof BIfStatement)) + { BIfStatement if1 = (BIfStatement) code1; + BIfStatement if2 = (BIfStatement) code2; + if1.extendWithCase(if2); + return if1; + } + res.add(code1); + res.add(code2); + return BStatement.separateUpdates(res); + } + } // for or, a choice + return pst.bupdateForm(env,false); + } + + + public BExpression buildBConstantDefinition(Entity ent, + Vector entities, Vector types) + { // (opname_E: es --> (parT --> resT)) & + // !ex.(ex : es => !x.(x: parT & pre => post[opname_E(ex,x)/result])) + + BExpression fdec = getBFunctionDec(); + Expression fcall = new BasicExpression("" + getBCall()); + java.util.Map env0 = new java.util.HashMap(); + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + BExpression exbe = new BBasicExpression(ex); + env0.put(ename,exbe); + String es = ename.toLowerCase() + "s"; + BExpression esbe = new BBasicExpression(es); + + + BExpression pre0 = getBParameterDec(); + BExpression pre1; + if (pre == null) + { pre1 = pre0; } + else + { pre1 = + BBinaryExpression.simplify("&",pre0,pre.binvariantForm(env0,false),true); + } + BExpression inst = new BBinaryExpression(":",exbe,esbe); + pre1 = BBinaryExpression.simplify("&",inst,pre1,false); + // Only for instance scope ops + Vector atts = (Vector) parameters.clone(); + + Vector pars = getParameterNames(); + pars.add(0,ex); + + Expression newpost = post.substituteEq("result",fcall); + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + newpost.typeCheck(types,entities,context,atts); + BExpression pred = newpost.binvariantForm(env0,false); + pred.setBrackets(true); + + BExpression fdef = + new BQuantifierExpression("forall",pars, + new BBinaryExpression("=>",pre1,pred)); + return new BBinaryExpression("&",fdec,fdef); + } + + + private BStatement buildBUpdateCode(Expression rscope, java.util.Map env, + Vector types, Vector entities, Vector atts) + { if (rscope instanceof BinaryExpression) + { return buildBUpdateCode((BinaryExpression) rscope,env,types,entities,atts); } + return null; + } + + private BStatement buildBUpdateCode(BinaryExpression rscope, java.util.Map env, + Vector types, Vector entities, Vector atts) + { String op = rscope.operator; + BExpression returnbe = new BBasicExpression("result"); + + Vector context = new Vector(); + if (entity != null) + { context.add(entity); } + + if (op.equals("=")) + { Expression returnval = returnValue(rscope); + returnval.typeCheck(types,entities,context,atts); + BStatement body = + new BAssignStatement(returnbe,returnval.binvariantForm(env,false)); + body.setWriteFrame("result"); + return body; + } + if (op.equals("=>")) + { BStatement body = buildBUpdateCode(rscope.right, env, types, entities, atts); + Expression cond = rscope.left; + cond.typeCheck(types,entities,context,atts); + BStatement code = new BIfStatement(cond.binvariantForm(env,false),body, + null); + code.setWriteFrame("result"); + return code; + } + if (op.equals("&")) + { Vector res = new Vector(); + BStatement code1 = buildBUpdateCode(rscope.left, env,types,entities,atts); + BStatement code2 = buildBUpdateCode(rscope.right, env,types,entities,atts); + if ((code1 instanceof BIfStatement) && (code2 instanceof BIfStatement)) + { BIfStatement if1 = (BIfStatement) code1; + BIfStatement if2 = (BIfStatement) code2; + if1.extendWithCase(if2); + return if1; + } + // res.add(code1); + // res.add(code2); + // return BStatement.separateUpdates(res); + } // for or, a choice + return null; + } + + + + public BOp buildBUpdateOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types) + { java.util.Map env0 = new java.util.HashMap(); + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + BExpression exbe = new BBasicExpression(ex); + if (instanceScope) + { env0.put(ename,exbe); } + String es = ename.toLowerCase() + "s"; + BExpression esbe = new BBasicExpression(es); + + Vector pars = getParameterNames(); + if (instanceScope) + { pars.add(0,ex); } + + Vector context = new Vector(); + if (ent != null) + { context.add(ent); } + + Expression presb; + if (pre == null) + { presb = new BasicExpression("true"); } + else + { presb = pre.substituteEq("self", new BasicExpression(ex)); } + + BExpression pre0 = getBParameterDec(); + BExpression pre1 = + BBinaryExpression.simplify("&",pre0,presb.binvariantForm(env0,false),true); + + if ("true".equals(post + "")) + { if (activity != null) + { Vector localatts = (Vector) parameters.clone(); + activity.typeCheck(types,entities,context,localatts); + // replace "self" by ex? + BStatement bactivity = activity.bupdateForm(env0,true); + return new BOp(opname,null,pars,pre1,bactivity); + } + } + + // type check pre? + BExpression inst = new BBinaryExpression(":",exbe,esbe); + if (instanceScope) + { pre1 = BBinaryExpression.simplify("&",inst,pre1,false); } + Vector atts = (Vector) parameters.clone(); + post.typeCheck(types,entities,context,atts); + if (stereotypes.contains("explicit")) + { return explicitBUpdateOp(ent,opname,t,resT,entities,types,env0,exbe,esbe,pre1); } + + Vector updates = post.updateVariables(); // take account of ent, + // ie, like updateFeature + // Assume just identifiers 4 now + // check that all update vars are features of ent: + Vector preterms = post.allPreTerms(); + Vector entfeatures = ent.allDefinedFeatures(); // allFeatures? + Vector pres = usedInPreForm(entfeatures,preterms); + updates = VectorUtil.union(updates,pres); + if (updates.size() == 0) + { System.err.println("ERROR: Cannot determine write frame of " + this); + updates = post.allFeatureUses(entfeatures); + System.err.println("ERROR: Assuming write frame is: " + updates); + } + + BExpression dec = null; + BParallelStatement body = new BParallelStatement(); + Vector vars = new Vector(); + + Expression newpost = (Expression) post.clone(); + + for (int i = 0; i < updates.size(); i++) + { BasicExpression var = (BasicExpression) updates.get(i); + if (entfeatures.contains(var.data)) + { BExpression oldbe = new BBasicExpression(var.data); + Type typ = var.getType(); + String new_var = "new_" + var.data; + if (vars.contains(new_var)) { continue; } + vars.add(new_var); + Attribute att = new Attribute(new_var,typ,ModelElement.INTERNAL); + att.setEntity(ent); // ? + + atts.add(att); + String btyp = typ.generateB(var); + // If a set type, should be FIN(elementType.generateB()) + + BExpression varbe = new BBasicExpression(new_var); + BExpression typebe = + new BBinaryExpression("-->",esbe,new BBasicExpression(btyp)); + + BExpression new_dec = new BBinaryExpression(":",varbe,typebe); + Expression newbe = new BasicExpression(new_var); + newbe.entity = var.entity; + newbe.type = var.type; + newbe.elementType = var.elementType; + newbe.umlkind = var.umlkind; + newbe.multiplicity = var.multiplicity; + dec = BBinaryExpression.simplify("&",dec,new_dec,true); + newpost = newpost.substituteEq(var.data,newbe); + // should only substitute for var itself, not var@pre + // and assign var := new_var; + BAssignStatement stat = new BAssignStatement(oldbe,varbe); + body.addStatement(stat); + } + else + { System.err.println("ERROR: " + var.data + " is not a feature of " + ent); } + } + + BExpression pred = newpost.binvariantForm(env0,false); + pred = BBinaryExpression.simplify("&",dec,pred,false); + BStatement code; + if (vars.size() > 0) + { code = new BAnyStatement(vars,pred,body); } + else + { code = body; } // skip + return new BOp(opname,null,pars,pre1,code); + } + + public BOp explicitBUpdateOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types,java.util.Map env0, + BExpression exbe, BExpression esbe, BExpression pre1) + { BStatement stat = post.bOpupdateForm(env0,true); + Vector pars = getParameterNames(); + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + if (instanceScope) + { pars.add(0,ex); } + return new BOp(opname,null,pars,pre1,stat); + } + + public BOp buildGlobalBUpdateOp(Entity ent, String opname, + Type t, String resT, + Vector entities, Vector types, Vector constraints) + { java.util.Map env0 = new java.util.HashMap(); + if (ent == null) + { return null; } + + String ename = ent.getName(); + String ex = ename.toLowerCase() + "x"; + BExpression exbe = new BBasicExpression(ex); + env0.put(ename,exbe); + String es = ename.toLowerCase() + "s"; + BExpression esbe = new BBasicExpression(es); + + Vector context = new Vector(); + context.add(ent); + + // type check pre? + Expression presb; + if (pre == null) + { presb = new BasicExpression("true"); } + else + { presb = pre.substituteEq("self", new BasicExpression(ex)); } + + BExpression pre0 = getBParameterDec(); + BExpression pre1 = + BBinaryExpression.simplify("&",pre0,presb.binvariantForm(env0,false),true); + BExpression inst = new BBinaryExpression(":",exbe,esbe); + pre1 = BBinaryExpression.simplify("&",inst,pre1,false); + Vector atts = (Vector) parameters.clone(); + // are these used? + + Vector pars = getParameterNames(); + pars.add(0,ex); + int count = 0; + + BParallelStatement body = new BParallelStatement(); + + BOperationCall call = new BOperationCall(opname,pars); + body.addStatement(call); + + for (int i = 0; i < constraints.size(); i++) + { Constraint cc = (Constraint) constraints.get(i); + Constraint ccnew = cc.matchesOp(opname,this); + if (ccnew != null) + { boolean ok = ccnew.typeCheck(types,entities,context); + if (ok) + { BStatement upd = ccnew.bupdateOperation(ent,false); + body.addStatement(upd); + count++; + } + } + } // B does not allow 2 ops of same machine to be called in + // parallel! + + if (count == 0) + { return new BOp(opname + "_" + ename,null,pars,pre1,call); } + return new BOp(opname + "_" + ename,null,pars,pre1,body); + // This operation must ensure the preconditions of ops that it calls. + } + + private Vector usedInPreForm(Vector features, Vector preForms) + { Vector res = new Vector(); + for (int i = 0; i < preForms.size(); i++) + { BasicExpression pf = (BasicExpression) preForms.get(i); + if (features.contains(pf.data)) + { BasicExpression var = (BasicExpression) pf.clone(); + var.setPrestate(false); + res.add(var); + } + } + return res; + } + + public Vector operationsUsedIn() + { Vector res = new Vector(); + if (pre == null) { } + else + { res.addAll(pre.allOperationsUsedIn()); } + + if (activity != null) + { res.addAll(activity.allOperationsUsedIn()); + return res; + } + + if (post == null) + { return res; } + + res.addAll(post.allOperationsUsedIn()); + return res; + } + + public int efo() + { Vector clls = operationsUsedIn(); + java.util.Set st = new HashSet(); + for (int i = 0; i < clls.size(); i++) + { st.add(clls.get(i)); } + return st.size(); + } + + public void getCallGraph(Map res) + { Vector bfcalls = operationsUsedIn(); + for (int j = 0; j < bfcalls.size(); j++) + { res.add_pair(name, bfcalls.get(j)); } + } + + public int analyseEFO(Map m) + { // count the number of different targets of calls from the map + java.util.Set calls = new HashSet(); + for (int i = 0; i < m.elements.size(); i++) + { Maplet mm = (Maplet) m.get(i); + calls.add(mm.getTarget() + ""); + } + int res = calls.size(); + + System.out.println("*** Operation " + getName() + " has fan-out = " + res); + return res; + } + + private static boolean isInScope(BinaryExpression be) + { if (be.operator.equals(":")) { return true; } + if (be.operator.equals("&")) + { return isInScope((BinaryExpression) be.left) && + isInScope((BinaryExpression) be.right); + } + // if (be.operator.equals("#") || be.operator.equals("#1")) + // { return isInScope((BinaryExpression) be.right); } + return false; + } + + private static boolean isEqScope(BinaryExpression be) + { if (be.operator.equals("=")) { return true; } + if (be.operator.equals("&")) + { return (be.left instanceof BinaryExpression) && + (be.right instanceof BinaryExpression) && + isEqScope((BinaryExpression) be.left) && + isEqScope((BinaryExpression) be.right); + } + if (be.operator.equals("=>")) + { return (be.right instanceof BinaryExpression) && + isEqScope((BinaryExpression) be.right); + } + // if (be.operator.equals("#") || be.operator.equals("#1")) + // { return isEqScope((BinaryExpression) be.right); } + return false; + } // if => then true if isEqScope right? + + private static boolean isSubScope(BinaryExpression be) + { if (be.operator.equals("<:")) { return true; } + if (be.operator.equals("&")) + { return isSubScope((BinaryExpression) be.left) && + isSubScope((BinaryExpression) be.right); + } + // if (be.operator.equals("#") || be.operator.equals("#1")) + // { return isSubScope((BinaryExpression) be.right); } + return false; + } + + private static Expression returnValue(BinaryExpression be) + { if (be.operator.equals("=") && "result".equals(be.left + "")) // check result is on left + { return be.right; } + else if (be.operator.equals("&")) + { if (be.left instanceof BinaryExpression) + { Expression res = returnValue((BinaryExpression) be.left); + if (res != null) + { return res; } + else if (be.right instanceof BinaryExpression) + { return returnValue((BinaryExpression) be.right); } + else + { return null; } + } + else if (be.right instanceof BinaryExpression) + { return returnValue((BinaryExpression) be.right); } + } + else if (be.operator.equals("=>") && + (be.right instanceof BinaryExpression)) + { return returnValue((BinaryExpression) be.right); } + else if (be.operator.equals("#") || be.operator.equals("#1")) + { return returnValue((BinaryExpression) be.right); } + return null; + } + + private static BExpression getBRange(BinaryExpression be, + java.util.Map env) + { if (be.operator.equals(":") || be.operator.equals("<:")) + { return be.right.binvariantForm(env,false); } + if (be.operator.equals("&")) // take intersection + { BExpression lqf = getBRange((BinaryExpression) be.left, + env); + BExpression rqf = getBRange((BinaryExpression) be.right, + env); + if (("" + lqf).equals("" + rqf)) { return lqf; } + return new BBinaryExpression("/\\",lqf,rqf); + } + return null; + } + + private static String getRange(BinaryExpression be, + java.util.Map env) + { if (be.operator.equals(":") || be.operator.equals("<:")) + { return be.right.queryForm(env,true); } + if (be.operator.equals("&")) // take intersection + { String lqf = getRange((BinaryExpression) be.left, + env); + String rqf = getRange((BinaryExpression) be.right, + env); + + if (lqf == null) { return rqf; } + if (rqf == null) { return lqf; } + if (("" + lqf).equals(rqf)) { return lqf; } + return "Set.intersection(" + lqf + "," + rqf + ")"; + } + return null; + } + + private static String getRangeJava6(BinaryExpression be, + java.util.Map env) + { if (be.operator.equals(":") || be.operator.equals("<:")) + { return be.right.queryFormJava6(env,true); } + if (be.operator.equals("&")) // take intersection + { String lqf = getRangeJava6((BinaryExpression) be.left, + env); + String rqf = getRangeJava6((BinaryExpression) be.right, + env); + + if (lqf == null) { return rqf; } + if (rqf == null) { return lqf; } + if (("" + lqf).equals(rqf)) { return lqf; } + return "Set.intersection(" + lqf + "," + rqf + ")"; + } + return null; + } + + private static String getRangeJava7(BinaryExpression be, + java.util.Map env) + { if (be.operator.equals(":") || be.operator.equals("<:")) + { return be.right.queryFormJava7(env,true); } + if (be.operator.equals("&")) // take intersection + { String lqf = getRangeJava7((BinaryExpression) be.left, + env); + String rqf = getRangeJava7((BinaryExpression) be.right, + env); + + if (lqf == null) { return rqf; } + if (rqf == null) { return lqf; } + if (("" + lqf).equals(rqf)) { return lqf; } + return "Ocl.intersection(" + lqf + "," + rqf + ")"; + } + return null; + } + + private static String getRangeCSharp(BinaryExpression be, + java.util.Map env) + { if (be.operator.equals(":") || be.operator.equals("<:")) + { return be.right.queryFormCSharp(env,true); } + if (be.operator.equals("&")) // take intersection + { String lqf = getRangeCSharp((BinaryExpression) be.left, + env); + String rqf = getRangeCSharp((BinaryExpression) be.right, + env); + + if (lqf == null) { return rqf; } + if (rqf == null) { return lqf; } + if (("" + lqf).equals(rqf)) { return lqf; } + return "SystemTypes.intersection(" + lqf + "," + rqf + ")"; + } + return null; + } + + private static String getRangeCPP(BinaryExpression be, + java.util.Map env) + { if (be.operator.equals(":") || be.operator.equals("<:")) + { return be.right.queryFormCPP(env,true); } + if (be.operator.equals("&")) // take intersection + { String lqf = getRangeCPP((BinaryExpression) be.left, + env); + String rqf = getRangeCPP((BinaryExpression) be.right, + env); + + if (lqf == null) { return rqf; } + if (rqf == null) { return lqf; } + if (("" + lqf).equals(rqf)) { return lqf; } + String lcet = be.left.elementType.getCPP(); + return "UmlRsdsLib<" + lcet + ">::intersection(" + lqf + "," + rqf + ")"; + } + return null; + } + + private static Type getElementType(BinaryExpression be) + { if (be.operator.equals("<:")) + { return be.right.elementType; } + if (be.operator.equals("&")) // take intersection + { return getElementType((BinaryExpression) be.left); } + return null; + } + + public Statement parameterAssignments(Expression call) + { // vars := exprs for corresponding parameters of call + // A parallel assignment. Serialise by storing old + // values of LHS variables before overwriting them. + + if (parameters == null || parameters.size() == 0) + { return null; } + + Vector exprs = call.getParameters(); + if (exprs == null) + { return null; } + + Vector stats = new Vector(); + + Vector previousVars = new Vector(); + Vector declared = new Vector(); // already have var old_v + + for (int i = 0; i < parameters.size(); i++) + { Attribute par = (Attribute) parameters.get(i); + + if (i < exprs.size()) + { BasicExpression parexpr = + new BasicExpression(par); + Expression expr = (Expression) exprs.get(i); + Expression newexpr = expr; + + if (("" + parexpr).equals(expr + "")) { } + else + { + Vector vuses = expr.getVariableUses(); + Vector previousVarOccurs = + VectorUtil.commonElementsByString( + previousVars, vuses); + + if (previousVarOccurs.size() > 0) + { // for each occ : previousVarOccurs, add + // var old_occ if occ not already in declared + // Substitute old_occ for occ in expr + + for (int j = 0; j < previousVarOccurs.size(); j++) + { Attribute occ = + (Attribute) previousVarOccurs.get(j); + String oname = occ.getName(); + + Attribute old_occ = (Attribute) occ.clone(); + old_occ.setName("old_" + oname); + + if (declared.contains(occ)) { } + else + { CreationStatement cs = + new CreationStatement(old_occ,occ); + stats.add(0,cs); + declared.add(occ); + } + + newexpr = newexpr.substituteEq(oname, + new BasicExpression(old_occ)); + } + } + + AssignStatement asgn = + new AssignStatement(parexpr,newexpr); + stats.add(asgn); + + /* JOptionPane.showInputDialog("## Assignment " + asgn + " variable uses " + vuses + " previous " + previousVars + " clash " + previousVarOccurs); */ + } + } + + previousVars.add(par); + } // if expr contains an earlier lhs variable v + // insert a var v_pre : vType := v declaration at start + // and use v_pre in expr instead of v. + + if (stats.size() == 0) + { return null; } + + return new SequenceStatement(stats); + } + + + // Check completeness: if post updates v but not w when w data depends on v + + public void removeUnusedStatements() + { if (activity == null) { return; } + + Statement newact = + Statement.removeUnusedStatements(activity); + activity = newact; + } + + public void unfoldOperationCall(String nme, Statement defn) + { if (activity == null) { return; } + + Statement newact = + Statement.unfoldCall(activity, nme, defn); + activity = newact; + } + + public Statement replaceRecursionByIteration(Statement act) + { // if there are simple calls to itself, replace by + // continue/break in a loop. + + // ... ; self.nme() ; *** + // is while true do (...) + + // ... ; self.nme(exprs) ; *** + // is while true do (... ; pars := exprs) + + // ... ; if E then self.nme() else skip ; *** + // is while true do (... ; if E then continue else + // skip) ; *** + + // ... ; if E then self.nme(exprs) else skip ; *** + // is while true do (... ; + // if E then (pars := exprs ; continue) else + // skip) ; *** + // + + Statement oldact = act; + if (oldact == null) + { oldact = activity; } + if (oldact == null) + { return act; } + + String nme = getName(); + + Statement loopBdy = + Statement.replaceSelfCallsByContinue( + this,nme,oldact); + + WhileStatement ws = new WhileStatement( + new BasicExpression(true), + loopBdy); + + System.out.println(">>> Restructured code: " + ws); + System.out.println(); + + return ws; + } + + public Statement selfCalls2Loops(Statement act) + { // if there are simple calls to itself, replace by + // continue/break in a loop. + + // ... ; self.nme() ; *** + // is while true do (...) + + // ... ; self.nme(exprs) ; *** + // is while true do (... ; pars := exprs) + + // ... ; if E then self.nme() else skip ; *** + // is while true do (... ; if E then continue else + // skip) ; *** + + // ... ; if E then self.nme(exprs) else skip ; *** + // is while true do (... ; + // if E then (pars := exprs ; continue) else + // skip) ; *** + // + + Statement oldact = act; + if (oldact == null) + { oldact = activity; } + if (oldact == null) + { return act; } + + String nme = getName(); + + Vector contexts = new Vector(); + Vector remainders = new Vector(); + + Vector opcalls = Statement.getOperationCallsContexts( + nme,oldact,contexts,remainders); + + // System.out.println(opcalls); + // System.out.println(contexts); + // System.out.println(remainders); + + int selfcalls = 0; + Vector branches = new Vector(); + Vector rems = new Vector(); + Vector assigns = new Vector(); + + for (int i = 0; i < opcalls.size(); i++) + { Statement opcall = + (Statement) opcalls.get(i); + Vector cntx = (Vector) contexts.get(i); + Vector rem = (Vector) remainders.get(i); + Expression expr = null; + if (opcall instanceof InvocationStatement) + { expr = ((InvocationStatement) opcall).getCallExp(); } + else if (opcall instanceof ReturnStatement) + { expr = ((ReturnStatement) opcall).getReturnValue(); } + + // if ((expr + "").startsWith("self." + nme + "(")) + + if (expr != null && expr.isSelfCall(nme)) + { selfcalls++; + branches.add(cntx); + rems.add(rem); + // System.out.println(cntx); + Statement parAssigns = parameterAssignments(expr); + assigns.add(parAssigns); + } + } + + System.out.println(">>> There are " + selfcalls + + " calls of self." + nme + "() in " + + oldact); + System.out.println(">>> Branches to calls: " + branches); + System.out.println(">>> Remainders: " + rems); + System.out.println(">>> Assignments: " + assigns); + + if (selfcalls <= 0) + { return act; } + + if (selfcalls == 1) + { int br = 0; + + // simple case. The call is the last item in + // branches[br]. Either a direct call or conditional. + + SequenceStatement loopBody = new SequenceStatement(); + + Vector branch = (Vector) branches.get(br); + int blen = branch.size(); + for (int i = 0; i < blen - 1; i++) + { Statement sx = (Statement) branch.get(i); + loopBody.addStatement(sx); + } + + Statement callAssigns = (Statement) assigns.get(br); + + + Vector remainder = (Vector) rems.get(br); + Object selfcall = branch.get(blen-1); + + if (selfcall instanceof Statement) + { if (callAssigns != null && + callAssigns instanceof SequenceStatement) + { loopBody.addStatements( + (SequenceStatement) callAssigns); + } + + WhileStatement ws = new WhileStatement( + new BasicExpression(true), + loopBody); + + System.out.println(">A> Restructured code: " + ws); + System.out.println(); + + return ws; + } + else if (selfcall instanceof Vector) + { // conditional cases + Vector selfcallv = (Vector) selfcall; + if (selfcallv.size() == 4 && + "if".equals(selfcallv.get(0) + "")) + { Expression tst = (Expression) selfcallv.get(1); + Vector sts = (Vector) selfcallv.get(2); + Statement cde = + Statement.replaceSelfCallByContinue( + nme,sts,callAssigns); + Statement elsePart = (Statement) selfcallv.get(3); + + Statement newelse = + SequenceStatement.combineSequenceStatements( + elsePart,new BreakStatement()); + ConditionalStatement cs = + new ConditionalStatement(tst, + cde, + newelse); + loopBody.addStatement(cs); + + WhileStatement ws = new WhileStatement( + new BasicExpression(true), + loopBody); + SequenceStatement res = new SequenceStatement(); + res.addStatement(ws); + res.addStatements(remainder); + + System.out.println(">0> Restructured code: " + res); + System.out.println(); + + return res; + } + else if (selfcallv.size() == 4 && + "else".equals(selfcallv.get(0) + "")) + { Expression tst = (Expression) selfcallv.get(1); + Statement ifpart = (Statement) selfcallv.get(2); + + Vector sts = (Vector) selfcallv.get(3); + Statement cde = + Statement.replaceSelfCallByContinue( + nme,sts,callAssigns); + Statement newif = + SequenceStatement.combineSequenceStatements( + ifpart,new BreakStatement()); + ConditionalStatement cs = + new ConditionalStatement(tst, + newif, cde); + loopBody.addStatement(cs); + + WhileStatement ws = new WhileStatement( + new BasicExpression(true), + loopBody); + SequenceStatement res = new SequenceStatement(); + res.addStatement(ws); + res.addStatements(remainder); + + System.out.println(">1> Restructured code: " + res); + System.out.println(); + + return res; + } + } + } + else if (selfcalls == 2) + { int br = 0; + + // if-else case. The calls are last item in + // branches[0] == branches[1]. + // A conditional that is last item of the branch. + + SequenceStatement loopBody = new SequenceStatement(); + + Vector branch = (Vector) branches.get(br); + int blen = branch.size(); + for (int i = 0; i < blen - 1; i++) + { Statement sx = (Statement) branch.get(i); + loopBody.addStatement(sx); + } + + Statement callAssigns1 = (Statement) assigns.get(0); + Statement callAssigns2 = (Statement) assigns.get(1); + + Vector remainder = (Vector) rems.get(br); + Object selfcall = branch.get(blen-1); + // vector representing conditional + + if (selfcall instanceof Vector && + (((Vector) selfcall).get(0) + "").equals("ifelse")) + { // conditional cases + Vector selfcallv = (Vector) selfcall; + if (selfcallv.size() == 4 && + "ifelse".equals(selfcallv.get(0) + "")) + { Expression tst = (Expression) selfcallv.get(1); + Vector sts1 = (Vector) selfcallv.get(2); + Vector sts2 = (Vector) selfcallv.get(3); + Statement cde1 = + Statement.replaceSelfCallByContinue( + nme,sts1,callAssigns1); + Statement cde2 = + Statement.replaceSelfCallByContinue( + nme,sts2,callAssigns2); + + ConditionalStatement cs = + new ConditionalStatement(tst, + cde1, + cde2); + loopBody.addStatement(cs); + + WhileStatement ws = new WhileStatement( + new BasicExpression(true), + loopBody); + SequenceStatement res = new SequenceStatement(); + res.addStatement(ws); + res.addStatements(remainder); + + System.out.println(">2> Restructured code: " + res); + System.out.println(); + + return res; + } + } + else // unrelated branches + { // replace self.nme(exprs) by pars := exprs; continue + + Statement loopBdy = + Statement.replaceSelfCallsByContinue( + this,nme,oldact); + + WhileStatement ws = new WhileStatement( + new BasicExpression(true), + loopBdy); + + System.out.println(">3> Restructured code: " + ws); + System.out.println(); + + return ws; + } + } + + return act; + } + + public void hoistLocalDeclarations() + { // Find all the local declarations. + // Give warnings if + // (i) multiple declarations with same variable name + // (ii) declaration with same name as a parameter + // Apart from case (ii) replace declarations by assigns + // in the code and put all declarations at the start + + if (activity == null) + { return; } + + Vector localdecs = + Statement.getLocalDeclarations(activity); + + Vector initialDecs = new Vector(); + Vector varnames = new Vector(); + + for (int i = 0; i < localdecs.size(); i++) + { CreationStatement cs = (CreationStatement) localdecs.get(i); + String vname = cs.assignsTo; + + ModelElement par = + ModelElement.lookupByName(vname, parameters); + + if (par != null) + { System.err.println("!! Code Smell (MDV): " + vname + " is both a parameter and"); + System.err.println("!! a local variable of operation " + this + "!"); + continue; + } + + if (varnames.contains(vname)) + { System.err.println("!! Code Smell (MDV): multiple declarations in same scope for variable " + vname); + System.err.println("!! of operation " + this + "!"); + continue; + } + + // System.out.println(">>> Local declaration: " + cs); + + varnames.add(vname); + initialDecs.add(cs.defaultVersion()); + } + + if (varnames.size() == 0) + { return; } + + Statement newactivity = + Statement.replaceLocalDeclarations(activity,varnames); + SequenceStatement ss = new SequenceStatement(initialDecs); + ss.addStatement(newactivity); + + // System.out.println(">>> New activity: " + ss); + activity = ss; + } + + public void reduceCodeNesting() + { // Replace each conditional + // if cond then stats1 else stats2 + // by + // if cond then stats1 else skip; stats2 + // where all code paths in stats1 end with a return. + + if (activity == null) + { return; } + + Statement newactivity = + Statement.replaceElseBySequence(activity); + + System.out.println(">>> New activity: " + newactivity); + activity = newactivity; + } +} + + diff --git a/version24/BidirectionalAssociation.class b/version24/BidirectionalAssociation.class new file mode 100644 index 0000000000000000000000000000000000000000..d688fcff090e881fecd090089b0b8afbfff79fcd GIT binary patch literal 1051 zcmZ`%?M@Rx6g^W)w_O&>SCxuYP}Btq6%-X~On_hlse}ZA;g?zHq#3j9lI_%lx6&U% zB8d;+LmAKPF1kU_)M$7>4@Z3xWRc!bAh_oN8dtg|-Cn6of% zqlkJ5Ls&3j(L%$9gBc4?Ei4J-<&s<$7;LR|yWz3&v9+!_Zfi5p zN}n~a)~&79C-1Y@@V%hZ*wc{;I?aEP*#l~Agl#EMZmB@-^iGaswC^4HM4XNcWaMeN zO(B5^H@UCE#xCXbhe&A|HI2kzN9tWK@=hd?uE4lEn{azt`Hcg4tiy;^J6^l}hbA!O zw$?N&JL+i}%UG1zKRadWA_dHjm#pp;SaK80WVH9fUUV$qDN|@|UA0xjEHuaSGfpiU z3j}UocVfM#{I-l7jA7ZrGl!#Eaqt2!1;j@Ougqx-s{#WVF$0Y|7{-W$QH%%-$Fi9g z>CsJ($r->KUfDD9B` z6?K@5U!d~8s|T3o!z=T>=J>I@c*h307Wh)xG-HLQ03}#lx92V)4lj_KKS$p=@}vC> z^<;mJ!UZf6iih*{S|wlYuM#MIgB@e_dL>`07OMR*Ht>~d0=F1Pk!KuZE#p{Wwk@I@ z946A-RsPKx_TMX}IK+f1?xeISk_=kBgu@C4znCj=f`mQE(>EYzkx+w)rf(x| YM04W0+%)m~m`Zs!%FU24Z3OV(Hw6sV%m4rY literal 0 HcmV?d00001 diff --git a/version24/BidirectionalAssociation.java b/version24/BidirectionalAssociation.java new file mode 100644 index 00000000..716d285a --- /dev/null +++ b/version24/BidirectionalAssociation.java @@ -0,0 +1,39 @@ +import java.util.Vector; +import java.io.*; + +/****************************** +* Copyright (c) 2003--2024 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class BidirectionalAssociation extends ModelElement +{ private Association e1e2; + private Association e2e1; + + public BidirectionalAssociation(Entity e1, Entity e2, int c1, int c2, + String r1, String r2) + { super(e1.getName() + "_" + e2.getName()); + e1e2 = new Association(e1,e2,c1,c2,r1,r2); + e2e1 = new Association(e2,e2,c2,c1,r2,r1); + } + + public void generateJava(PrintWriter out) { } + + public Vector getParameters() + { return new Vector(); } + + public void addParameter(Attribute att) + { } + + public Type getType() + { return null; } + + public void setType(Type t) + { } + +} + diff --git a/version24/BinaryExpression.class b/version24/BinaryExpression.class new file mode 100644 index 0000000000000000000000000000000000000000..ae30ce704dc0d29355adde9755a7b539924cd68c GIT binary patch literal 343626 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 z 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 literal 0 HcmV?d00001 diff --git a/version24/BinaryExpression.java b/version24/BinaryExpression.java new file mode 100644 index 00000000..4550c4b1 --- /dev/null +++ b/version24/BinaryExpression.java @@ -0,0 +1,21143 @@ +import java.util.Vector; +import java.io.*; +import javax.swing.JOptionPane; + +/****************************** +* Copyright (c) 2003--2024 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ +// package: OCL + +class BinaryExpression extends Expression +{ // Represents binary expressions: left operator right + + Expression left; + Expression right; + String operator; + Expression objectRef; // just for B + + String iteratorVariable = null; + // for ->exists( x, ->forAll( x, etc + + Attribute accumulator = null; + // let and ->iterate( ) + // secondary variable y in + // col->collect( x; y : T | expr ) + Expression accumulatorRange = null; + // ->select(x; acc : range | expr) + // ->collect(x; acc : range | expr) + + Expression keyValue = null; + // for map operators ->including(key,right), + // ->excluding(key,right) + + + public BinaryExpression(String op, Expression ll, Expression rr) + { operator = op; + + if ("<>".equals(op) || op.equals("!=")) + { operator = "/="; } + else if ("->one".equals(op)) + { operator = "->exists1"; } + // else if ("div".equals(op)) + // { operator = "/"; } + + left = ll; + right = rr; + } // change <> to /=, ->one to ->exists1, etc + + public static BinaryExpression newBinaryExpression(String op, Expression lx, Expression rx) + { if (lx == null || rx == null) + { return null; } + return new BinaryExpression(op,lx,rx); + } + + public static BinaryExpression newBinaryExpression(String op, String lx, String rx) + { if (lx == null || rx == null) + { return null; } + BasicExpression ex1 = new BasicExpression(lx); + BasicExpression ex2 = new BasicExpression(rx); + return new BinaryExpression(op,ex1,ex2); + } + + public static Expression newLetBinaryExpression( + Expression body, + Type typ, Type etyp, + Expression expr) + { // let v : typ = expr in body[v/expr] + String vname = + Identifier.nextIdentifier("factored_expr"); + Attribute accum = + new Attribute(vname, typ, ModelElement.INTERNAL); + accum.setElementType(etyp); + + BasicExpression var = + BasicExpression.newVariableBasicExpression(vname,typ); + + Expression sbody = body.substituteEq(expr + "", var); + sbody.setBrackets(true); + + BinaryExpression res = + new BinaryExpression("let", expr, sbody); + res.setAccumulator(accum); + return res; + } + + public Object clone() + { BinaryExpression res = + new BinaryExpression(operator,(Expression) left.clone(),(Expression) right.clone()); + + res.iteratorVariable = iteratorVariable; + res.accumulator = accumulator; + res.keyValue = keyValue; + res.type = type; + res.elementType = elementType; + res.entity = entity; + res.umlkind = umlkind; + res.multiplicity = multiplicity; + res.modality = modality; + res.needsBracket = needsBracket; + res.formalParameter = formalParameter; + res.refactorELV = refactorELV; + + return res; + } + + /* + public Object clone() + { BinaryExpression be = new BinaryExpression(operator, + (Expression) left.clone(), + (Expression) right.clone()); + if (javaForm != null) + { be.javaForm = (Expression) javaForm.clone(); } + be.modality = modality; // surely? + be.type = type; + be.entity = entity; + be.elementType = elementType; + be.multiplicity = multiplicity; + be.umlkind = umlkind; + be.setBrackets(needsBracket); + return be; + } // is this sufficient? + */ + + public BinaryExpression(Attribute att) + { left = new BasicExpression(att); + right = new BasicExpression(att.getType()); + operator = ":"; + type = new Type("boolean", null); + } + + public BinaryExpression(BasicExpression be) + { // obj.op(par) becomes obj->op(par) + + left = ((BasicExpression) be).getObjectRef(); + right = (Expression) ((Vector) be.getParameters()).get(0); + operator = "->" + be.getData(); + type = be.getType(); + elementType = be.getElementType(); + } + + public void setLeft(Expression le) { left = le; } + + public void setRight(Expression re) { right = re; } + + public void setKeyValue(Expression key) { keyValue = key; } + + public void setOperator(String op) { operator = op; } + + public void setIteratorVariable(String var) + { iteratorVariable = var; } + + public void setVariable(String var) + { iteratorVariable = var; } + + public void setAccumulator(Attribute acc) + { accumulator = acc; } + + public void setAccumulatorRange(Expression rnge) + { accumulatorRange = rnge; } + + public Attribute getAccumulator() + { return accumulator; } + + public Vector getParameters() + { return new Vector(); } + + public Expression getLeft() { return left; } + + public Expression getRight() { return right; } + + public String getOperator() { return operator; } + + public Expression getKeyValue() { return keyValue; } + + public BasicExpression getVariable() + { if (iteratorVariable == null) + { return null; } + BasicExpression res = new BasicExpression(iteratorVariable); + res.umlkind = VARIABLE; + res.setType(elementType); // except for any, when it is type + if ("|A".equals(operator)) + { res.setType(type); } + return res; + } + + public Expression definedness() + { Expression dl = left.definedness(); + Expression dr = right.definedness(); + Expression res = simplify("&",dl,dr,null); + // simplifyAnd(dl,dr); + + if ("/".equals(operator) || + "mod".equals(operator) || "div".equals(operator)) + { Expression zero = new BasicExpression(0); + Expression rexpr = (Expression) right.clone(); + rexpr.setBrackets(true); + Expression neqz = new BinaryExpression("/=",rexpr,zero); + return simplify("&",res,neqz,null); + } + + // and case for ->pow + if ("->pow".equals(operator)) + { Expression zero = new BasicExpression(0); + Expression eqz = new BinaryExpression("=",left,zero); + Expression geqz = new BinaryExpression(">",right,zero); + Expression pex = new BinaryExpression("=>",eqz,geqz); + pex.setBrackets(true); + return simplify("&",res,pex,null); + } // left < 0 => right->oclIsTypeOf("int") + + if ("->at".equals(operator)) + { if ("String".equals(right.getType() + "") || + left.isMap()) + { UnaryExpression kexp = new UnaryExpression("->keys", left); + Expression inkeys = new BinaryExpression(":", right, kexp); + return simplify("&",res,inkeys,null); + } + + UnaryExpression selfsize = new UnaryExpression("->size", left); + Expression lbnd = new BinaryExpression("<=", new BasicExpression(1), right); + Expression ubnd = new BinaryExpression("<=", right, selfsize); + Expression inrange = new BinaryExpression("&",lbnd,ubnd); + return simplify("&",res,inrange,null); + } + + return res; + } + + public Expression determinate() + { if ("or".equals(operator)) + { return new BasicExpression(false); } + + if ("#".equals(operator) || "#LC".equals(operator) || "#1".equals(operator) || "!".equals(operator) || + "|".equals(operator) || "|R".equals(operator) || "|C".equals(operator)) + { Expression leftdet = ((BinaryExpression) left).right.determinate(); + Expression rightdet = right.determinate(); + return (new BinaryExpression("&",leftdet,rightdet)).simplify(); + } + + if ("->exists".equals(operator) || "=".equals(operator) || + "->existsLC".equals(operator) || + "->forAll".equals(operator) || "->exists1".equals(operator) || + "->select".equals(operator) || "->reject".equals(operator) || + "->collect".equals(operator) || + "=>".equals(operator) || + "->closure".equals(operator) || + "->isUnique".equals(operator) || + "->unionAll".equals(operator) || + "->concatenateAll".equals(operator) || + "->intersectAll".equals(operator) || + "->symmetricDifference".equals(operator) || + "->selectMaximals".equals(operator) || + "->sortedBy".equals(operator) || + "->selectMinimals".equals(operator) || + "->at".equals(operator) || + "->iterate".equals(operator) || + "->apply".equals(operator)) + { Expression leftdet = left.determinate(); + Expression rightdet = right.determinate(); + return (new BinaryExpression("&",leftdet,rightdet)).simplify(); + } + + + + /* if (":".equals(operator) || + "/:".equals(operator) || "<:".equals(operator) || + "->includes".equals(operator) || "->excludes".equals(operator) || + "->includesAll".equals(operator) || "->excludesAll".equals(operator) || + "->including".equals(operator) || "->excluding".equals(operator) || + "->count".equals(operator) || "->prepend".equals(operator) || + "->indexOf".equals(operator) || "->hasPrefix".equals(operator) || + "->hasSuffix".equals(operator) || + "->hasMatch".equals(operator) || + "->isMatch".equals(operator) || + "/<:".equals(operator)) + { return new BasicExpression(true); } + // provided left, right have no common features */ + + if ("&".equals(operator) && isCaseExpression()) + { return caseDisjointness(); } + else // if ("&".equals(operator)) + { Expression dand = + new BinaryExpression("&",left.determinate(),right.determinate()); + return dand.simplify(); + } + // union, intersection, etc? + // return new BasicExpression("false",0); + } + + public Expression firstConjunct() + { if ("&".equals(operator)) + { return left.firstConjunct(); } + return this; + } + + public Expression removeFirstConjunct() + { if ("&".equals(operator)) + { Expression lrem = left.removeFirstConjunct(); + return simplify("&",lrem,right,null); + } + return new BasicExpression(true); + } + + public void setPre() + { left.setPre(); + right.setPre(); + if (accumulator != null && + accumulator.getInitialExpression() != null) + { accumulator.getInitialExpression().setPre(); } + } + + public Expression removePrestate() + { Expression dl = left.removePrestate(); + Expression dr = right.removePrestate(); + BinaryExpression res = new BinaryExpression(operator,dl,dr); + res.setType(type); + res.setElementType(elementType); + res.needsBracket = needsBracket; + res.formalParameter = formalParameter; + res.accumulator = accumulator; + res.iteratorVariable = iteratorVariable; + return res; + } + + + + public Expression checkConversions(Type propType, Type propElemType, java.util.Map interp) + { /* if (type != null && type.isEntity()) + { Entity ent = type.getEntity(); + if (ent.hasStereotype("source")) + { Entity tent = (Entity) interp.get(ent + ""); + + System.out.println("INTERPRETATION OF " + ent + " IS= " + tent); + + if (tent == null) // use the expected target type instead + { if (propType != null && propType.isEntity()) + { tent = propType.getEntity(); } + } */ + + Expression leftres = null; + Expression rightres = null; + + if ("boolean".equals(type + "") || "int".equals(type + "") || "long".equals(type + "") || + "double".equals(type + "") || "String".equals(type + "")) + { return this; } + + if (operator.equals("->exists") || operator.equals("->forAll") || + "->existsLC".equals(operator) || "#LC".equals(operator) || + operator.equals("#") || operator.equals("!") || operator.equals("->exists1") || + operator.equals("#1") || operator.equals("and") || operator.equals("or")) + { return this; } // intended as a boolean value + + if (operator.equals("->select") || operator.equals("->reject") || operator.equals("->collect") || + operator.equals("|") || operator.equals("|R") || operator.equals("|C")) + { if (elementType != null && elementType.isEntity()) + { Entity ent = elementType.getEntity(); + if (ent.hasStereotype("source")) + { Entity tent = (Entity) interp.get(ent + ""); + if (tent == null) + { if (propElemType != null && propElemType.isEntity()) + { tent = propElemType.getEntity(); } + else + { return this; } // no interpretation + } + BasicExpression res = new BasicExpression(tent + ""); + res.setType(type); + res.setMultiplicity(multiplicity); + res.setElementType(new Type(tent)); + res.setUmlKind(Expression.CLASSID); + BinaryExpression ind = + new BinaryExpression("->collect",this,new BasicExpression("$id")); + ind.setType(type); + ind.setElementType(new Type("String",null)); + res.setArrayIndex(ind); + return res; + } + } + } + + if (operator.equals("^") || + "->concatenate".equals(operator) + || operator.equals("\\/") || + operator.equals("->at") || operator.equals("->apply") || + operator.equals("/\\") || operator.equals("->union") || + operator.equals("->intersection") || + operator.equals("->symmetricDifference")) + { leftres = left.checkConversions(propType, propElemType, interp); + rightres = right.checkConversions(propType, propElemType, interp); + return new BinaryExpression(operator,leftres,rightres); + } + else if (operator.equals("->append") || + operator.equals("->including") || + operator.equals("->prepend") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst")) + { leftres = left.checkConversions(propType, propElemType, interp); + rightres = right.checkConversions(propElemType, propElemType, interp); + return new BinaryExpression(operator,leftres,rightres); + } + // if ->append, ->prepend, ->including expect a single elem + + if (elementType != null && elementType.isEntity()) + { Entity ent = elementType.getEntity(); + if (ent.hasStereotype("source")) + { Entity tent = (Entity) interp.get(ent + ""); + if (tent == null) + { if (propElemType != null && propElemType.isEntity()) + { tent = propElemType.getEntity(); } + else + { return this; } // no interpretation + } + BasicExpression res = new BasicExpression(tent + ""); + res.setType(type); + res.setMultiplicity(multiplicity); + res.setElementType(new Type(tent)); + res.setUmlKind(Expression.CLASSID); + BinaryExpression ind = + new BinaryExpression("->collect",this,new BasicExpression("$id")); + ind.setType(type); + ind.setElementType(new Type("String",null)); + res.setArrayIndex(ind); + return res; + } + } + return this; + } + + public Expression replaceModuleReferences(UseCase uc) + { Expression rr = right.replaceModuleReferences(uc); + Expression ll = left.replaceModuleReferences(uc); + Expression res = new BinaryExpression(operator,ll,rr); + res.setType(type); + res.setElementType(elementType); + res.umlkind = umlkind; + res.formalParameter = formalParameter; + return res; + } + + private boolean isForallExists() + { if (operator.equals("!") && (right instanceof BinaryExpression)) + { BinaryExpression br = (BinaryExpression) right; + if (br.operator.equals("#") || "#LC".equals(br.operator) || br.operator.equals("#1")) + { if (br.right instanceof BinaryExpression) + { return true; } + } + } + return false; + } + + private boolean isCaseExpression() + { boolean res = "&".equals(operator); + BinaryExpression beleft; + BinaryExpression beright; + if (res && left instanceof BinaryExpression && + right instanceof BinaryExpression) + { beleft = (BinaryExpression) left; + beright = (BinaryExpression) right; + } + else + { return false; } + + if ("=>".equals(beleft.operator) && "=>".equals(beright.operator)) + { return res; } + if ("=>".equals(beleft.operator) && beright.isCaseExpression()) + { return res; } + if ("=>".equals(beright.operator) && beleft.isCaseExpression()) + { return res; } + return false; + } + + private Vector caseConditions() + { Vector res = new Vector(); + BinaryExpression beleft; + BinaryExpression beright; + if (left instanceof BinaryExpression && + right instanceof BinaryExpression) + { beleft = (BinaryExpression) left; + beright = (BinaryExpression) right; + } + else + { return res; } + + if ("=>".equals(beleft.operator) && "=>".equals(beright.operator)) + { res.add(beleft.left); + res.add(beright.left); + return res; + } + if ("=>".equals(beleft.operator) && beright.isCaseExpression()) + { res.add(beleft.left); + res.addAll(beright.caseConditions()); + return res; + } + if ("=>".equals(beright.operator) && beleft.isCaseExpression()) + { res.addAll(beleft.caseConditions()); + res.add(beright.left); + return res; + } + return res; + } + + private Vector cases(Vector caselist) + { Vector res = new Vector(); + BinaryExpression beleft; + BinaryExpression beright; + if (left instanceof BinaryExpression && + right instanceof BinaryExpression) + { beleft = (BinaryExpression) left; + beright = (BinaryExpression) right; + } + else + { return res; } + + if ("=>".equals(beleft.operator) && "=>".equals(beright.operator)) + { res.add(beleft.left); + res.add(beright.left); + caselist.add(beleft); + caselist.add(beright); + return res; + } + if ("=>".equals(beleft.operator) && beright.isCaseExpression()) + { res.add(beleft.left); + caselist.add(beleft); + res.addAll(beright.cases(caselist)); + return res; + } + if ("=>".equals(beright.operator) && beleft.isCaseExpression()) + { res.addAll(beleft.cases(caselist)); + res.add(beright.left); + caselist.add(beright); + return res; + } + return res; + } + + private Expression caseDisjointness() + { Vector cases = caseConditions(); + Expression res = new BasicExpression(true); + for (int i = 0; i < cases.size(); i++) + { Expression e1 = (Expression) cases.get(i); + for (int j = i + 1; j < cases.size(); j++) + { Expression e2 = (Expression) cases.get(j); + Expression neg = e2.computeNegation4succ(); + Expression next = new BinaryExpression("=>",e1,neg); + next.setBrackets(true); + res = simplify("&",res,next,null); + } + } + return res; + } + + private Expression caseCompleteness(Entity ent) + { Vector caselist = new Vector(); + Vector caseconds = cases(caselist); + Expression res = new BasicExpression(true); + for (int i = 0; i < caselist.size(); i++) + { BinaryExpression cse = (BinaryExpression) caselist.get(i); + Expression e1 = (Expression) caseconds.get(i); + Expression ce = cse.completeness(ent); + Expression next = new BinaryExpression("=>",e1,ce); + next.setBrackets(true); + res = simplify("&",res,next,null); + } + return res; + } // and disjunction of guards is true + + + public Expression completeness(Entity ent) + { Expression res = new BasicExpression(true); + if (operator.equals("or")) + { Expression cleft = left.completeness(ent); + Expression cright = right.completeness(ent); + res = simplify("&",cleft,cright,null); + return res; + } + if (operator.equals("&") && isCaseExpression()) + { return caseCompleteness(ent); } // /\i Ei => completeness(casei) + else + { Vector v = updateFeatures(); + Vector feats = ent.allDefinedFeatures(); + if (v.containsAll(feats)) // complete + { // System.out.println("Expression: " + this + " complete."); + return res; + } + else + { System.out.println("! Expression: " + this + + " may be incomplete: updates " + v + + ", but not all defined features: " + feats); + return new BasicExpression(false); + } + } + } + + public Expression addPreForms(String v) + { Expression l1 = left.addPreForms(v); + Expression r1 = right.addPreForms(v); + Expression res = new BinaryExpression(operator,l1,r1); + res.needsBracket = needsBracket; + res.formalParameter = formalParameter; + return res; + } + + public Vector updateFeatures() + { Vector uv = updateVariables(); + Vector res = new Vector(); + for (int i = 0; i < uv.size(); i++) + { Expression e = (Expression) uv.get(i); + if (e instanceof BasicExpression) + { res.add(((BasicExpression) e).data); } + } + return res; + } + + public String toZ3() + { String res = ""; + String op = operator; + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + + String leftz3 = left.toZ3(); + String rightz3 = right.toZ3(); + String memberEnt = ""; + + Type membt = right.elementType; + if (membt != null) + { Entity e = membt.getEntity(); + memberEnt = e + ""; + } + + if (operator.equals("!")) // Should be no # or #1 remaining + { res = "(forall ((" + ((BinaryExpression) left).left + " " + + ((BinaryExpression) left).right + ")) " + rightz3 + ")"; + return res; + } + + if (operator.equals("&")) + { return "(and " + leftz3 + " " + rightz3 + ")"; } + + if (operator.equals("->at") || operator.equals("->apply")) + { return "(" + leftz3 + " " + rightz3 + ")"; } + + if (operator.equals(":")) + { return "(member" + memberEnt + " " + leftz3 + " " + rightz3 + ")"; } + + if (operator.equals("/:")) + { return "(not (member" + memberEnt + " " + leftz3 + " " + rightz3 + "))"; } + + if (operator.equals("->includes")) + { return "(member" + memberEnt + " " + rightz3 + " " + leftz3 + ")"; } + + if (operator.equals("->excludes")) + { return "(not (member" + memberEnt + " " + rightz3 + " " + leftz3 + "))"; } + + if (operator.equals("->including") || operator.equals("->prepend")) + { return "(insert " + rightz3 + " " + leftz3 + ")"; } + + return "(" + op + " " + leftz3 + " " + rightz3 + ")"; + } + + + public String toOcl(java.util.Map env, boolean local) + { String re = right.toOcl(env,local); + + if ("#LC".equals(operator) || operator.equals("#")) + { String lle = ((BinaryExpression) left).left.toOcl(env,local); + String lri = ((BinaryExpression) left).right.toOcl(env,local); + return lri + "->exists(" + lle + " | " + re + ")"; + } + + if (operator.equals("#1")) + { String lle = ((BinaryExpression) left).left.toOcl(env,local); + String lri = ((BinaryExpression) left).right.toOcl(env,local); + return lri + "->one(" + lle + " | " + re + ")"; + } + + if (operator.equals("!")) + { String lle = ((BinaryExpression) left).left.toOcl(env,local); + String lri = ((BinaryExpression) left).right.toOcl(env,local); + return lri + "->forAll(" + lle + " | " + re + ")"; + } + + if (operator.equals("|")) + { String lle = ((BinaryExpression) left).left.toOcl(env,local); + String lri = ((BinaryExpression) left).right.toOcl(env,local); + return lri + "->select(" + lle + " | " + re + ")"; + } + + if (operator.equals("|R")) + { String lle = ((BinaryExpression) left).left.toOcl(env,local); + String lri = ((BinaryExpression) left).right.toOcl(env,local); + return lri + "->reject(" + lle + " | " + re + ")"; + } + + if (operator.equals("|C")) + { String lle = ((BinaryExpression) left).left.toOcl(env,local); + String lri = ((BinaryExpression) left).right.toOcl(env,local); + return lri + "->collect(" + lle + " | " + re + ")"; + } + + String le = left.toOcl(env,local); + if (operator.equals("=>")) + { return le + " implies " + re; } + if (operator.equals("&")) + { return le + " and " + re; } + if (operator.equals(":")) + { return re + "->includes(" + le + ")"; } + if (operator.equals("/:")) + { return re + "->excludes(" + le + ")"; } + if (operator.equals("<:")) + { return re + "->includesAll(" + le + ")"; } + if (operator.equals("/<:")) + { return "not(" + re + "->includesAll(" + le + "))"; } + if (operator.equals("\\/") || operator.equals("^") || + "->concatenate".equals(operator)) + { return le + "->union(" + re + ")"; } + if (operator.equals("/\\")) + { return le + "->intersection(" + re + ")"; } + + if (operator.equals("->including") && keyValue != null) + { return le + "->including(" + keyValue.toOcl(env,local) + ", " + re + ")"; } + if (operator.equals("->excluding") && keyValue != null) + { return le + "->excluding(" + keyValue.toOcl(env,local) + ", " + re + ")"; } + + + if (operator.startsWith("->")) + { return le + operator + "(" + re + ")"; } // always brackets on re + + return le + " " + operator + " " + re; + } // - on collections is excludesAll in OCL? Plus set < elem, etc + + // saveTextModel + public String saveModelData(PrintWriter out) + { String id = + Identifier.nextIdentifier("binaryexpression_"); + out.println(id + " : BinaryExpression"); + out.println(id + ".expId = \"" + id + "\""); + + String op = operator; + Expression lft = left; + + if (operator.equals("->iterate")) + { op = "->iterate"; + out.println(id + ".variable = \"" + iteratorVariable + "\""); + if (accumulator != null) + { String accid = accumulator.saveModelData(out); + out.println(id + ".accumulator = " + accid); + } + } + else if (operator.equals("#")) + { op = "->exists"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if ("#LC".equals(operator)) + { op = "->existsLC"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("!")) + { op = "->forAll"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("#1")) + { op = "->exists1"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|")) + { op = "->select"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|R")) + { op = "->reject"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|C")) + { op = "->collect"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|unionAll")) + { op = "->unionAll"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|intersectAll")) + { op = "->intersectAll"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|concatenateAll")) + { op = "->concatenateAll"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|selectMaximals")) + { op = "->selectMaximals"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|selectMinimals")) + { op = "->selectMinimals"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("|sortedBy")) + { op = "->sortedBy"; + lft = ((BinaryExpression) left).right; + out.println(id + ".variable = \"" + ((BinaryExpression) left).left + "\""); + } + else if (operator.equals("let")) + { op = "let"; + String var = accumulator.getName(); + out.println(id + ".variable = \"" + var + "\""); + Type vtype = accumulator.getType(); + if (vtype != null) + { String vtypeid = vtype.getUMLModelName(out); + out.println(id + ".variableType = " + vtypeid); + } + } + else if (operator.equals("->exists") || + operator.equals("->exists1") || + "->existsLC".equals(operator) || + operator.equals("->forAll") || + operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->collect")) + { out.println(id + ".variable = \"self\""); } + // Cannot use self, because it is a keyword in Python, etc. + + if (operator.equals("->including") && keyValue != null) + { String varid = keyValue.saveModelData(out); + out.println(id + ".variable = " + varid); + } + else if (operator.equals("->excluding") && keyValue != null) + { String varid = keyValue.saveModelData(out); + out.println(id + ".variable = " + varid); + } + + out.println(id + ".operator = \"" + op + "\""); + String leftid = lft.saveModelData(out); + String rightid = right.saveModelData(out); + + out.println(id + ".left = " + leftid); + out.println(id + ".right = " + rightid); + + String tname = "void"; + if (type != null) + { tname = type.getUMLModelName(out); } + out.println(id + ".type = " + tname); + + + if (elementType != null) + { String etname = elementType.getUMLModelName(out); + out.println(id + ".elementType = " + etname); + } + else if (type != null && + type.getElementType() != null) + { String etname = + type.getElementType().getUMLModelName(out); + out.println(id + ".elementType = " + etname); + } + else if (type != null && + Type.isBasicType(type)) + { out.println(id + ".elementType = " + tname); } + else + { out.println(id + ".elementType = " + tname); } + + out.println(id + ".needsBracket = " + needsBracket); + out.println(id + ".umlKind = " + umlkind); + // out.println(id + ".prestate = " + prestate); + + return id; + } + + public boolean containsSubexpression(Expression expr) + { if (operator.equals("->iterate")) + { if (accumulator != null && + accumulator.containsSubexpression(expr)) + { return true; } + } + + if (operator.equals("#") || "#LC".equals(operator) || + operator.equals("!") || operator.equals("#1") || + operator.equals("|") || operator.equals("|R") || + operator.equals("|C") || operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|selectMaximals") || + operator.equals("|selectMinimals") || + operator.equals("|sortedBy")) + { Expression lft = ((BinaryExpression) left).right; + if (lft.containsSubexpression(expr)) + { return true; } + } + else + { if (left.containsSubexpression(expr)) + { return true; } + } + + if (right.containsSubexpression(expr)) + { return true; } + + return (this + "").equals(expr + ""); + } + + public Vector mutantOperators(String op) + { Vector res = new Vector(); + if (":".equals(op)) + { res.add("/:"); } + else if ("/:".equals(op)) + { res.add(":"); } + else if ("<".equals(op)) + { res.add("<="); } + else if (">".equals(op)) + { res.add(">="); } + else if ("/=".equals(op)) + { res.add("="); } + else if ("<>=".equals(op)) // && left.isNotLocalVariable()) + { res.add("/="); } + else if ("->union".equals(op)) + { res.add("->intersection"); } + else if ("->intersection".equals(op)) + { res.add("->union"); } + else if ("->unionAll".equals(op)) + { res.add("->intersectAll"); } + else if ("->intersectAll".equals(op)) + { res.add("->unionAll"); } + else if ("->append".equals(op)) + { res.add("->prepend"); } + else if ("->prepend".equals(op)) + { res.add("->append"); } + else if ("->including".equals(op)) + { res.add("->excluding"); } + else if ("->excluding".equals(op)) + { res.add("->including"); } + else if ("->includes".equals(op)) + { res.add("->excludes"); } + else if ("->excludes".equals(op)) + { res.add("->includes"); } + else if ("->select".equals(op)) + { res.add("->reject"); } + else if ("->reject".equals(op)) + { res.add("->select"); } + else if ("->selectMinimals".equals(op)) + { res.add("->selectMaximals"); } + else if ("->selectMaximals".equals(op)) + { res.add("->selectMinimals"); } + else if ("|".equals(op)) + { res.add("|R"); } + else if ("|R".equals(op)) + { res.add("|"); } + else if ("|unionAll".equals(op)) + { res.add("|intersectAll"); } + else if ("|intersectAll".equals(op)) + { res.add("|unionAll"); } + else if ("->exists".equals(op)) + { res.add("->forAll"); } + else if ("->forAll".equals(op) || "->exists1".equals(op)) + { res.add("->exists"); } + else if ("!".equals(op) || "#1".equals(op)) + { res.add("#"); } + else if ("->before".equals(op)) + { res.add("->after"); } + else if ("->after".equals(op)) + { res.add("->before"); } + else if ("->hasPrefix".equals(op)) + { res.add("->hasSuffix"); } + else if ("->hasSuffix".equals(op)) + { res.add("->hasPrefix"); } + else if ("->restrict".equals(op)) + { res.add("->antirestrict"); } + else if ("->antirestrict".equals(op)) + { res.add("->restrict"); } + else if ("/".equals(op)) + { res.add("*"); } + else if ("mod".equals(op)) + { res.add("div"); } + else if ("div".equals(op)) + { res.add("mod"); } + else if (left.isNumeric() && right.isNumeric() && op.equals("+")) + { res.add("-"); + res.add("*"); + } + else if (left.isNumeric() && right.isNumeric() && op.equals("-")) + { res.add("+"); } + + res.add(op); + return res; + } // ->compareTo: swap left & right. + + public Vector mutants() + { Vector lms = left.mutants(); + Vector rms = right.mutants(); + Vector res = new Vector(); + + if ("->compareTo".equals(operator)) + { for (int i = 0; i < lms.size(); i++) + { Expression lm = (Expression) lms.get(i); + for (int j = 0; j < rms.size(); j++) + { Expression rm = (Expression) rms.get(j); + BinaryExpression mutant = + (BinaryExpression) this.clone(); + mutant.operator = "->compareTo"; + mutant.left = rm; + mutant.right = lm; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + } + System.out.println(">>> All mutants of " + this + " are: " + res); + return res; + } + + Vector mutantOps = mutantOperators(operator); + + for (int i = 0; i < lms.size(); i++) + { Expression lm = (Expression) lms.get(i); + for (int j = 0; j < rms.size(); j++) + { Expression rm = (Expression) rms.get(j); + for (int k = 0; k < mutantOps.size(); k++) + { String mop = (String) mutantOps.get(k); + BinaryExpression mutant = (BinaryExpression) this.clone(); + mutant.operator = mop; + mutant.left = lm; + mutant.right = rm; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + } + } + System.out.println(">>> All mutants of " + this + " are: " + res); + return res; + } + + public Vector singleMutants() + { Vector rms = right.singleMutants(); + Vector mutantOps = mutantOperators(operator); + if ("result".equals(left + "") && "=".equals(operator)) + { mutantOps = new Vector(); } + Vector res = new Vector(); + + if ("#".equals(operator) || "!".equals(operator) || + "#1".equals(operator) || "|C".equals(operator) || + "|".equals(operator) || "|R".equals(operator) || + "|A".equals(operator) || "#LC".equals(operator) || + "|intersectAll".equals(operator) || + "|unionAll".equals(operator) || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator) || + "|concatenateAll".equals(operator) || + "|sortedBy".equals(operator)) + { BinaryExpression dom = (BinaryExpression) left; + Expression var = dom.left; + Expression lhs = dom.right; + + Vector leftmuts = lhs.singleMutants(); + + for (int i = 0; i < leftmuts.size(); i++) + { Expression lm = (Expression) leftmuts.get(i); + BinaryExpression mutant = + (BinaryExpression) this.clone(); + mutant.operator = operator; + mutant.left = new BinaryExpression(":", var, lm); + mutant.right = right; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + for (int i = 0; i < rms.size(); i++) + { Expression rm = (Expression) rms.get(i); + BinaryExpression mutant = + (BinaryExpression) this.clone(); + mutant.operator = operator; + mutant.left = left; + mutant.right = rm; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + if (mutantOps.size() > 0) + { String mutop = (String) mutantOps.get(0); + BinaryExpression mut = (BinaryExpression) this.clone(); + mut.left = left; + mut.right = right; + mut.operator = mutop; + if (VectorUtil.containsEqualString(mut + "",res)) { } + else + { res.add(mut); } + } + + Vector selfs = new Vector(); + selfs.add(this); + res.removeAll(selfs); + + return res; + } + + + Vector lms = left.singleMutants(); + + + if ("->compareTo".equals(operator)) + { for (int i = 0; i < lms.size(); i++) + { Expression lm = (Expression) lms.get(i); + BinaryExpression mutant = + (BinaryExpression) this.clone(); + mutant.operator = "->compareTo"; + mutant.left = lm; + mutant.right = right; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + for (int i = 0; i < rms.size(); i++) + { Expression rm = (Expression) rms.get(i); + BinaryExpression mutant = + (BinaryExpression) this.clone(); + mutant.operator = "->compareTo"; + mutant.left = left; + mutant.right = rm; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + BinaryExpression mut = (BinaryExpression) this.clone(); + mut.left = right; + mut.right = left; + if (VectorUtil.containsEqualString(mut + "",res)) { } + else + { res.add(mut); } + + Vector selfs = new Vector(); + selfs.add(this); + res.removeAll(selfs); + + System.out.println(">>> All single mutants of " + this + " are: " + res); + return res; + } + + for (int i = 0; i < lms.size(); i++) + { Expression lm = (Expression) lms.get(i); + BinaryExpression mutant = (BinaryExpression) this.clone(); + mutant.operator = operator; + mutant.left = lm; + mutant.right = right; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + for (int j = 0; j < rms.size(); j++) + { Expression rm = (Expression) rms.get(j); + BinaryExpression mutant = (BinaryExpression) this.clone(); + mutant.operator = operator; + mutant.left = left; + mutant.right = rm; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + for (int k = 0; k < mutantOps.size(); k++) + { String mop = (String) mutantOps.get(k); + BinaryExpression mutant = (BinaryExpression) this.clone(); + mutant.operator = mop; + mutant.left = left; + mutant.right = right; + if (VectorUtil.containsEqualString(mutant + "",res)) { } + else + { res.add(mutant); } + } + + Vector selfs = new Vector(); + selfs.add(this); + res.removeAll(selfs); + + System.out.println(">>> Single mutants of " + this + " are: " + res); + return res; + } + + public String toString() + { String basicString = + left + " " + operator + " " + right; + + if ("let".equals(operator) && + accumulator != null) + { String rstring = "" + right; + if (right.needsBracket) { } + else + { rstring = "(" + rstring + ")"; } + String res = "let " + accumulator.getName() + " : " + accumulator.getType() + " = " + left + " in " + rstring; + if (needsBracket) + { return "(" + res + ")"; } + return res; + } + + if ("->iterate".equals(operator) && + iteratorVariable != null && accumulator != null) + { String rangestring = "" + left; + if (left.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + String res = rangestring + "->iterate(" + + iteratorVariable + "; " + + accumulator.getName() + " = " + + accumulator.getInitialExpression() + + " | " + right + ")"; + return res; + } + + if (operator.equals("#") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->exists( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if ("#LC".equals(operator) && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->existsLC( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("#1") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + basicString = rangestring + "->exists1( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("!") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + basicString = rangestring + "->forAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->select( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|C") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->collect( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|A") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->any( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|R") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->reject( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|selectMinimals") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->selectMinimals( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|selectMaximals") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->selectMaximals( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|unionAll") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->unionAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|intersectAll") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->intersectAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|concatenateAll") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->concatenateAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|sortedBy") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->sortedBy( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|isUnique") && left instanceof BinaryExpression) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->isUnique( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("->including") && keyValue != null) + { basicString = left + "->including(" + keyValue + ", " + right + ")"; } + else if (operator.equals("->excluding") && keyValue != null) + { basicString = left + "->excluding(" + keyValue + ", " + right + ")"; } + else if (operator.equals("->includesAll") || + operator.equals("->collect") || + operator.equals("->excludesAll") || + operator.equals("->append") || + operator.equals("->prepend") || + operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->including") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("->pow") || + operator.equals("->roundTo") || + operator.equals("->truncateTo") || + operator.equals("->sortedBy") || + operator.equals("->hasSuffix") || + operator.equals("->hasPrefix") || + "->isUnique".equals(operator) || + operator.equals("->oclAsType") || + "->forAll".equals(operator) || + "->exists".equals(operator) || + "->exists1".equals(operator) || + "->existsLC".equals(operator) || + "->any".equals(operator) || + operator.equals("->selectMaximals") || + operator.equals("->oclIsKindOf") || + operator.equals("->oclIsTypeOf") || + operator.equals("->includesKey") || + operator.equals("->excludesKey") || + operator.equals("->includesValue") || + operator.equals("->excludesValue") || + operator.equals("->restrict") || + operator.equals("->antirestrict") || + operator.equals("->selectMinimals") || + operator.equals("->union") || + operator.equals("->resizeTo") || + operator.equals("->sequenceRange") || + operator.equals("->intersectAll") || + operator.equals("->unionAll") || + operator.equals("->count") || + operator.equals("->indexOf") || + operator.equals("->lastIndexOf") || + operator.equals("->equalsIgnoreCase") || + operator.equals("->before") || + operator.equals("->after") || + operator.equals("->hasMatch") || + operator.equals("->isMatch") || + operator.equals("->split") || + operator.equals("->allMatches") || + operator.equals("->firstMatch") || + operator.equals("->at") || + operator.equals("->apply") || + operator.equals("->closure") || + operator.equals("->intersection") || + operator.equals("->symmetricDifference")) + { basicString = left + operator + "(" + right + ")"; } + + if (operator.startsWith("->")) + { basicString = left + operator + "(" + right + ")"; } + + if (needsBracket) + { return "( " + basicString + " )"; } + // eg, for or inside & + + return basicString; + } + + public String toAST() + { String leftast = left.toAST(); + String rightast = right.toAST(); + String basicString = + "(OclBinaryExpression " + leftast + " " + operator + " " + rightast + ")"; + + if ("let".equals(operator) && accumulator != null) + { String res = "(OclBinaryExpression let " + accumulator.getName() + " : " + accumulator.getType().toAST() + " = " + leftast + " in ( " + rightast + " ) )"; + // if (needsBracket) + // { return "(BracketedExpression ( " + res + " ) )"; } + return res; + } + + if (operator.equals("#")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->exists ( " + varstring + " | " + rightast + " ) )"; + } + else if ("#LC".equals(operator)) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->existsLC ( " + varstring + " | " + rightast + " ) )"; + } + else if (operator.equals("#1")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->exists1 ( " + varstring + " | " + rightast + " ) )"; + } + else if (operator.equals("!")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->forAll ( " + varstring + " | " + rightast + " ) )"; + } + else if (operator.equals("|")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->select ( " + varstring + " | " + rightast + " ) )"; + } + else if (operator.equals("|C")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->collect ( " + varstring + " | " + rightast + " ) )"; + } + else if (operator.equals("|A")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->any ( " + varstring + " | " + rightast + " ) )"; + } + else if (operator.equals("|R")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = range.toAST(); + String varstring = ((BinaryExpression) left).left.toAST(); + + basicString = "(OclBinaryExpression " + rangestring + " ->reject ( " + varstring + " | " + rightast + " ) )"; + } + /* else if (operator.equals("|selectMinimals")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->selectMinimals( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|selectMaximals")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->selectMaximals( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|unionAll")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->unionAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|intersectAll")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->intersectAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|concatenateAll")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->concatenateAll( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|sortedBy")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->sortedBy( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("|isUnique")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->isUnique( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } + else if (operator.equals("->including") && keyValue != null) + { basicString = left + "->including(" + keyValue + ", " + right + ")"; } + else if (operator.equals("->excluding") && keyValue != null) + { basicString = left + "->excluding(" + keyValue + ", " + right + ")"; } */ + else if (operator.equals("->includesAll") || + operator.equals("->collect") || + operator.equals("->excludesAll") || + operator.equals("->append") || + operator.equals("->prepend") || + operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->including") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("->pow") || + operator.equals("->roundTo") || + operator.equals("->truncateTo") || + operator.equals("->sortedBy") || + operator.equals("->hasSuffix") || + operator.equals("->hasPrefix") || + "->isUnique".equals(operator) || + operator.equals("->oclAsType") || + "->forAll".equals(operator) || + "->exists".equals(operator) || + "->exists1".equals(operator) || + "->existsLC".equals(operator) || + "->any".equals(operator) || + operator.equals("->selectMaximals") || + operator.equals("->oclIsKindOf") || + operator.equals("->oclIsTypeOf") || + operator.equals("->includesKey") || + operator.equals("->excludesKey") || + operator.equals("->includesValue") || + operator.equals("->excludesValue") || + operator.equals("->restrict") || + operator.equals("->antirestrict") || + operator.equals("->selectMinimals") || + operator.equals("->union") || + operator.equals("->resizeTo") || + operator.equals("->sequenceRange") || + operator.equals("->intersectAll") || + operator.equals("->unionAll") || + operator.equals("->count") || + operator.equals("->indexOf") || + operator.equals("->lastIndexOf") || + operator.equals("->equalsIgnoreCase") || + operator.equals("->before") || + operator.equals("->after") || + operator.equals("->hasMatch") || + operator.equals("->isMatch") || + operator.equals("->split") || + operator.equals("->allMatches") || + operator.equals("->firstMatch") || + operator.equals("->at") || + operator.equals("->apply") || + operator.equals("->closure") || + operator.equals("->intersection") || + operator.equals("->symmetricDifference")) + { basicString = "(OclBinaryExpression " + leftast + " " + operator + " ( " + rightast + " ) )"; } + + if (operator.startsWith("->")) + { basicString = "(OclBinaryExpression " + leftast + " " + operator + " ( " + rightast + " ) )"; } + + // if (needsBracket) + // { return "(BracketedExpression ( " + basicString + " ) )"; } + + return basicString; + } + + public Expression addReference(BasicExpression ref, Type t) + { BinaryExpression res = (BinaryExpression) clone(); + Expression lr = left.addReference(ref,t); + res.left = lr; + + if ("->select".equals(operator) || + "->reject".equals(operator) || + "->collect".equals(operator) || + "->closure".equals(operator) || + "->selectMinimals".equals(operator) || + "->selectMaximals".equals(operator) || + "->isUnique".equals(operator) || + "->sortedBy".equals(operator) || + "->unionAll".equals(operator) || + "->intersectAll".equals(operator) || + "->concatenateAll".equals(operator) || + "->existsLC".equals(operator) || + "->exists".equals(operator) || + "->exists1".equals(operator) || + "->forAll".equals(operator)) + { res.right = right; } // assume no objects of type t in the rhs. + else if ("->iterate".equals(operator)) + { Expression rr = right.addReference(ref,t); + res.right = rr; + + if (accumulator != null) + { Attribute newacc = + new Attribute(accumulator.getName(), + accumulator.getType(), + ModelElement.INTERNAL); + Expression init = accumulator.getInitialExpression(); + if (init != null) + { Expression ii = + init.addReference(ref,t); + newacc.setInitialExpression(ii); + } + res.accumulator = newacc; + } + + } + else + { Expression rr = right.addReference(ref,t); + res.right = rr; + } + + if (keyValue != null) + { Expression kv = keyValue.addReference(ref,t); + res.keyValue = kv; + } + + return res; + } + + public Expression addContainerReference( + BasicExpression ref, String var, Vector excls) + { BinaryExpression res = (BinaryExpression) clone(); + + if ("->iterate".equals(operator)) + { + if (accumulator != null) + { Attribute newacc = + new Attribute(accumulator.getName(), + accumulator.getType(), + ModelElement.INTERNAL); + Vector newexcls = new Vector(); + newexcls.addAll(excls); + newexcls.add(iteratorVariable); + newexcls.add(accumulator.getName()); + Expression init = accumulator.getInitialExpression(); + if (init != null) + { Expression ii = + init.addContainerReference(ref,var,newexcls); + newacc.setInitialExpression(ii); + } + res.accumulator = newacc; + res.left = left.addContainerReference( + ref,var,newexcls); + res.right = + right.addContainerReference(ref,var,newexcls); + } + } + else if ("|".equals(operator) || + "|C".equals(operator) || + "|R".equals(operator) || + "#".equals(operator) || + "!".equals(operator) || + "#1".equals(operator)) + { BinaryExpression dm = (BinaryExpression) left; + Vector newex = new Vector(); + newex.addAll(excls); + newex.add(dm.getLeft() + ""); + res.left = dm.addContainerReference(ref,var,newex); + res.right = right.addContainerReference(ref,var,newex); + } + else + { Expression lr = + left.addContainerReference(ref,var,excls); + res.left = lr; + Expression rr = + right.addContainerReference(ref,var,excls); + res.right = rr; + } + + if (keyValue != null) + { Expression kv = + keyValue.addContainerReference(ref,var,excls); + res.keyValue = kv; + } + + System.out.println(">>>> Substituted " + ref + " in " + this + " is " + res); + + return res; + } + + public Expression replaceReference(BasicExpression ref, Type t) + { BinaryExpression res = (BinaryExpression) clone(); + Expression lr = left.replaceReference(ref,t); + res.left = lr; + if ("->select".equals(operator) || "->reject".equals(operator) || + "->collect".equals(operator) || "->closure".equals(operator) || + "->selectMinimals".equals(operator) || "->selectMaximals".equals(operator) || + "->isUnique".equals(operator) || "->sortedBy".equals(operator) || + "->unionAll".equals(operator) || "->existsLC".equals(operator) || + "->intersectAll".equals(operator) || "->concatenateAll".equals(operator) || + "->exists".equals(operator) || "->exists1".equals(operator) || + "->forAll".equals(operator)) + { res.right = right; } + else if ("->iterate".equals(operator)) + { Expression rr = right.replaceReference(ref,t); + res.right = rr; + + if (accumulator != null) + { Attribute newacc = + new Attribute(accumulator.getName(), + accumulator.getType(), + ModelElement.INTERNAL); + Expression init = accumulator.getInitialExpression(); + if (init != null) + { Expression ii = + init.replaceReference(ref,t); + newacc.setInitialExpression(ii); + } + res.accumulator = newacc; + } + + } + else + { Expression rr = right.replaceReference(ref,t); + res.right = rr; + } + + if (keyValue != null) + { Expression kv = keyValue.replaceReference(ref,t); + res.keyValue = kv; + } + + return res; + } + + public Expression dereference(BasicExpression ref) + { BinaryExpression res = (BinaryExpression) clone(); + res.left = left.dereference(ref); + res.right = right.dereference(ref); + + if ("->iterate".equals(operator)) + { + if (accumulator != null) + { Attribute newacc = + new Attribute(accumulator.getName(), + accumulator.getType(), + ModelElement.INTERNAL); + Expression init = accumulator.getInitialExpression(); + if (init != null) + { Expression ii = + init.dereference(ref); + newacc.setInitialExpression(ii); + } + res.accumulator = newacc; + } + } + + if (keyValue != null) + { Expression kv = keyValue.dereference(ref); + res.keyValue = kv; + } + return res; + } + + public Expression invert() + { BinaryExpression res = (BinaryExpression) clone(); + + if (operator.equals("&")) + { res.left = left.invert(); + res.right = right.invert(); + if (res.left.entity != null) + { res.entity = res.left.entity; } + else + { res.entity = res.right.entity; } // for & -- should be the same. + return res; + } // strictly, should swap the order of the arguments + + if (operator.equals("=")) // left should be basic + { if (right instanceof BasicExpression) + { // System.out.println("RTYNG TO INVERT " + right.umlkind); + + BasicExpression rightbe = (BasicExpression) right; + if (left instanceof BasicExpression && rightbe.umlkind == CLASSID && + rightbe.arrayIndex != null && (rightbe.arrayIndex instanceof BasicExpression)) + { BasicExpression lbe = (BasicExpression) left; + BasicExpression rightbearrayInd = (BasicExpression) rightbe.arrayIndex; + // System.out.println("RTYNG TO INVERT " + this); + Expression lref = lbe.objectRef; + Type t2 = lbe.elementType; + if (lref != null && lref.umlkind == CLASSID && lref.entity != null && + (lref instanceof BasicExpression) && + ((BasicExpression) lref).arrayIndex != null && + rightbearrayInd.objectRef != null && + (rightbearrayInd.objectRef instanceof BasicExpression) && + t2 != null && t2.isEntity()) + { // T1[idS1].f = T2[g.idS2] on S1 + return invertEqClassClassBasic(lbe, rightbe, (BasicExpression) lref, rightbearrayInd,t2); + } + } + else if (left instanceof BasicExpression && rightbe.umlkind == CLASSID && + rightbe.arrayIndex != null && (rightbe.arrayIndex instanceof BinaryExpression)) + { BasicExpression lbe = (BasicExpression) left; + BinaryExpression rightbearrayInd = (BinaryExpression) rightbe.arrayIndex; + Expression lref = lbe.objectRef; + Type t2 = lbe.elementType; + if (lref != null && lref.umlkind == CLASSID && lref.entity != null && + (lref instanceof BasicExpression) && + ((BasicExpression) lref).arrayIndex != null && + rightbearrayInd.operator.equals("->collect") && + (rightbearrayInd.left instanceof BasicExpression) && + t2 != null && t2.isEntity()) + { // T1[idS1].f = T2[g->collect(idS2)] on S1 + return invertEqClassClassCollect(lbe, rightbe, (BasicExpression) lref, rightbearrayInd, t2); + } + else if (lref != null && lref.umlkind == CLASSID && lref.entity != null && + (lref instanceof BasicExpression) && + ((BasicExpression) lref).arrayIndex != null && + rightbearrayInd.operator.equals("->unionAll") && + (rightbearrayInd.left instanceof BinaryExpression) && + t2 != null && t2.isEntity()) + { // T1[idS1].f = T2[g->unionAll(idS2)] on S1 + return invertEqClassClassUnionAll(lbe, rightbe, (BasicExpression) lref, rightbearrayInd, t2); + } + } + + if (rightbe.umlkind == CLASSID) // t.g = T[] + { return invertEqClass(res,rightbe); } + + if (right.umlkind == FUNCTION) // t.g = f( ) + { return invertEqFunction(res,rightbe); } + + res.left = right.invert(); + res.right = left.invert(); + res.entity = res.left.entity; + return res; + } + else if (right instanceof UnaryExpression && + (((UnaryExpression) right).argument instanceof BasicExpression)) + { UnaryExpression ue = (UnaryExpression) right; + return invertEqUnary(ue); // t.g = bl->op() + } + else if (right instanceof BinaryExpression) // t.g = l->op(r) + { BinaryExpression rbine = (BinaryExpression) right; + return invertEqBinary(rbine); + } + else if (left instanceof BasicExpression && right instanceof SetExpression) + { SetExpression sright = (SetExpression) right; + return sright.invertEq((BasicExpression) left); + } + // else if both basic, eg., t.g = s.r.f + } + + if (isForallExists()) + { // s->forAll( x | E->exists( y | P(x,y) & y : t ) ) inverts to + // t->forAll( y | F->exists( x | P~(x,y) & x : s ) ) where F = s.elementType.entity + BinaryExpression bl = (BinaryExpression) left; // x : s + BinaryExpression br = (BinaryExpression) right; // E->exists( y | br.right ) + BinaryExpression succ = (BinaryExpression) br.right; // pxy & y : t + Expression x = bl.left; + Expression s = bl.right; + Expression y = ((BinaryExpression) br.left).left; + Vector remainder = new Vector(); + Expression t = succ.featureAdding2("" + y, remainder); + Type selemt = s.getElementType(); + if (t != null && selemt != null && selemt.isEntity()) + { Expression pxy = (Expression) remainder.get(0); + Expression pinv = pxy.invert(); + Expression newsucc = new BinaryExpression("&", pinv, (Expression) bl.clone()); // pxy~ & x : s + Entity sent = selemt.getEntity(); + Expression sentexp = new BasicExpression(sent); + Expression sinv = new BinaryExpression("#", new BinaryExpression(":", x, sentexp), newsucc); + BinaryExpression fres = new BinaryExpression("!", new BinaryExpression(":", y, t), sinv); + return fres; + } + } + + + /* if ("&".equals(operator)) + { Expression newll = left.invert(); + Expression newrr = right.invert(); + res.left = newll; + res.right = newrr; + return res; + } */ + + if ("=>".equals(operator)) + { Expression newrr = right.invert(); + res.left = left; + res.right = newrr; + return res; + } + + Expression nl = left.invert(); + Expression nr = right.invert(); + res.left = nl; + res.right = nr; + return res; + } + + + private Expression invertEqClassClassBasic(BasicExpression lbe, BasicExpression rightbe, + BasicExpression lref, BasicExpression rightbearrayInd, Type t2) + { BinaryExpression res = (BinaryExpression) this.clone(); + + // T1[idS1].f = T2[g.idS2] + + System.out.println("Invert-eq-class-basic: " + this); + + BasicExpression newleft = (BasicExpression) + ((BasicExpression) rightbearrayInd.objectRef).clone(); // g + Entity s1ent = newleft.entity; // S1, owner of g + Entity t1ent = lref.entity; // T1, owner of f + Type s2 = newleft.elementType; + Entity s2ent; + s2ent = s2.getEntity(); + // res is S1[idT1].g = S2[f.idT2] on T1 + Attribute idT1 = null; + Vector t1ids = t1ent.allDefinedUniqueAttributes(); + if (t1ids.size() > 0) + { idT1 = (Attribute) t1ids.get(0); } + Entity t2ent; + t2ent = t2.getEntity(); + Attribute idT2 = null; + Vector t2ids = t2ent.allDefinedUniqueAttributes(); + if (t2ids.size() > 0) + { idT2 = (Attribute) t2ids.get(0); } + BasicExpression newleftoref = new BasicExpression(s1ent); + BasicExpression newleftorefind = new BasicExpression(idT1); + newleftoref.arrayIndex = newleftorefind; + newleft.objectRef = newleftoref; + // S1[idT1].g + res.left = newleft; + BasicExpression newright = new BasicExpression(s2ent); + BasicExpression newrightind = new BasicExpression(idT2); + BasicExpression nrindoref = (BasicExpression) lbe.clone(); // f + nrindoref.objectRef = null; + newrightind.objectRef = nrindoref; + newright.arrayIndex = newrightind; + res.right = newright; // S2[f.idT2] + res.entity = t1ent; // owner of this constraint. + return res; + } + + private Expression invertEqClassClassCollect(BasicExpression lbe, BasicExpression rightbe, + BasicExpression lref, BinaryExpression rightbearrayInd, Type t2) + { System.out.println("Invert-eq-class-collect: " + this); + + // T1[idS1].f = T2[g->collect(idS2)] + + BinaryExpression res = (BinaryExpression) this.clone(); + BasicExpression newleft = (BasicExpression) + ((BasicExpression) rightbearrayInd.left).clone(); // g + Entity s1ent = newleft.entity; // S1, owner of g + Entity t1ent = lref.entity; // T1, owner of f + Type s2 = newleft.elementType; + Entity s2ent; + s2ent = s2.getEntity(); + // res is S1[idT1].g = S2[f->collect(idT2)] on T1 + Attribute idT1 = null; + Vector t1ids = t1ent.allDefinedUniqueAttributes(); + if (t1ids.size() > 0) + { idT1 = (Attribute) t1ids.get(0); } + Entity t2ent; + t2ent = t2.getEntity(); + Attribute idT2 = null; + Vector t2ids = t2ent.allDefinedUniqueAttributes(); + if (t2ids.size() > 0) + { idT2 = (Attribute) t2ids.get(0); } + BasicExpression newleftoref = new BasicExpression(s1ent); + BasicExpression newleftorefind = new BasicExpression(idT1); + newleftoref.arrayIndex = newleftorefind; + newleft.objectRef = newleftoref; + // S1[idT1].g + res.left = newleft; + BasicExpression newright = new BasicExpression(s2ent); + BasicExpression newrightind = new BasicExpression(idT2); + BasicExpression nrindoref = (BasicExpression) lbe.clone(); // f + nrindoref.objectRef = null; + + newright.arrayIndex = new BinaryExpression("->collect", nrindoref, newrightind); + res.right = newright; // S2[f->collect(idT2)] + res.entity = t1ent; // owner of this constraint. + return res; + } + + private Expression invertEqClassClassUnionAll(BasicExpression lbe, BasicExpression rightbe, + BasicExpression lref, BinaryExpression rightbearrayInd, Type t2) + { System.out.println("Invert-eq-class-unionAll: " + this); + + // T1[idS1].f = T2[Set{self}->closure(r)->unionAll(g.idS2)] + + BinaryExpression res = (BinaryExpression) this.clone(); + Expression closurer = rightbearrayInd.left; + if (closurer instanceof BinaryExpression && + ((BinaryExpression) closurer).operator.equals("->closure")) { } + // T1[idS1].f = T2[r->unionAll(g.idS2)] inverts to + // S1[idT1].r->unionAll(g) = S2[f->collect(idT2)] + else if (closurer instanceof BasicExpression) + { BasicExpression r = (BasicExpression) closurer; + BasicExpression unionarg = (BasicExpression) rightbearrayInd.right; // g.idS2 + BasicExpression g = (BasicExpression) unionarg.objectRef.clone(); + Entity s1ent = r.entity; // S1 + Entity t1ent = lref.entity; // T1 + Type s2 = g.elementType; + Entity s2ent = s2.getEntity(); + Attribute idT1 = null; + Vector t1ids = t1ent.getUniqueAttributes(); + if (t1ids.size() > 0) + { idT1 = (Attribute) t1ids.get(0); } + else + { System.err.println("Cannot invert " + this); + return this; + } + Attribute idT2 = null; + Entity t2ent = t2.getEntity(); + Vector t2ids = t2ent.getUniqueAttributes(); + if (t2ids.size() > 0) + { idT2 = (Attribute) t2ids.get(0); } + else + { System.err.println("Cannot invert " + this); + return this; + } + BasicExpression newleftoref = new BasicExpression(s1ent); + BasicExpression newleftorefind = new BasicExpression(idT1); + newleftoref.arrayIndex = newleftorefind; // S1[idT1] + r.objectRef = newleftoref; // S1[idT1].r + res.left = new BinaryExpression("->unionAll", r, g); + BasicExpression f = (BasicExpression) lbe.clone(); + f.objectRef = null; + BinaryExpression newrightind = new BinaryExpression("->collect", f, new BasicExpression(idT2)); + BasicExpression newright = new BasicExpression(s2ent); + newright.arrayIndex = newrightind; // S2[f->collect(idT2)] + res.right = newright; + res.entity = t1ent; + return res; + } + else { return this; } + + + BinaryExpression beclosurer = (BinaryExpression) closurer; + BasicExpression r = (BasicExpression) beclosurer.right; + + BasicExpression newleft = (BasicExpression) + ((BasicExpression) rightbearrayInd.right).clone(); // g.idS2 + BasicExpression g = (BasicExpression) newleft.objectRef; + + Entity s1ent = g.entity; // S1, owner of g + Entity t1ent = lref.entity; // T1, owner of f + Type s2 = g.elementType; + Entity s2ent; + s2ent = s2.getEntity(); + // res is S1[idT1].g = S2[f.idT2 - S1[idT1].r->closure(r)->unionAll(g.idS2)] on T1 + Attribute idT1 = null; + Vector t1ids = t1ent.allDefinedUniqueAttributes(); + if (t1ids.size() > 0) + { idT1 = (Attribute) t1ids.get(0); } + else + { System.err.println("Unable to invert: " + this); + return this; + } + + Entity t2ent; + t2ent = t2.getEntity(); + Attribute idT2 = null; + Vector t2ids = t2ent.allDefinedUniqueAttributes(); + if (t2ids.size() > 0) + { idT2 = (Attribute) t2ids.get(0); } + else + { System.err.println("Unable to invert: " + this); + return this; + } + + BasicExpression newleftoref = new BasicExpression(s1ent); + BasicExpression newleftorefind = new BasicExpression(idT1); + newleftoref.arrayIndex = newleftorefind; // S1[idT1] + g.objectRef = newleftoref; + // S1[idT1].g + res.left = g; + + BasicExpression newright = new BasicExpression(s2ent); + BasicExpression rclone = (BasicExpression) r.clone(); + BasicExpression f = (BasicExpression) lbe.clone(); // f + f.objectRef = null; + + BasicExpression idT2be = new BasicExpression(idT2); + idT2be.setObjectRef(f); // f.idT2 + rclone.setObjectRef(newleftoref); // S1[idT1].r + BinaryExpression newclosure = new BinaryExpression("->closure", rclone, r); + BinaryExpression newunionall = + new BinaryExpression("->unionAll", newclosure, rightbearrayInd.right); + + newright.arrayIndex = new BinaryExpression("-", idT2be, newunionall); + res.right = newright; // S2[f.idT2 - S1[idT1].r->closure(r)->unionAll(g.idS2)] + res.entity = t1ent; // owner of this constraint. + return res; + } + + private Expression invertEqUnary(UnaryExpression ue) + { BinaryExpression res = (BinaryExpression) clone(); + if ("->reverse".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->reverse",left); + res.right = newr; + return res; + } + else if ("->log".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->exp",left); + res.right = newr; + return res; + } + else if ("->exp".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->log",left); + res.right = newr; + return res; + } + else if ("->sqrt".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->sqr",left); + res.right = newr; + return res; + } + else if ("->sin".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->asin",left); + res.right = newr; + return res; + } + else if ("->cos".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->acos",left); + res.right = newr; + return res; + } + else if ("->tan".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->atan",left); + res.right = newr; + return res; + } + else if ("->asin".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->sin",left); + res.right = newr; + return res; + } + else if ("->acos".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->cos",left); + res.right = newr; + return res; + } + else if ("->atan".equals(ue.operator)) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->tan",left); + res.right = newr; + return res; + } + else if ("->sort".equals(ue.operator) && !(ue.argument.isOrdered())) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->asSet",left); + res.right = newr; + return res; + } + else if ("->sort".equals(ue.operator) && ue.argument.isOrdered()) + { res.left = ue.argument; + res.right = left; + return res; + } + else if ("->asSequence".equals(ue.operator) && !(ue.argument.isOrdered())) + { res.left = ue.argument; + UnaryExpression newr = new UnaryExpression("->asSet",left); + res.right = newr; + return res; + } + else if ("->asSequence".equals(ue.operator) && ue.argument.isOrdered()) + { res.left = ue.argument; + res.right = left; + return res; + } + res.left = right; + res.right = left; + return res; + } // also ->asSet inverts to ->any on ue.argument not multiple + + private Expression invertEqBinary(BinaryExpression rbine) + { BinaryExpression res = (BinaryExpression) clone(); + if ("+".equals(rbine.operator) && + rbine.right.umlkind == VALUE && Type.isNumericType(type.getName())) + { // left = rbine.left + VAL, reversed is rbine.left = left - VALUE + res.left = rbine.left; + res.right = new BinaryExpression("-",left,rbine.right); + return res; + } + if ("-".equals(rbine.operator) && + rbine.right.umlkind == VALUE && + Type.isNumericType(type.getName())) + { // left = rbine.left - VAL, reversed is rbine.left = left + VALUE + res.left = rbine.left; + res.right = new BinaryExpression("+",left,rbine.right); + return res; + } + if ("/".equals(rbine.operator) && + rbine.right.umlkind == VALUE && + Type.isNumericType(type.getName())) + { // left = rbine.left / VAL, reversed is rbine.left = left * VALUE + res.left = rbine.left; + res.right = new BinaryExpression("*",left,rbine.right); + return res; + } + if ("*".equals(rbine.operator) && + rbine.right.umlkind == VALUE && + Type.isNumericType(type.getName())) + { // left = rbine.left * VAL, reversed is rbine.left = left / VALUE + res.left = rbine.left; + res.right = new BinaryExpression("/",left,rbine.right); + return res; + } + else if (rbine.operator.equals("->pow")) + { res.left = rbine.left; + Expression x = rbine.right; + BinaryExpression newpow = + new BinaryExpression("/", new BasicExpression(1.0), x); + res.right = new BinaryExpression("->pow", left, newpow); + return res; + } + else if ((rbine.operator.equals("->including") && left.isOrdered()) || + rbine.operator.equals("->append")) + { // left = rl->including(rr) + + Expression rl = rbine.left; + Expression rr = rbine.right; + BinaryExpression neweq1 = + new BinaryExpression("=", rr, new UnaryExpression("->last", left)); + BinaryExpression neweq2 = + new BinaryExpression("=", rl, new UnaryExpression("->front", left)); + res = new BinaryExpression("&", neweq1, neweq2); + return res; + } + else if (rbine.operator.equals("->prepend")) + { // left = rl->prepend(rr) + + Expression rl = rbine.left; + Expression rr = rbine.right; + BinaryExpression neweq1 = + new BinaryExpression("=", rr, new UnaryExpression("->first", left)); + BinaryExpression neweq2 = + new BinaryExpression("=", rl, new UnaryExpression("->tail", left)); + res = new BinaryExpression("&", neweq1, neweq2); + return res; + } + + return this; + } + + public Expression invertEqClass(BinaryExpression res, BasicExpression rightbe) + { // t.g = T2[exp] + if (rightbe.arrayIndex != null) + { if (rightbe.arrayIndex instanceof BasicExpression) // T2[s.f.id] + { BasicExpression rindex = (BasicExpression) rightbe.arrayIndex; + if (rindex.objectRef != null) + { res.left = rindex.objectRef; // s.f = T2[t.g.id] + String id2 = ""; + Type s2type = rindex.objectRef.elementType; + Type leftelemtype = left.elementType; + if (leftelemtype != null && leftelemtype.isEntity()) + { Entity leent = leftelemtype.getEntity(); + Vector idatts = leent.allDefinedUniqueAttributes(); + if (idatts.size() > 0) + { id2 = idatts.get(0) + ""; } + else + { System.err.println("Cannot invert " + this); + return this; + } + } + BasicExpression newright = new BasicExpression(s2type + ""); + if (id2.length() > 0) + { newright.arrayIndex = new BasicExpression(id2); + ((BasicExpression) newright.arrayIndex).objectRef = left; + } + else + { newright.arrayIndex = left; } + res.right = newright; // t.g = S2[s.f.id2] + return res; + } + else // left = T2[rindex] + { String id2 = ""; + Type leftelemtype = left.elementType; + if (leftelemtype != null && leftelemtype.isEntity()) + { Entity leent = leftelemtype.getEntity(); + Vector idatts = leent.allDefinedUniqueAttributes(); + if (idatts.size() > 0) + { id2 = idatts.get(0) + ""; } + else + { System.err.println("Cannot invert " + this); + return this; + } + } + BasicExpression newright = new BasicExpression("" + left); + if (id2.length() > 0) + { newright = new BasicExpression(id2); + ((BasicExpression) newright).objectRef = left; + } + res.left = rindex; + res.right = newright; // rindex = left.id2 + return res; + } + } + else if ((rightbe.arrayIndex instanceof BinaryExpression) && + "->collect".equals(((BinaryExpression) rightbe.arrayIndex).operator)) + // t.g = T2[s.f->collect(id)] + { BinaryExpression rindex = (BinaryExpression) rightbe.arrayIndex; + + res.left = rindex.left; // s.f = + String id2 = ""; + Type s2type = rindex.left.elementType; + Type leftelemtype = left.elementType; + if (leftelemtype != null && leftelemtype.isEntity()) + { Entity leent = leftelemtype.getEntity(); + Vector idatts = leent.allDefinedUniqueAttributes(); + if (idatts.size() > 0) + { id2 = idatts.get(0) + ""; } + else + { System.err.println("Cannot invert " + this); + return this; + } + } + BasicExpression newright = new BasicExpression(s2type + ""); + if (id2.length() > 0) + { BinaryExpression newcollect = new BinaryExpression("->collect", left, + new BasicExpression(id2)); + newright.arrayIndex = newcollect; + } + else + { newright.arrayIndex = left; } + res.right = newright; // S2[t.g->collect(id2)] + + if (rindex.left instanceof UnaryExpression) + { UnaryExpression rindexleft = (UnaryExpression) rindex.left; + if (rindexleft.operator.equals("->reverse")) + { res.left = rindexleft.argument; + res.right = new UnaryExpression("->reverse", newright); + } + } + + return res; + } + else if ((rightbe.arrayIndex instanceof BinaryExpression) && + "->unionAll".equals(((BinaryExpression) rightbe.arrayIndex).operator)) + // t.rr = T2[s.r->unionAll(f.id)] + { BinaryExpression rindex = (BinaryExpression) rightbe.arrayIndex; + + Expression f = null; + if (rindex.right instanceof BasicExpression) + { f = ((BasicExpression) rindex.right).objectRef; } + else + { f = rindex.right; } // doesn't make sense. + + res.left = new BinaryExpression("->unionAll", rindex.left, f); + // s.r->unionAll(f) = S2[t.rr->collect(id2)] + + String id2 = ""; + Type s2type = rindex.left.elementType; + Type leftelemtype = left.elementType; + if (leftelemtype != null && leftelemtype.isEntity()) + { Entity leent = leftelemtype.getEntity(); + Vector idatts = leent.allDefinedUniqueAttributes(); + if (idatts.size() > 0) + { id2 = idatts.get(0) + ""; } + else + { System.err.println("Cannot invert " + this); + return this; + } + } + BasicExpression newright = new BasicExpression(s2type + ""); + if (id2.length() > 0) + { BinaryExpression newcollect = new BinaryExpression("->collect", left, + new BasicExpression(id2)); + newright.arrayIndex = newcollect; + } + else + { newright.arrayIndex = left; } + res.right = newright; // S2[t.rr->collect(id2)] + return res; + } + } + res.left = right; + res.right = left; + return res; + } // also cases of s.f->reverse()->collect(id), s.f->sort()->collect(id) etc. + + public Expression invertEqFunction(BinaryExpression res, BasicExpression rbe) + { // BasicExpression rbe = (BasicExpression) right; + if (rbe.data.equals("sqrt")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("sqr"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + /* else if (rbe.data.equals("sqr")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("sqrt"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } */ + else if (rbe.data.equals("reverse")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("reverse"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("log")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("exp"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("exp")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("log"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("sin")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("asin"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("cos")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("acos"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("tan")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("atan"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("asin")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("sin"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("acos")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("cos"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("atan")) + { res.left = rbe.objectRef; + BasicExpression newr = new BasicExpression("tan"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + return res; + } + else if (rbe.data.equals("pow")) + { res.left = rbe.objectRef; + Expression x = (Expression) rbe.getParameters().get(0); + BasicExpression newr = new BasicExpression("pow"); + newr.umlkind = FUNCTION; + newr.objectRef = left; + res.right = newr; + BinaryExpression newarg = + new BinaryExpression("/", new BasicExpression(1.0), x); + newr.addParameter(newarg); + return res; + } + res.left = right; + res.right = left; + return res; + } + + + public String toSQL() + { String ls = left.toSQL(); + String rs = right.toSQL(); + String res; + if (operator.equals("&")) + { res = ls + " AND " + rs; } + else if (operator.equals("or")) + { res = ls + " OR " + rs; } + else if (operator.equals("+") && + (left.getType().getName().equals("String") || + right.getType().getName().equals("String"))) + { res = "CONCAT(" + ls + "," + rs + ")"; } + else // MOD as well? + { res = ls + " " + operator + " " + rs; } + if (needsBracket) + { res = "( " + res + " )"; } + return res; + } + + + public boolean isPrimitive() + { // Strings are not counted as primitive + + if (operator.equals("->count") || + operator.equals("->indexOf") || + operator.equals("->lastIndexOf") || + operator.equals("->oclIsKindOf") || + operator.equals("->oclIsTypeOf") || + operator.equals("->pow") || + operator.equals("->roundTo") || + operator.equals("->truncateTo") || + operator.equals("->hasPrefix") || + operator.equals("->hasSuffix") || + operator.equals("->exists") || + "->existsLC".equals(operator) || + operator.equals("->exists1") || + operator.equals("->isUnique") || + operator.equals("|isUnique") || + operator.equals("->forAll") || operator.equals("<:") || + operator.equals("=") || + operator.equals("/=") || operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("!=") || operator.equals("<>") || + operator.equals("#") || operator.equals("#LC") || + operator.equals("/<:") || + operator.equals("!") || operator.equals("#1") || + operator.equals("->excludesAll") || + operator.equals("->includesAll") || + operator.equals("->compareTo") || + comparitors.contains(operator)) + { return true; } + + if (operator.equals("\\/") || operator.equals("/\\") || + operator.equals("^") || + "->concatenate".equals(operator) || + operator.equals("->sequenceRange") || + operator.equals("->resizeTo") || + operator.equals("->collect") || + operator.equals("->union") || + operator.equals("->sortedBy") || + operator.equals("->select") || + operator.equals("->closure") || + operator.equals("->reject") || + operator.equals("|") || operator.equals("|R") || + operator.equals("|C") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("->prepend") || + operator.equals("->unionAll") || + operator.equals("->intersectAll") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|sortedBy") || + operator.equals("->selectMaximals") || + operator.equals("->selectMinimals") || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator) || + operator.equals("->append") || + operator.equals("->including") || + operator.equals("->restrict") || + operator.equals("->antirestrict") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("->excluding")) + { return false; } + + if (operator.equals("->oclAsType")) + { String typ = right + ""; + + if ("int".equals(typ) || + "long".equals(typ) || "double".equals(typ) || + "boolean".equals(typ)) + { return true; } // or it is the name of an enum - but a strange thing to do + + if (right.type != null && right.type.isEnumeration()) + // ModelElement.lookupByName(typ, types) != null) + { return true; } + + return false; + } + + if (operator.equals("->at") || operator.equals("|A") || + operator.equals("->any")) + { return Type.isPrimitiveType(left.elementType); } + + if (operator.equals("->apply")) + { return Type.isPrimitiveType(type); } + + // for +, -, *, / + return left.isPrimitive() && right.isPrimitive(); + } // e->oclAsType(T) if T is a primitive type + + // Also s->exists(p) and s->forAll(p) are primitive? + + public Vector allEntitiesUsedIn() + { Vector les = left.allEntitiesUsedIn(); + Vector res = right.allEntitiesUsedIn(); + return VectorUtil.union(les,res); + } + + public Vector innermostEntities() + { Vector res = left.innermostEntities(); + return VectorUtil.union(res,right.innermostEntities()); + } + + public Vector innermostVariables() + { Vector res = left.innermostVariables(); + return VectorUtil.union(res,right.innermostVariables()); + } + + public Vector metavariables() + { if ("|C".equals(operator) || "|R".equals(operator) || "|".equals(operator) || + "|A".equals(operator) || "#".equals(operator) || "#1".equals(operator) || + "!".equals(operator) || + (operator.startsWith("|") && (left instanceof BinaryExpression)) + ) + { BinaryExpression beleft = (BinaryExpression) left; + Vector res = beleft.right.metavariables(); + res = VectorUtil.union(res,beleft.left.metavariables()); + return VectorUtil.union(res,right.metavariables()); + } + + if ("let".equals(operator)) + { String accname = accumulator.getName(); + Vector res = CGRule.metavariables(accname); + Type typ = accumulator.getType(); + res = VectorUtil.union(res, typ.metavariables()); + res = VectorUtil.union(res, left.metavariables()); + res = VectorUtil.union(res, right.metavariables()); + return res; + } + + if ("->iterate".equals(operator)) + { Vector res = left.metavariables(); + if (iteratorVariable != null) + { res.addAll(CGRule.metavariables(iteratorVariable)); } + if (accumulator != null) + { res.addAll(CGRule.metavariables( + accumulator.getName())); + Expression init = accumulator.getInitialExpression(); + if (init != null) + { res.addAll(init.metavariables()); } + } + + System.out.println(">>> Metavariables for " + this + + " are " + res); + + return VectorUtil.union(res,right.metavariables()); + } + + Vector res = left.metavariables(); + return VectorUtil.union(res,right.metavariables()); + } + + public Vector allPreTerms() + { Vector res = left.allPreTerms(); + Vector rpterms = right.allPreTerms(); + + if ("->forAll".equals(operator) || "->exists".equals(operator) || + "->exists1".equals(operator) || "->select".equals(operator) || + "->existsLC".equals(operator) || "->any".equals(operator) || + "->reject".equals(operator) || "->collect".equals(operator) || + "->selectMinimals".equals(operator) || "->selectMaximals".equals(operator) || + "->unionAll".equals(operator) || "->intersectAll".equals(operator) || + "->concatenateAll".equals(operator)) + { // discard pre-terms of features defined in the left.elementType.entity + // because these are handled by the inner iteration + + Type letype = left.elementType; + if (letype == null) + { letype = left.type; } + Entity lent = left.entity; + Vector removals = new Vector(); + + if (letype != null && letype.isEntity()) + { lent = letype.entity; + for (int i = 0; i < rpterms.size(); i++) + { Expression rpt = (Expression) rpterms.get(i); + if (rpt instanceof BasicExpression) + { BasicExpression berpt = (BasicExpression) rpt; + if (berpt.umlkind == ROLE || berpt.umlkind == ATTRIBUTE) + { if (berpt.entity == lent) + { removals.add(rpt); } + else if (lent.hasFeature(berpt.data)) + { removals.add(rpt); } + } + } + } + } + rpterms.removeAll(removals); + } + else if ("->iterate".equals(operator)) + { if (accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.allPreTerms()); } + } + } // and "let" + else if ("!".equals(operator) || "#".equals(operator) || "|A".equals(operator) || + "#1".equals(operator) || "|".equals(operator) || operator.equals("#LC") || + "|R".equals(operator) || "|C".equals(operator) || + "|selectMinimals".equals(operator) || "|selectMaximals".equals(operator) || + "|unionAll".equals(operator) || "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { // discard pre-terms of features of the left.left + // because these are invalid + + BinaryExpression lbe = (BinaryExpression) left; + BasicExpression v = (BasicExpression) lbe.left; + + Vector removals = new Vector(); + + for (int i = 0; i < rpterms.size(); i++) + { Expression rpt = (Expression) rpterms.get(i); + Vector inns = rpt.innermostVariables(); + + if (inns.contains(v + "")) + { removals.add(rpt); } + } + rpterms.removeAll(removals); + } + + return VectorUtil.union(res,rpterms); + } // also discard for ->select, ->reject, ->collect, ->isUnique, ->selectMaximals, + // ->selectMinimals, ->unionAll, ->intersectAll + + + public Vector allPreTerms(String var) + { Vector res = left.allPreTerms(var); + Vector rpterms = right.allPreTerms(var); + + if ("->forAll".equals(operator) || "->exists".equals(operator) || + "->existsLC".equals(operator) || "->any".equals(operator) || + "->exists1".equals(operator) || "->select".equals(operator) || + "->reject".equals(operator) || "->collect".equals(operator) || + "->selectMinimals".equals(operator) || "->selectMaximals".equals(operator) || + "->unionAll".equals(operator) || "->intersectAll".equals(operator) || + "->concatenateAll".equals(operator)) + { // discard pre-terms of features of the left.elementType.entity + Type letype = left.elementType; + if (letype == null) + { letype = left.type; } + Entity lent = left.entity; + Vector removals = new Vector(); + + if (letype != null && letype.isEntity()) + { lent = letype.entity; + for (int i = 0; i < rpterms.size(); i++) + { Expression rpt = (Expression) rpterms.get(i); + if (rpt instanceof BasicExpression) + { BasicExpression berpt = (BasicExpression) rpt; + if (berpt.umlkind == ROLE || berpt.umlkind == ATTRIBUTE) + { if (berpt.entity == lent) + { removals.add(rpt); } + else if (lent.hasFeature(berpt.data)) + { removals.add(rpt); } + } + } + } + } + rpterms.removeAll(removals); + } + else if ("->iterate".equals(operator)) + { if (accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.allPreTerms(var)); } + } + } + else if ("!".equals(operator) || "#".equals(operator) || + operator.equals("#LC") || + "#1".equals(operator) || "|".equals(operator) || + "|A".equals(operator) || + "|R".equals(operator) || "|C".equals(operator) || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator) || + "|unionAll".equals(operator) || + "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { // discard pre-terms of features of the left.left + // because these are invalid + + BinaryExpression lbe = (BinaryExpression) left; + BasicExpression v = (BasicExpression) lbe.left; + + Vector removals = new Vector(); + + for (int i = 0; i < rpterms.size(); i++) + { Expression rpt = (Expression) rpterms.get(i); + Vector inns = rpt.innermostVariables(); + + if (inns.contains(v + "")) + { removals.add(rpt); } + } + rpterms.removeAll(removals); + } + + return VectorUtil.union(res,rpterms); + } // As above, also for ->select, etc. + + public Vector getBaseEntityUses() // entities E such that f occurs without an object ref + { if (operator.equals("->forAll") || + operator.equals("->exists") || + "->existsLC".equals(operator) || + operator.equals("->any") || + operator.equals("->exists1") || + operator.equals("->sortedBy") || + operator.equals("->select") || + operator.equals("->reject") || + "->isUnique".equals(operator) || + operator.equals("->unionAll") || + operator.equals("->intersectAll") || + operator.equals("->collect") || operator.equals("->selectMaximals") || + operator.equals("->selectMinimals")) + { Vector ss = right.getBaseEntityUses(); + Vector removals = new Vector(); + Type elemtype = left.getElementType(); + if (elemtype != null && elemtype.isEntity()) + { Entity e2 = elemtype.getEntity(); + + for (int i = 0; i < ss.size(); i++) + { Entity e1 = (Entity) ss.get(i); + if (Entity.inheritanceRelated(e1,e2)) + { removals.add(e1); } + } + ss.removeAll(removals); + } + + Vector ss1 = left.getBaseEntityUses(); + ss = VectorUtil.union(ss,ss1); + + // System.out.println("Base entities of " + this + " = " + ss); + return ss; + } + + // forAll, exists, exists1 and select, reject, collect: ignore the + // entity being quantified/ranged over. + + if (operator.equals("->closure")) + { return left.getBaseEntityUses(); } + + if ("->iterate".equals(operator) || "let".equals(operator)) + { Vector ss1 = left.getBaseEntityUses(); + Vector ss2 = right.getBaseEntityUses(); + + if (accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { ss1.addAll(expr.allPreTerms()); } + } + + return VectorUtil.union(ss1,ss2); + } + + if (operator.equals("!") || operator.equals("#") || operator.equals("#LC") || + operator.equals("#1") || operator.equals("|") || operator.equals("|R") || + operator.equals("|A") || operator.equals("|C") || + "|selectMinimals".equals(operator) || "|selectMaximals".equals(operator) || + "|unionAll".equals(operator) || "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { Vector ss = right.getBaseEntityUses(); + if (left instanceof BinaryExpression) + { Vector res = ((BinaryExpression) left).right.getBaseEntityUses(); + return VectorUtil.union(ss,res); + } + return ss; + } + + Vector res = left.getBaseEntityUses(); + res = VectorUtil.union(res,right.getBaseEntityUses()); + // System.out.println("Base entities of " + this + " = " + res); + return res; + } // This is what you need in uml2Cbmm to obtain the parameters of lambda expressions. + + public Vector allVariableNames() + { Vector res = left.allVariableNames(); + res = VectorUtil.union(res, right.allVariableNames()); + return res; + } + + public Vector getVariableUses() + { if (operator.equals("#") || operator.equals("|") || + operator.equals("|A") || + operator.equals("|C") || operator.equals("#LC") || + operator.equals("|R") || operator.equals("#1") || + operator.equals("!") || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator) || + "|unionAll".equals(operator) || + "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { Vector ss = right.getVariableUses(); + Vector removals = new Vector(); + if (left instanceof BinaryExpression) + { Expression e = ((BinaryExpression) left).left; + for (int i = 0; i < ss.size(); i++) + { Expression e1 = (Expression) ss.get(i); + if ((e1 + "").equals(e + "")) + { removals.add(e1); } + } + ss.removeAll(removals); + Expression scope = ((BinaryExpression) left).right; + ss = VectorUtil.union(ss,scope.getVariableUses()); + } + return ss; + } + + if ("->iterate".equals(operator) || "let".equals(operator)) + { Vector ss1 = left.getVariableUses(); + Vector ss2 = right.getVariableUses(); + Vector removals = new Vector(); + + if (accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { ss1.addAll(expr.getVariableUses()); } + String acc = accumulator.getName(); + + for (int i = 0; i < ss2.size(); i++) + { Expression e1 = (Expression) ss2.get(i); + if ((e1 + "").equals(acc)) + { removals.add(e1); } + } + } + + ss2.removeAll(removals); + return VectorUtil.union(ss1,ss2); + } + + Vector res = left.getVariableUses(); + res = VectorUtil.union(res,right.getVariableUses()); + return res; + } + + public Vector getUses(String feature) + { Vector res = new Vector(); + res.addAll(left.getUses(feature)); + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.getUses(feature)); } + } + res.addAll(right.getUses(feature)); + return res; + } // VectorUtil.union of the uses? + + public Vector allFeaturesUsedIn() + { Vector res = new Vector(); + res.addAll(left.allFeaturesUsedIn()); + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.allFeaturesUsedIn()); } + } + return VectorUtil.union(res, + right.allFeaturesUsedIn()); + } // ->iterate, add accumulator expression + + public Vector allAttributesUsedIn() + { Vector res = new Vector(); + res.addAll(left.allAttributesUsedIn()); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.allAttributesUsedIn()); } + } + + return VectorUtil.union(res, + right.allAttributesUsedIn()); + } // ->iterate, add accumulator expression + + public Vector allOperationsUsedIn() + { Vector res = new Vector(); + res.addAll(left.allOperationsUsedIn()); + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.allOperationsUsedIn()); } + } + return VectorUtil.union(res, + right.allOperationsUsedIn()); + } // ->iterate, add accumulator expression + + public Vector equivalentsUsedIn() + { Vector res = new Vector(); + res.addAll(left.equivalentsUsedIn()); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.equivalentsUsedIn()); } + } + + return VectorUtil.union(res, + right.equivalentsUsedIn()); + } // ->iterate, add accumulator expression + + public Vector allValuesUsedIn() + { Vector res = new Vector(); + res.addAll(left.allValuesUsedIn()); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res.addAll(expr.allValuesUsedIn()); } + } + + return VectorUtil.union(res, + right.allValuesUsedIn()); + } // ->iterate, add accumulator expression + +public void findClones(java.util.Map clones, String rule, String op) +{ /* System.out.println(">>> complexity of " + this + " = " + + this.syntacticComplexity()); + System.out.println(">>> Clone limit = " + + UCDArea.CLONE_LIMIT); */ + + if (this.syntacticComplexity() < UCDArea.CLONE_LIMIT) + { return; } + String val = this + ""; + Vector used = (Vector) clones.get(val); + if (used == null) + { used = new Vector(); } + if (rule != null) + { used.add(rule); } + else if (op != null) + { used.add(op); } + clones.put(val,used); + left.findClones(clones,rule,op); + right.findClones(clones,rule,op); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { expr.findClones(clones,rule,op); } + } +} + +public void findClones(java.util.Map clones, + java.util.Map cloneDefs, + String rule, String op) +{ /* System.out.println(">>> complexity of " + this + " = " + + this.syntacticComplexity()); + System.out.println(">>> Clone limit = " + + UCDArea.CLONE_LIMIT); */ + + if (this.syntacticComplexity() < UCDArea.CLONE_LIMIT) + { return; } + String val = this + ""; + Vector used = (Vector) clones.get(val); + if (used == null) + { used = new Vector(); } + if (rule != null) + { used.add(rule); } + else if (op != null) + { used.add(op); } + clones.put(val,used); + cloneDefs.put(val, this); + left.findClones(clones,cloneDefs,rule,op); + right.findClones(clones,cloneDefs,rule,op); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { expr.findClones(clones,cloneDefs,rule,op); } + } + +} + + public void findMagicNumbers(java.util.Map mgns, String rule, String op) + { left.findMagicNumbers(mgns,rule,op); + right.findMagicNumbers(mgns,rule,op); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { expr.findMagicNumbers(mgns,rule,op); } + } + } + + + public Vector variableRanges(java.util.Map ranges, Vector pars) + { Vector res = new Vector(); + if (operator.equals(":") && left.umlkind == VARIABLE) + { if (ranges.keySet().contains(left + "")) + { Expression oldright = (Expression) ranges.get(left + ""); + System.out.println("->> redefinition of " + left + " : " + oldright + " by " + this); + + if (Expression.isEntity(oldright) && Expression.isEntity(right)) + { Entity oldent = oldright.getElementType().getEntity(); + Entity newent = right.getElementType().getEntity(); + if (oldent != null && newent != null && Entity.isAncestor(oldent,newent)) + { ranges.put(left + "", new BasicExpression(newent)); + System.out.println("--> Set range of " + left + " to " + right); + } // replace by most-specific type + else { } + } + else { } + } + else if (pars.contains(left + "")) + { } // Only the first scope is used, later ones are further conditions + else + { res.add(left + ""); + System.out.println("--> Set range of " + left + " to " + right); + ranges.put(left + "", right); + } + } + else if (operator.equals("&")) + { res.addAll(left.variableRanges(ranges,pars)); + res.addAll(right.variableRanges(ranges,pars)); + } + + return res; + } + + public Vector letDefinitions(java.util.Map ranges, Vector pars) + { Vector res = new Vector(); + if (operator.equals("=") && left.umlkind == VARIABLE) + { if (ranges.keySet().contains(left + "") || pars.contains(left + "")) + { } // Only the first scope is used, later ones are further conditions + else + { res.add(left + ""); + ranges.put(left + "", right); + } + } + else if (operator.equals("&")) + { res.addAll(left.letDefinitions(ranges,pars)); + res.addAll(right.letDefinitions(ranges,pars)); + } + + return res; + } + + public Expression excel2Ocl(Entity target, Vector entities, Vector qvars, Vector antes) + { BinaryExpression enew = (BinaryExpression) clone(); + enew.left = left.excel2Ocl(target, entities, qvars, antes); + enew.right = right.excel2Ocl(target, entities, qvars, antes); + return enew; + } + + public void getParameterBounds(Vector atts, Vector bounds, java.util.Map attBounds) + { if ("&".equals(operator)) + { left.getParameterBounds(atts,bounds,attBounds); + right.getParameterBounds(atts,bounds,attBounds); + } + else if ("<".equals(operator) || "<=".equals(operator) || ">".equals(operator) || "=".equals(operator) || + ">=".equals(operator)) + { bounds.add(this); + + for (int i = 0; i < atts.size(); i++) + { Attribute attr = (Attribute) atts.get(i); + if ((left + "").equals(attr + "") || + (right + "").equals(attr + "")) + { Vector abounds = (Vector) attBounds.get(attr + ""); + if (abounds == null) + { abounds = new Vector(); } + abounds.add(this); + attBounds.put(attr + "", abounds); + } + } + } + } + + public Expression getUpperBound(String attname) + { if (("<".equals(operator) || + "<=".equals(operator) || + "=".equals(operator)) && + attname.equals(left + "") && + (right.umlkind == VALUE || + Expression.isValue(right)) + ) + { return right; } + + if ((">".equals(operator) || + ">=".equals(operator) || + "=".equals(operator)) && + attname.equals(right + "") && + (left.umlkind == VALUE || Expression.isValue(left)) + ) + { return left; } + + return null; + } + + public Expression getLowerBound(String attname) + { if (("<".equals(operator) || + "<=".equals(operator) || + "=".equals(operator)) && + attname.equals(right + "") && + (left.umlkind == VALUE || Expression.isValue(left)) + ) + { return left; } + + if ((">".equals(operator) || + ">=".equals(operator) || + "=".equals(operator)) && + attname.equals(left + "") && + (right.umlkind == VALUE || Expression.isValue(right)) + ) + { return right; } + + return null; + } + + + // The following turns x : e & P & l = g & Q into [x,P,l,Q] in allvars + public Vector splitToCond0Cond1(Vector conds, Vector pars, + Vector qvars, Vector lvars, Vector allvars) + { Expression cond0 = (Expression) conds.get(0); // predicates defining variables + Expression cond1 = (Expression) conds.get(1); // other predicates + Vector res = new Vector(); + + if (operator.equals(":") && left.umlkind == VARIABLE) // && not in qvars + { if (qvars.contains(left + "") || lvars.contains(left + "") || pars.contains(left + "")) + // condition on existing variable + { Expression c2 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c2); + Type t1 = left.getType(); + Type t2 = right.getElementType(); + left.setType(Type.mostSpecificType(t1,t2)); + // System.out.println("DEDUCED TYPE: " + left.getType() + " of " + left); + // allvars.add(this); + } + else + { qvars.add(left + ""); + allvars.add(left + ""); + Expression c0 = Expression.simplifyAnd(cond0,this); + res.add(c0); + res.add(cond1); + } + } // add to qvars + else if (operator.equals("=") && left.umlkind == VARIABLE) + { if (qvars.contains(left + "") || lvars.contains(left + "") || pars.contains(left + "")) + // condition on existing variable + { Expression c2 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c2); + // allvars.add(this); + } + else + { lvars.add(left + ""); + allvars.add(left + ""); + Expression c0 = Expression.simplifyAnd(cond0,this); + res.add(c0); + res.add(cond1); + } + } // add to lvars + else if (operator.equals("&")) + { Vector res1 = left.splitToCond0Cond1(conds,pars,qvars,lvars,allvars); + res = right.splitToCond0Cond1(res1,pars,qvars,lvars,allvars); + } + else // it is a cond1 formula + { Expression c1 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c1); + // allvars.add(this); + } + + return res; + } + + public static Expression findDefinitionOf(Expression key, Vector exps) + { // finds e where v : e is in exps with v + "" = key + "" + for (int i = 0; i < exps.size(); i++) + { Expression ex = (Expression) exps.get(i); + if (ex instanceof BinaryExpression) + { BinaryExpression bex = (BinaryExpression) ex; + if (bex.operator.equals(":") && (bex.left + "").equals(key + "")) + { return bex.right; } + } + } + return null; + } + + public static void replaceDefinition(Expression key, Expression newvalue, Vector exps) + { // replaces e where v : e is in exps with v + "" = key + "" by newvalue + + for (int i = 0; i < exps.size(); i++) + { Expression ex = (Expression) exps.get(i); + if (ex instanceof BinaryExpression) + { BinaryExpression bex = (BinaryExpression) ex; + if (bex.operator.equals(":") && (bex.left + "").equals(key + "")) + { bex.right = newvalue; + return; + } + } + } + } + + // The following turns x : e & P & l = g & Q into [x,P,l,Q] in allvars + public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, + Vector qvars, Vector lvars, + Vector allvars, Vector allpreds) + { Expression cond0 = (Expression) conds.get(0); + Expression cond1 = (Expression) conds.get(1); + Vector res = new Vector(); + // System.out.println("Split conds on: " + this); + + if (operator.equals(":") && left.umlkind == VARIABLE) // && not in qvars + { if (qvars.contains(left + "") || lvars.contains(left + "") || pars.contains(left + "")) + // condition on existing variable + { if (Expression.isSimpleEntity(right)) + { // if previous occurrence was also left : Entity, replace that by left : Specific + // where Specific is the most specific of the two. + Expression vardef = BinaryExpression.findDefinitionOf(left,allpreds); + if (vardef != null && Expression.isSimpleEntity(vardef)) + { Entity eold = vardef.getElementType().getEntity(); + Entity enew = right.getElementType().getEntity(); + if (eold != null && enew != null && Entity.isAncestor(eold,enew)) + { BinaryExpression.replaceDefinition(left,right,allpreds); + left.setType(new Type(enew)); + } + else + { } // new condition is redundant + res.add(cond0); + res.add(cond1); + } + else // is genuine new condition + { Expression c2 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c2); + Type t1 = left.getType(); + Type t2 = right.getElementType(); + left.setType(Type.mostSpecificType(t1,t2)); + // System.out.println("DEDUCED TYPE: " + left.getType() + " of " + left); + allvars.add(this); + allpreds.add(this); + } + } + else + { Expression c2 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c2); + Type t1 = left.getType(); + Type t2 = right.getElementType(); + left.setType(Type.mostSpecificType(t1,t2)); + // System.out.println("DEDUCED TYPE: " + left.getType() + " of " + left); + allvars.add(this); + allpreds.add(this); + } + } + else + { qvars.add(left + ""); + allvars.add(left + ""); + Expression c0 = Expression.simplifyAnd(cond0,this); + res.add(c0); + res.add(cond1); + allpreds.add(this); + } + } // add to qvars + else if (operator.equals("=") && left.umlkind == VARIABLE) + { if (qvars.contains(left + "") || lvars.contains(left + "") || pars.contains(left + "")) + // condition on existing variable + { Expression c2 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c2); + allvars.add(this); + allpreds.add(this); + } + else + { lvars.add(left + ""); + allvars.add(left + ""); + Expression c0 = Expression.simplifyAnd(cond0,this); + res.add(c0); + res.add(cond1); + allpreds.add(this); + } + } // add to lvars + else if (operator.equals("&")) + { Vector res1 = left.splitToCond0Cond1Pred(conds,pars,qvars,lvars,allvars,allpreds); + res = right.splitToCond0Cond1Pred(res1,pars,qvars,lvars,allvars,allpreds); + } + else // it is a cond1 formula + { Expression c1; + if (cond1 == null) + { c1 = this; } + else + { c1 = new BinaryExpression("&",cond1,this); } + res.add(cond0); + res.add(c1); + allvars.add(this); + allpreds.add(this); + // System.out.println("Added condition: " + this); + } + + return res; + } + + // Assumes all existential quantifiers are first: + + public Vector splitToTCondPost(Vector tvars, Vector conds) + { Expression cond0 = (Expression) conds.get(0); // TCond + Expression cond1 = (Expression) conds.get(1); // Post + Vector res = new Vector(); + + // This is a TCond conjunct if: it only has a tvar as base of + // its basic expressions, or they are values + + if (operator.equals("&")) + { Vector res1 = left.splitToTCondPost(tvars,conds); + res = right.splitToTCondPost(tvars,res1); + return res; + } + + Vector vleft = left.innermostVariables(); + // System.out.println("Innermost variables of " + left + " = " + vleft); + Vector vright = right.innermostVariables(); + // System.out.println("Innermost variables of " + right + " = " + vright); + if (tvars.containsAll(vleft) && tvars.containsAll(vright)) + { Expression c0 = Expression.simplifyAnd(cond0,this); + res.add(c0); + res.add(cond1); + } + else // it is a post formula + { Expression c1 = Expression.simplifyAnd(cond1,this); + res.add(cond0); + res.add(c1); + } + + return res; + } + + public Vector updateVariables() // updated variables in the expression + { Vector res = new Vector(); + if (operator.equals("&") || operator.equals("#") || operator.equals("#LC") || + operator.equals("#1")) + { res = left.updateVariables(); + return VectorUtil.union(res,right.updateVariables()); + } + /* else if (operator.equals("->forAll") || */ + else if ( operator.equals("!") || operator.equals("=>")) + { return right.updateVariables(); } + else if (operator.equals("=")) + { if (left instanceof BasicExpression) + { res.add(left); } // and l->at(e) = val also + } + else if (operator.equals(":") || operator.equals("<:") || + operator.equals("/:") || operator.equals("/<:")) + { if (right instanceof BasicExpression) + { res.add(right); } + } // Not quite. x /: e.r.att can remove an element of r. + else if (operator.equals("->includesAll") || operator.equals("->includes") || + operator.equals("->excludesAll") || operator.equals("->excludes")) + { if (left instanceof BasicExpression) + { res.add(left); } + } + return res; + } + + public int maxModality() + { int ml = left.maxModality(); + int mr = right.maxModality(); + if (ml > mr) + { return ml; } + return mr; + } + + public int minModality() + { int ml = left.minModality(); + int mr = right.minModality(); + if (ml > mr && mr > ModelElement.NONE) + { return mr; } + return ml; // could be NONE + } + + public String toB() + { String op; + if (operator.equals("!=") || operator.equals("<>")) + { op = "/="; } + else + { op = operator; } + String basicString = left.toB() + " " + op + " " + right.toB(); + if (needsBracket) + { return "(" + basicString + ")"; } // eg, for or inside & + else + { return basicString; } + } + + // Should not use this in Statement: + public String toJava() + { String javaop; + if (operator.equals("=")) + { javaop = "=="; } + else if (operator.equals("&") || operator.equals("and")) + { javaop = "&&"; } + else if (operator.equals("or")) + { javaop = "||"; } + else if (operator.equals("/=") || operator.equals("<>")) + { javaop = "!="; } + else if (operator.equals("mod")) + { javaop = "%"; } + else if (operator.equals("div")) + { javaop = "/"; } + else + { javaop = operator; } + + String basicString = left.toJava() + " " + javaop + " " + right.toJava(); + if (needsBracket) + { return "(" + basicString + ")"; } // eg, for or inside & + else + { return basicString; } + } + + public String toJavaImp(Vector components) + { String javaop; + if (operator.equals("=")) + { javaop = "=="; } + else if (operator.equals("&") || operator.equals("and")) + { javaop = "&&"; } + else if (operator.equals("or")) + { javaop = "||"; } + else if (operator.equals("/=") || operator.equals("<>")) + { javaop = "!="; } + else if (operator.equals("mod")) + { javaop = "%"; } + else if (operator.equals("div")) + { javaop = "/"; } + else + { javaop = operator; } + + String basicString = left.toJavaImp(components) + " " + javaop + " " + + right.toJavaImp(components); + if (needsBracket) + { return "(" + basicString + ")"; } // eg, for or inside & + else + { return basicString; } + } + + + public Expression toSmv(Vector cnames) + { String smvop; + if (operator.equals("=>")) + { smvop = "->"; } + else if (operator.equals("or")) + { smvop = "|"; } + else + { smvop = operator; } + + return new BinaryExpression(smvop, left.toSmv(cnames), + right.toSmv(cnames)); + } + + public String toImp(final Vector components) + { + return left.toImp(components) + " " + operator + " " + + right.toImp(components); + } + + public boolean isOrExpression() + { return operator.equals("or"); } + + + public Expression buildJavaForm(final Vector comps) + { Expression newleft; + + if (operator.equals("=")) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + Statemachine sm = + (Statemachine) VectorUtil.lookup(bel.data, comps); + if (sm != null && sm.getMultiplicity() <= 1) + { newleft = new BasicExpression("M" + sm.label + "." + sm.label); + javaForm = new BinaryExpression("==", newleft, right); + return javaForm; + } + else + { Statemachine smr = + (Statemachine) VectorUtil.lookup(ber.data, comps); + if (smr != null && smr.getMultiplicity() <= 1) + { newleft = new BasicExpression("M" + smr.label + "." + smr.label) ; + javaForm = new BinaryExpression("==", newleft, left); + return javaForm; + } + } + } + else if (operator.equals("&")) + { Expression jaf1 = left.buildJavaForm(comps); + Expression jaf2 = right.buildJavaForm(comps); + javaForm = new BinaryExpression("&&",jaf1,jaf2); + return javaForm; + } + else if (operator.equals("or")) + { Expression jaf1 = left.buildJavaForm(comps); + Expression jaf2 = right.buildJavaForm(comps); + javaForm = new BinaryExpression("||",jaf1,jaf2); + return javaForm; + } + javaForm = this; // for multiple instance ac1.ac, etc. + return javaForm; + } + + + public int typeCheck(Vector sms) + { if (comparitors.contains(operator)) + { return typeCheckEq(sms); } + else if (operator.equals("&") || operator.equals("or")) + { return typeCheckAnd(sms); } + else + { System.out.println("Unexpected operator: " + operator); + modality = ERROR; + return ERROR; + } + } + + public boolean typeInference(final Vector types, + final Vector entities, + final Vector contexts, final Vector env, + java.util.Map vartypes) + { left.typeInference(types,entities,contexts,env,vartypes); + right.typeInference(types,entities,contexts,env,vartypes); + + Type tleft = left.getType(); + Type tright = right.getType(); + + if (operator.equals("let") && accumulator != null) + { // let v : T = left in right + + Vector context = new Vector(); + context.addAll(contexts); + + String vname = accumulator.getName(); + Type vtype = accumulator.getType(); + // Expression vinit = accumulator.getInitialisation(); + + java.util.Map vartypes1 = new java.util.HashMap(); + vartypes1.putAll(vartypes); + + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(accumulator); + + if (Type.isVacuousType(vtype) && + !Type.isVacuousType(left.getType())) + { accumulator.setType(left.getType()); + vtype = accumulator.getType(); + } + + boolean rtc = right.typeInference(types,entities, + context,env1,vartypes1); + + Type vetype = (Type) vartypes1.get(vname); + + if (Type.isVacuousType(vtype) && + !Type.isVacuousType(vetype)) + { accumulator.setType(vetype); } + + type = right.type; + elementType = right.elementType; + System.out.println(">>> Typechecked let expression: let " + vname + " : " + accumulator.getType() + " = " + left + " in (" + type + ")"); + return true; + } + + if (operator.equals("->exists") || + operator.equals("->exists1") || + "->existsLC".equals(operator) || + operator.equals("->isUnique") || + operator.equals("->forAll")) + { // left must be a collection, right must be boolean + + type = new Type("boolean", null); + elementType = new Type("boolean", null); + multiplicity = ModelElement.ONE; + + if (left.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + left.setType(new Type("Sequence", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + if (right.isBoolean()) { } + else + { System.err.println("!! Right argument of " + operator + + " must be boolean"); + right.setType(new Type("boolean", null)); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + } + else if (operator.equals("#") || operator.equals("#1") || + operator.equals("#LC") || operator.equals("!")) + { BinaryExpression lexp = (BinaryExpression) left; + Expression scope = lexp.right; + + type = new Type("boolean", null); + elementType = new Type("boolean", null); + multiplicity = ModelElement.ONE; + + if (scope.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + scope.setType(new Type("Sequence", null)); + + if (scope instanceof BasicExpression) + { String vname = ((BasicExpression) scope).basicString(); + vartypes.put(vname, scope.getType()); + } + } + + if (right.isBoolean()) { } + else + { System.err.println("!! Right argument of " + operator + + " must be boolean"); + right.setType(new Type("boolean", null)); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + } + else if (operator.equals("->select") || + operator.equals("->reject")) + { if (left.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + left.setType(new Type("Sequence", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + if (right.isBoolean()) { } + else + { System.err.println("!! Right argument of " + operator + + " must be boolean"); + right.setType(new Type("boolean", null)); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + type = left.type; + elementType = left.elementType; + multiplicity = ModelElement.MANY; + } + else if (operator.equals("|") || operator.equals("|R")) + { BinaryExpression lexp = (BinaryExpression) left; + Expression scope = lexp.right; + Expression vbl = lexp.left; + + Type vblType = (Type) vartypes.get(vbl + ""); + + if (scope.isCollection()) + { if (Type.isVacuousType(scope.elementType)) + { System.err.println("!! No element type for " + scope); + Type tt = (Type) vartypes.get(scope + ""); + if (tt != null && + !Type.isVacuousType(tt.elementType)) + { scope.setElementType(tt.elementType); + vbl.setType(tt.elementType); + } + else if (vblType != null) + { scope.setElementType(vblType); + vbl.setType(vblType); + } + + System.out.println(">> Set element type to " + scope.getElementType()); + } + } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + + Type tt = (Type) vartypes.get(scope + ""); + if (tt != null) + { scope.setType(tt); } + else + { scope.setType(new Type("Sequence", null)); } + + if (tt != null && + !Type.isVacuousType(tt.elementType)) + { scope.setElementType(tt.elementType); + vbl.setType(tt.elementType); + } + else if (vblType != null) + { scope.setElementType(vblType); + vbl.setType(vblType); + } + + if (scope instanceof BasicExpression) + { String vname = ((BasicExpression) scope).basicString(); + vartypes.put(vname, scope.getType()); + } + } + + if (right.isBoolean()) { } + else + { System.err.println("!! Right argument of " + operator + + " must be boolean"); + right.setType(new Type("boolean", null)); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + type = scope.type; + elementType = scope.elementType; + multiplicity = ModelElement.MANY; + } + else if (operator.equals("->selectMinimals") || + operator.equals("->selectMaximals")) + { if (left.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + left.setType(new Type("Sequence", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + // right argument should be comparables. + + type = left.type; + elementType = left.elementType; + multiplicity = ModelElement.MANY; + } + else if ("|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator)) + { BinaryExpression lexp = (BinaryExpression) left; + Expression scope = lexp.right; + + if (scope.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + scope.setType(new Type("Sequence", null)); + + if (scope instanceof BasicExpression) + { String vname = ((BasicExpression) scope).basicString(); + vartypes.put(vname, scope.getType()); + } + } + + type = scope.type; + elementType = scope.elementType; + multiplicity = ModelElement.MANY; + } + else if (operator.equals("->sortedBy")) + { if (left.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + left.setType(new Type("Sequence", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + // right argument should be comparable or list. + + type = new Type("Sequence", null); + type.setElementType(left.elementType); + elementType = left.elementType; + multiplicity = ModelElement.MANY; + } + else if ("|sortedBy".equals(operator)) + { BinaryExpression lexp = (BinaryExpression) left; + Expression scope = lexp.right; + + if (scope.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + scope.setType(new Type("Sequence", null)); + + if (scope instanceof BasicExpression) + { String vname = ((BasicExpression) scope).basicString(); + vartypes.put(vname, scope.getType()); + } + } + + // right argument should be comparable or list. + + type = new Type("Sequence", null); + type.setElementType(scope.elementType); + elementType = scope.elementType; + multiplicity = ModelElement.MANY; + } + else if (operator.equals("->collect")) + { if (left.isCollection() || left.isMap()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection or map"); + left.setType(new Type("Sequence", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + Type tl = (Type) vartypes.get(left + ""); + + if (left.isMap() || Type.isMapType(tl)) + { elementType = right.getType(); + type = new Type("Map", null); + type.setElementType(elementType); + if (tl == null) { tl = tleft; } + type.setKeyType(tleft.getKeyType()); + } + else + { elementType = right.getType(); + type = new Type("Sequence", null); + type.setElementType(elementType); + } // NOT sorted + } + else if (operator.equals("->unionAll") || + operator.equals("->intersectAll") || + operator.equals("->concatenateAll") || + operator.equals("->any")) + { if (left.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + left.setType(new Type("Sequence", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + if (operator.equals("->any")) + { if (right.isBoolean()) { } + else + { System.err.println("!! Right argument of " + operator + + " must be boolean"); + right.setType(new Type("boolean", null)); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + type = left.elementType; + } + } + else if (operator.equals("|C")) + { BinaryExpression lexp = (BinaryExpression) left; + Expression scope = lexp.right; + Expression vbl = lexp.left; + + Type vblType = (Type) vartypes.get(vbl + ""); + + Type scopetype = (Type) vartypes.get(scope + ""); + + if (scope.isCollection() || scope.isMap()) + { if (Type.isVacuousType(scope.elementType)) + { System.err.println("!! No element type for " + scope); + Type tt = (Type) vartypes.get(scope + ""); + if (tt != null && + !Type.isVacuousType(tt.elementType)) + { scope.setElementType(tt.elementType); + vbl.setType(tt.elementType); + } + else if (vblType != null) + { scope.setElementType(vblType); + vbl.setType(vblType); + } + + System.out.println(">> Set " + scope + " element type to " + scope.getElementType()); + } + } + else if (Type.isMapType(scopetype) || + Type.isCollectionType(scopetype)) + { if (Type.isVacuousType(scope.elementType)) + { System.err.println("!! No element type for " + scope); + if (scopetype != null && + !Type.isVacuousType(scopetype.elementType)) + { scope.setElementType(scopetype.elementType); + vbl.setType(scopetype.elementType); + } + else if (vblType != null) + { scope.setElementType(vblType); + vbl.setType(vblType); + } + + scope.setType(scopetype); + + System.out.println(">> Set " + this + " element type to " + scope.getElementType()); + } + } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + scope.setType(new Type("Sequence", null)); + + if (scope instanceof BasicExpression) + { String vname = ((BasicExpression) scope).basicString(); + vartypes.put(vname, scope.getType()); + } + } + + if (scope.isMap() || Type.isMapType(scopetype)) + { elementType = right.getType(); + type = new Type("Map", null); + type.setElementType(elementType); + if (scopetype == null) { scopetype = scope.getType(); } + type.setKeyType(scopetype.getKeyType()); + + // JOptionPane.showInputDialog(">> Type of " + this + " is " + type); + } + else + { elementType = right.getType(); + type = new Type("Sequence", null); + type.setElementType(elementType); + } // NOT sorted + } + else if ("|unionAll".equals(operator) || + "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { BinaryExpression lexp = (BinaryExpression) left; + Expression scope = lexp.right; + Expression vbl = lexp.left; + + Type vblType = (Type) vartypes.get(vbl + ""); + + if (scope.isCollection()) + { if (Type.isVacuousType(scope.elementType)) + { System.err.println("!! No element type for " + scope); + Type tt = (Type) vartypes.get(scope + ""); + if (tt != null && + !Type.isVacuousType(tt.elementType)) + { scope.setElementType(tt.elementType); + vbl.setType(tt.elementType); + } + else if (vblType != null) + { scope.setElementType(vblType); + vbl.setType(vblType); + } + + System.out.println(">> Set element type to " + scope.getElementType()); + } + } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + scope.setType(new Type("Sequence", null)); + + if (scope instanceof BasicExpression) + { String vname = ((BasicExpression) scope).basicString(); + vartypes.put(vname, scope.getType()); + } + } + } + else if ("->closure".equals(operator)) + { if (left.isCollection()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a collection"); + left.setType(new Type("Set", null)); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + else if (":".equals(operator) || "/:".equals(operator)) + { // right must be a collection + if (right.isCollection()) { } + else + { System.err.println("!! Right argument of " + operator + + " must be a collection"); + right.setType(new Type("Set", null)); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + type = new Type("boolean", null); + } + else if ("=".equals(operator) || "/=".equals(operator)) + { type = new Type("boolean", null); + if (Type.hasVacuousType(left) && + !Type.hasVacuousType(right)) + { left.setType(right.getType()); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, right.getType()); + } + } // and vice-versa + } + else if ("->compareTo".equals(operator)) + { type = new Type("int", null); + if (Type.hasVacuousType(left) && + !Type.hasVacuousType(right)) + { left.setType(right.getType()); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, right.getType()); + } + } + } + else if ("->count".equals(operator) || + "->indexOf".equals(operator) || + operator.equals("->lastIndexOf")) + { type = new Type("int",null); + + // left must be string or sequence: + if (left.isSequence() || left.isString()) { } + else + { System.err.println("!! Left argument of " + operator + + " must be a string or sequence"); + } + } + else if ("->oclAsType".equals(operator)) + { type = Type.getTypeFor(right + "", types, entities); + if (type == null) + { System.err.println("!! ERROR: unrecognised type in cast expression: " + this); + // JOptionPane.showMessageDialog(null, "Unrecognised type in cast " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + type = left.getType(); + } + else if (type.getElementType() != null) + { elementType = type.getElementType(); } + else + { elementType = left.getElementType(); } + + System.out.println(">>> Type of " + this + " is " + type); + } + else if ("->at".equals(operator)) + { if (left.isSequence() || left.isMap() || left.isString()) + { } + else + { System.err.println("!! Left hand side of ->at must be a sequence, string or map!"); + } + + if (left.isString() && right.isInt()) { } + else if (left.isSequence() && right.isInt()) { } + else if (left.isString() || left.isSequence()) + { System.err.println("!! Index of " + this + " must be an integer"); + right.setType(new Type("int", null)); + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + type = left.elementType; + } // and right for map must be of keytype of left. + else if ("->apply".equals(operator)) + { // lhs must be a function + + if (left.hasFunctionType()) + { Type ftype = left.getType(); + if (ftype != null) + { type = ftype.getElementType(); } + + if (Type.isVacuousType(type)) + { Type vtype = (Type) vartypes.get(left + ""); + if (vtype != null && + !Type.isVacuousType(vtype.getElementType())) + { type = vtype.getElementType(); } + } + + if (ftype != null) + { Type ktype = ftype.getKeyType(); + if (Type.isVacuousType(ktype) && + !Type.isVacuousType(right.getType())) + { ftype.setKeyType(right.getType()); } + } + } + else + { System.err.println("!! LHS of " + this + " must be a function"); + Type ftype = new Type("Function", null); + ftype.setKeyType(right.getType()); + ftype.setElementType(new Type("OclAny", null)); + left.setType(ftype); + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if ("->pow".equals(operator)) + { type = new Type("double",null); + elementType = type; + + if (left.isNumeric()) { } + else + { System.err.println("!! LHS of " + this + " must be a number"); + Type ftype = new Type("double", null); + ftype.setElementType(new Type("double", null)); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isNumeric()) { } + else + { System.err.println("!! RHS of " + this + " must be a number"); + Type ftype = new Type("double", null); + ftype.setElementType(new Type("double", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if ("->roundTo".equals(operator) || + "->truncateTo".equals(operator)) + { type = new Type("double",null); + elementType = type; + + if (left.isNumeric()) { } + else + { System.err.println("!! LHS of " + this + " must be a number"); + Type ftype = new Type("double", null); + ftype.setElementType(new Type("double", null)); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isInt()) { } + else + { System.err.println("!! RHS of " + this + " must be an int"); + Type ftype = new Type("int", null); + ftype.setElementType(new Type("int", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if ("->gcd".equals(operator) || + operator.equals("div") || + operator.equals("mod")) + { type = left.getType(); + if (type == null) + { type = new Type("long", null); } + + if (left.isInteger()) { } + else + { System.err.println("!! LHS of " + this + " must be an integer"); + Type ftype = new Type("long", null); + ftype.setElementType(new Type("long", null)); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isInteger()) { } + else + { System.err.println("!! RHS of " + this + " must be an integer"); + Type ftype = new Type("long", null); + ftype.setElementType(new Type("long", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + if (operator.equals("->oclIsKindOf".equals(operator) || + "->oclIsTypeOf".equals(operator))) + { type = new Type("boolean",null); + type = Type.getTypeFor(right + "", types, entities); + if (type == null) + { System.err.println("!! ERROR: unrecognised type in cast expression: " + this); + type = left.getType(); + right.setType(new Type("OclType", null)); + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + } // right must be a type + else if ("->hasPrefix".equals(operator) || + "->hasSuffix".equals(operator) || + "->hasMatch".equals(operator) || + "->isMatch".equals(operator) || + operator.equals("->equalsIgnoreCase")) + { type = new Type("boolean",null); + + if (left.isString()) { } + else + { System.err.println("!! LHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isString()) { } + else + { System.err.println("!! RHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if (operator.equals("->before") || + operator.equals("->after") || + operator.equals("->firstMatch")) + { type = new Type("String",null); + elementType = new Type("String", null); + + if (left.isString()) { } + else + { System.err.println("!! LHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isString()) { } + else + { System.err.println("!! RHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if (operator.equals("->excludingAt") && left.isString()) + { type = new Type("String",null); + elementType = new Type("String", null); + + if (right.isString()) { } + else + { System.err.println("!! RHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if (operator.equals("->excludingAt") && + left.isCollection()) + { type = left.type; + elementType = left.elementType; + } + else if ("->split".equals(operator) || + "->allMatches".equals(operator)) + { type = new Type("Sequence",null); + elementType = new Type("String",null); + type.elementType = elementType; + + if (left.isString()) { } + else + { System.err.println("!! LHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isString()) { } + else + { System.err.println("!! RHS of " + this + " must be a string"); + Type ftype = new Type("String", null); + ftype.setElementType(new Type("String", null)); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if ("->restrict".equals(operator) || + "->antirestrict".equals(operator)) + { if (tleft != null) + { type = tleft; + elementType = left.elementType; + } // sorted if left is sorted + else + { type = new Type("Map", null); } + + if (left.isMap()) { } + else + { System.err.println("!! LHS of " + this + " must be a map"); + Type ftype = new Type("Map", null); + ftype.setElementType(new Type("OclAny", null)); + ftype.setKeyType(right.elementType); + left.setType(ftype); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, ftype); + } + } + + if (right.isCollection()) { } + else + { System.err.println("!! RHS of " + this + " must be a collection"); + Type ftype = new Type("Set", null); + right.setType(ftype); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, ftype); + } + } + } + else if (operator.equals("->resizeTo")) + { type = new Type("Ref", null); + elementType = left.elementType; + type.setElementType(left.elementType); + left.setArray(true); + isArray = true; + } + else if (operator.equals("->sequenceRange")) + { type = new Type("Sequence", null); + elementType = left.elementType; + type.setElementType(left.elementType); + } + else if (operator.equals("<>=") || + comparitors.contains(operator)) + { type = new Type("boolean", null); + elementType = new Type("boolean", null); + + if (Type.hasVacuousType(left) && + !Type.hasVacuousType(right)) + { left.setType(right.getType()); + + if (left instanceof BasicExpression) + { String vname = ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + else if (Type.hasVacuousType(right) && + !Type.hasVacuousType(left)) + { right.setType(left.getType()); + + if (right instanceof BasicExpression) + { String vname = ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + } + else if (operator.equals("+")) + { // either one or both is a string, + // or both are numeric + + if (left.isString() || right.isString()) + { type = new Type("String", null); + elementType = new Type("String", null); + } + else if (left.isNumeric() && right.isNumeric()) + { } + else + { if (!right.isNumeric()) + { System.err.println("!! RHS of " + this + + " must be numeric"); + right.setType(new Type("double", null)); + type = new Type("double", null); + elementType = new Type("double", null); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + if (!left.isNumeric()) + { System.err.println("!! LHS of " + this + + " must be numeric"); + left.setType(new Type("double", null)); + type = new Type("double", null); + elementType = new Type("double", null); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + } + else if (operator.equals("*") || operator.equals("/")) + { // both are numeric + + if (left.isNumeric() && right.isNumeric()) + { } + else + { if (!right.isNumeric()) + { System.err.println("!! RHS of " + this + + " must be numeric"); + right.setType(new Type("double", null)); + type = new Type("double", null); + elementType = new Type("double", null); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + if (!left.isNumeric()) + { System.err.println("!! LHS of " + this + + " must be numeric"); + left.setType(new Type("double", null)); + type = new Type("double", null); + elementType = new Type("double", null); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + } + else if (operator.equals("-")) + { // Either both are maps, both are collections or + // both are numeric + + if (left.isNumeric() && !right.isNumeric()) + { System.err.println("!! RHS of " + this + + " must be numeric"); + right.setType(new Type("double", null)); + type = new Type("double", null); + elementType = new Type("double", null); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + else if (!left.isNumeric() && right.isNumeric()) + { System.err.println("!! LHS of " + this + + " must be numeric"); + left.setType(new Type("double", null)); + type = new Type("double", null); + elementType = new Type("double", null); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + else if (left.isMap() && !right.isMap()) + { System.err.println("!! RHS of " + this + + " must be map"); + right.setType(new Type("Map", null)); + type = new Type("Map", null); + elementType = left.elementType; + type.setKeyType(left.getType().getKeyType()); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + else if (!left.isMap() && right.isMap()) + { System.err.println("!! LHS of " + this + + " must be map"); + left.setType(new Type("Map", null)); + type = new Type("Map", null); + elementType = right.elementType; + type.setKeyType(right.getType().getKeyType()); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + else if (left.isCollection() && !right.isCollection()) + { System.err.println("!! RHS of " + this + + " must be collection"); + right.setType(left.getType()); + type = left.getType(); + elementType = left.getElementType(); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + else if (!left.isCollection() && right.isCollection()) + { System.err.println("!! LHS of " + this + + " must be collection"); + left.setType(right.getType()); + type = right.getType(); + elementType = right.getElementType(); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + else if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\") || + operator.equals("<:") || + operator.equals("->includesAll") || + operator.equals("/<:") || + operator.equals("->excludesAll")) + { // both are maps or both are collections + left.multiplicity = ModelElement.MANY; + right.multiplicity = ModelElement.MANY; + + Type lftype = left.getType(); + Type rtype = right.getType(); + + Type letype = left.getElementType(); + Type retype = right.getElementType(); + + if (left.isMap() && right.isMap()) + { if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { Vector etypes = new Vector(); + etypes.add(left); + etypes.add(right); + elementType = Type.determineElementType(etypes); + type = new Type("Map", null); + type.setSorted(lftype.isSorted()); + type.setKeyType(lftype.getKeyType()); + type.setElementType(elementType); + } + else + { type = new Type("boolean", null); } + } + else if (left.isCollection() && right.isCollection()) + { if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { Vector etypes = new Vector(); + etypes.add(left); + etypes.add(right); + elementType = Type.determineElementType(etypes); + type = new Type(lftype.getName(), null); + type.setSorted(lftype.isSorted()); + type.setElementType(elementType); + } + else + { type = new Type("boolean", null); } + } + else if (left.isMap() && !right.isMap()) + { System.err.println("!! RHS of " + this + + " must be map"); + + rtype = new Type("Map", null); + rtype.setKeyType(lftype.getKeyType()); // assume + rtype.setElementType(lftype.elementType); + right.setType(rtype); + + if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { type = new Type("Map", null); + elementType = left.elementType; + type.setKeyType(lftype.getKeyType()); + type.setElementType(left.elementType); + type.setSorted(lftype.isSorted()); + } + else + { type = new Type("boolean", null); } + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, rtype); + } + } + else if (!left.isMap() && right.isMap()) + { System.err.println("!! LHS of " + this + + " must be map"); + + lftype = new Type("Map", null); + lftype.setKeyType(rtype.getKeyType()); + lftype.setElementType(right.elementType); + left.setType(lftype); + + if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { type = new Type("Map", null); + elementType = right.elementType; + type.setKeyType(rtype.getKeyType()); + type.setElementType(right.elementType); + // type.setSorted(ltype.isSorted()); + } + else + { type = new Type("boolean", null); } + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + else if (left.isCollection() && !right.isCollection()) + { System.err.println("!! RHS of " + this + + " must be collection"); + right.setType(lftype); + + if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { type = lftype; + elementType = left.getElementType(); + } + else + { type = new Type("boolean", null); } + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + else if (!left.isCollection() && right.isCollection()) + { System.err.println("!! LHS of " + this + + " must be collection"); + left.setType(rtype); + + if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { type = rtype; + elementType = right.getElementType(); + } + else + { type = new Type("boolean", null); } + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + else if (!left.isCollection() && + !left.isMap()) + { System.err.println("!! Arguments of " + this + + " must be collections/maps"); + Type ltype = left.getType(); + + if (ltype.getAlias() != null && + ltype.getAlias().isCollectionType()) + { left.setType(ltype.getAlias()); + right.setType(ltype.getAlias()); + } + else + { Type newsettype = new Type("Set", null); + newsettype.setElementType(new Type("OclAny", null)); + left.setType(newsettype); + right.setType(newsettype); + } + + if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->symmetricDifference") || + operator.equals("->intersection") || + operator.equals("/\\")) + { type = left.getType(); + elementType = left.getElementType(); + } + else + { type = new Type("boolean", null); } + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + } + else if (operator.equals("^") || + "->concatenate".equals(operator)) + { // both are sequences + if (left.isSequence() && !right.isSequence()) + { System.err.println("!! RHS of " + this + + " must be sequence"); + right.setType(left.getType()); + type = left.getType(); + elementType = left.getElementType(); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + else if (!left.isSequence() && right.isSequence()) + { System.err.println("!! LHS of " + this + + " must be sequence"); + left.setType(right.getType()); + type = right.getType(); + elementType = right.getElementType(); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + else if (operator.equals("->including") || + operator.equals("->excluding") || + operator.equals("->excludingFirst")) + { // LHS must be a collection, not a map + + if (!left.isCollection()) + { System.err.println("!! LHS of " + this + + " must be a collection"); + left.setType(new Type("Sequence", null)); + elementType = right.getType(); + left.setElementType(elementType); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + type = left.getType(); + } + else if (operator.equals("->prepend") || + operator.equals("->append")) + { // LHS must be a sequence + + if (!left.isSequence()) + { System.err.println("!! LHS of " + this + + " must be sequence"); + left.setType(new Type("Sequence", null)); + elementType = right.getType(); + left.setElementType(elementType); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + + type = left.getType(); + } + else if (operator.equals("|->")) + { type = new Type("OclAny", null); + elementType = tright; + type.setElementType(tright); + } // Really a Tuple type. + else if (operator.equals("<+")) + { type = tleft; } // Map override. + else if (operator.equals(":") || + operator.equals("/:")) + { + type = new Type("boolean",null); + + if (!right.isCollection()) + { System.err.println("!! RHS of " + this + + " must be a collection"); + right.setType(new Type("Sequence", null)); + elementType = left.getType(); + right.setElementType(elementType); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + } + else if (operator.equals("->includes") || + operator.equals("->excludes")) + { type = new Type("boolean",null); + if (!left.isCollection()) + { System.err.println("!! LHS of " + this + + " must be a collection"); + left.setType(new Type("Sequence", null)); + left.setElementType(right.getType()); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + else if (operator.equals("&") || operator.equals("<=>") || + operator.equals("xor") || + operator.equals("or") || operator.equals("=>")) + { // both must be boolean + + if (left.isBoolean() && right.isBoolean()) { } + else + { if (!right.isBoolean()) + { System.err.println("!! RHS of " + this + + " must be boolean"); + right.setType(new Type("boolean", null)); + type = new Type("boolean", null); + elementType = new Type("boolean", null); + + if (right instanceof BasicExpression) + { String vname = + ((BasicExpression) right).basicString(); + vartypes.put(vname, right.getType()); + } + } + + if (!left.isBoolean()) + { System.err.println("!! LHS of " + this + + " must be boolean"); + left.setType(new Type("boolean", null)); + type = new Type("boolean", null); + elementType = new Type("boolean", null); + + if (left instanceof BasicExpression) + { String vname = + ((BasicExpression) left).basicString(); + vartypes.put(vname, left.getType()); + } + } + } + } + + return true; + // return typeCheck(types,entities,contexts,env); + } + + public boolean typeCheck(final Vector types, + final Vector entities, + final Vector contexts, + final Vector env) + { Vector context = new Vector(); + + if (operator.equals(",")) + { left.typeCheck(types,entities,contexts,env); + right.typeCheck(types,entities,contexts,env); + type = right.type; + elementType = right.elementType; + multiplicity = right.multiplicity; + return true; + } + + if (operator.equals("let") && accumulator != null) + { boolean lrt = left.typeCheck(types,entities,contexts,env); + context.addAll(contexts); + + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(accumulator); + boolean rtc = right.typeCheck(types,entities,context,env1); + // type = new Type("Function",accumulator.getType(),right.type); + // elementType = right.type; + type = right.type; + elementType = right.elementType; + System.out.println(">>> Typechecked let expression: " + lrt + " " + rtc + " " + type); + return true; + } + + if (operator.equals("->iterate") && + iteratorVariable != null && + accumulator != null) + { boolean lrt = left.typeCheck(types,entities,contexts,env); + context.addAll(contexts); + Expression init = accumulator.getInitialExpression(); + // assumed non-null + + if (init != null) + { init.typeCheck(types,entities,context,env); + System.out.println(">>> Type of " + init + + " is " + init.getType()); + accumulator.setType(init.getType()); + if (init.getElementType() != null) + { accumulator.setElementType(init.getElementType()); } + else if (init.getType() != null && + init.getType().getElementType() != null) + { accumulator.setElementType( + init.getType().getElementType()); + } + else + { accumulator.setElementType( + new Type("OclAny", null)); + } + } + + // if ((accumulator.getType() == null || + // "OclType".equals(accumulator.getType() + "")) + // && init != null) + // { accumulator.setType(init.getType()); } + + System.out.println(">>> Type of " + accumulator + + " is " + accumulator.getType()); + + Attribute itvar = + new Attribute(iteratorVariable, left.getElementType(), + ModelElement.INTERNAL); + + System.out.println(">>> Type of " + itvar + + " is " + itvar.getType()); + + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(itvar); + env1.add(accumulator); + boolean rtc = + right.typeCheck(types,entities,context,env1); + + if (accumulator.getType() != null && + accumulator.getElementType() != null) + { type = accumulator.getType(); + elementType = accumulator.getElementType(); + } + else + { type = right.getType(); + elementType = right.getElementType(); + } + + + System.out.println(">>> Typechecked ->iterate expression: " + this + " Type: " + type + " Elementtype: " + elementType); + return true; + } + + + if (operator.equals("#") || operator.equals("#1") || + operator.equals("#LC") || operator.equals("!")) + { BinaryExpression lexp = (BinaryExpression) left; + boolean lrt = lexp.right.typeCheck(types,entities,contexts,env); + + // lexp.right must be multiple, also + + Type et = lexp.right.elementType; + + // but if lexp.right.isMap, actually the keyType + + if (et == null) + { System.err.println("!!! TYPE ERROR: null element type in " + lexp.right + " in " + this); + // JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + et = new Type("OclAny", null); + } + + context.addAll(contexts); + + Attribute att = + new Attribute(lexp.left + "",et,ModelElement.INTERNAL); + att.setEntity(et.getEntity()); + att.setElementType(et.getElementType()); + // FOR (s->subcollections())->exists( x | ... ) + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(att); + lexp.typeCheck(types,entities,contexts,env1); + boolean rtc = right.typeCheck(types,entities,context,env1); + type = new Type("boolean",null); + elementType = new Type("boolean", null); + return true; + } + + if (operator.equals("->exists") || + operator.equals("->exists1") || + "->existsLC".equals(operator) || + operator.equals("->isUnique") || + operator.equals("->forAll")) + { + boolean lrt = left.typeCheck(types,entities,contexts,env); + Type et = left.elementType; + + // but if left.isMap, actually the keyType + + if (et != null && et.isEntity()) + { context.add(et.getEntity()); } + context.addAll(contexts); + // left must be multiple + + // Attribute att = + // new Attribute(et.getName().toLowerCase() + + // "x",et,ModelElement.INTERNAL); + // Vector env1 = new Vector(); + // env1.addAll(env); + // env1.add(att); + // lexp.typeCheck(types,entities,env1); + boolean rtc = right.typeCheck(types,entities,context,env); + type = new Type("boolean",null); + elementType = new Type("boolean", null); + return true; + } + else if (operator.equals("|") || operator.equals("|R") || + "|sortedBy".equals(operator) || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator)) + { BinaryExpression lexp = (BinaryExpression) left; + boolean lrt = + lexp.right.typeCheck(types,entities,contexts,env); + + // lexp.right must be multiple + + Type et = lexp.right.elementType; + + // but if lexp.right.isMap, actually the keyType + + if (et == null) + { Type tt = lexp.right.getType(); + if (tt != null) + { et = tt.getElementType(); } + } + + System.out.println(">> *** Type of " + lexp.right + " = " + lexp.right.type + "(" + et + ")"); + + if (et == null) + { System.err.println("!! Warning: no element type for " + lexp.right + " in " + this + " in environment " + env); + // JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + Attribute attr = + (Attribute) ModelElement.lookupByName(lexp.right + "", env); + + if (attr != null && + !Type.isVacuousType(attr.getElementType())) + { et = attr.getElementType(); } + else + { et = new Type("OclAny", null); } + } + + // && et.isEntity()) + // { context.add(et.getEntity()); } + context.addAll(contexts); + + Attribute att = + new Attribute(lexp.left + "",et,ModelElement.INTERNAL); + att.setEntity(et.getEntity()); + att.setElementType(et.getElementType()); + // FOR (s->subcollections())->exists( x | ... ) + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(att); + lexp.typeCheck(types,entities,contexts,env1); + boolean rtc = + right.typeCheck(types,entities,context,env1); + Type stleft = lexp.right.getType(); + Type stright = right.getType(); + Entity seleft = lexp.right.getEntity(); + tcSelect(stleft,stright,seleft); + + if (operator.equals("|") || operator.equals("|R") || + operator.equals("|selectMinimals") || + operator.equals("|selectMaximals")) + { isSorted = lexp.right.isSorted; } + + return true; + } + else if (operator.equals("->select") || + operator.equals("->sortedBy") || + operator.equals("->reject") || + operator.equals("->selectMinimals") || + operator.equals("->selectMaximals")) + { // System.out.println("Type-checking select/reject " + this); + left.typeCheck(types,entities,contexts,env); + Vector scontext = new Vector(); + Type stleft = left.getType(); + // must be collection type + Type seltype = left.elementType; + if (seltype != null && seltype.isEntity()) + { scontext.add(seltype.getEntity()); } + else if (stleft != null && stleft.isEntity()) + { scontext.add(stleft.getEntity()); } + else if (seltype == null) + { System.err.println("! Warning: no valid element type in " + left + " in " + this); + // JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + } + + scontext.addAll(contexts); + right.typeCheck(types,entities,scontext,env); + Type stright = right.getType(); + Entity seleft = left.getEntity(); + tcSelect(stleft,stright,seleft); + + if (operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->selectMinimals") || + operator.equals("->selectMaximals")) + { isSorted = left.isSorted; } + + return true; + } + else if (operator.equals("->collect") || + operator.equals("->unionAll") || + operator.equals("->intersectAll") || + operator.equals("->concatenateAll")) // and |C + { // System.out.println("Type-checking collect " + this); + left.typeCheck(types,entities,contexts,env); + Vector ccontext = new Vector(); + Type ctleft = left.getType(); + // must be a collection type + Type celtype = left.elementType; + if (celtype != null && celtype.isEntity()) + { ccontext.add(celtype.getEntity()); } + else if (ctleft != null && ctleft.isEntity()) + { ccontext.add(ctleft.getEntity()); } + else if (celtype == null) + { System.err.println("! Warning: no element type in " + left + " in " + this); + // JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + celtype = new Type("OclAny", null); + } + + ccontext.addAll(contexts); + right.typeCheck(types,entities,ccontext,env); + Type ctright = right.getType(); + Entity ceright = right.getEntity(); + tcCollect(ctleft,ctright,ceright); + return true; + } // as for exists etc, include |C + else if (operator.equals("|C") || + "|unionAll".equals(operator) || + "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { BinaryExpression lexp = (BinaryExpression) left; + // must be a collection + + boolean lrt = + lexp.right.typeCheck(types,entities,contexts,env); + Type et = lexp.right.elementType; + + // if (lexp.right.isMap()) + // { et = lexp.right.getType().getKeyType(); } + + if (et == null) + { Type tt = lexp.right.getType(); + if (tt != null) + { et = tt.getElementType(); } + System.out.println(">> Type of " + lexp.right + " = " + tt + "(" + et + ")"); + } + + if (et == null) + { System.err.println("! Warning: no element type for " + lexp.right + " in " + this); + // JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + et = new Type("OclAny", null); + } + + context.addAll(contexts); + Attribute att = + new Attribute(lexp.left + "", et, ModelElement.INTERNAL); + if (et != null) + { att.setElementType(et.getElementType()); } + + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(att); + lexp.typeCheck(types,entities,contexts,env1); + boolean rtc = right.typeCheck(types,entities,context,env1); + Type stleft = lexp.right.getType(); + Type stright = right.getType(); + Entity seright = null; + if (right.elementType != null) + { if (right.elementType.isEntity()) + { seright = right.elementType.getEntity(); } + } + + tcCollect(stleft,stright,seright); + // System.out.println("TYPE OF " + this + " IS " + type + ", " + elementType); + return true; + } + else if (operator.equals("->any")) + { left.typeCheck(types,entities,contexts,env); + Vector ccontext = new Vector(); + Type ctleft = left.getType(); + // must be a collection type + Type celtype = left.elementType; + if (celtype != null && celtype.isEntity()) + { ccontext.add(celtype.getEntity()); } + else if (ctleft != null && ctleft.isEntity()) + { ccontext.add(ctleft.getEntity()); } + else if (celtype == null) + { System.err.println("!! Warning: no element type in " + left + " in " + this); + // JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + celtype = new Type("OclAny", null); + } + + ccontext.addAll(contexts); + right.typeCheck(types,entities,ccontext,env); + type = celtype; // for ->any(Pred) + if (type != null && type.isCollectionType()) + { multiplicity = ModelElement.MANY; + elementType = type.getElementType(); + } + return true; + } + else if (operator.equals("|A")) + { BinaryExpression lexp = (BinaryExpression) left; + // must be a collection + + boolean lrt = lexp.right.typeCheck(types,entities,contexts,env); + Type et = lexp.right.elementType; + if (et == null) + { System.err.println("! Warning: no element type for " + lexp.right + " in " + this); + + // JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + et = new Type("OclAny", null); + } + + context.addAll(contexts); + Attribute att = + new Attribute(lexp.left + "", et, ModelElement.INTERNAL); + if (et != null) + { att.setElementType(et.getElementType()); } + + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(att); + lexp.typeCheck(types,entities,contexts,env1); + boolean rtc = right.typeCheck(types,entities,context,env1); + Type stleft = lexp.right.getType(); + Type stright = right.getType(); + Entity seright = null; + if (right.elementType != null) + { if (right.elementType.isEntity()) + { seright = right.elementType.getEntity(); } + } + // tcCollect(stleft,stright,seright); + // System.out.println("TYPE OF " + this + " IS " + type + ", " + elementType); + type = et; // for ->any(x | Pred) + if (type != null && type.isCollectionType()) + { multiplicity = ModelElement.MANY; + elementType = type.getElementType(); + } + return true; + } + else if ("->closure".equals(operator)) + { type = new Type("Set",null); + context.addAll(contexts); + left.typeCheck(types,entities,context,env); + + if (left.elementType != null && left.elementType.isEntity()) + { entity = left.elementType.getEntity(); } + else + { entity = left.entity; } // the owner of the relation being closured + + if (left.isMultiple()) {} + else + { System.err.println("!! ERROR: LHS of " + this + " must be collection"); + // JOptionPane.showMessageDialog(null, "ERROR: LHS of " + this + " must be collection", + // "Type error", JOptionPane.ERROR_MESSAGE); + } + + if (entity != null) + { Association ast = entity.getDefinedRole(right + ""); + elementType = left.elementType; + type.setElementType(elementType); + if (ast != null) + { Entity entc = ast.closureEntity(); + if (entc != null) + { elementType = new Type(entc); + type.setElementType(elementType); + } + + if (ast.isClosurable()) { } + else + { JOptionPane.showMessageDialog(null, "ERROR: association in " + this + " cannot be closured", + "Expression error", JOptionPane.ERROR_MESSAGE); + } + // System.out.println(">>> FOUND ASSOCIATION " + ast); + } + Vector context2 = new Vector(); + context2.add(entity); + right.typeCheck(types,entities,context2,env); + } + else + { System.err.println("!! ERROR: no entity for " + this); + elementType = left.elementType; + type.setElementType(elementType); + } + multiplicity = ModelElement.MANY; + // System.out.println(">>>> Element type = " + elementType + " TYPE= " + type + " ENTIY=" + entity); + return true; + } + + boolean lt = false; + if (left == null) + { System.err.println("!! SYNTAX ERROR: Left expression of " + this + " invalid!"); + JOptionPane.showMessageDialog(null, "Left expression of " + this + " invalid!", + "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + else + { lt = left.typeCheck(types,entities,contexts,env); } + + boolean rt = false; + + if (right == null) + { System.err.println("!! SYNTAX ERROR: Right expression of " + this + " invalid!"); + JOptionPane.showMessageDialog(null, "Right expression of " + this + " invalid!", + "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + else + { rt = right.typeCheck(types,entities,contexts,env); } + + // For a -> operator, treat left like objectRef + Type tleft = left.getType(); + Type tright = right.getType(); + Entity eleft = left.getEntity(); + Entity eright = right.getEntity(); + + if (operator.equals(":") && left.umlkind == VARIABLE) // or UNKNOWN + { Attribute var = (Attribute) ModelElement.lookupByName(left + "",env); + if (var == null && !("result".equals(left + ""))) + { // add it for subsequent type checking + Attribute att = + new Attribute(left + "",right.elementType,ModelElement.INTERNAL); + env.add(att); + if (right.elementType != null) + { att.setElementType( + right.elementType.getElementType()); + } + } // set the entity to eleft or eright? + + if (left.type == null) + { left.type = right.elementType; } + } + + if (operator.equals("=") && left.umlkind == VARIABLE) // or UNKNOWN + { Attribute var = (Attribute) ModelElement.lookupByName(left + "",env); + if (var == null && !("result".equals(left + ""))) + { // add it for subsequent type checking + Attribute att = + new Attribute(left + "",right.type,ModelElement.INTERNAL); + att.setElementType(right.elementType); + env.add(att); + } // set the entity to eleft? + + if (left.type == null) + { left.type = right.type; } + + if (left.elementType == null) + { left.elementType = right.elementType; } + // System.out.println("SETTING VARIABLE TYPE: " + type + " " + elementType + " " + var); + } + + // ->oclAsType(T)? T.umlkind == CLASSID, and type = T.elementType + + if ("->count".equals(operator) || + "->indexOf".equals(operator) || + operator.equals("->lastIndexOf") || + operator.equals("->compareTo")) + { type = new Type("int",null); } + else if ("->oclAsType".equals(operator)) + { type = Type.getTypeFor(right + "", types, entities); + if (type == null) + { System.err.println("!! ERROR: unrecognised type in cast expression: " + this); + // JOptionPane.showMessageDialog(null, "Unrecognised type in cast " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + type = left.getType(); + } + else if (type.getElementType() != null) + { elementType = type.getElementType(); } + else + { elementType = left.getElementType(); } + + System.out.println(">>> Type of " + this + " is " + type); + } + else if ("->at".equals(operator)) + { if (left.type != null && "String".equals(left.type.getName())) + { type = new Type("String", null); + elementType = type; + } + else + { type = left.elementType; + if (type != null && "String".equals(type.getName())) + { elementType = new Type("String", null); } + else if (type != null) + { elementType = type.getElementType(); } + else + { Attribute leftvar = + (Attribute) ModelElement.lookupByName(left + "", env); + if (leftvar != null) + { type = leftvar.getElementType(); + if (type != null) + { elementType = type.getElementType(); } + } + + if (elementType == null) + { System.err.println("! Warning: no element type for " + left + " in environment " + env); + elementType = new Type("OclAny", null); + } + } + } + } // and right must be of type int. + else if ("->apply".equals(operator)) + { // lhs must be a function + Type ftype = left.getType(); + + if (ftype != null) + { type = ftype.getElementType(); } + + if (type == null) + { System.err.println("!! Warning: no function result type in " + this); + type = new Type("OclAny", null); + if (ftype == null) + { ftype = new Type("Function", null); + ftype.setKeyType(right.getType()); + } + ftype.setElementType(type); + } + else + { elementType = type.elementType; } + } + else if ("->pow".equals(operator)) + { type = new Type("double",null); + elementType = type; + } + else if ("->roundTo".equals(operator) || + "->truncateTo".equals(operator)) + { type = new Type("double",null); + elementType = type; + } + else if ("->gcd".equals(operator)) + { type = new Type("long",null); + elementType = type; + } + else if (operator.equals("div")) + { type = left.getType(); + if (type == null) + { type = new Type("int", null); } + } + /* else if (operator.equals("->split")) + { elementType = new Type("String",null); + type = new Type("Sequence", null); + type.setElementType(elementType); + } */ + else if ("->hasPrefix".equals(operator) || + "->hasSuffix".equals(operator) || + "->hasMatch".equals(operator) || + "->isMatch".equals(operator) || + operator.equals("->equalsIgnoreCase") || + "->oclIsKindOf".equals(operator) || + "->oclIsTypeOf".equals(operator)) + { type = new Type("boolean",null); } + else if (operator.equals("->before") || + operator.equals("->after") || + operator.equals("->firstMatch")) + { type = new Type("String",null); + elementType = new Type("String", null); + } + else if (operator.equals("->excludingAt") && + left.isString()) + { type = new Type("String",null); + elementType = new Type("String", null); + } + else if (operator.equals("->excludingAt") && + left.isCollection()) + { type = left.type; + elementType = left.elementType; + isSorted = left.isSorted; + } + else if ("->split".equals(operator) || + "->allMatches".equals(operator)) + { type = new Type("Sequence",null); + elementType = new Type("String",null); + type.elementType = elementType; + } + else if ("->restrict".equals(operator) || + "->antirestrict".equals(operator)) + { if (tleft != null) + { type = tleft; + elementType = left.elementType; + } + else + { type = new Type("Map", null); } + isSorted = left.isSorted; + } + else if (operator.equals("->resizeTo")) + { type = new Type("Ref", null); + elementType = left.elementType; + type.setElementType(left.elementType); + left.setArray(true); + isArray = true; + } + else if (operator.equals("->sequenceRange")) + { type = new Type("Sequence", null); + elementType = left.elementType; + type.setElementType(left.elementType); + } + else if (operator.equals("<>=") || + comparitors.contains(operator)) + { tcEq(tleft,tright,eleft,eright); + type = new Type("boolean", null); + elementType = new Type("boolean", null); + } + else if (operator.equals("+")) + { tcPlus(tleft,tright,eleft,eright); } + else if (operator.equals("-")) + { tcMinus(tleft,tright,eleft,eright); + isSorted = left.isSorted; + } + else if (operator.equals("\\/") || + operator.equals("^") || + "->concatenate".equals(operator) || + operator.equals("->append") || + operator.equals("->union") || + operator.equals("->including") || + operator.equals("->symmetricDifference") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("->prepend") || + operator.equals("->append") || + operator.equals("->intersection") || + operator.equals("/\\")) + { tcSetOps(tleft,tright,eleft,eright); } + else if (operator.equals("*") || operator.equals("mod") || + operator.equals("/")) + { tcMathOps(tleft,tright,eleft,eright); } + else if (operator.equals("|->")) + { type = new Type("OclAny", null); + elementType = tright; + type.setElementType(tright); + } // Really a Tuple type. + else if (operator.equals("<+")) + { type = tleft; } // Map override. + else if (operator.equals(":") || + operator.equals("<:") || operator.equals("->includesAll") || + operator.equals("/<:") || operator.equals("->excludesAll") || + operator.equals("/:")) + { boolean rmult = right.isMultiple(); + type = new Type("boolean",null); + // System.out.println(left + " type= " + tleft); + // System.out.println(right + " type= " + tright); + + if (rmult) + { } + else + { System.err.println("!! TYPE ERROR: RHS of " + this + " must be a collection"); + // JOptionPane.showMessageDialog(null, "RHS of " + this + " must be a collection!", + // "Type error", JOptionPane.ERROR_MESSAGE); + } // deduce type of one side from that of other + + if (tleft == null && tright != null) + { if (operator.equals(":") || operator.equals("/:")) + { left.setType(right.getElementType()); } + else // if (operator.equals("<:") || operator.equals("/<:")) + { left.setType(tright); } + } + else if (tright == null && tleft != null) + { if (operator.equals(":") || operator.equals("/:")) + { Type rst = new Type("Set", null); + right.setType(rst); + if (right.elementType == null && eleft != null) + { right.setElementType(tleft); // new Type(eleft)); + rst.setElementType(tleft); + } + } + else + { right.setType(tleft); } + } // and set one element type to the other when not null + } + else if (operator.equals("->includes") || + operator.equals("->excludes")) + { boolean lmult = left.isMultiple(); + type = new Type("boolean",null); + if (lmult) + { } + else + { System.err.println("!! TYPE ERROR: LHS of " + this + " must be a collection"); + // JOptionPane.showMessageDialog(null, "LHS of " + this + " must be a collection!", + // "Type error", JOptionPane.ERROR_MESSAGE); + } // deduce type of one side from that of other + + if (tright == null && tleft != null) + { right.setType(left.getElementType()); } + else if (tleft == null && tright != null) + { Type lst = new Type("Set", null); + left.setType(lst); + if (left.elementType == null && eright != null) + { left.setElementType(tright); // new Type(eright)); + lst.setElementType(tright); // new Type(eright)); + } + } // and set one element type to the other when not null + } + else if (operator.equals("&") || operator.equals("<=>") || + operator.equals("xor") || + operator.equals("or") || operator.equals("=>")) + { tcLogical(tleft,tright,eleft,eright); } + // else, it is an extension operator, type is given by its definition + else if (extensionoperators.keySet().contains(operator)) + { type = Expression.getOperatorType(operator); } + + if (type == null) + { System.out.println("! Warning: No type found for " + this); + type = new Type("OclAny", null); + + return false; + } + return true; + } + // x : y, x <: y is x = y if y single. x /: y, x /<: y is x /= y + +// rolea = roleb ?? one multiple other not? + private void tcEq(Type tleft, Type tright, + Entity eleft, Entity eright) + { type = new Type("boolean", null); + elementType = new Type("boolean", null); + + if (tleft != null && tright != null) + { String tlname = tleft.getName(); + String trname = tright.getName(); + if (tleft.equals(tright)) + { type = new Type("boolean",null); } + else if (Type.isNumericType(tlname) && Type.isNumericType(trname)) + { type = new Type("boolean",null); } // not valid to assign though + else if (left.elementType != null && trname.equals("" + left.elementType)) + { type = new Type("boolean",null); } + else if (right.elementType != null && tlname.equals("" + right.elementType)) + { type = new Type("boolean",null); } + else // or if same element types + { System.err.println("! WARNING: different " + + "types " + tleft + " " + tright + " in comparison " + this); + type = new Type("boolean",null); + } + } + else if (eleft != null && eright != null) + { if (eleft.equals(eright)) // only valid for =, /= + { type = new Type("boolean",null); } + else + { Entity common = Entity.commonSuperclass(eleft,eright); + if (common != null) + { // System.out.println("Common superclass is: " + common); + type = new Type("boolean",null); + } + else + { System.err.println("WARNING: incompatible " + + "entities in comparison " + this); + type = new Type("boolean",null); + } + } + } + else + { if (tleft != null && right.getType() == null) + { right.setType(tleft); + right.setElementType(left.getElementType()); + type = new Type("boolean",null); + } + else if (tright != null) + { left.setType(tright); + left.setElementType(right.getElementType()); + type = new Type("boolean",null); + } + else + { System.err.println("!!! TYPE ERROR: Unable to type: " + this); + // JOptionPane.showMessageDialog(null, "Unable to type " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + type = null; + } + } + + type = new Type("boolean", null); + elementType = new Type("boolean", null); + } + + private void tcPlus(Type tleft, Type tright, Entity eleft, Entity eright) + { if (tleft != null && tright != null) + { String tlname = tleft.getName(); + String trname = tright.getName(); + + if (tlname.equals("double") && Type.isNumericType(trname)) + { type = new Type("double",null); } + else if (trname.equals("double") && Type.isNumericType(tlname)) + { type = new Type("double",null); } + else if (tlname.equals("long") && Type.isNumericType(trname)) + { type = new Type("long",null); } + else if (trname.equals("long") && Type.isNumericType(tlname)) + { type = new Type("long",null); } + else if (tleft.equals(tright) && tlname.equals("int")) + { type = new Type("int",null); } + else if (tlname.equals("String") || trname.equals("String")) + { type = new Type("String",null); } + else + { System.err.println("! Warning: unexpected types " + tlname + " " + trname + " in +: " + this); + + if (left.isRef()) + { left.setArray(true); + System.out.println("! Pointer arithmetic may not translate correctly!!"); + } + + // JOptionPane.showMessageDialog(null, "Disallowed types in " + this, + // "Type error", JOptionPane.WARNING_MESSAGE); + + if (tleft != null && tleft.isNumeric()) + { + type = tleft; // new Type("double",null); + } + else if (tright != null && tright.isNumeric()) + { type = tright; } + else + { type = new Type("OclAny", null); } + } + } + else + { if (tright == null && !Type.isVacuousType(tleft)) + { right.setType(tleft); + type = tleft; + } + else if (tleft == null && + !Type.isVacuousType(tright)) + { left.setType(tright); + type = tright; + } + else + { System.err.println("!! TYPE ERROR: disallowed types " + tleft + " " + tright + " in +: " + this); + // JOptionPane.showMessageDialog(null, "Disallowed types in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + type = new Type("OclAny", null); + } + } + } + + // also case of left - right with left multiple? + private void tcMinus(Type tleft, Type tright, + Entity eleft, Entity eright) + { // System.out.println("FOR " + this + " Left type is " + left.getType() + " Elementtype is: " + left.getElementType()); + + if (left.isRef() && right.isRef()) + { type = new Type("long", null); } + else if (left.isRef()) + { System.err.println("!! Warning: pointer subtraction: " + this); + type = left.getType(); + elementType = left.getElementType(); + } + else if (Type.isCollectionType(left.getType())) + { type = left.getType(); // so inherits sortedness + elementType = left.getElementType(); + } + else if (left.isMultiple() && left.isOrdered()) + { type = new Type("Sequence",null); + elementType = left.elementType; + type.setElementType(elementType); + } + else if (left.isMultiple()) + { type = new Type("Set",null); + elementType = left.elementType; + type.setElementType(elementType); + } // also set entities + else if (tleft != null && tright != null) + { String tlname = tleft.getName(); + String trname = tright.getName(); + if (tlname.equals("String") && trname.equals("String")) + { type = new Type("String",null); } + else if (tlname.equals("Sequence")) + { type = new Type("Sequence",null); + elementType = left.elementType; + type.setElementType(elementType); + } + else if (tlname.equals("Set")) + { type = new Type("Set",null); + elementType = left.elementType; + type.setElementType(elementType); + } + else if (Type.isNumericType(trname) && tlname.equals("double")) + { type = new Type("double",null); } + else if (Type.isNumericType(tlname) && trname.equals("double")) + { type = new Type("double",null); } + else if (Type.isNumericType(trname) && tlname.equals("long")) + { type = new Type("long",null); } + else if (Type.isNumericType(tlname) && trname.equals("long")) + { type = new Type("long",null); } + else if (tleft.equals(tright) && tlname.equals("int")) + { type = new Type("int",null); } + else if (type == null) + { System.err.println("Warning!: disallowed types in -: " + this); + // JOptionPane.showMessageDialog(null, "Disallowed types in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + type = tleft; + } + } + else + { System.err.println("!! TYPE ERROR: undefined types in -: " + this); + if (tright == null && tleft != null) + { right.setType(tleft); + type = tleft; + } + else if (tleft == null && tright != null) + { left.setType(tright); + type = tright; + } + else + { type = new Type("OclAny", null); } + } + Type etleft = left.getElementType(); + Type etright = right.getElementType(); + if (etleft != null) // if classes, take closest common super + { elementType = etleft; + if (etright == null) + { right.setElementType(etleft); } + } // should be the same + else if (etright != null) + { elementType = etright; + left.setElementType(etright); + } // seems wrong to do this. + } + + private void tcSetOps(Type tleft, Type tright, + Entity eleft, Entity eright) + { // union and intersection + + String tlname = "Set"; + if (tleft != null) + { tlname = tleft.getName(); } + else + { System.err.println("!! WARNING: no type for: " + left); } + + String trname = "Set"; + if (tright != null) + { trname = tright.getName(); } + else + { System.err.println("!! WARNING: no type for: " + right); } + + + if (operator.equals("^") || + "->concatenate".equals(operator) || + operator.equals("->prepend") || + operator.equals("->append")) + { if ("Sequence".equals(tlname)) + { type = tleft; } + else + { System.err.println("!! WARNING: ^, ->prepend, ->append can only be applied to a sequence: " + this); + type = new Type("Sequence",null); + type.elementType = right.getType(); + } + } + else if (operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("->including") || + operator.equals("->restrict") || + operator.equals("->antirestrict") || + operator.equals("->intersection") || + operator.equals("/\\")) + { if ("Sequence".equals(tlname)) + { type = tleft; } + else if ("Map".equals(tlname)) + { type = tleft; } + else if ("Set".equals(tlname)) + { type = tleft; } + else + { System.err.println("!! WARNING: unknown type for LHS of " + this); + type = new Type("Set",null); + elementType = new Type("OclAny", null); + } + isSorted = left.isSorted; + } + else if (operator.equals("->union") || + operator.equals("\\/")) + { if (tlname.equals("Sequence") && trname.equals("Sequence")) + { type = tleft; } + else if (tlname.equals("Map") && trname.equals("Map")) + { type = tleft; } + else if (tlname.equals("Set") && trname.equals("Set")) + { type = tleft; } + else + { System.err.println("!! WARNING: different types for LHS and RHS of " + this); + type = tleft; + } + } + else // ->symmetricDifference: & makes sense for maps + { type = left.getType(); + elementType = left.elementType; + } + + + if (operator.equals("^") || + "->concatenate".equals(operator) + || operator.equals("->union") || + operator.equals("->intersection") || + // || operator.equals("->restrict") || + operator.equals("->symmetricDifference") || + operator.equals("/\\") || operator.equals("\\/")) + { if (tright == null && tleft != null) + { right.setType(tleft); + type = tleft; // new Type("Set",null); + } + else if (tleft == null && tright != null) + { left.setType(tright); + type = tright; // new Type("Set",null); + } + else if (tleft == null && tright == null) + { + // JOptionPane.showMessageDialog(null, "Null types in " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + System.err.println("!! Warning: null types on both sides of " + this); + if (operator.equals("^") || "->concatenate".equals(operator)) + { type = new Type("Sequence", null); } + else if (operator.equals("->restrict") || + operator.equals("->antirestrict")) + { type = new Type("Map", null); } + else + { type = new Type("Set",null); } + // new Type("void", null); + } + } + + if (operator.equals("->restrict") || + operator.equals("->antirestrict")) + { if (type == null) + { type = new Type("Map", null); + type.setSorted(left.isSorted); + } + isSorted = left.isSorted; + } + + if (operator.equals("->append") || + operator.equals("->prepend") || + operator.equals("^") || + "->concatenate".equals(operator)) + { if (type == null) + { type = new Type("Sequence", null); } + } + + Type etleft = left.getElementType(); + Type etright = right.getElementType(); + Type maxtype = etleft; + if (Type.isSubType(etleft,etright)) + { maxtype = etright; } + + if (operator.equals("->intersection") || + operator.equals("/\\") || + operator.equals("->restrict") || + operator.equals("->antirestrict") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") + ) + { elementType = etleft; + type.setElementType(elementType); + isSorted = left.isSorted; + } + else if (operator.equals("->including") || + operator.equals("->prepend") || + operator.equals("->append")) + { Type newleftET = + Type.refineType(etleft,right.getType()); + System.out.println(">> Deduced element type of " + this + " = " + newleftET); + elementType = newleftET; + if (type == null) + { type = new Type("Sequence", null); } + type.setElementType(newleftET); + } + else if (operator.equals("->union") || + operator.equals("^") || + "->concatenate".equals(operator)) + { Type newleftET = Type.refineType(etleft,etright); + System.out.println(">> Deduced element type of " + this + " = " + newleftET); + elementType = newleftET; + if (type != null) + { type.setElementType(newleftET); } + } + else if (etleft != null) // if classes, take closest common super + { elementType = maxtype; + if (type != null) + { type.setElementType(elementType); } + if (etright == null) + { right.setElementType(etleft); } + } // should be the same + else if (etright != null && type != null) + { elementType = maxtype; + type.setElementType(elementType); + left.setElementType(etright); + } // it's wrong to do this. + + if (elementType != null && elementType.isEntity()) + { entity = elementType.getEntity(); } + + if (isSorted()) + { type.setSorted(true); } + } + + private void tcSelect(Type tleft, Type tright, Entity eleft) + { // left should be set, sequence or map, right a boolean + // All cases where result is a subset or rearrangement of the selectleft + // ie., operators "selectMaximals", + // "selectMinimals", "sortedBy", "select", "reject" + + // The result is sorted if the LHS is, *except* for + // 'sortedBy' + + Expression selectleft = left; + + if (operator.equals("|") || operator.equals("|R") || + operator.equals("|sortedBy") || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator)) + { selectleft = ((BinaryExpression) left).right; + // tleft = selectleft.getType(); + } + + // if (selectleft.isMultiple()) + + if (selectleft.isMap()) + { Type restype = new Type("Map", null); + restype.keyType = tleft.keyType; + restype.elementType = tleft.elementType; + type = restype; + elementType = tleft.elementType; + + if (operator.equals("->sortedBy") || + operator.equals("|sortedBy")) + { type.setSorted(false); } + else if (tleft.isSorted()) + { type.setSorted(true); } + + return; + } + else if (Type.isSequenceType(tleft)) + { type = new Type("Sequence",null); } + else if (operator.equals("->sortedBy") || + operator.equals("|sortedBy")) + { type = new Type("Sequence",null); } + else if (Type.isMapType(tleft)) + { type = new Type("Map", null); } + else if (Type.isSetType(tleft)) + { type = new Type("Set",null); } + else + { System.err.println("!!TYPE ERROR!!: LHS of select/reject must be a collection! " + this); + // JOptionPane.showMessageDialog(null, "LHS of " + this + " must be a collection", + // "Type error", JOptionPane.ERROR_MESSAGE); + type = new Type("Set",null); + // return; + } + + Type etleft = selectleft.getElementType(); + if (etleft != null) + { elementType = etleft; } + else if ((selectleft + "").equals(eleft + "")) + { elementType = new Type(eleft); } + type.setElementType(elementType); + entity = eleft; // ? + // System.out.println("Element type of: " + this + " is " + elementType); + + if (operator.equals("->sortedBy") || + operator.equals("|sortedBy")) + { type.setSorted(false); } + else if (isSorted()) + { type.setSorted(true); } + } + + private void tcCollect(Type tleft, Type tright, Entity eright) + { // left should be set or sequence, right an expression + + Expression collectleft = left; + + if (operator.equals("|C") || + "|unionAll".equals(operator) || + "|intersectAll".equals(operator) || + "|concatenateAll".equals(operator)) + { collectleft = ((BinaryExpression) left).right; } + + if (collectleft.isMap()) + { Type restype = new Type("Map", null); + restype.keyType = tleft.keyType; + restype.elementType = tright; + type = restype; + elementType = tright; + + // JOptionPane.showInputDialog("Type of " + this + + // " is " + type); + return; + } + else if (collectleft.isMultiple()) + { } + else + { System.err.println("!!! TYPE ERROR: LHS of collect must be a collection! " + this); + // JOptionPane.showMessageDialog(null, "LHS must be a collection: " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + // type = null; + // return; + } + + if (tright == null) + { System.err.println("!!! TYPE ERROR: No type for collect RHS: " + this); + // JOptionPane.showMessageDialog(null, "ERROR: No type for collect RHS: " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + return; + } + + + if (operator.equals("->collect") || operator.equals("|C")) + { elementType = (Type) tright.clone(); + type = new Type("Sequence",null); + if (Type.isMapType(tleft)) + { type = new Type("Map", null); } // map->collect(e) is the composed map. + } + else // ->intersectAll, ->unionAll, ->concatenateAll and | versions of these + { if (right.elementType == null) + { elementType = null; } + else + { elementType = (Type) right.elementType.clone(); } + + if (operator.equals("->unionAll") && tleft.getName().equals("Sequence") && + (right.isOrdered() || "self".equals("" + right))) // dcat in B + { type = new Type("Sequence",null); + if ("self".equals("" + right)) + { elementType = left.getElementType(); + type.setElementType(left.getElementType()); + } + } + else if (operator.equals("|concatenateAll") || operator.equals("->concatenateAll")) + { type = new Type("Sequence", null); } + else + { type = new Type("Set",null); } // intersectAll always unordered + // entity = eright; + } // ?? + + if (elementType != null && elementType.isEntity()) + { entity = elementType.getEntity(); } + + type.setElementType(elementType); + + // System.out.println("++++ Type/Element type of: " + this + " is " + type + " " + elementType); + + if (isSorted()) + { type.setSorted(true); } + } + + private void tcMathOps(Type tleft, Type tright, + Entity eleft, Entity eright) + { // *, mod and divide -- not allowed to do Set*number. mod not valid for doubles. + + if (tleft != null && tright != null) + { String tlname = tleft.getName(); + String trname = tright.getName(); + if (Type.isNumericType(tlname) && + Type.isNumericType(trname)) + { } + else + { type = Expression.deduceType(operator,left,right); + + System.err.println("! Warning!: arguments must be numeric in: " + this + " Deduced type: " + type); + if (type == null) + { // JOptionPane.showMessageDialog(null, "Arguments not numeric in: " + this, + // "Type error", JOptionPane.ERROR_MESSAGE); + } + } + + if (trname.equals("double") || tlname.equals("double")) + { type = new Type("double",null); } + else if (tlname.equals("long") || trname.equals("long")) + { type = new Type("long",null); } + else if (trname.equals("int") && trname.equals("int")) + { type = new Type("int",null); } + else + { System.err.println("!! TYPE ERROR: invalid types " + tlname + " " + trname + " in: " + this); + type = new Type("int", null); + } + } + else + { type = Expression.deduceType(operator,left,right); + + System.err.println("!! TYPE ERROR: invalid types " + tleft + " " + tright + " in: " + this + ". Deduced type " + type); + JOptionPane.showMessageDialog(null, "Missing types in: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + if (tleft != null) + { right.setType(tleft); + type = tleft; + } + else if (tright != null) + { left.setType(tright); + type = tright; + } + else + { type = null; } + } + elementType = type; + } + + + private void tcLogical(Type tleft, Type tright, + Entity eleft, Entity eright) + { // must both be boolean. Events are boolean + if (tleft != null && tright != null) + { String tlname = tleft.getName(); + String trname = tright.getName(); + if (tlname.equals("boolean") && trname.equals("boolean")) + { } + else + { System.err.println("! Warning: invalid types " + tlname + " " + trname + " in: " + this); + JOptionPane.showMessageDialog(null, "Arguments must be booleans: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + if ("int".equals(tlname) && "int".equals(trname)) + { // bitwise operator + System.err.println("!! Bitwise operator expected here !!"); + type = new Type("int", null); + } + } + type = new Type("boolean",null); + } + else + { System.err.println("!! TYPE ERROR: invalid types in: " + this); + JOptionPane.showMessageDialog(null, "Missing types in: " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + } + type = new Type("boolean",null); + elementType = type; + } + +/* + private void tcInOps(Type tleft, Type tright, + Entity eleft, Entity eright) +*/ + + public boolean conflictsWith(Expression e) + { if (e instanceof UnaryExpression) + { UnaryExpression ue = (UnaryExpression) e; + if ("->isDeleted".equals(ue.operator) && operator.equals(":")) + { if ((ue.argument + "").equals(left + "")) // l : e & l->isDeleted() + { return true; } + if ((ue.argument + "").equals(right + "")) // l : e & e->isDeleted() + { return true; } + } + if ("->isDeleted".equals(ue.operator) && operator.equals("->includes")) + { if ((ue.argument + "").equals(right + "")) // e->includes(l) & l->isDeleted() + { return true; } + if ((ue.argument + "").equals(left + "")) // e->includes(r) & e->isDeleted() + { return true; } + } + if ("->isEmpty".equals(ue.operator) && operator.equals(":")) + { if ((ue.argument + "").equals(right + "")) // l : e & e->isEmpty() + { return true; } + } + if ("->isEmpty".equals(ue.operator) && operator.equals("->includes")) + { if ((ue.argument + "").equals(left + "")) // e->includes(l) & e->isEmpty() + { return true; } + } + return false; + } /* These cases also belong in UnaryExpression */ + + if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (be.operator.equals("&")) + { return conflictsWith(be.left) || + conflictsWith(be.right); + } + if (be.operator.equals("or")) + { return conflictsWith(be.left) && + conflictsWith(be.right); + } + if (be.operator.equals("=>")) + { boolean leftconflict = conflictsWith(be.left); + return !leftconflict && conflictsWith(be.right); + } + if (be.operator.equals("#") || be.operator.equals("#1") || be.operator.equals("#LC") || + "->existsLC".equals(operator) || be.operator.equals("->exists")) + { return conflictsWith(be.right); } // provided be.left var not in this + + if (operator.equals("->exists") && be.operator.equals("->forAll") && + (left + "").equals(be.left + "")) + { return right.conflictsWith(be.right); } + if (operator.equals("->exists1") && be.operator.equals("->forAll") && + (left + "").equals(be.left + "")) + { return right.conflictsWith(be.right); } + if (operator.equals("->forAll") && be.operator.equals("->exists") && + (left + "").equals(be.left + "")) + { return right.conflictsWith(be.right); } + if (operator.equals("->forAll") && be.operator.equals("->exists1") && + (left + "").equals(be.left + "")) + { return right.conflictsWith(be.right); } + // likewise for #, #1, ! + if (operator.equals("->forAll") && be.operator.equals("->forAll") && + (left + "").equals(be.left + "")) + { return right.conflictsWith(be.right); } + else + { return conflictsWith(be.operator, + be.left,be.right); + } + } + return false; +} + +public boolean conflictsWith(String op, Expression el, + Expression er) +{ // System.out.println("CONFLICT: " + this + " " + el + " " + op + " " + er); + + if (left.toString().equals(el.toString()) && + right.toString().equals(er.toString())) + { boolean res = conflictsOp(operator,op); + // System.out.println("CONFLCT: " + res); + return res; + } + if (left.toString().equals(er.toString()) && + right.toString().equals(el.toString())) + { return conflictsReverseOp(operator,op); } + if (operator.equals("=")) + { return conflictsWithEq(op,el,er); } + if (operator.equals(":")) + { return conflictsWithIn(op,el,er); } +// if (comparitors.contains(operator)) +// { return conflictsWithComp(op,el,er); } + if (operator.equals("&")) // shouldn't occur + { return left.conflictsWith(op,el,er) || + right.conflictsWith(op,el,er); + } + if (operator.equals("or")) + { return left.conflictsWith(op,el,er) && + right.conflictsWith(op,el,er); + } + return false; +} + +public boolean conflictsWithEq(String op, Expression el, + Expression er) +{ /* if (op.equals("=")) + { if (left.toString().equals(el.toString()) && + right.getKind() == VALUE && + er.getKind() == VALUE && + !right.toString().equals(er.toString())) + { return true; } + } + else + */ + if (op.equals(":")) + { if ((right + "").equals("Set{}") && (left + "").equals(er + "")) + { return true; } // left = Set{} & x : left + if ((right + "").equals("Set{}") && ("self." + left).equals(er + "")) + { return true; } // left = Set{} & x : self.left + if ((right + "").equals("Sequence{}") && (left + "").equals(er + "")) + { return true; } + if ((right + "").equals("Sequence{}") && ("self." + left).equals(er + "")) + { return true; } + if ((right + "").equals("0") && (left + "").equals(er + ".size")) + { return true; } // er.size = 0 & x : er + if ((right + "").equals("0") && ("self." + left).equals(er + ".size")) + { return true; } + if ((right + "").equals("0") && (left + "").equals(er + "->size()")) + { return true; } + if ((right + "").equals("0") && ("self." + left).equals(er + "->size()")) + { return true; } + } // and other cases of p = Set{} & x : p + + return false; +} + +public boolean conflictsWithIn(String op, Expression el, + Expression er) +{ if (op.equals("=")) + { if ((right + "").equals(el + "") && ("Set{}").equals(er + "")) + { return true; } // x = Set{} & er : x + if ((right + "").equals(el + "") && ("Sequence{}").equals(er + "")) + { return true; } + if ((right + ".size").equals(el + "") && ("0").equals(er + "")) + { return true; } // left : right & right.size = 0 + if ((right + "->size()").equals(el + "") && ("0").equals(er + "")) + { return true; } + } // and other cases of x : p & p = Set{} + + return false; +} + + public Expression skolemize(Expression sourceVar, java.util.Map env) + { Expression res; + + if (operator.equals("#") || operator.equals("#LC") || + operator.equals("#1")) // and right.right.umlkind == CLASSID + { Expression var = ((BinaryExpression) left).left; + Expression targetType = ((BinaryExpression) left).right; + Expression sourceType = new BasicExpression(sourceVar.type + ""); + // replace var in right by func(sourceVar), record func: sourceType -> targetType + String func = Identifier.nextIdentifier("sk_"); + UnaryExpression fapp = new UnaryExpression(func,sourceVar); + Expression newr = right.substituteEq(var + "", fapp); + env.put(func,new BinaryExpression("->",sourceType,targetType)); + return newr.skolemize(sourceVar,env); + } + + Expression nleft = left.skolemize(sourceVar,env); + Expression nrigh = right.skolemize(sourceVar,env); + res = new BinaryExpression(operator,nleft,nrigh); + res.setBrackets(needsBracket); + return res; + } + + public String cstlQueryForm(java.util.Map srcvarMap) + { String lqf = left.cstlQueryForm(srcvarMap); + String rqf = right.cstlQueryForm(srcvarMap); + if ("+".equals(operator) && isString()) + { return lqf + "" + rqf; } + if ("->union".equals(operator)) + { return lqf + "" + rqf; } + if ("^".equals(operator) || "->concatenate".equals(operator)) + { return lqf + "" + rqf; } + + return this + ""; + } + + public String cstlConditionForm(java.util.Map srcvarmap) + { String lqf = left.cstlConditionForm(srcvarmap); + String rqf = right.cstlConditionForm(srcvarmap); + if ("&".equals(operator)) + { return lqf + ", " + rqf; } + // for "or", copy the rule + if ("=".equals(operator)) + { return lqf + " " + rqf; } + if ("/=".equals(operator)) + { return lqf + " not " + rqf; } + if ("->hasStereotype".equals(operator)) + { return lqf + " " + rqf; } + return this + ""; + } + + public String negatedcstlConditionForm(java.util.Map srcvarmap) + { String lqf = left.cstlConditionForm(srcvarmap); + String rqf = right.cstlConditionForm(srcvarmap); + // if ("&".equals(operator)) + // { return lqf + ", " + rqf; } + // for "or", copy the rule + if ("=".equals(operator)) + { return lqf + " not " + rqf; } + if ("/=".equals(operator)) + { return lqf + " " + rqf; } + if ("->hasStereotype".equals(operator)) + { return lqf + " not " + rqf; } + return "not " + this + ""; + } + + public String queryForm(java.util.Map env, boolean local) + { String res; + boolean bNeeded = needsBracket; + + String cont = "Controller.inst()"; + + if (operator.equals("#") || "->existsLC".equals(operator) || + operator.equals("#LC") || operator.equals("->exists")) + { return existsQueryForm(env,local); } + + if (operator.equals("#1") || operator.equals("->exists1")) + { return exists1QueryForm(env,local); } + + if (operator.equals("->forAll") || operator.equals("!")) + { return forAllQueryForm(env,local); } + + /* + if (operator.equals("let")) + { String acc = accumulator.getName(); + Expression sbst = right.substituteEq(acc,left); + return sbst.queryForm(env,local); + } // Or, extend env by acc |-> left + */ + + boolean lmult = left.isMultiple(); + boolean rmult = right.isMultiple(); + boolean lprim = left.isPrimitive(); + boolean rprim = right.isPrimitive(); + String lqf = left.classqueryForm(env,local); + String rqf = right.queryForm(env,local); + String rw = rqf; + if (rprim) + { rw = right.wrap(rqf); } + + // System.out.println(left + " is primitive: " + lprim + " is multiple: " + lmult); + // System.out.println(right + " is primitive: " + rprim + " is multiple: " + rmult); + + + String typ = ""; + if (type != null) + { typ = type.getJava(); } + else + { System.err.println("!! Warning: no type for " + this); } + + String javaOp = javaOpOf(operator); + res = lqf + " " + javaOp + " " + rqf; // default + // if & or or: &&, || + + if (operator.equals("|") || operator.equals("->select")) + { return selectQueryForm(lqf,rqf,env,local); } + + if (operator.equals("|C") || operator.equals("->collect")) + { return collectQueryForm(lqf,rqf,rprim,env,local); } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryForm(lqf,rqf,rprim,env,local); + if (Type.isPrimitiveType(type)) + { return unwrap(getany); } + return "((" + typ + ") " + getany + ")"; + } + + if (operator.equals("->selectMaximals") || + operator.equals("|selectMaximals")) + { String col = collectQueryForm(lqf,rqf,rprim,env,local); + if (operator.equals("->selectMaximals") && left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryForm(env,local); } // And pass lqf to collectQueryForm? + else if (operator.equals("|selectMaximals") && ((BinaryExpression) left).right.umlkind == CLASSID) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = ((BasicExpression) leftbe.right).classExtentQueryForm(env,local); + } // And pass lqf to collectQueryForm? + else if (operator.equals("|selectMaximals")) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryForm(env,local); + } + + return "Set.maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->selectMinimals") || + operator.equals("|selectMinimals")) + { String col = collectQueryForm(lqf,rqf,rprim,env,local); + if (operator.equals("->selectMinimals") && left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryForm(env,local); } // And pass lqf to collectQueryForm? + else if (operator.equals("|selectMinimals") && ((BinaryExpression) left).right.umlkind == CLASSID) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = ((BasicExpression) leftbe.right).classExtentQueryForm(env,local); + } + else if (operator.equals("|selectMinimals")) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryForm(env,local); + } + return "Set.minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->sortedBy") || + operator.equals("|sortedBy")) + { String col = collectQueryForm(lqf,rqf,rprim,env,local); + if (operator.equals("->sortedBy") && left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryForm(env,local); } // And pass lqf to collectQueryForm? + else if (operator.equals("|sortedBy") && ((BinaryExpression) left).right.umlkind == CLASSID) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = ((BasicExpression) leftbe.right).classExtentQueryForm(env,local); + } + else if (operator.equals("|sortedBy")) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryForm(env,local); + } + return "Set.sortedBy(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->count")) + { return "Set.count(" + lqf + "," + rw + ")"; } + + if (operator.equals("->restrict")) + { return "Set.restrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->antirestrict")) + { return "Set.antirestrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->includesKey")) + { return "Set.includesKey(" + lqf + "," + rw + ")"; } + + if (operator.equals("->excludesKey")) + { return "Set.excludesKey(" + lqf + "," + rw + ")"; } + + if (operator.equals("->apply")) + { return "(" + lqf + ").apply(" + rqf + ")"; } + + if (operator.equals("let")) + { // (new Object() { public typ call(acct acc) { return rqf; } })(lqf) + + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getJava(); + return "(new Object() { public " + typ + " call(" + + lett + " " + acc + ") { return " + rqf + "; } }).call(" + lqf + ")"; + } + + if (operator.equals("->at")) + { if (left.type != null && + "String".equals(left.type.getName())) + { return "(" + lqf + ".charAt(" + rqf + " - 1) + \"\")"; } // and for Java6, 7, etc. + + if (left.type == null) + { if (right.type != null && + "String".equals(right.type.getName())) + { lqf = "((Map) " + lqf + ")"; + left.type = new Type("Map", null); + left.elementType = type; + left.type.keyType = new Type("String", null); + left.type.elementType = type; + } + else + { lqf = "((List) " + lqf + ")"; + left.type = new Type("Sequence", null); + left.elementType = type; + left.type.elementType = type; + } + } + + String ind = lqf + ".get(" + rqf + ")"; + String getind = lqf + ".get(" + rqf + " - 1)"; + + if (left.type != null && left.type.isMapType()) + { return "((" + typ + ") " + ind + ")"; } + + if ("String".equals(right.type + "")) // a map lookup + { getind = lqf + ".get(" + rqf + ")"; } + + if (type == null) + { if (left.elementType == null) + { return getind; } + else + { type = left.elementType; + typ = type.getJava(); + } + } + + if (Type.isPrimitiveType(type)) + { return unwrap(getind); } + + if (left.isRef()) + { return getind; } + + // System.out.println(">********> Type of " + this + " is " + typ); + + return "((" + typ + ") " + getind + ")"; + } + + if (operator.equals("->pow")) + { return "Math.pow(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->gcd")) + { return "Set.gcd(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->truncateTo")) + { if (left.isInteger()) + { return lqf; } + return "Set.truncateN(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->roundTo")) + { if (left.isInteger()) + { return lqf; } + return "Set.roundN(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->compareTo")) + { if (left.isNumeric() && right.isNumeric()) + { res = "(" + lqf + " - (" + rqf + "))"; } + else if (left.isString()) + { res = "((Comparable) " + lqf + ").compareTo(\"\" + " + rqf + ")"; } + else if (left.hasSequenceType() && right.hasSequenceType()) + { res = "Set.sequenceCompare(" + lqf + "," + rqf + ")"; } + else + { res = "((Comparable) " + lqf + ").compareTo(" + rqf + ")"; } + + return res; + } + + if (operator.equals("->isUnique") || + operator.equals("|isUnique")) // and define for B and for Maps + { String fcollect = collectQueryForm(lqf,rqf,rprim,env,local); + return "Set.isUnique(" + fcollect + ")"; + } + + if (operator.equals("->closure")) + { String rel = right + ""; + + // System.err.println(">>>> Entity= " + entity + " left= " + left + + // " LEFTTYPE= " + left.type + + // " " + left.elementType); + + if (entity != null) { } + else if (left.elementType != null && left.elementType.isEntity()) + { entity = left.elementType.getEntity(); } + else if (left.entity != null) + { entity = left.entity; } // the owner of the relation being closured + else if (left instanceof SetExpression) + { entity = ((SetExpression) left).findEntity(); + type = new Type("Set", null); + typ = type.getJava(); + } + + if (entity == null) + { System.err.println("!! No entity for " + this); + JOptionPane.showMessageDialog(null, "No entity for: " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + return ""; + } + + if (left.isMultiple()) {} + else + { System.err.println("!! ERROR: LHS of " + this + " must be collection"); + JOptionPane.showMessageDialog(null, "ERROR: LHS of " + this + " must be collection", + "Type error", JOptionPane.ERROR_MESSAGE); + } + + if (entity != null) + { Association ast = entity.getDefinedRole(right + ""); + if (ast != null) + { Entity entc = ast.closureEntity(); + if (entc != null) + { elementType = new Type(entc); } + if (type != null) + { type.setElementType(elementType); } + + if (ast.isClosurable()) { } + else + { JOptionPane.showMessageDialog(null, "ERROR: association in " + this + " cannot be closured", + "Expression error", JOptionPane.ERROR_MESSAGE); + } + Entity ent1 = ast.getEntity1(); + return "Set.closure" + ent1.getName() + rel + "(" + lqf + ")"; + } + return "Set.closure" + entity.getName() + rel + "(" + lqf + ")"; + } + } // left must be set-valued. + + if (operator.equals("->intersectAll") || operator.equals("|intersectAll")) + { String col = collectQueryForm(lqf,rqf,rprim,env,local); + return "Set.intersectAll(" + col + ")"; + } + + if (operator.equals("->unionAll") || operator.equals("|unionAll")) + { String col = collectQueryForm(lqf,rqf,rprim,env,local); + if (left.isOrdered() && (right.isOrdered() || "self".equals(right + ""))) + { return "Set.concatenateAll(" + col + ")"; } + return "Set.unionAll(" + col + ")"; + } + + if (operator.equals("|concatenateAll")) + { String col = collectQueryForm(lqf,rqf,rprim,env,local); + return "Set.concatenateAll(" + col + ")"; + } + + if (operator.equals("->reject") || operator.equals("|R")) + { String sel = rejectQueryForm(lqf,rqf,env,local); + return sel; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals(":")) + { return "(" + lqf + " instanceof " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsKindOf")) + { return "(" + lqf + " instanceof " + right + ")"; } + + if (operator.equals("->oclIsKindOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestJava(lqf, right + "") + ")"; + } + + // ->oclIsTypeOf (in the exact class) + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsTypeOf")) + { return "(" + lqf + ".getClass() == " + right + ".class)"; } + + if (operator.equals("->oclIsTypeOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestJava(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("<:")) + { rqf = ((BasicExpression) right).classExtentQueryForm(env,local); + return "(" + rqf + ".containsAll(" + lqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includes")) + { return "(" + rqf + " instanceof " + left + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includesAll")) + { lqf = ((BasicExpression) left).classExtentQueryForm(env,local); + return "(" + lqf + ".containsAll(" + rqf + "))"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("/:")) + { return "!(" + lqf + " instanceof " + right + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludes")) + { return "!(" + rqf + " instanceof " + left + ")"; } + + + if (operator.equals("=>")) + { return "(!(" + lqf + ") || " + rqf + ")"; } + + if (operator.equals("xor")) + { return "((" + lqf + " && !(" + rqf + ")) || (!(" + lqf + ") && " + rqf + "))"; } + + if (operator.equals("->oclAsType")) + { // Type typ = Type.getTypeFor("" + right,types,entities); + if (type != null) + { String jtyp = type.getJava(); + return "((" + jtyp + ") " + lqf + ")"; + } + return "((" + right + ") " + lqf + ")"; + } + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opjava = Expression.getOperatorJava(op); + if (opjava != null && opjava.length() > 0) + { return opjava.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + if (!lmult && !rmult) + { if (operator.equals("<>=")) + { res = lqf + " == " + rqf; } + else if (operator.equals("=")) // and comparitors + { res = composeEqQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = composeNeqQueryForms(lqf,rqf,lprim,rprim); } + else if (comparitors.contains(operator)) + { res = composeComparitorQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("+") || operator.equals("-") || + operator.equals("*") || operator.equals("/") || + operator.equals("mod") || + operator.equals("div")) + { res = composeMathOpQueryForms(lqf,rqf,lprim,rprim); + bNeeded = needsBracket; + } + else if (operator.equals("->indexOf")) + { res = lqf + ".indexOf(" + rqf + ") + 1"; + bNeeded = true; + } + else if (operator.equals("->lastIndexOf")) + { res = lqf + ".lastIndexOf(" + rqf + ") + 1"; + bNeeded = true; + } + else if (operator.equals("->count")) // for strings + { res = "Set.count(" + lqf + "," + rw + ")"; + bNeeded = false; + } + else if (operator.equals("->pow")) + { res = "Math.pow(" + lqf + ", " + rqf + ")"; + bNeeded = false; + } + else if (operator.equals("->truncateTo")) + { if (left.isInteger()) + { res = lqf; } + else + { res = "Set.truncateN(" + lqf + "," + rqf + ")"; } + bNeeded = false; + } + else if (operator.equals("->roundTo")) + { if (left.isInteger()) + { res = lqf; } + else + { res = "Set.roundN(" + lqf + "," + rqf + ")"; } + bNeeded = false; + } + else if (operator.equals("->hasPrefix")) + { res = lqf + ".startsWith(" + rqf + ")"; + bNeeded = true; + } + else if (operator.equals("->hasSuffix")) + { res = lqf + ".endsWith(" + rqf + ")"; + bNeeded = true; + } + else if (operator.equals("->hasMatch")) + { res = "Set.hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = lqf + ".matches(" + rqf + ")"; } + else if (operator.equals("->equalsIgnoreCase")) + { res = lqf + ".equalsIgnoreCase(" + rqf + ")"; } + else if (operator.equals("->before")) + { res = "Set.before(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->after")) + { res = "Set.after(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->split")) + { res = "Set.split(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->allMatches")) + { res = "Set.allMatches(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->firstMatch")) + { res = "Set.firstMatch(" + lqf + ", " + rqf + ")"; } + } + else if (lmult && !rmult) // convert right to mult + { String rss = right.makeSet(rw); + bNeeded = false; + + if (operator.equals("->includes")) + { res = lqf + ".contains(" + rw + ")"; } + else if (operator.equals("->excludes")) + { res = "!(" + lqf + ".contains(" + rw + "))"; } + else if (operator.equals("->excluding")) + { res = "Set.subtract(" + lqf + "," + rss + ")"; } + else if (operator.equals("->excludingAt")) + { res = "Set.removeAt(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->excludingFirst")) + { res = "Set.removeFirst(" + lqf + "," + rw + ")"; } + else if (operator.equals("->append")) + { res = "Set.append(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->including") && left.isSetValued()) + { res = "Set.union(" + lqf + "," + rss + ")"; } + else if (operator.equals("->including") && left.isSequenceValued()) + { res = "Set.concatenate(" + lqf + "," + rss + ")"; } + else if (operator.equals("->prepend")) + { + res = "Set.concatenate(" + rss + "," + lqf + ")"; + } + else if (operator.equals("<>=")) + { res = lqf + " == " + rqf; } + else if (operator.equals("=")) + { if (Type.isSetType(left.getType())) + { res = "Set.equals(" + lqf + "," + rss + ")"; } + else + { res = lqf + ".equals(" + rss + ")"; } + } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isSetType(left.getType())) + { res = "!(Set.equals(" + lqf + "," + rss + "))"; } + else + { res = "!(" + lqf + ".equals(" + rss + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = rss + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->includesAll")) + { res = lqf + ".containsAll(" + rss + ")"; } + else if (operator.equals("/<:")) + { res = "!(" + rss + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->excludesAll")) + { res = "Set.intersection(" + rss + "," + lqf + ").size() == 0"; + bNeeded = true; + } + else if (operator.equals("->count")) + { res = "Set.count(" + lqf + "," + rw + ")"; } + else if (operator.equals("->indexOf")) + { res = lqf + ".indexOf(" + rw + ") + 1"; + bNeeded = true; + } + else if (operator.equals("->lastIndexOf")) + { res = lqf + ".lastIndexOf(" + rw + ") + 1"; + bNeeded = true; + } + else + { // res = lqf + " " + operator + " " + rqf; + res = composeSetQueryForms(lqf,rqf); + bNeeded = true; + } // composeSetQueryForms(lqf,rs,rqf); } + } + else if (rmult && !lmult) + { String lw = ""; + bNeeded = false; + + if (lprim) + { lw = left.wrap(lqf); } // only if left primitive + else + { lw = lqf; } + String ls = left.makeSet(lw); + + if (operator.equals("=")) + { if (Type.isSetType(right.getType())) + { res = "Set.equals(" + ls + "," + rqf + ")"; } + else + { res = ls + ".equals(" + rqf + ")"; } + } + else if (operator.equals("<>=")) + { res = lqf + " == " + rqf; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isSetType(right.getType())) + { res = "!(Set.equals(" + ls + "," + rqf + "))"; } + else + { res = "!(" + ls + ".equals(" + rqf + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".contains(" + lw + ")"; } + else if (operator.equals("/:")) + { res = "!(" + rqf + ".contains(" + lw + "))"; } + else if (operator.equals("->excludesAll")) + { res = "Set.intersection(" + rqf + "," + ls + ").size() == 0"; + bNeeded = true; + } + else + { res = lqf + " " + operator + " " + rqf; + bNeeded = true; + } // composeSetQueryForms(ls,rqf); } + } + else // both sets + if (operator.equals("->indexOf")) + { res = "Collections.indexOfSubList(" + lqf + "," + rqf + ")+1"; + bNeeded = true; + } + else if (operator.equals("->lastIndexOf")) + { res = "Collections.lastIndexOfSubList(" + lqf + "," + rqf + ") + 1"; + bNeeded = true; + } + else if (operator.equals("<>=")) + { res = lqf + " == " + rqf; } + else + { // res = lqf + " " + operator + " " + rqf; + res = composeSetQueryForms(lqf,rqf); + bNeeded = true; + } + // { res = composeSetQueryForms(lqf,rqf); } + + if (bNeeded) + { return "( " + res + " )"; } + return res; + } // add brackets if needed + + public String queryFormJava6(java.util.Map env, boolean local) + { String res; + String cont = "Controller.inst()"; + + if (operator.equals("#") || operator.equals("#LC") || + "->existsLC".equals(operator) || operator.equals("->exists")) + { return existsQueryFormJava6(env,local); } + + if (operator.equals("#1") || operator.equals("->exists1")) + { return exists1QueryFormJava6(env,local); } + + if (operator.equals("->forAll") || operator.equals("!")) + { return forAllQueryFormJava6(env,local); } + + boolean lmult = left.isMultiple(); + boolean rmult = right.isMultiple(); + boolean lprim = left.isPrimitive(); + boolean rprim = right.isPrimitive(); + String lqf = left.queryFormJava6(env,local); + String rqf = right.queryFormJava6(env,local); + String rw = rqf; + if (rprim) + { rw = right.wrap(rqf); } + + String javaOp = javaOpOf(operator); + + String typ = ""; + if (type != null) + { typ = type.getJava6(); } + else + { System.err.println("!! Warning: no type for " + this); } + + res = lqf + " " + javaOp + " " + rqf; // default + // if & or or: &&, || + + if (operator.equals("|") || operator.equals("->select")) + { return selectQueryFormJava6(lqf,rqf,env,local); } + + if (operator.equals("|C") || operator.equals("->collect")) + { return collectQueryFormJava6(lqf,rqf,rprim,env,local); } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormJava6(lqf,rqf,rprim,env,local); + if (Type.isPrimitiveType(type)) + { return unwrapJava6(getany); } + + return "((" + typ + ") " + getany + ")"; + } + + if (operator.equals("->selectMaximals")) + { String col = + collectQueryFormJava6(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); } + // And pass lqf to collectQueryForm? + return "Set.maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|selectMaximals")) + { String col = + collectQueryFormJava6(lqf,rqf,rprim,env,local); + BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryFormJava6(env,local); + if (leftbe.getRight().umlkind == CLASSID) + { lqf = ((BasicExpression) leftbe.getRight()).classExtentQueryFormJava6(env,local); } + // And pass lqf to collectQueryForm? + return "Set.maximalElements(" + lqf + ", " + col + ")"; + } + + + if (operator.equals("->selectMinimals")) + { String col = + collectQueryFormJava6(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); } + return "Set.minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|selectMinimals")) + { String col = + collectQueryFormJava6(lqf,rqf,rprim,env,local); + BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryFormJava6(env,local); + if (leftbe.getRight().umlkind == CLASSID) + { lqf = ((BasicExpression) leftbe.getRight()).classExtentQueryFormJava6(env,local); } + // And pass lqf to collectQueryForm? + return "Set.minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->sortedBy")) // left must be ordered + { String col = + collectQueryFormJava6(lqf,rqf,rprim,env,local); // ordered version + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); } + return "Set.sortedBy(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|sortedBy")) + { String col = + collectQueryFormJava6(lqf,rqf,rprim,env,local); + BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryFormJava6(env,local); + if (leftbe.getRight().umlkind == CLASSID) + { lqf = ((BasicExpression) leftbe.getRight()).classExtentQueryFormJava6(env,local); } + // And pass lqf to collectQueryForm? + return "Set.sortedBy(" + lqf + ", " + col + ")"; + } + + + if (operator.equals("->count")) // not for strings + { return "Collections.frequency(" + lqf + "," + rw + ")"; } + + if (operator.equals("->restrict")) + { return "Set.restrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->antirestrict")) + { return "Set.antirestrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->at") && type != null) + { String getind = lqf + ".get(" + rqf + " - 1)"; + String ind = lqf + ".get(" + rqf + ")"; + + System.out.println(">> ->at expression " + this + + " " + typ); + + if ("String".equals(left.type + "")) + { return "(" + lqf + ".charAt(" + rqf + " - 1) + \"\")"; } // and for Java6, 7, etc. + else if (left.type != null && left.type.isMapType()) + { if (left.getElementType() != null) + { typ = left.getElementType().getJava6(); } + return "((" + typ + ") " + ind + ")"; + } + + if (left.isRef()) + { return getind; } + + if (Type.isPrimitiveType(type)) + { return unwrapJava6(getind); } + + return "((" + typ + ") " + getind + ")"; + } + + /* + if (operator.equals("let")) + { // right[left/acc] + String acc = accumulator.getName(); + // Type acct = accumulator.getType(); + // String lett = acct.getJava(); + Expression subst = + right.substituteEq(acc,left); + String stats = subst.queryFormJava6(env,local); + return stats; + } */ + + if (operator.equals("let")) + { // (new Object() { public typ call(acct acc) { return rqf; } })(lqf) + + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getJava6(); + return "(new Object() { public " + typ + " call(" + + lett + " " + acc + ") { return " + rqf + "; } }).call(" + lqf + ")"; + } + + + if (operator.equals("->apply")) + { return "(" + lqf + ").apply(" + rqf + ")"; } + + if (operator.equals("->pow")) + { return "Math.pow(" + lqf + ", " + rqf + ")"; } + + if (operator.equals("->truncateTo")) + { if (left.isInteger()) + { return lqf; } + return "Set.truncateN(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->roundTo")) + { if (left.isInteger()) + { return lqf; } + return "Set.roundN(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->compareTo")) + { if (left.isNumeric() && right.isNumeric()) + { res = "(" + lqf + " - (" + rqf + "))"; } + else if (left.isString()) + { res = "((Comparable) " + lqf + ").compareTo(\"\" + " + rqf + ")"; } + else if (left.hasSequenceType() && right.hasSequenceType()) + { res = "Set.sequenceCompare(" + lqf + "," + rqf + ")"; } + else + { res = "((Comparable) " + lqf + ").compareTo(" + rqf + ")"; } + return res; + } + + if (operator.equals("->gcd")) + { return "Set.gcd(" + lqf + "," + rqf + ")"; } + + if (operator.equals("<>=")) + { res = lqf + " == " + rqf; + if (needsBracket) + { res = "(" + res + ")"; } + return res; + } + + if (operator.equals("->isUnique")) // and define for B + { String fcollect = collectQueryFormJava6(lqf,rqf,rprim,env,local); + return "Set.isUnique(" + fcollect + ")"; + } + + if (operator.equals("->intersectAll")) + { String col = collectQueryFormJava6(lqf,rqf,rprim,env,local); + return "Set.intersectAll(" + col + ")"; + } + + if (operator.equals("->unionAll")) + { String col = collectQueryFormJava6(lqf,rqf,rprim,env,local); + if (left.isOrdered() && (right.isOrdered() || "self".equals(right + ""))) + { return "Set.concatenateAll(" + col + ")"; } + return "Set.unionAll(" + col + ")"; + } + + if (operator.equals("->closure")) + { String rel = right + ""; + if (entity == null) + { JOptionPane.showMessageDialog(null, "No entity for: " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + return ""; + } + return "Set.closure" + entity.getName() + rel + "(" + lqf + ")"; + } // left must be set-valued. + + if (operator.equals("->reject") || operator.equals("|R")) + { String sel = rejectQueryFormJava6(lqf,rqf,env,local); + return sel; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals(":")) + { return "(" + lqf + " instanceof " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsKindOf")) + { return "(" + lqf + " instanceof " + right + ")"; } // Java6 version of type named by right + + if (operator.equals("->oclIsKindOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestJava6(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsTypeOf")) + { return "(" + lqf + ".getClass() == " + right + ".class)"; } + + if (operator.equals("->oclIsTypeOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestJava6(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("/:")) + { return "!(" + lqf + " instanceof " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("<:")) + { rqf = ((BasicExpression) right).classExtentQueryFormJava6(env,local); + return "(" + rqf + ".containsAll(" + lqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includes")) + { return "(" + rqf + " instanceof " + left + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includesAll")) + { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); + return "(" + lqf + ".containsAll(" + rqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludes")) + { return "!(" + rqf + " instanceof " + left + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludesAll")) + { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); + return "Collections.disjoint(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("=>")) + { return "(!(" + lqf + ") || " + rqf + ")"; } + + if (operator.equals("->oclAsType")) + { if (type != null) + { String jtyp = type.getJava6(); + return "((" + jtyp + ") " + lqf + ")"; + } + return lqf; + } + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opjava = Expression.getOperatorJava(op); + if (opjava != null && opjava.length() > 0) + { return opjava.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + if (!lmult && !rmult) + { if (operator.equals("=")) // and comparitors + { res = composeEqQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = composeNeqQueryForms(lqf,rqf,lprim,rprim); } + else if (comparitors.contains(operator)) + { res = composeComparitorQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("+") || operator.equals("-") || + operator.equals("*") || operator.equals("/") || + operator.equals("mod") || operator.equals("div")) + { res = composeMathOpQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("->count")) + { res = "Set.count(" + lqf + "," + rw + ")"; } + else if (operator.equals("->indexOf")) + { res = "(" + lqf + ".indexOf(" + rw + ") + 1)"; } + else if (operator.equals("->lastIndexOf")) + { res = "(" + lqf + ".lastIndexOf(" + rw + ") + 1)"; } + else if (operator.equals("->hasPrefix")) + { res = "(" + lqf + ".startsWith(" + rqf + "))"; } + else if (operator.equals("->hasSuffix")) + { res = "(" + lqf + ".endsWith(" + rqf + "))"; } + else if (operator.equals("->hasMatch")) + { res = "Set.hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = lqf + ".matches(" + rqf + ")"; } + else if (operator.equals("->equalsIgnoreCase")) + { res = "(" + lqf + ".equalsIgnoreCase(" + rqf + "))"; } + else if (operator.equals("->before")) + { res = "Set.before(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->after")) + { res = "Set.after(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->split")) + { res = "Set.split(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->allMatches")) + { res = "Set.allMatches(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->firstMatch")) + { res = "Set.firstMatch(" + lqf + ", " + rqf + ")"; } + } + else if (lmult && !rmult) // convert right to mult + { String rss = right.makeSetJava6(rw); + if (left.isOrdered()) + { rss = right.makeSequenceJava6(rw); } + + if (operator.equals("->includes")) + { res = lqf + ".contains(" + rw + ")"; } + else if (operator.equals("->excludes")) + { res = "!(" + lqf + ".contains(" + rw + "))"; } + else if (operator.equals("->excluding")) + { res = "Set.subtract(" + lqf + "," + rss + ")"; } + else if (operator.equals("->excludingAt")) + { res = "Set.removeAt(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->excludingFirst")) + { res = "Set.removeFirst(" + lqf + "," + rw + ")"; } + else if (operator.equals("->append")) + { res = "Set.append(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->including")) + { res = "Set.union(" + lqf + "," + rss + ")"; } + else if (operator.equals("->prepend")) + { res = "Set.concatenate(" + rss + "," + lqf + ")"; } + else + { String rs = right.makeSetJava6(rqf); + if (left.isOrdered()) + { rs = right.makeSequenceJava6(rqf); } + + if (operator.equals("=")) + { res = lqf + ".equals(" + rs + ")"; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = "!(" + lqf + ".equals(" + rs + "))"; } + else if (operator.equals(":") || operator.equals("<:")) + { res = rs + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->includesAll")) + { res = lqf + ".containsAll(" + rs + ")"; } + else if (operator.equals("/<:")) + { res = "!(" + rs + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->excludesAll")) + { res = "Collections.disjoint(" + rs + "," + lqf + ")"; } + else if (operator.equals("->including")) + { res = "Set.union(" + lqf + "," + rs + ")"; } + else if (operator.equals("->excluding")) + { res = "Set.subtract(" + lqf + "," + rs + ")"; } + else if (operator.equals("->excludingAt")) + { res = "Set.removeAt(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->excludingFirst")) + { res = "Set.removeFirst(" + lqf + "," + rw + ")"; } + else if (operator.equals("->prepend")) + { res = "Set.concatenate(" + rs + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "Set.append(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->count")) + { res = "Collections.frequency(" + lqf + "," + rw + ")"; } + else if (operator.equals("->indexOf")) + { res = "(" + lqf + ".indexOf(" + rw + ") + 1)"; } + else if (operator.equals("->lastIndexOf")) + { res = "(" + lqf + ".lastIndexOf(" + rw + ") + 1)"; } + else if (operator.equals("->hasMatch")) + { res = "Set.hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = lqf + ".matches(" + rqf + ")"; } + /* else if (operator.equals("->hasPrefix")) + { res = "(" + lqf + ".startsWith(" + rqf + "))"; } + else if (operator.equals("->hasSuffix")) + { res = "(" + lqf + ".endsWith(" + rqf + "))"; } */ + else + { res = composeSetQueryFormsJava6(lqf,rs); } + } + } + else if (rmult && !lmult) + { String ls = left.makeSetJava6(lqf); + if (right.isOrdered()) + { ls = left.makeSequenceJava6(lqf); } + String lw = ""; + if (lprim) + { lw = left.wrapJava6(lqf); } // only if left primitive + else + { lw = lqf; } + + if (operator.equals("=")) + { res = ls + ".equals(" + rqf + ")"; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = "!(" + ls + ".equals(" + rqf + "))"; } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".contains(" + lw + ")"; } + else if (operator.equals("/:")) + { res = "!(" + rqf + ".contains(" + lw + "))"; } + else if (operator.equals("->excludesAll")) + { res = "Collections.disjoint(" + ls + "," + rqf + ")"; } + else + { res = "(" + lqf + " " + operator + " " + rqf + ")"; + // bNeeded = true; + } // composeSetQueryForms(ls,rqf); } + // else + // { res = composeSetQueryFormsJava6(ls,rqf); } + } + else // both sets + if (operator.equals("->indexOf")) + { res = "(Collections.indexOfSubList(" + lqf + "," + rqf + ")+1)"; + } + else if (operator.equals("->lastIndexOf")) + { res = "(Collections.lastIndexOfSubList(" + lqf + "," + rqf + ") + 1)"; + } + else + { res = composeSetQueryFormsJava6(lqf,rqf); } + + if (needsBracket) + { return "( " + res + " )"; } + return res; + } // add brackets if needed + + public String queryFormJava7(java.util.Map env, boolean local) + { String res; + String cont = "Controller.inst()"; + + if (operator.equals("#") || operator.equals("#LC") || + "->existsLC".equals(operator) || + operator.equals("->exists")) + { return quantifierQueryFormJava7(env,local); } + + if (operator.equals("#1") || operator.equals("->exists1")) + { return quantifierQueryFormJava7(env,local); } + + if (operator.equals("->forAll") || operator.equals("!")) + { return forAllQueryFormJava7(env,local); } + + boolean lmult = left.isMultiple(); + boolean rmult = right.isMultiple(); + boolean lprim = left.isPrimitive(); + boolean rprim = right.isPrimitive(); + String lqf = left.queryFormJava7(env,local); + String rqf = right.queryFormJava7(env,local); + String rw = rqf; + if (rprim) + { rw = right.wrap(rqf); } + + String javaOp = javaOpOf(operator); + + String typ = ""; + if (type != null) + { typ = type.getJava7(elementType); } + else + { System.err.println("!! Warning: no type for " + this); + typ = "Object"; + } + + res = lqf + " " + javaOp + " " + rqf; // default + // if & or or: &&, || + + if (operator.equals("|") || operator.equals("->select")) + { return selectQueryFormJava7(lqf,rqf,env,local); } + + if (operator.equals("->reject") || operator.equals("|R")) + { String sel = rejectQueryFormJava7(lqf,rqf,env,local); + return sel; + } + + if (operator.equals("|C") || operator.equals("->collect")) + { return collectQueryFormJava7(lqf,rqf,rprim,env,local); } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormJava7(lqf,rqf,rprim,env,local); + if (Type.isPrimitiveType(type)) + { return unwrapJava7(getany); } + return "((" + typ + ") " + getany + ")"; + } + + if (operator.equals("->iterate") && accumulator != null && + accumulator.getInitialExpression() != null) + { Expression initexpr = + accumulator.getInitialExpression(); + Type letype = left.getElementType(); + String letypestr = Type.getJava7type(letype); + String acc = accumulator.getName(); + String init = initexpr.queryFormJava7(env,local); + Type acctype = accumulator.getType(); + String j7acctype = Type.getJava7type(acctype); + + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava7(env,local); } + return "Ocl.iterate(" + lqf + ", " + init + + ", (" + letypestr + " " + iteratorVariable + ")->((" + j7acctype + " " + acc + ")-> { return " + rqf + "; }))"; + } + + if (operator.equals("->selectMaximals")) + { String col = collectQueryFormJava7(lqf,rqf,rprim,env,local); + String jType = type.getJava7(elementType); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava7(env,local); } + return "((" + jType + ") Ocl.maximalElements(" + lqf + ", ((ArrayList) " + col + ")))"; + } + + if (operator.equals("|selectMinimals")) + { String col = + collectQueryFormJava7(lqf,rqf,rprim,env,local); + BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryFormJava7(env,local); + if (leftbe.getRight().umlkind == CLASSID) + { lqf = ((BasicExpression) leftbe.getRight()).classExtentQueryFormJava7(env,local); } + // And pass lqf to collectQueryForm? + return "Ocl.maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->selectMinimals")) + { String col = collectQueryFormJava7(lqf,rqf,rprim,env,local); + String jType = type.getJava7(elementType); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava7(env,local); } + return "((" + jType + ") Ocl.minimalElements(" + lqf + ", ((ArrayList) " + col + ")))"; + } + + if (operator.equals("|selectMinimals")) + { String col = + collectQueryFormJava7(lqf,rqf,rprim,env,local); + BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryFormJava7(env,local); + if (leftbe.getRight().umlkind == CLASSID) + { lqf = ((BasicExpression) leftbe.getRight()).classExtentQueryFormJava7(env,local); } + // And pass lqf to collectQueryForm? + return "Ocl.minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->sortedBy")) // left must be ordered + { String col = collectQueryFormJava7(lqf,rqf,rprim,env,local); // ordered version + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormJava7(env,local); } + return "Ocl.sortedBy(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|sortedBy") && + left instanceof BinaryExpression) + { BinaryExpression leftbe = (BinaryExpression) left; + lqf = leftbe.getRight().queryFormJava7(env,local); + if (leftbe.getRight().umlkind == CLASSID) + { lqf = ((BasicExpression) leftbe.getRight()).classExtentQueryFormJava7(env,local); } + // And pass lqf to collectQueryForm? + String col = + collectQueryFormJava7(lqf,rqf,rprim,env,local); + return "Ocl.sortedBy(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->includes")) + { if (left.isString()) + { return "(" + lqf + ").indexOf(" + rqf + ") >= 0"; } + else + { return lqf + ".contains(" + rqf + ")"; } + } + + if (operator.equals("->count") && + !("String".equals(left.type + ""))) // not for strings + { return "Collections.frequency(" + lqf + "," + rw + ")"; } + + if (operator.equals("->restrict")) + { return "Ocl.restrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->antirestrict")) + { return "Ocl.antirestrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->at")) + { String getind = lqf + ".get(" + rqf + " - 1)"; + String ind = lqf + ".get(" + rqf + ")"; + + if ("String".equals(left.type + "")) + { return "(" + lqf + ".charAt(" + rqf + " - 1) + \"\")"; } // and for Java6, 7, etc. + else if (left.type != null && left.type.isMapType()) + { return "((" + typ + ") " + ind + ")"; } + + if (left.isRef()) + { return getind; } + + if (Type.isPrimitiveType(type)) + { return unwrapJava7(getind); } + + return "((" + typ + ") " + getind + ")"; + } + + if (operator.equals("let")) + { // (new Object() { public typ call(acct acc) { return rqf; } })(lqf) + + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getJava7(); + return "(new Object() { public " + typ + " call(" + + lett + " " + acc + ") { return " + rqf + "; } }).call(" + lqf + ")"; + } + +/* if (operator.equals("let")) + { // ((acc) -> { return right; }).apply(left) + + String acc = accumulator.getName(); + // Type acct = accumulator.getType(); + // String lett = acct.getJava(); + // Expression subst = + // right.substituteEq(acc,left); + String stats = + "(" + acc + ") -> { return " + rqf + "; }"; + return "(" + stats + ").apply(" + lqf + ")"; + } */ + + if (operator.equals("->apply")) + { return "(" + lqf + ").apply(" + rqf + ")"; } + + if (operator.equals("->pow")) + { return "Math.pow(" + lqf + ", " + rqf + ")"; } + + if (operator.equals("->truncateTo")) + { if (left.isInteger()) + { return lqf; } + return "Ocl.truncateN(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->roundTo")) + { if (left.isInteger()) + { return lqf; } + return "Ocl.roundN(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->compareTo")) + { if (left.isNumeric() && right.isNumeric()) + { res = "(" + lqf + " - (" + rqf + "))"; } + else if (left.isString()) + { res = "((Comparable) " + lqf + ").compareTo(\"\" + " + rqf + ")"; } + else if (left.hasSequenceType() && right.hasSequenceType()) + { res = "Ocl.sequenceCompare(" + lqf + "," + rqf + ")"; } + else + { res = "((Comparable) " + lqf + ").compareTo(" + rqf + ")"; } + return res; + } + + if (operator.equals("->gcd")) + { return "Ocl.gcd(" + lqf + "," + rqf + ")"; } + + if (operator.equals("<>=")) + { res = lqf + " == " + rqf; + if (needsBracket) + { res = "(" + res + ")"; } + return res; + } + + if (operator.equals("->isUnique")) // and define for B + { String fcollect = collectQueryFormJava7(lqf,rqf,rprim,env,local); + return "Ocl.isUnique(" + fcollect + ")"; + } + + if (operator.equals("->intersectAll")) + { String col = collectQueryFormJava7(lqf,rqf,rprim,env,local); + return "Ocl.intersectAll(" + col + ")"; + } + + if (operator.equals("->unionAll")) + { String col = collectQueryFormJava7(lqf,rqf,rprim,env,local); + String jtype = type.getJava7(elementType); + if (left.isOrdered() && (right.isOrdered() || "self".equals(right + ""))) + { return "((" + jtype + ") Ocl.concatenateAll(" + col + "))"; } + return "((" + jtype + ") Ocl.unionAll(" + col + "))"; + } + + if (operator.equals("->closure")) + { String rel = right + ""; + if (entity == null) + { JOptionPane.showMessageDialog(null, "No entity for: " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + return ""; + } + return "Ocl.closure" + entity.getName() + rel + "(" + lqf + ")"; + } // left must be set-valued. + + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals(":")) + { return "(" + lqf + " instanceof " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsKindOf")) + { return "(" + lqf + " instanceof " + right + ")"; } + + if (operator.equals("->oclIsKindOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestJava7(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsTypeOf")) + { return "(" + lqf + ".getClass() == " + right + ".class)"; } + + if (operator.equals("->oclIsTypeOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestJava7(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("/:")) + { return "!(" + lqf + " instanceof " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("<:")) + { rqf = ((BasicExpression) right).classExtentQueryFormJava7(env,local); + return "(" + rqf + ".containsAll(" + lqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includes")) + { return "(" + rqf + " instanceof " + left + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includesAll")) + { lqf = ((BasicExpression) left).classExtentQueryFormJava7(env,local); + return "(" + lqf + ".containsAll(" + rqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludes")) + { return "!(" + rqf + " instanceof " + left + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludesAll")) + { lqf = ((BasicExpression) left).classExtentQueryFormJava7(env,local); + return "Collections.disjoint(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("=>")) + { return "(!(" + lqf + ") || " + rqf + ")"; } + + if (operator.equals("->oclAsType")) + { if (type != null) + { String jtyp = type.getJava7(elementType); + return "((" + jtyp + ") " + lqf + ")"; + } + return lqf; + } + + if (operator.equals("\\/") || + operator.equals("->union")) + { if (left.isMap() || right.isMap()) + { res = "Ocl.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) + { res = "Ocl.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Ocl.union(" + lqf + "," + rqf + ")"; } + } + + if (operator.equals("/\\") || + operator.equals("->intersection")) + { if (left.isMap() && right.isMap()) + { res = "Ocl.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Ocl.intersection(" + lqf + "," + rqf + ")"; } + } + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opjava = Expression.getOperatorJava(op); + if (opjava != null && opjava.length() > 0) + { return opjava.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + if (!lmult && !rmult) + { if (operator.equals("=")) // and comparitors + { res = composeEqQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("/=") || operator.equals("!=") || + operator.equals("<>")) + { res = composeNeqQueryForms(lqf,rqf,lprim,rprim); } + else if (comparitors.contains(operator)) + { res = composeComparitorQueryForms(lqf,rqf,lprim,rprim); } + else if (operator.equals("+") || operator.equals("-") || + operator.equals("*") || operator.equals("/") || + operator.equals("mod") || + operator.equals("div")) + { res = composeMathOpQueryFormsJava7(lqf,rqf,lprim,rprim); } + else if (operator.equals("->count")) + { res = "Ocl.count(" + lqf + "," + rw + ")"; } + else if (operator.equals("->indexOf")) + { res = "(" + lqf + ".indexOf(" + rw + ") + 1)"; } + else if (operator.equals("->lastIndexOf")) + { res = "(" + lqf + ".lastIndexOf(" + rw + ") + 1)"; } + else if (operator.equals("->hasPrefix")) + { res = "(" + lqf + ".startsWith(" + rqf + "))"; } + else if (operator.equals("->hasSuffix")) + { res = "(" + lqf + ".endsWith(" + rqf + "))"; } + else if (operator.equals("->hasMatch")) + { res = "Ocl.hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = lqf + ".matches(" + rqf + ")"; } + else if (operator.equals("->equalsIgnoreCase")) + { res = "(" + lqf + ".equalsIgnoreCase(" + rqf + "))"; } + else if (operator.equals("->before")) + { res = "Ocl.before(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->after")) + { res = "Ocl.after(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->split")) + { res = "Ocl.split(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->allMatches")) + { res = "Ocl.allMatches(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->firstMatch")) + { res = "Ocl.firstMatch(" + lqf + ", " + rqf + ")"; } + } + else if (lmult && !rmult) // convert right to mult + { String rss = right.makeSetJava7(rw); + if (left.isOrdered()) + { rss = right.makeSequenceJava7(rw); } + else if (left.isSorted()) + { rss = right.makeSortedSetJava7(rw); } + + if (operator.equals("->includes")) + { res = lqf + ".contains(" + rw + ")"; } + else if (operator.equals("->excludes")) + { res = "!(" + lqf + ".contains(" + rw + "))"; } + else if (operator.equals("->excluding")) + { res = "Ocl.subtract(" + lqf + "," + rss + ")"; } + else if (operator.equals("->excludingAt")) + { res = "Ocl.removeAt(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->excludingFirst")) + { res = "Ocl.removeFirst(" + lqf + "," + rw + ")"; } + else if (operator.equals("->append")) + { res = "Ocl.append(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->including")) + { res = "Ocl.union(" + lqf + "," + rss + ")"; } + else if (operator.equals("->prepend")) + { res = "Ocl.concatenate(" + rss + "," + lqf + ")"; } + else + { String rs = right.makeSetJava7(rqf); + if (left.isOrdered()) + { rs = right.makeSequenceJava7(rqf); } + else if (left.isSorted()) + { rss = right.makeSortedSetJava7(rw); } + + if (operator.equals("=")) + { res = lqf + ".equals(" + rs + ")"; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = "!(" + lqf + ".equals(" + rs + "))"; } + else if (operator.equals(":") || operator.equals("<:")) + { res = rs + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->includesAll")) + { res = lqf + ".containsAll(" + rs + ")"; } + else if (operator.equals("/<:")) + { res = "!(" + rs + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->excludesAll")) + { res = "Collections.disjoint(" + rs + "," + lqf + ")"; } + else if (operator.equals("->including")) + { res = "Ocl.union(" + lqf + "," + rs + ")"; } + else if (operator.equals("->excluding")) + { res = "Ocl.subtract(" + lqf + "," + rs + ")"; } + else if (operator.equals("->excluding")) + { res = "Ocl.removeAt(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->prepend")) + { res = "Ocl.concatenate(" + rs + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "Ocl.append(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->count")) + { res = "Collections.frequency(" + lqf + "," + rw + ")"; } + else if (operator.equals("->indexOf")) + { res = "(" + lqf + ".indexOf(" + rw + ") + 1)"; } + else if (operator.equals("->lastIndexOf")) + { res = "(" + lqf + ".lastIndexOf(" + rw + ") + 1)"; } + /* else if (operator.equals("->hasPrefix")) + { res = "(" + lqf + ".startsWith(" + rqf + "))"; } + else if (operator.equals("->hasSuffix")) + { res = "(" + lqf + ".endsWith(" + rqf + "))"; } */ + else + { res = composeSetQueryFormsJava7(lqf,rs); } + } + } + else if (rmult && !lmult) + { String lw = ""; + if (lprim) + { lw = left.wrap(lqf); } // only if left primitive + else + { lw = lqf; } + + String ls = left.makeSetJava7(lw); + if (right.isOrdered()) + { ls = left.makeSequenceJava7(lw); } + else if (right.isSorted()) + { ls = left.makeSortedSetJava7(lw); } + + if (operator.equals("=")) + { res = ls + ".equals(" + rqf + ")"; } + else if (operator.equals("/=") || + operator.equals("!=") || operator.equals("<>")) + { res = "!(" + ls + ".equals(" + rqf + "))"; } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".contains(" + lw + ")"; } + else if (operator.equals("/:")) + { res = "!(" + rqf + ".contains(" + lw + "))"; } + else if (operator.equals("->excludesAll")) + { res = "Collections.disjoint(" + ls + "," + rqf + ")"; } + else + { res = "(" + lqf + " " + operator + " " + rqf + ")"; + // bNeeded = true; + } + // else + // { res = composeSetQueryFormsJava7(ls,rqf); } + } + else // both sets + if (operator.equals("->indexOf")) + { res = "(Collections.indexOfSubList(" + lqf + "," + rqf + ")+1)"; + // bNeeded = true; + } + else if (operator.equals("->lastIndexOf")) + { res = "(Collections.lastIndexOfSubList(" + lqf + "," + rqf + ") + 1)"; + // bNeeded = true; + } + else + { res = composeSetQueryFormsJava7(lqf,rqf); } + + if (needsBracket) + { return "( " + res + " )"; } + return res; + } // add brackets if needed + + public String queryFormCSharp(java.util.Map env, boolean local) + { String res; + String cont = "Controller.inst()"; + + if (operator.equals("#") || operator.equals("#LC") || + "->existsLC".equals(operator) || operator.equals("->exists")) + { return existsQueryFormCSharp(env,local); } + + if (operator.equals("#1") || operator.equals("->exists1")) + { return exists1QueryFormCSharp(env,local); } + + if (operator.equals("->forAll") || operator.equals("!")) + { return forAllQueryFormCSharp(env,local); } + + boolean lmult = left.isMultiple(); + boolean rmult = right.isMultiple(); + boolean lprim = left.isPrimitive(); + boolean rprim = right.isPrimitive(); + String lqf = left.queryFormCSharp(env,local); + String rqf = right.queryFormCSharp(env,local); + // if (lqf == null || rqf == null) + // { return null; } + + boolean bNeeded = false; + + String javaOp = javaOpOf(operator); + res = lqf + " " + javaOp + " " + rqf; // default + // if & or or: &&, || + + if (operator.equals("|") || operator.equals("->select")) + { return selectQueryFormCSharp(lqf,rqf,env,local); } + + if (operator.equals("|C") || operator.equals("->collect")) + { return collectQueryFormCSharp(lqf,rqf,rprim,env,local); } + + if (operator.equals("->selectMaximals")) + { String col = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCSharp(env,local); } + return "SystemTypes.maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|selectMaximals")) + { String col = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + Expression actualLeft = ((BinaryExpression) left).getRight(); + lqf = actualLeft.queryFormCSharp(env,local); + if (actualLeft.umlkind == CLASSID) + { lqf = ((BasicExpression) actualLeft).classExtentQueryFormCSharp(env,local); } + return "SystemTypes.maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->iterate") && accumulator != null && + accumulator.getInitialExpression() != null) + { Expression initexpr = + accumulator.getInitialExpression(); + Type letype = left.getElementType(); + String letypestr = Type.getCSharptype(letype); + String acc = accumulator.getName(); + String init = initexpr.queryFormCSharp(env,local); + Type acctype = accumulator.getType(); + String csacctype = Type.getCSharptype(acctype); + + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCSharp(env,local); } + String typ = Type.getCSharptype(type); + + return "(" + typ + ") SystemTypes.iterate(" + lqf + ", " + init + + ", (" + iteratorVariable + "_x) => ( (" + acc + "_x) => { " + csacctype + " " + acc + " = (" + csacctype + ") " + acc + "_x; " + letypestr + " " + iteratorVariable + " = (" + letypestr + ") " + iteratorVariable + "_x; return " + rqf + "; } ) )"; + } + + if (operator.equals("->selectMinimals")) + { String col = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCSharp(env,local); } + return "SystemTypes.minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|selectMinimals")) + { String col = + collectQueryFormCSharp(lqf,rqf,rprim,env,local); + Expression actualLeft = + ((BinaryExpression) left).getRight(); + lqf = actualLeft.queryFormCSharp(env,local); + if (actualLeft.umlkind == CLASSID) + { lqf = ((BasicExpression) actualLeft).classExtentQueryFormCSharp(env,local); } + return "SystemTypes.minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->sortedBy")) + { String col = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCSharp(env,local); } + return "SystemTypes.sortedBy(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|sortedBy") && + left instanceof BinaryExpression) + { String col = + collectQueryFormCSharp(lqf,rqf,rprim,env,local); + Expression actualLeft = + ((BinaryExpression) left).getRight(); + lqf = actualLeft.queryFormCSharp(env,local); + if (actualLeft.umlkind == CLASSID) + { lqf = ((BasicExpression) actualLeft).classExtentQueryFormCSharp(env,local); } + return "SystemTypes.sortedBy(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->count")) + { return "SystemTypes.count(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->restrict")) + { return "SystemTypes.restrictMap(" + lqf + "," + rqf + ")"; } + + + if (operator.equals("->antirestrict")) + { return "SystemTypes.antirestrictMap(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->sequenceRange")) + { return "SystemTypes.sequenceRange(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->resizeTo")) + { return "SystemTypes.resizeTo(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->prepend")) + { return "SystemTypes.prepend(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->append")) + { return "SystemTypes.append(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->at")) + { + System.err.println(this + " with " + left.type + " " + left.elementType); + + if ("String".equals(left.type + "")) + { return "(" + lqf + ").Substring(" + rqf + "-1 , 1)"; } + + if (Type.isReferenceType(left.type)) + { return lqf + "[" + rqf + "-1]"; } + + if (left.getElementType() != null) + { String typ = left.getElementType().getCSharp(); + + if (left.type != null && left.type.isMapType()) + { return "((" + typ + ") " + lqf + "[" + rqf + "])"; } + + if (right.type != null && right.type.isStringType()) + { return "((" + typ + ") " + lqf + "[" + rqf + "])"; } + + return "((" + typ + ") " + lqf + "[" + rqf + " - 1])"; + } + + System.err.println("!WARNING!: no element type in " + left); + + if (left.type != null && left.type.isMapType()) + { return "(" + lqf + ")[" + rqf + "]"; } + + if (right.type != null && right.type.isStringType()) + { return "(" + lqf + ")[" + rqf + "]"; } + + return "(" + lqf + ")[" + rqf + " - 1]"; + } + + if (operator.equals("let")) + { // (new Func((acc) -> { return right; })).Invoke(left) + + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getCSharp(); + String typ = "object"; + if (type != null) + { typ = type.getCSharp(); } + + String stats = + acc + " => (" + rqf + ")"; + return "(new Func<" + lett + "," + typ + ">(" + stats + ")).Invoke(" + lqf + ")"; + } + + if (operator.equals("->apply")) + { return lqf + ".Invoke(" + rqf + ")"; } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormCSharp(lqf,rqf,rprim,env,local); + String typ = type.getCSharp(); + return "((" + typ + ") " + getany + ")"; + } + + if (operator.equals("->pow")) + { return "Math.Pow(" + lqf + ", " + rqf + ")"; } + + if (operator.equals("->gcd")) + { return "SystemTypes.gcd(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->truncateTo")) + { if (left.isInteger()) + { return lqf; } + return "SystemTypes.truncateTo(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->roundTo")) + { if (left.isInteger()) + { return lqf; } + return "SystemTypes.roundTo(" + lqf + "," + rqf + ")"; + } + + + if (operator.equals("<>=")) + { res = lqf + " == " + rqf; + if (needsBracket) + { res = "(" + res + ")"; } + return res; + } + + if (operator.equals("->compareTo")) + { if (left.isNumeric() && right.isNumeric()) + { res = "((" + lqf + " < " + rqf + ") ? -1 : ((" + lqf + " > " + rqf + ") ? 1 : 0))"; } + else if (left.hasSequenceType() && right.hasSequenceType()) + { res = "SystemTypes.sequenceCompare(" + lqf + "," + rqf + ")"; } + else + { res = "((IComparable) " + lqf + ").CompareTo(" + rqf + ")"; } + return res; + } + + if (operator.equals("+")) + { String pres = lqf + " + " + rqf; + if (needsBracket) + { pres = "(" + pres + ")"; } + + if ("null".equals(lqf) || "null".equals(rqf)) + { return pres; } + if (left.isPrimitive() && right.isPrimitive()) + { return pres; } + if (left.isString() && right.isString()) + { return pres; } + if (left.isString() && right.isPrimitive()) + { return pres; } + if (left.isPrimitive() && right.isString()) + { return pres; } + + if (left.isString()) + { pres = lqf + " + " + rqf + ".ToString()"; + if (needsBracket) + { pres = "(" + pres + ")"; } + } + else if (right.isString()) + { pres = lqf + ".ToString() + " + rqf; + if (needsBracket) + { pres = "(" + pres + ")"; } + } + + return pres; + } + + if (operator.equals("->isUnique")) // and define for B + { String fcollect = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + return "SystemTypes.isUnique(" + fcollect + ")"; + } + + if (operator.equals("->intersectAll")) + { String col = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + return "SystemTypes.intersectAll(" + col + ")"; + } + + if (operator.equals("->unionAll")) + { String col = collectQueryFormCSharp(lqf,rqf,rprim,env,local); + if (left.isOrdered() && (right.isOrdered() || "self".equals(right + ""))) + { return "SystemTypes.concatenateAll(" + col + ")"; } + return "SystemTypes.unionAll(" + col + ")"; + } + + if (operator.equals("->closure")) + { String rel = right + ""; + if (entity == null) + { JOptionPane.showMessageDialog(null, "No entity for: " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + return ""; + } + return "SystemTypes.closure" + entity.getName() + rel + "(" + lqf + ")"; + } // left must be set-valued. + + if (operator.equals("->reject") || operator.equals("|R")) + { String sel = rejectQueryFormCSharp(lqf,rqf,env,local); + return sel; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && + operator.equals(":")) + { return "(" + lqf + " is " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && + operator.equals("->oclIsKindOf")) + { return "(" + lqf + " is " + right + ")"; } + + if (operator.equals("->oclIsKindOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestCSharp(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && + operator.equals("->oclIsTypeOf")) + { return "(" + lqf + " is " + right + ")"; } + + if (operator.equals("->oclIsTypeOf")) + { // right is a type name: int, Sequence, etc + return "(" + Type.typeTestCSharp(lqf, right + "") + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("/:")) + { return "!(" + lqf + " is " + right + ")"; } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("<:")) + { rqf = ((BasicExpression) right).classExtentQueryFormCSharp(env,local); + return "(SystemTypes.isSubset(" + lqf + ", " + rqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includes")) + { return "(" + rqf + " is " + left + ")"; } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includesAll")) + { lqf = ((BasicExpression) left).classExtentQueryFormCSharp(env,local); + return "(SystemTypes.isSubset(" + rqf + ", " + lqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludes")) + { return "!(" + rqf + " is " + left + ")"; } + + + if (operator.equals("=>")) + { return "(!(" + lqf + ") || " + rqf + ")"; } + + if (operator.equals("->oclAsType")) + { if (type != null) + { String jtyp = type.getCSharp(); + return "((" + jtyp + ") " + lqf + ")"; + } + return lqf; + } + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opcsharp = Expression.getOperatorCSharp(op); + if (opcsharp != null && opcsharp.length() > 0) + { return opcsharp.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + if (!lmult && !rmult) + { if (operator.equals("=")) // and comparitors + { res = composeEqQueryFormsCSharp(lqf,rqf,lprim,rprim); } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = composeNeqQueryFormsCSharp(lqf,rqf,lprim,rprim); } + else if (comparitors.contains(operator)) + { res = composeComparitorQueryFormsCSharp(lqf,rqf,lprim,rprim); + bNeeded = needsBracket; + } + else if (operator.equals("+") || operator.equals("-") || + operator.equals("*") || operator.equals("/") || + operator.equals("mod") || operator.equals("div")) + { res = composeMathOpQueryFormsCSharp(lqf,rqf,lprim,rprim); + bNeeded = needsBracket; + } + else if (operator.equals("->indexOf")) + { res = "(" + lqf + ".IndexOf(" + rqf + ") + 1)"; } + else if (operator.equals("->lastIndexOf")) + { res = "(" + lqf + ".LastIndexOf(" + rqf + ") + 1)"; } + else if (operator.equals("->count")) + { res = "SystemTypes.count(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->hasPrefix")) + { res = "(" + lqf + ".StartsWith(" + rqf + "))"; } + else if (operator.equals("->hasSuffix")) + { res = "(" + lqf + ".EndsWith(" + rqf + "))"; } + else if (operator.equals("->hasMatch")) + { res = "SystemTypes.hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = "SystemTypes.isMatch(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->equalsIgnoreCase")) + { res = "(" + lqf + ".ToLower().Equals(" + rqf + ".ToLower()))"; } + else if (operator.equals("->before")) + { res = "SystemTypes.before(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->after")) + { res = "SystemTypes.after(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->split")) + { res = "SystemTypes.split(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->allMatches")) + { res = "SystemTypes.allMatches(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->firstMatch")) + { res = "SystemTypes.firstMatch(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->excludingAt") && left.isString()) + { res = "SystemTypes.removeAtString(" + + lqf + "," + rqf + ")"; + } + else if (operator.equals("->excludingAt")) + { res = "SystemTypes.removeAt(" + + lqf + "," + rqf + ")"; + } + } + else if (lmult && !rmult) // convert right to mult + { String rw = rqf; + String rss = right.makeSetCSharp(rw); + + if (operator.equals("->includes")) + { res = lqf + ".Contains(" + rw + ")"; } + else if (operator.equals("->excludes")) + { res = "!(" + lqf + ".Contains(" + rw + "))"; } + else if (operator.equals("->excluding")) + { res = "SystemTypes.subtract(" + lqf + "," + rss + ")"; } + else if (operator.equals("->excludingAt")) + { if (left.isString()) + { res = "SystemTypes.removeAtString(" + + lqf + "," + rqf + ")"; + } + else + { res = "SystemTypes.removeAt(" + + lqf + "," + rqf + ")"; + } + } + else if (operator.equals("->excludingFirst")) + { res = "SystemTypes.removeFirst(" + lqf + "," + rw + ")"; } + else if (operator.equals("->including") && left.isOrdered()) + { res = "SystemTypes.concatenate(" + lqf + "," + rss + ")"; } + else if (operator.equals("->including")) + { res = "SystemTypes.union(" + lqf + "," + rss + ")"; } + else + { String rs = right.makeSetCSharp(rqf); + if (operator.equals("=")) + { if (Type.isSetType(left.getType())) + { res = "SystemTypes.equalsSet(" + lqf + "," + rs + ")"; } + else + { res = lqf + ".Equals(" + rs + ")"; } + } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isSetType(left.getType())) + { res = "!(SystemTypes.equalsSet(" + lqf + "," + rs + "))"; } + else + { res = "!(" + lqf + ".Equals(" + rs + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = "SystemTypes.isSubset(" + lqf + "," + rs + ")"; } + else if (operator.equals("->includesAll")) + { res = "SystemTypes.isSubset(" + rs + "," + lqf + ")"; } + else if (operator.equals("/<:")) + { res = "!(SystemTypes.isSubset(" + lqf + "," + rs + "))"; } + else if (operator.equals("->excludesAll")) + { res = "SystemTypes.intersection(" + rs + "," + lqf + ").Count == 0"; } + else if (operator.equals("->including")) + { res = "SystemTypes.union(" + lqf + "," + rs + ")"; } + else if (operator.equals("->excluding")) + { res = "SystemTypes.subtract(" + lqf + "," + rs + ")"; } + else if (operator.equals("->prepend")) + { res = "SystemTypes.concatenate(" + rs + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "SystemTypes.concatenate(" + lqf + "," + rs + ")"; } + else if (operator.equals("->count")) + { res = "SystemTypes.count(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->indexOf")) + { res = "(" + lqf + ".IndexOf(" + rqf + ") + 1)"; } + else if (operator.equals("->lastIndexOf")) + { res = "(" + lqf + ".LastIndexOf(" + rqf + ") + 1)"; } + else if (operator.equals("->hasMatch")) + { res = "SystemTypes.hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = "SystemTypes.isMatch(" + lqf + "," + rqf + ")"; } + /* else if (operator.equals("->hasPrefix")) + { res = "(" + lqf + ".StartsWith(" + rqf + "))"; } + else if (operator.equals("->hasSuffix")) + { res = "(" + lqf + ".EndsWith(" + rqf + "))"; } */ + else + { res = composeSetQueryFormsCSharp(lqf,rs); } + } + } + else if (rmult && !lmult) + { String ls = left.makeSetCSharp(lqf); + String lw = lqf; + + if (operator.equals("=")) + { if (Type.isSetType(right.getType())) + { res = "SystemTypes.equalsSet(" + ls + "," + rqf + ")"; } + else + { res = ls + ".Equals(" + rqf + ")"; } + } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isSetType(right.getType())) + { res = "!(SystemTypes.equalsSet(" + ls + "," + rqf + "))"; } + else + { res = "!(" + ls + ".Equals(" + rqf + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".Contains(" + lw + ")"; } + else if (operator.equals("/:")) + { res = "!(" + rqf + ".Contains(" + lw + "))"; } + else if (operator.equals("->excludesAll")) + { res = "(SystemTypes.intersection(" + rqf + "," + ls + ").Count == 0)"; } + else + { res = "(" + lqf + " " + operator + " " + rqf + ")"; + // bNeeded = true; + } + // else + // { res = composeSetQueryFormsCSharp(ls,rqf); } + } + else // both sets + if (operator.equals("->indexOf")) + { res = "SystemTypes.indexOfSubList(" + lqf + "," + rqf + ") + 1"; + bNeeded = true; + } + else if (operator.equals("->lastIndexOf")) + { res = "SystemTypes.lastIndexOfSubList(" + lqf + "," + rqf + ") + 1"; + bNeeded = true; + } + else + { res = composeSetQueryFormsCSharp(lqf,rqf); } + + if (needsBracket || bNeeded) + { return "( " + res + " )"; } + return res; + } // add brackets if needed + + public String queryFormCPP(java.util.Map env, boolean local) + { String res; + String cont = "Controller::inst->"; + + if (operator.equals("#") || operator.equals("#LC") || + "->existsLC".equals(operator) || operator.equals("->exists")) + { return existsQueryFormCPP(env,local); } + + if (operator.equals("#1") || operator.equals("->exists1")) + { return exists1QueryFormCPP(env,local); } + + if (operator.equals("->forAll") || operator.equals("!")) + { return forAllQueryFormCPP(env,local); } + + boolean lmult = left.isMultiple(); + boolean rmult = right.isMultiple(); + boolean lprim = left.isPrimitive(); + boolean rprim = right.isPrimitive(); + String lqf = left.queryFormCPP(env,local); + String rqf = right.queryFormCPP(env,local); + + Type lelemt = left.getElementType(); + String ename = ""; + Entity ent = null; + String lcet = "void*"; + if (lelemt != null) + { lcet = lelemt.getCPP(); + ent = lelemt.getEntity(); + ename = lelemt.getName(); + } + + Type relemt = right.getElementType(); + String rename = ""; + String rcet = "void*"; + if (relemt != null) + { rcet = relemt.getCPP(); + rename = relemt.getName(); + } + + String javaOp = javaOpOf(operator); + res = lqf + " " + javaOp + " " + rqf; // default + // if & or or: &&, || + + if (operator.equals("|") || operator.equals("->select")) + { return selectQueryFormCPP(lqf,rqf,env,local); } + + if (operator.equals("|C") || operator.equals("->collect")) + { return collectQueryFormCPP(lqf,rqf,rprim,env,local); } + + if (operator.equals("->iterate") && accumulator != null && + accumulator.getInitialExpression() != null) + { Expression initexpr = + accumulator.getInitialExpression(); + Type letype = left.getElementType(); + String letypestr = Type.getCPPtype(letype); + String acc = accumulator.getName(); + String init = initexpr.queryFormCPP(env,local); + Type acctype = accumulator.getType(); + String csacctype = Type.getCPPtype(acctype); + + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCPP(env,local); } + String typ = Type.getCPPtype(type); + + return "(" + typ + ") UmlRsdsOcl<" + letypestr + ", " + csacctype + ", " + csacctype + ">.iterate(" + lqf + ", " + init + + ", [=](" + letypestr + " " + iteratorVariable + ", " + csacctype + " " + acc + ") -> " + csacctype + " { return " + rqf + "; } )"; + } + + if (operator.equals("->selectMaximals")) + { String col = collectQueryFormCPP(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCPP(env,local); } + return "UmlRsdsLib<" + lcet + ">::maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|selectMaximals")) + { String col = collectQueryFormCPP(lqf,rqf,rprim,env,local); + Expression actualLeft = + ((BinaryExpression) left).getRight(); + lqf = actualLeft.queryFormCPP(env,local); + + if (actualLeft.umlkind == CLASSID) + { lqf = ((BasicExpression) actualLeft).classExtentQueryFormCPP(env,local); } + return "UmlRsdsLib<" + lcet + ">::maximalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->selectMinimals")) + { String col = collectQueryFormCPP(lqf,rqf,rprim,env,local); + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCPP(env,local); } + return "UmlRsdsLib<" + lcet + ">::minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("|selectMinimals")) + { String col = + collectQueryFormCPP(lqf,rqf,rprim,env,local); + Expression actualLeft = + ((BinaryExpression) left).getRight(); + lqf = actualLeft.queryFormCPP(env,local); + + if (actualLeft.umlkind == CLASSID) + { lqf = ((BasicExpression) actualLeft).classExtentQueryFormCPP(env,local); } + return "UmlRsdsLib<" + lcet + ">::minimalElements(" + lqf + ", " + col + ")"; + } + + if (operator.equals("->restrict")) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + return "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::restrict(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->antirestrict")) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + return "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::antirestrict(" + lqf + "," + rqf + ")"; + } + + if (operator.equals("->sortedBy")) + { // String col = collectQueryFormCPP(lqf,rqf,rprim,env,local); + java.util.Map enva = (java.util.Map) ((java.util.HashMap) env).clone(); + java.util.Map envb = (java.util.Map) ((java.util.HashMap) env).clone(); + + if ("".equals(ename)) + { ename = "void"; } + + String var1 = ename.toLowerCase() + "_1"; + String var2 = ename.toLowerCase() + "_2"; + enva.put(ename,var1); + envb.put(ename,var2); + String rqf1 = right.queryFormCPP(enva,false); + String rqf2 = right.queryFormCPP(envb,false); + String fname = Identifier.nextIdentifier(ename); + String compareFunction = + "[=](" + ename + "* " + var1 + + ", " + ename + "* " + var2 + ") -> bool " + + " { return " + rqf1 + " < " + rqf2 + "; }"; + // System.out.println(compareFunc); + + /* + if (ent != null) + { ent.addAux(compareFunc); } + else if (entity != null) + { entity.addAux(compareFunc); } */ + + if (left.umlkind == CLASSID) + { lqf = ((BasicExpression) left).classExtentQueryFormCPP(env,local); } + return "UmlRsdsLib<" + lcet + ">::sort(" + lqf + ", " + compareFunction + ")"; + } + + if (operator.equals("|sortedBy") && + left instanceof BinaryExpression) + { java.util.Map enva = (java.util.Map) ((java.util.HashMap) env).clone(); + java.util.Map envb = (java.util.Map) ((java.util.HashMap) env).clone(); + if ("".equals(ename)) + { ename = "void"; } + String var1 = ename.toLowerCase() + "_1"; + String var2 = ename.toLowerCase() + "_2"; + enva.put(ename,var1); + envb.put(ename,var2); + BinaryExpression lbe = (BinaryExpression) left; + BasicExpression leftvar = (BasicExpression) lbe.getLeft(); + Expression col = lbe.getRight(); + lelemt = col.getElementType(); + if (lelemt != null) + { lcet = lelemt.getCPP(); } + + BasicExpression var1e = + BasicExpression.newVariableBasicExpression(var1); + BasicExpression var2e = + BasicExpression.newVariableBasicExpression(var2); + var1e.setType(leftvar.getType()); + var2e.setType(leftvar.getType()); + var1e.setElementType(leftvar.getElementType()); + var2e.setElementType(leftvar.getElementType()); + + Expression right1 = right.substituteEq(leftvar + "",var1e); + Expression right2 = right.substituteEq(leftvar + "",var2e); + + String rqf1 = right1.queryFormCPP(enva,false); + String rqf2 = right2.queryFormCPP(envb,false); + String fname = Identifier.nextIdentifier(ename); + String compareFunction = + " [=](" + ename + "* " + var1 + + ", " + ename + "* " + var2 + ") -> bool " + + "{ return " + rqf1 + " < " + rqf2 + "; }"; + // System.out.println(compareFunc); + + /* if (ent != null) + { ent.addAux(compareFunc); } + else if (entity != null) + { entity.addAux(compareFunc); } + else if (col.getElementType() != null && + col.getElementType().isEntity()) + { Entity colent = col.getElementType().getEntity(); + colent.addAux(compareFunc); + } */ + + String colqf = col.queryFormCPP(env,local); + + if (col.umlkind == CLASSID) + { colqf = ((BasicExpression) col).classExtentQueryFormCPP(env,local); } + return "UmlRsdsLib<" + lcet + ">::sort(" + colqf + ", " + compareFunction + ")"; + } + + if (operator.equals("->count")) + { return "UmlRsdsLib<" + lcet + ">::count(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->equalsIgnoreCase")) + { return "UmlRsdsLib<" + lcet + ">::equalsIgnoreCase(" + lqf + "," + rqf + ")"; } + + if (operator.equals("<>=")) + { res = lqf + " == " + rqf; + if (needsBracket) + { res = "(" + res + ")"; } + return res; + } + + if (operator.equals("->compareTo")) + { /* if (left.hasSequenceType() && right.hasSequenceType()) + { res = "UmlRsdsLib<" + lcet + ">::sequenceCompare(" + lqf + "," + rqf + ")"; + return res; + } */ + + res = "(" + lqf + " < " + rqf + ")?-1:((" + rqf + " < " + lqf + ")?1:0)"; + return res; + } + // User must define operator< in their classes + + if (operator.equals("->at") && left.getType() != null) + { Type lefttype = left.getType(); + Type lelemtype = left.getElementType(); + + if ("String".equals(lefttype.getName())) + { return "(" + lqf + ").substr(" + rqf + "-1 , 1)"; } + + if (lefttype.isMapType()) + { if (lelemtype != null) + { String etyp = + lelemtype.getCPP(lelemtype.getElementType()); + return "((" + etyp + ") (" + lqf + ")->at(" + rqf + "))"; + } + return "(" + lqf + ")->at(" + rqf + ")"; + } + + if (left.isRef()) + { return "(" + lqf + ")[" + rqf + "-1]"; } + + if (lelemtype != null) + { String etyp = + lelemtype.getCPP(lelemtype.getElementType()); + return "((" + etyp + ") (" + lqf + ")->at(" + rqf + " - 1))"; + } + + return "(" + lqf + ")->at(" + rqf + " - 1)"; + } + + if (operator.equals("let")) + { + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getCPP(); + String typ = "void*"; + if (type != null) + { typ = type.getCPP(); } + + return "([=](" + lett + " " + acc + ") -> " + + typ + " { return " + rqf + "; })(" + lqf + ")"; + } + + if (operator.equals("->apply")) + { return "(" + lqf + ")(" + rqf + ")"; } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormCPP(lqf,rqf,env,local); + String typ = type.getCPP(elementType); + return "((" + typ + ") " + getany + ")"; + } + + + if (operator.equals("->pow")) + { return "pow(" + lqf + ", " + rqf + ")"; } + + if (operator.equals("->gcd")) + { return "UmlRsdsLib::gcd(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->truncateTo")) + { return "UmlRsdsLib::truncateTo(" + lqf + "," + rqf + ")"; } + + if (operator.equals("->roundTo")) + { return "UmlRsdsLib::roundTo(" + lqf + "," + rqf + ")"; } + + if (operator.equals("+")) + { String pres = lqf + " + " + rqf; + if (needsBracket) + { pres = "(" + pres + ")"; } + + if ("null".equals(lqf) && "null".equals(rqf)) + { return "\"\""; } + if ("null".equals(lqf)) + { return cppStringOf(rqf, right.getType()); } + if ("null".equals(rqf)) + { return cppStringOf(lqf, left.getType()); } + + if (left.isPrimitive() && right.isPrimitive()) + { return pres; } + if (left.isString() && right.isString()) + { pres = "string(" + lqf + ").append(" + rqf + ")"; + return pres; + } + else if (left.isString()) + { return "string(" + lqf + ").append(" + cppStringOf(rqf, right.getType()) + ")"; } + else if (right.isString()) + { return "(" + cppStringOf(lqf, left.getType()) + ").append(" + rqf + ")"; } + + /* if (left.isString() && right.isPrimitive()) + { return pres; } + if (left.isPrimitive() && right.isString()) + { return pres; } + + if (left.isString()) + { pres = lqf + " + " + rqf + ".ToString()"; + if (needsBracket) + { pres = "(" + pres + ")"; } + } + else if (right.isString()) + { pres = lqf + ".ToString() + " + rqf; + if (needsBracket) + { pres = "(" + pres + ")"; } + } */ + + return pres; + } + + if (operator.equals("->isUnique")) // and define for B + { String fcollect = collectQueryFormCPP(lqf,rqf,rprim,env,local); + // if (left.umlkind == CLASSID) + // { lqf = ((BasicExpression) left).classExtentQueryFormCPP(env,local); } + // return "(" + lqf + "->size() == " + fcollect + "->size())"; + return "UmlRsdsLib<" + rcet + ">::isUnique(" + fcollect + ")"; + } + + if (operator.equals("->intersectAll")) + { String col = collectQueryFormCPP(lqf,rqf,rprim,env,local); + return "UmlRsdsLib<" + rcet + ">::intersectAll(" + col + ")"; + } // rcet, not lcet? + + if (operator.equals("->unionAll")) + { String col = collectQueryFormCPP(lqf,rqf,rprim,env,local); + if (left.isOrdered() && (right.isOrdered() || "self".equals(right + ""))) + { return "UmlRsdsLib<" + rcet + ">::concatenateAll(" + col + ")"; } + return "UmlRsdsLib<" + rcet + ">::unionAll(" + col + ")"; + } // rcet, not lcet + + if (operator.equals("->closure")) + { String rel = right + ""; + if (entity == null) + { JOptionPane.showMessageDialog(null, "No entity for: " + this, + "Semantic error", JOptionPane.ERROR_MESSAGE); + return ""; + } + return "UmlRsdsLib<" + rcet + ">::closure" + entity.getName() + rel + "(" + lqf + ")"; + } // left must be set-valued. + + if (operator.equals("->reject") || operator.equals("|R")) + { String sel = rejectQueryFormCPP(lqf,rqf,env,local); + return sel; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals(":")) + { String rinstances = cont + "get" + ("" + right).toLowerCase() + "_s()"; + return "UmlRsdsLib<" + right + "*>::isIn((" + right + "*) " + lqf + ", " + rinstances + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsKindOf")) + { String rinstances = cont + "get" + ("" + right).toLowerCase() + "_s()"; + return "UmlRsdsLib<" + right + "*>::isIn((" + right + "*) " + lqf + ", " + rinstances + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("->oclIsTypeOf")) + { String rinstances = cont + "get" + ("" + right).toLowerCase() + "_s()"; + return "UmlRsdsLib<" + right + "*>::isIn((" + right + "*) " + lqf + ", " + rinstances + ")"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("/:")) + { String rinstances = cont + "get" + ("" + right).toLowerCase() + "_s()"; + return "!(UmlRsdsLib<" + right + "*>::isIn((" + right + "*) " + lqf + ", " + rinstances + "))"; + } + + if (right.umlkind == CLASSID && + ((BasicExpression) right).arrayIndex == null && operator.equals("<:")) + { rqf = ((BasicExpression) right).classExtentQueryFormCPP(env,local); + return "(UmlRsdsLib<" + right + "*>::isSubset(" + lqf + ", " + rqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includes")) + { String linstances = cont + "get" + ("" + left).toLowerCase() + "_s()"; + return "UmlRsdsLib<" + left + "*>::isIn(" + rqf + ", " + linstances + ")"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->includesAll")) + { lqf = ((BasicExpression) left).classExtentQueryFormCPP(env,local); + return "(UmlRsdsLib<" + left + "*>::isSubset(" + rqf + ", " + lqf + "))"; + } + + if (left.umlkind == CLASSID && + ((BasicExpression) left).arrayIndex == null && operator.equals("->excludes")) + { String linstances = cont + "get" + ("" + left).toLowerCase() + "_s()"; + return "!(UmlRsdsLib<" + left + "*>::isIn(" + rqf + ", " + linstances + "))"; + } + + if (operator.equals("=>")) + { return "(!(" + lqf + ") || " + rqf + ")"; } + + if (operator.equals("->oclAsType")) + { if (type != null) + { String jtyp = type.getCPP(elementType); + if ("string".equals(jtyp)) + { return "string(" + lqf + ")"; } + return "((" + jtyp + ") " + lqf + ")"; + } + return lqf; + } + + if (operator.equals("->at")) + { if (type != null) + { String jtyp = type.getCPP(elementType); + return "((" + jtyp + ") (" + lqf + ")->at(" + rqf + " -1))"; + } + return lqf; + } // plus version for strings + + + // No extension ops for C++? + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opcpp = Expression.getOperatorCPP(op); + if (opcpp != null && opcpp.length() > 0) + { return opcpp.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + if (!lmult && !rmult) + { if (operator.equals("=")) // and comparitors + { res = composeEqQueryFormsCPP(lqf,rqf,lprim,rprim); } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = composeNeqQueryFormsCPP(lqf,rqf,lprim,rprim); } + else if (comparitors.contains(operator)) + { res = composeComparitorQueryFormsCPP(lqf,rqf,lprim,rprim); } + else if (operator.equals("+") || operator.equals("-") || + operator.equals("*") || operator.equals("/") || + operator.equals("mod") || operator.equals("div")) + { res = composeMathOpQueryFormsCPP(lqf,rqf,lprim,rprim); } + else if (operator.equals("->indexOf")) + { res = "UmlRsdsLib<" + lcet + ">::indexOf(" + rqf + ", " + lqf + ")"; } + else if (operator.equals("->lastIndexOf")) + { res = "UmlRsdsLib<" + lcet + ">::lastIndexOf(" + rqf + ", " + lqf + ")"; } + else if (operator.equals("->count")) + { res = "UmlRsdsLib<" + lcet + ">::count(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->equalsIgnoreCase")) + { res = "UmlRsdsLib::equalsIgnoreCase(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->hasPrefix")) + { res = "UmlRsdsLib::startsWith(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->hasSuffix")) + { res = "UmlRsdsLib::endsWith(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->before")) + { res = "UmlRsdsLib::before(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->after")) + { res = "UmlRsdsLib::after(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->isMatch")) + { res = "UmlRsdsLib::isMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->hasMatch")) + { res = "UmlRsdsLib::hasMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->allMatches")) + { res = "UmlRsdsLib::allMatches(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->firstMatch")) + { res = "UmlRsdsLib::firstMatch(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->split")) + { res = "UmlRsdsLib::split(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->excludingAt")) + { res = "UmlRsdsLib<" + lcet + ">::removeAt(" + lqf + "," + rqf + ")"; } + } + else if (lmult && !rmult) // convert right to mult + { String rw = rqf; + + if (operator.equals("->includes")) + { res = "UmlRsdsLib<" + lcet + ">::isIn(" + rw + ", " + lqf + ")"; } + else if (operator.equals("->excludes")) + { res = "!(UmlRsdsLib<" + lcet + ">::isIn(" + rw + ", " + lqf + "))"; } + else if (operator.equals("->excluding")) + { String rss = right.makeSetCPP(rw); + res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + "," + rss + ")"; + } + else if (operator.equals("->excludingAt")) + { res = "UmlRsdsLib<" + lcet + ">::removeAt(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->excludingFirst")) + { res = "UmlRsdsLib<" + lcet + ">::removeFirst(" + lqf + "," + rw + ")"; } + else if (operator.equals("->append")) // Only for sequences + { String rss = right.makeSequenceCPP(rw); + res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + "," + rss + ")"; + } + else if (operator.equals("->including")) // Only for sets + { if (left.isOrdered() || left.hasSequenceType()) + { String rssq = right.makeSequenceCPP(rw); + res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + "," + rssq + ")"; + } + else + { String rss = right.makeSetCPP(rw); + res = "UmlRsdsLib<" + lcet + ">::unionSet(" + lqf + "," + rss + ")"; + } + } + else if (operator.equals("->prepend")) // Only for sequences + { String rss = right.makeSequenceCPP(rw); + res = "UmlRsdsLib<" + lcet + ">::concatenate(" + rss + "," + lqf + ")"; + } + else + { String rs = right.makeSetCPP(rqf); + String rsq = right.makeSequenceCPP(rqf); + if (operator.equals("=")) + { if (left.isOrdered() || left.hasSequenceType()) + { res = "(*(" + lqf + ") == *(" + rsq + "))"; } + else + { res = "(*(" + lqf + ") == *(" + rs + "))"; } + } + else if (operator.equals("/=") || + operator.equals("!=") || + operator.equals("<>")) + { if (left.isOrdered() || left.hasSequenceType()) + { res = "(*(" + lqf + ") != *(" + rsq + "))"; } + else + { res = "(*(" + lqf + ") != *(" + rs + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { if (left.isOrdered() || left.hasSequenceType()) + { lqf = "UmlRsdsLib<" + lcet + ">::asSet(" + lqf + ")"; } + res = "UmlRsdsLib<" + lcet + ">::isSubset(" + lqf + ", " + rs + ")"; + } + else if (operator.equals("->includesAll")) + { res = "UmlRsdsLib<" + lcet + ">::isSubset(" + rs + ", " + lqf + ")"; } + else if (operator.equals("/<:")) + { res = "!(UmlRsdsLib<" + lcet + ">::isSubset(" + lqf + ", " + rs + "))"; } + else if (operator.equals("->excludesAll")) + { res = "(UmlRsdsLib<" + lcet + ">::intersection(" + rs + ", " + lqf + ")->size() == 0)"; } + else if (operator.equals("->including")) + { res = "UmlRsdsLib<" + lcet + ">::unionSet(" + lqf + ", " + rs + ")"; } + else if (operator.equals("->excluding")) + { res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + ", " + rs + ")"; } + else if (operator.equals("->prepend")) + { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + rsq + ", " + lqf + ")"; } + else if (operator.equals("->append")) + { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + ", " + rsq + ")"; } + else if (operator.equals("->count")) + { res = "UmlRsdsLib<" + lcet + ">::count(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->indexOf")) + { res = "UmlRsdsLib<" + lcet + ">::indexOf(" + rqf + ", " + lqf + ")"; } + else if (operator.equals("->lastIndexOf")) + { res = "UmlRsdsLib<" + lcet + ">::lastIndexOf(" + rqf + ", " + lqf + ")"; } + /* else if (operator.equals("->hasPrefix")) + { res = "UmlRsdsLib::startsWith(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->hasSuffix")) + { res = "UmlRsdsLib::endsWith(" + lqf + ", " + rqf + ")"; } */ + else + { res = composeSetQueryFormsCPP(lqf,rs,lcet); } + } + } + else if (rmult && !lmult) + { String ls = left.makeSetCPP(lqf); + String lw = lqf; + + if (operator.equals("=")) + { if (Type.isCollectionOrEntity(right.getType())) + { res = "(*(" + ls + ") == *(" + rqf + "))"; } + else + { res = "(" + lqf + " == " + rqf + ")"; } + } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isCollectionOrEntity(right.getType())) + { res = "(*(" + ls + ") != *(" + rqf + "))"; } + else + { res = "(" + lqf + " != " + rqf + ")"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = "UmlRsdsLib<" + lcet + ">::isIn(" + lw + ", " + rqf + ")"; } + else if (operator.equals("/:")) + { res = "!(UmlRsdsLib<" + lcet + ">::isIn(" + lw + ", " + rqf + "))"; } + else if (operator.equals("->excludesAll")) + { res = "(UmlRsdsLib<" + lcet + ">::intersection(" + rqf + ", " + ls + ")->size() == 0)"; } + else + { res = "(" + lqf + " " + operator + " " + rqf + ")"; + // bNeeded = true; + } + // else + // { res = composeSetQueryFormsCPP(ls,rqf,lcet); } + } + else // both sets + if (operator.equals("->indexOf")) + { res = "UmlRsdsLib<" + lcet + ">::indexOf(" + rqf + ", " + lqf + ")"; } + else if (operator.equals("->lastIndexOf")) + { res = "UmlRsdsLib<" + lcet + ">::lastIndexOf(" + rqf + ", " + lqf + ")"; } + else + { res = composeSetQueryFormsCPP(lqf,rqf,lcet); } + + if (needsBracket) + { return "( " + res + " )"; } + return res; + } // add brackets if needed + + public String exists1QueryForm(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if (operator.equals("->exists1")) + { lqf = left.queryForm(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("!! Warning: no element type for: " + left); + // JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + // "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#1")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("!! Warning: no element type of: " + beleft); + // JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + // "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = null; + if (operator.equals("->exists1") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; // formal parameter + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); // actual parameter + if (ex == null) + { ex = "this"; } // for outer instance context only. NOT VALID IN STATIC CONTEXT + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self")) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Exists1 query form " + uses + " " + env1 + " " + pars); + String res = BSystemTypes.getExists1Definition(existsleft,lqf,right,existsvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String exists1QueryFormJava6(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if (operator.equals("->exists1")) + { lqf = left.queryFormJava6(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("!! DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#1")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("!! DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = null; + if (operator.equals("->exists1") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; // formal parameter + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); // actual parameter + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self")) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Exists1 query form " + uses + " " + env1 + " " + pars); + String res = BSystemTypes.getExists1DefinitionJava6(existsleft,lqf,right,existsvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String quantifierQueryFormJava7(java.util.Map env, boolean local) + { String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if (operator.equals("->exists1") || + "->existsLC".equals(operator) || operator.equals("->exists") || operator.equals("->forAll")) + { lqf = left.queryFormJava7(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("!! DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#1") || operator.equals("#LC") || + operator.equals("#") || operator.equals("!")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("!! DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = null; + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; // formal parameter + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); // actual parameter + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self")) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = "unknownQuantifier()"; + if (operator.equals("->exists1") || operator.equals("#1")) + { res = BSystemTypes.getExists1DefinitionJava7(existsleft,lqf,right,existsvar,env1,pars); } + else if (operator.equals("->exists") || operator.equals("#") || + operator.equals("#LC") || operator.equals("->existsLC")) + { res = BSystemTypes.getExistsDefinitionJava7(existsleft,lqf,right,existsvar,env1,pars); } + else if (operator.equals("->forAll") || operator.equals("!")) + { res = BSystemTypes.getForAllDefinitionJava7(existsleft,lqf,right,existsvar,env1,pars); } + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String exists1QueryFormCSharp(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if (operator.equals("->exists1")) + { lqf = left.queryFormCSharp(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#1")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = null; + if (operator.equals("->exists1") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; // formal parameter + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); // actual parameter + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self")) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Exists1 query form " + uses + " " + env1 + " " + pars); + String res = BSystemTypes.getExists1DefinitionCSharp(existsleft,lqf,right,existsvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String exists1QueryFormCPP(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if (operator.equals("->exists1")) + { lqf = left.queryFormCPP(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#1")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = null; + if (operator.equals("->exists1") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; // formal parameter + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); // actual parameter + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self")) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Exists1 query form " + uses + " " + env1 + " " + pars); + String res = BSystemTypes.getExists1DefinitionCPP(existsleft,lqf,right,existsvar,env1,pars); + return "" + res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String selectQueryForm(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->select")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|") || + operator.equals("|selectMaximals") || + operator.equals("|selectMinimals")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self")) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); // so that it is not expressed as 'this' in the code + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + /* for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (use.getType() != null) + { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + if (pars.contains(par)) { } + else + { pars.add(par); + if ("self".equals(use.data)) + { callpars = callpars + ", this"; } + else + { callpars = callpars + "," + use.data; } + } + } + } */ + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getSelectDefinition(selectleft,lqf,right,selectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String selectQueryFormJava6(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->select")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); // so that it is not expressed as 'this' in the code + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getSelectDefinitionJava6(selectleft,lqf,right,selectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String selectQueryFormJava7(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->select") || operator.equals("->reject")) + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|") || operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (selectleft.isMap()) + { // Ocl.selectMap(lqf, (selectvar)-> { return rqf;}) + + if ("|".equals(operator)) + { return "Ocl.selectMap(" + lqf + ", (" + + selectvar + ") -> { return " + rqf + "; })"; + } + else + { return "Ocl.rejectMap(" + lqf + ", (" + + selectvar + ") -> { return " + rqf + "; })"; + } + } + } + + + Vector euses = right.getBaseEntityUses(); + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = "unknownSelect()"; + if (operator.equals("->select") || operator.equals("|")) + { res = BSystemTypes.getSelectDefinitionJava7(selectleft,lqf,right,selectvar,env1,pars); } + else if (operator.equals("->reject") || operator.equals("|R")) + { res = BSystemTypes.getRejectDefinitionJava7(selectleft,lqf,right,selectvar,env1,pars); } + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String selectQueryFormCSharp(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + String selectvar = null; + Expression selectleft = left; + + Entity localentity = entity; + if (operator.equals("->select")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (selectleft.isMap()) + { // Ocl.selectMap(lqf, (selectvar)-> { return rqf;}) + + String elemT = + Type.getCSharptype(selectleft.elementType); + + if ("|".equals(operator)) + { return "SystemTypes.selectMap(" + lqf + ", (" + + selectvar + "_x) => { " + elemT + " " + selectvar + " = (" + elemT + ") " + selectvar + "_x; return " + rqf + "; })"; + } + else + { return "SystemTypes.rejectMap(" + lqf + ", (" + + selectvar + "_x) => { " + elemT + " " + selectvar + " = (" + elemT + ") " + selectvar + "_x; return " + rqf + "; })"; + } + } + } + + // Entity localentity = left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getSelectDefinitionCSharp(selectleft,lqf,right,selectvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String selectQueryFormCPP(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + Entity localentity = entity; // left.elementType.getEntity(); + String selectvar = null; + Expression selectleft = left; + + if (operator.equals("->select")) + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (selectleft.isMap()) + { // UmlRsdsOcl::selectMap + + String stype = Type.getCPPtype(type.getKeyType()); + String rtype = "bool"; + String ttype = + Type.getCPPtype(selectleft.elementType); + return "UmlRsdsOcl<" + stype + "," + ttype + "," + rtype + ">::selectMap(" + lqf + ", [=](" + ttype + " " + selectvar + ") -> " + rtype + " { return " + rqf + "; })"; + } + } + + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar) || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getSelectDefinitionCPP(selectleft,lqf,right,selectvar,env1,pars); + return // "UmlRsdsLib<" + localentity.getName() + "*>::" + + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryForm(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating REJECT " + uses + " " + env1); + String res = BSystemTypes.getRejectDefinition(selectleft,lqf,right,selectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormJava6(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getRejectDefinitionJava6(selectleft,lqf,right,selectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormJava7(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (selectleft.isMap()) + { // Ocl.selectMap(lqf, (selectvar)-> { return rqf;}) + + if ("|".equals(operator)) + { return "Ocl.selectMap(" + lqf + ", (" + + selectvar + ") -> { return " + rqf + "; })"; + } + else + { return "Ocl.rejectMap(" + lqf + ", (" + + selectvar + ") -> { return " + rqf + "; })"; + } + } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getRejectDefinitionJava7(selectleft,lqf,right,selectvar,env1,pars); + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormCSharp(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (selectleft.isMap()) + { // Ocl.selectMap(lqf, (selectvar)-> { return rqf;}) + + String elemT = + Type.getCSharptype(selectleft.elementType); + + if ("|".equals(operator)) + { return "SystemTypes.selectMap(" + lqf + ", (" + + selectvar + "_x) => { " + elemT + " " + selectvar + " = (" + elemT + ") " + selectvar + "_x; return " + rqf + "; })"; + } + else + { return "SystemTypes.rejectMap(" + lqf + ", (" + + selectvar + "_x) => { " + elemT + " " + selectvar + " = (" + elemT + ") " + selectvar + "_x; return " + rqf + "; })"; + } + } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getRejectDefinitionCSharp(selectleft,lqf,right,selectvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormCPP(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (selectleft.isMap()) + { // UmlRsdsOcl::rejectMap + + String stype = Type.getCPPtype(type.getKeyType()); + String rtype = "bool"; + String ttype = + Type.getCPPtype(selectleft.elementType); + return "UmlRsdsOcl<" + stype + "," + ttype + "," + rtype + ">::rejectMap(" + lqf + ", [=](" + ttype + " " + selectvar + ") -> " + rtype + " { return " + rqf + "; })"; + } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getRejectDefinitionCPP(selectleft,lqf,right,selectvar,env1,pars); + return res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String anyQueryForm(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; // left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Collect " + uses + " " + env1); + String res = BSystemTypes.getAnyDefinition(collectleft,lqf,right,collectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String anyQueryFormJava6(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; + // left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getAnyDefinitionJava6(collectleft,lqf,right,collectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String anyQueryFormJava7(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; + // left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getAnyDefinitionJava7(collectleft,lqf,right,collectvar,env1,pars); + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String anyQueryFormCSharp(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; + // left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getAnyDefinitionCSharp(collectleft,lqf,right,collectvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String anyQueryFormCPP(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + Entity localentity = entity; // left.elementType.getEntity(); + String selectvar = null; + Expression selectleft = left; + + if (operator.equals("->any")) + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|A")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar) || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getAnyDefinitionCPP(selectleft,lqf,right,selectvar,env1,pars); + return // "UmlRsdsLib<" + localentity.getName() + "*>::" + + res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String collectQueryForm(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // collect_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; // left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|C") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|sortedBy") || + operator.equals("|isUnique")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("!! DESIGN ERROR: no element type for: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("!! DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Collect " + uses + " " + env1); + String res = BSystemTypes.getCollectDefinition(collectleft,lqf,right,rprim,collectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String collectQueryFormJava6(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // collect_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + String collectvar = null; + Expression collectleft = left; + + Entity localentity = left.entity; // left.elementType.getEntity(); + if (operator.equals("|C") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|sortedBy") || + operator.equals("|isUnique")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("TYPE ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " filtered: " + trueeuses); + // System.out.println("Collect local entity: " + localentity); + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Collect " + uses + " " + env); + String res = BSystemTypes.getCollectDefinitionJava6(collectleft,lqf,right,rprim,collectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String collectQueryFormJava7(String lqf, + String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // collect_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + String collectvar = null; + Expression collectleft = left; + + Entity localentity = left.entity; // left.elementType.getEntity(); + if (operator.equals("|C") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|sortedBy") || + operator.equals("|isUnique")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("TYPE ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } // May be null if primitive, String, etc + + if (collectleft.isMap()) + { // Ocl.collectMap(lqf, (collectvar)-> { return rqf;}) + return "Ocl.collectMap(" + lqf + ", (" + collectvar + ") -> { return " + rqf + "; })"; + } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " filtered: " + trueeuses); + // System.out.println("Collect local entity: " + localentity); + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println(">>>>> Creating Collect " + right + " " + right.getType()); + String res = BSystemTypes.getCollectDefinitionJava7(collectleft,lqf,right,rprim,collectvar,env1,pars); + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String collectQueryFormCSharp(String lqf, + String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // collect_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + String collectvar = null; + Expression collectleft = left; + + Entity localentity = left.entity; + // left.elementType.getEntity(); + + if (operator.equals("|C") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|sortedBy") || + operator.equals("|isUnique")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("TYPE ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (collectleft.isMap()) + { // Ocl.collectMap(lqf, (collectvar_x) => { return rqf;}) + String elemT = + Type.getCSharptype(beleft.right.elementType); + return "SystemTypes.collectMap(" + lqf + ", (" + collectvar + "_x) => { " + elemT + " " + collectvar + " = (" + elemT + ") " + collectvar + "_x; return " + rqf + "; })"; + } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " filtered: " + trueeuses); + // System.out.println("Collect local entity: " + localentity); + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + + System.out.println(">> Variable use: " + use + " " + use.getType() + " " + use.arrayType + " " + use.getElementType()); + + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + pars.add(par); + par.setElementType(use.getElementType()); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Collect " + uses + " " + env); + String res = BSystemTypes.getCollectDefinitionCSharp(collectleft,lqf,right,rprim,collectvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String collectQueryFormCPP(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // collect_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + String collectvar = null; + Expression collectleft = left; + + Entity localentity = left.entity; // left.elementType.getEntity(); + if (operator.equals("|C") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|sortedBy") || + operator.equals("|isUnique")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("TYPE ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + + if (collectleft.isMap()) + { // UmlRsdsOcl::collectMap + + String stype = Type.getCPPtype(type.getKeyType()); + String rtype = Type.getCPPtype(elementType); + String ttype = + Type.getCPPtype(beleft.right.elementType); + return "UmlRsdsOcl<" + stype + "," + ttype + "," + rtype + ">::collectMap(" + lqf + ", [=](" + ttype + " " + collectvar + ") -> " + rtype + " { return " + rqf + "; })"; + } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Collect " + uses + " " + env); + String res = BSystemTypes.getCollectDefinitionCPP(collectleft,lqf,right,rprim,collectvar,env1,pars); + return "" + res.substring(0,res.length()-1) + callpars + ")"; + } + + + + public String existsQueryForm(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if ("->existsLC".equals(operator) || operator.equals("->exists")) + { lqf = left.queryForm(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#") || operator.equals("#LC")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { Type eltype = beleft.right.elementType; + // System.out.println("Element type of: " + beleft + " is " + eltype); + localentity = eltype.getEntity(); + } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->exists") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("******* Creating Exists query form " + existsleft + " " + lqf + " " + existsvar + " " + right); + String res = BSystemTypes.getExistsDefinition(existsleft,lqf,right,existsvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String existsQueryFormJava6(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if ("->existsLC".equals(operator) || operator.equals("->exists")) + { lqf = left.queryFormJava6(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#") || operator.equals("#LC")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { Type eltype = beleft.right.elementType; + // System.out.println("Element type of: " + beleft + " is " + eltype); + localentity = eltype.getEntity(); + } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->exists") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Exists query form " + uses + " " + env1 + " " + pars); + String res = BSystemTypes.getExistsDefinitionJava6(existsleft,lqf,right,existsvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + + public String existsQueryFormCSharp(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if ("->existsLC".equals(operator) || operator.equals("->exists")) + { lqf = left.queryFormCSharp(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#") || operator.equals("#LC")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.out.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { Type eltype = beleft.right.elementType; + // System.out.println("Element type of: " + beleft + " is " + eltype); + localentity = eltype.getEntity(); + } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->exists") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getExistsDefinitionCSharp(existsleft,lqf,right,existsvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String existsQueryFormCPP(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String existsvar = null; + Expression existsleft = null; + Entity localentity = null; + + String lqf = ""; + if ("->existsLC".equals(operator) || operator.equals("->exists")) + { lqf = left.queryFormCPP(env,local); + existsleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("#") || operator.equals("#LC")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + existsleft = beleft.right; + existsvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { Type eltype = beleft.right.elementType; + // System.out.println("Element type of: " + beleft + " is " + eltype); + localentity = eltype.getEntity(); + } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->exists") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the exists. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(existsvar) || + (existsvar == null && (use.data + "").equals("self"))) + {} + else if (existsvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Exists query form " + uses + " " + env1 + " " + pars); + String res = BSystemTypes.getExistsDefinitionCPP(existsleft,lqf,right,existsvar,env1,pars); + return "" + res.substring(0,res.length()-1) + callpars + ")"; + } + + + public String forAllQueryForm(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String forallvar = null; + Expression forallleft = null; + String lqf = ""; + Entity localentity = null; + + if (operator.equals("->forAll")) + { lqf = left.queryForm(env,local); + forallleft = left; + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("!")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + forallleft = beleft.right; + forallvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->forAll") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the forAll. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(forallvar) || + (forallvar == null && (use.data + "").equals("self"))) + {} + else if (forallvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + // System.out.println("Creating forAll query form " + uses + " " + env1); + String res = BSystemTypes.getForAllDefinition(forallleft,lqf,right, + forallvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String forAllQueryFormJava6(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String forallvar = null; + Expression forallleft = null; + String lqf = ""; + Entity localentity = null; + + if (operator.equals("->forAll")) + { lqf = left.queryFormJava6(env,local); + forallleft = left; + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("!")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + forallleft = beleft.right; + forallvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->forAll") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + /* if (trueeuses.size() > 0) + { Entity context = (Entity) trueeuses.get(0); + + // Not the true context, only the apparant type of naked features + System.out.println("Apparent context: " + context); + + Type etype = new Type(context); + Attribute eself = new Attribute("self",etype,ModelElement.INTERNAL); + pars.add(eself); + callpars = ", this"; + } */ + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the forAll. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(forallvar) || + (forallvar == null && (use.data + "").equals("self"))) + {} + else if (forallvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + // System.out.println("Creating forAll query form " + uses + " " + env1); + String res = BSystemTypes.getForAllDefinitionJava6(forallleft,lqf,right, + forallvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String forAllQueryFormJava7(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String forallvar = null; + Expression forallleft = null; + String lqf = ""; + Entity localentity = null; + + if (operator.equals("->forAll")) + { lqf = left.queryFormJava7(env,local); + forallleft = left; + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("!")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + forallleft = beleft.right; + forallvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->forAll") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + /* if (trueeuses.size() > 0) + { Entity context = (Entity) trueeuses.get(0); + + // Not the true context, only the apparant type of naked features + System.out.println("Apparent context: " + context); + + Type etype = new Type(context); + Attribute eself = new Attribute("self",etype,ModelElement.INTERNAL); + pars.add(eself); + callpars = ", this"; + } */ + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the forAll. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(forallvar) || + (forallvar == null && (use.data + "").equals("self"))) + {} + else if (forallvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + // System.out.println("Creating forAll query form " + uses + " " + env1); + String res = BSystemTypes.getForAllDefinitionJava7(forallleft,lqf,right, + forallvar,env1,pars); + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String forAllQueryFormCSharp(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String forallvar = null; + Expression forallleft = null; + String lqf = ""; + Entity localentity = null; + + if (operator.equals("->forAll")) + { lqf = left.queryFormCSharp(env,local); + forallleft = left; + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("!")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + forallleft = beleft.right; + forallvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->forAll") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the forAll. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(forallvar) || + (forallvar == null && (use.data + "").equals("self"))) + {} + else if (forallvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Type useType = use.getType(); + Type useElementType = use.getElementType(); + + if (use.arrayIndex != null) + { useType = use.arrayType; + useElementType = use.getType(); + } + + Attribute par = + new Attribute(use.data,useType,ModelElement.INTERNAL); + par.setElementType(useElementType); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + // System.out.println("Creating forAll query form " + uses + " " + env1); + String res = BSystemTypes.getForAllDefinitionCSharp(forallleft,lqf,right, + forallvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + public String forAllQueryFormCPP(java.util.Map env, boolean local) + { // String rqf = right.queryForm(env,local); + String forallvar = null; + Expression forallleft = null; + String lqf = ""; + Entity localentity = null; + + if (operator.equals("->forAll")) + { lqf = left.queryFormCPP(env,local); + forallleft = left; + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("!")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + forallleft = beleft.right; + forallvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + Vector trueeuses = new Vector(); + if (operator.equals("->forAll") && localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the forAll. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || + (use.data + "").equals(forallvar) || + (forallvar == null && (use.data + "").equals("self"))) + {} + else if (forallvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + // System.out.println("Creating C++ forAll query form " + uses + " " + env1); + String res = + BSystemTypes.getForAllDefinitionCPP(forallleft,lqf,right,forallvar,env1,pars); + return // "UmlRsdsLib<" + localentity + "*>::" + + res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String composeNeqQueryForms(String lqf, + String rqf, boolean lprim, + boolean rprim) + { String res; + + if (left.isRef() && right.isRef()) + { res = lqf + " != " + rqf; } + else if (lprim && rprim) + { res = lqf + " != " + rqf; } + else if (lprim) // also for booleans, doubles + { String rr = right.unwrap(rqf); + res = lqf + " != " + rr; + } + else if (rprim) + { String ll = left.unwrap(lqf); + res = ll + " != " + rqf; + } + else // both objects + { res = "!(" + lqf + ".equals(" + rqf + "))"; } + return res; + } + + + private String composeNeqQueryFormsCSharp(String lqf, + String rqf, boolean lprim, + boolean rprim) + { String res; + if (lprim || rprim) + { res = lqf + " != " + rqf; } + else // both objects + { res = "!(" + lqf + ".Equals(" + rqf + "))"; } + return res; + } + + private String composeNeqQueryFormsCPP(String lqf, + String rqf, boolean lprim, + boolean rprim) + { String res = lqf + " != " + rqf; + if (Type.isCollectionOrEntity(left.getType()) || + Type.isCollectionOrEntity(right.getType())) + { res = "(*(" + lqf + ") != *(" + rqf + "))"; } + return res; + } + + + private String composeEqQueryForms(String lqf, + String rqf, boolean lprim, + boolean rprim) + { String res; + + if (left.isRef() && right.isRef()) + { res = lqf + " == " + rqf; } + else if (left.isString()) + { res = "((String) " + lqf + ").equals(" + rqf + ")"; } + else if (right.isString()) + { res = "((String) " + rqf + ").equals(" + lqf + ")"; } + else if (lprim && rprim) + { res = lqf + " == " + rqf; } + else if (lprim) // also for booleans, doubles + { String rr = right.unwrap(rqf); + res = lqf + " == " + rr; + } + else if (rprim) + { String ll = left.unwrap(lqf); + res = ll + " == " + rqf; + } + else // both objects. Special case for sets: lqf.containsAll(rqf) && + // rqf.containsAll(lqf) + { res = lqf + ".equals(" + rqf + ")"; } + return res; + } + + private String composeEqQueryFormsCSharp(String lqf, + String rqf, boolean lprim, + boolean rprim) + { String res; + if (left.isString()) + { res = "((string) " + lqf + ").Equals(" + rqf + ")"; } + else if (right.isString()) + { res = "((string) " + rqf + ").Equals(" + lqf + ")"; } + else if (lprim || rprim) + { res = lqf + " == " + rqf; } + else // both objects. Special case for sets: lqf.containsAll(rqf) && + // rqf.containsAll(lqf) + { res = lqf + ".Equals(" + rqf + ")"; } + return res; + } + + private String composeEqQueryFormsCPP(String lqf, + String rqf, boolean lprim, + boolean rprim) + { String res = lqf + " == " + rqf; + if (Type.isCollectionOrEntity(left.getType()) || + Type.isCollectionOrEntity(right.getType())) + { res = "(*(" + lqf + ") == *(" + rqf + "))"; } + return res; + } + + + private String composeComparitorQueryForms(String lqf, String rqf, + boolean lprim, boolean rprim) + { String res; + // System.out.println("Comparitor query form: " + this + " " + lprim + " " + + // rprim); + + if (left.isRef() && right.isRef()) + { res = rqf + ".length " + operator + " " + lqf + ".length"; } + else if (lprim && rprim) + { res = lqf + " " + operator + " " + rqf; } + else if (lprim) + { String rr = right.unwrap(rqf); + res = lqf + " " + operator + " " + rr; + } + else if (rprim) + { String ll = left.unwrap(lqf); + res = ll + " " + operator + " " + rqf; + } + else // includes case of Strings and dates + { res = "(" + lqf + ".compareTo(" + rqf + ") " + operator + " 0)"; } + // System.out.println("Comparitor query form: " + this + " is " + res); + return res; + } + + private String composeComparitorQueryFormsCSharp(String lqf, String rqf, + boolean lprim, boolean rprim) + { String res; + // System.out.println("Comparitor query form: " + this + " " + lprim + " " + + // rprim); + if (lprim || rprim) + { res = lqf + " " + operator + " " + rqf; } + else // includes case of Strings + { res = "(" + lqf + ".CompareTo(" + rqf + ") " + operator + " 0)"; } + // System.out.println("Comparitor query form: " + this + " is " + res); + return res; + } + + private String composeComparitorQueryFormsCPP(String lqf, String rqf, + boolean lprim, boolean rprim) + { String res = lqf + " " + operator + " " + rqf; + return res; + } + + private String composeMathOpQueryForms(String lqf, + String rqf, boolean lprim, + boolean rprim) + { // operator is *, mod, /, +, - + String res; + String op = operator; + if (operator.equals("mod")) + { op = "%"; } + else if (operator.equals("div")) + { op = "/"; } + + if (operator.equals("+") && left.isRef()) + { // Pointer addition - only valid for read-only accesses + res = "Arrays.copyOfRange(" + lqf + ", " + rqf + + ", " + lqf + ".length)"; + } + else if (operator.equals("-") && left.isRef() && + right.isRef()) + { res = rqf + ".length - " + lqf + ".length"; } + else if (operator.equals("-") && + "String".equals(left.getType() + "") && + "String".equals(right.getType() + "")) + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + else if (lprim && rprim) + { res = lqf + " " + op + " " + rqf; } + else if (lprim) + { String rr = right.unwrap(rqf); + res = lqf + " " + op + " " + rr; + } + else if (rprim) + { String ll = left.unwrap(lqf); + res = ll + " " + op + " " + rqf; + } + else + { String rr = right.unwrap(rqf); + String ll = left.unwrap(lqf); + res = ll + " " + op + " " + rr; + } + + if ("div".equals(operator)) + { if ("int".equals(type + "")) + { res = "((int) (" + res + "))"; } + else + { res = "((long) (" + res + "))"; } + } + + return res; + } + + private String composeMathOpQueryFormsJava7(String lqf, + String rqf, boolean lprim, + boolean rprim) + { // operator is *, mod, /, +, - + String res; + String op = operator; + if (operator.equals("mod")) + { op = "%"; } + else if (operator.equals("div")) + { op = "/"; } + + if (operator.equals("+") && left.isRef()) + { // Pointer addition - only valid for read-only accesses + res = "Arrays.copyOfRange(" + lqf + ", " + rqf + + ", " + lqf + ".length)"; + } + else if (operator.equals("-") && left.isRef() && + right.isRef()) + { res = rqf + ".length - " + lqf + ".length"; } + else if (operator.equals("-") && + "String".equals(left.getType() + "") && + "String".equals(right.getType() + "")) + { res = "Ocl.subtract(" + lqf + "," + rqf + ")"; } + else if (lprim && rprim) + { res = lqf + " " + op + " " + rqf; } + else if (lprim) + { String rr = right.unwrapJava7(rqf); + res = lqf + " " + op + " " + rr; + } + else if (rprim) + { String ll = left.unwrapJava7(lqf); + res = ll + " " + op + " " + rqf; + } + else + { String rr = right.unwrapJava7(rqf); + String ll = left.unwrapJava7(lqf); + res = ll + " " + op + " " + rr; + } + + if ("div".equals(operator)) + { if ("int".equals(type + "")) + { res = "((int) (" + res + "))"; } + else + { res = "((long) (" + res + "))"; } + } + + return res; + } + + private String composeMathOpQueryFormsCSharp(String lqf, + String rqf, boolean lprim, + boolean rprim) + { // operator is *, mod, /, +, - + String res; + String op = operator; + if (operator.equals("mod")) + { op = "%"; } + else if (operator.equals("div")) + { op = "/"; } + + if (operator.equals("+")) + { if ("null".equals(lqf) || "null".equals(rqf)) + { return lqf + " + " + rqf; } + // if (left.isRef()) + // { } + if (left.isPrimitive() && right.isPrimitive()) + { return lqf + " + " + rqf; } + if (left.isString() && right.isString()) + { return lqf + " + " + rqf; } + if (left.isString() && right.isPrimitive()) + { return lqf + " + " + rqf; } + if (left.isPrimitive() && right.isString()) + { return lqf + " + " + rqf; } + if (left.isString()) + { return lqf + " + " + rqf + ".ToString()"; } + if (right.isString()) + { return lqf + ".ToString() + " + rqf; } + + return lqf + " + " + rqf; + } + + + + if (operator.equals("-") && + "String".equals(left.getType().getName()) && + "String".equals(right.getType().getName())) + { res = "SystemTypes.subtract(" + lqf + "," + rqf + ")"; } + else + { res = lqf + " " + op + " " + rqf; } + + if ("div".equals(operator)) + { if ("int".equals(type + "")) + { res = "((int) (" + res + "))"; } + else + { res = "((long) (" + res + "))"; } + } + + return res; + } + + private String composeMathOpQueryFormsCPP(String lqf, + String rqf, boolean lprim, + boolean rprim) + { // operator is *, mod, /, +, - + String res; + String op = operator; + if (operator.equals("mod")) + { op = "%"; } + else if (operator.equals("div")) + { op = "/"; } + + if (operator.equals("+")) + { if ("String".equals(left.getType().getName())) + { if ("String".equals(right.getType().getName())) + { if (left.umlkind == VALUE) + { res = "string(" + lqf + ").append(" + rqf + ")"; } + else + { res = lqf + ".append(" + rqf + ")"; } + } + else + { if (left.umlkind == VALUE) + { res = "string(" + lqf + ").append(std::to_string(" + rqf + "))"; } + else + { res = lqf + ".append(std::to_string(" + rqf + "))"; } + } + } + else if ("String".equals(right.getType().getName())) + { res = "std::to_string(" + lqf + ").append(" + rqf + ")"; } + else + { res = lqf + " + " + rqf; } + } + else if (operator.equals("-") && "String".equals(left.getType().getName()) && + "String".equals(right.getType().getName())) + { res = "UmlRsdsLib::subtract(" + lqf + ", " + rqf + ")"; } + else + { res = lqf + " " + op + " " + rqf; } + + if ("div".equals(operator)) + { res = "((int) (" + res + "))"; } + + return res; + } + + + private String composeSetQueryForms(String lqf, String rqf) + { String res = lqf + " " + operator + " " + rqf; + if (operator.equals("=")) + { if (Type.isSetType(left.getType()) || Type.isSetType(right.getType())) + { res = "Set.equals(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".equals(" + rqf + ")"; } + } // order shouldn't matter + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isSetType(left.getType()) || Type.isSetType(right.getType())) + { res = "!(Set.equals(" + lqf + "," + rqf + "))"; } + else + { res = "!(" + lqf + ".equals(" + rqf + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->includesAll")) + { if (left.isMap() && right.isMap()) + { res = "Set.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".containsAll(" + rqf + ")"; } + } + else if (operator.equals("-")) + { if (left.isMap() && right.isMap()) + { res = "Set.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->excluding")) + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + else if (operator.equals("\\/") || + operator.equals("->union") || + operator.equals("->concatenate")) + { if (left.isMap()) + { res = "Set.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered()) + { res = "Set.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Set.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->including")) + { if (left.isOrdered()) + { res = "Set.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Set.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/\\") || operator.equals("->intersection")) + { if (left.isMap()) + { res = "Set.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.intersection(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/:") || operator.equals("/<:")) + { res = "!(" + rqf + ".containsAll(" + lqf + "))"; } + else if (operator.equals("->excludesAll")) + { if (left.isMap()) + { res = "Set.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "(Set.intersection(" + rqf + "," + lqf + ").size() == 0)"; } + } + else if (operator.equals("^") || operator.equals("->concatenate")) + { res = "Set.concatenate(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->symmetricDifference")) + { res = "Set.symmetricDifference(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->prepend")) + { res = "Set.concatenate(" + rqf + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "Set.concatenate(" + lqf + "," + rqf + ")"; } + return res; + } // what about comparitors? + + private String composeSetQueryFormsJava6(String lqf, String rqf) + { String res = lqf + " " + operator + " " + rqf; + if (operator.equals("=")) + { res = lqf + ".equals(" + rqf + ")"; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = "!(" + lqf + ".equals(" + rqf + "))"; } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->includesAll")) + { if (left.isMap()) + { res = "Set.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".containsAll(" + rqf + ")"; } + } + else if (operator.equals("-")) + { if (left.isMap()) + { res = "Set.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->excluding")) + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + else if (operator.equals("\\/") || + operator.equals("->union") + || operator.equals("->concatenate")) + { if (left.isMap()) + { res = "Set.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) + { res = "Set.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Set.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->including")) + { if (left.isOrdered()) + { res = "Set.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Set.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/\\") || operator.equals("->intersection")) + { if (left.isMap()) + { res = "Set.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.intersection(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/:") || operator.equals("/<:")) + { res = "!(" + rqf + ".containsAll(" + lqf + "))"; } + else if (operator.equals("->excludesAll")) + { if (left.isMap()) + { res = "Set.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Collections.disjoint(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("^") || operator.equals("->concatenate")) + { res = "Set.concatenate(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->symmetricDifference")) + { res = "Set.symmetricDifference(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->prepend")) + { res = "Set.concatenate(" + rqf + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "Set.concatenate(" + lqf + "," + rqf + ")"; } + return res; + } // what about comparitors? + + private String composeSetQueryFormsJava7(String lqf, String rqf) + { String res = lqf + " " + operator + " " + rqf; + if (operator.equals("=")) + { res = lqf + ".equals(" + rqf + ")"; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { res = "!(" + lqf + ".equals(" + rqf + "))"; } + else if (operator.equals(":") || operator.equals("<:")) + { res = rqf + ".containsAll(" + lqf + ")"; } + else if (operator.equals("->includesAll")) + { if (left.isMap() && right.isMap()) + { res = "Ocl.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".containsAll(" + rqf + ")"; } + } + else if (operator.equals("-")) + { if (left.isMap() && right.isMap()) + { res = "Ocl.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Ocl.subtract(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->excluding")) + { res = "Ocl.subtract(" + lqf + "," + rqf + ")"; } + else if (operator.equals("\\/") || + operator.equals("->union")) + { if (left.isMap() || right.isMap()) + { res = "Ocl.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) + { res = "Ocl.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Ocl.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->including")) + { if (left.isOrdered()) + { res = "Ocl.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "Ocl.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/\\") || + operator.equals("->intersection")) + { if (left.isMap() && right.isMap()) + { res = "Ocl.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Ocl.intersection(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/:") || operator.equals("/<:")) + { res = "!(" + rqf + ".containsAll(" + lqf + "))"; } + else if (operator.equals("->excludesAll")) + { if (left.isMap() && right.isMap()) + { res = "Ocl.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Collections.disjoint(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("^") || + operator.equals("->concatenate")) + { res = "Ocl.concatenate(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->symmetricDifference")) + { res = "Ocl.symmetricDifference(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->prepend")) + { res = "Ocl.concatenate(" + rqf + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "Ocl.append(" + lqf + "," + rqf + ")"; } + return res; + } // what about comparitors? + + + private String composeSetQueryFormsCSharp(String lqf, String rqf) + { String res = lqf + " " + operator + " " + rqf; + if (operator.equals("=")) + { if (Type.isSetType(left.getType()) || Type.isSetType(right.getType())) + { res = "SystemTypes.equalsSet(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".Equals(" + rqf + ")"; } + } // order shouldn't matter + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { if (Type.isSetType(left.getType()) || Type.isSetType(right.getType())) + { res = "!(SystemTypes.equalsSet(" + lqf + "," + rqf + "))"; } + else + { res = "!(" + lqf + ".Equals(" + rqf + "))"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = "SystemTypes.isSubset(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->includesAll")) + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "SystemTypes.isSubset(" + rqf + "," + lqf + ")"; } + } + else if (operator.equals("-")) + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "SystemTypes.subtract(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->excluding")) + { res = "SystemTypes.subtract(" + lqf + "," + rqf + ")"; } + else if (operator.equals("\\/") || operator.equals("->union")) + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered()) + { res = "SystemTypes.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "SystemTypes.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("->including")) + { if (left.isOrdered()) + { res = "SystemTypes.concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "SystemTypes.union(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/\\") || operator.equals("->intersection")) + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "SystemTypes.intersection(" + lqf + "," + rqf + ")"; } + } + else if (operator.equals("/:") || operator.equals("/<:")) + { res = "!(SystemTypes.isSubset(" + lqf + ", " + rqf + "))"; } + else if (operator.equals("->excludesAll")) + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "(SystemTypes.intersection(" + rqf + "," + lqf + ").Count == 0)"; } + } + else if (operator.equals("^") || operator.equals("->concatenate")) + { res = "SystemTypes.concatenate(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->symmetricDifference")) + { res = "SystemTypes.symmetricDifference(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->prepend")) + { res = "SystemTypes.concatenate(" + rqf + "," + lqf + ")"; } + else if (operator.equals("->append")) + { res = "SystemTypes.concatenate(" + lqf + "," + rqf + ")"; } + return res; + } // what about comparitors? + + private String composeSetQueryFormsCPP(String lqf, String rqf, String lcet) + { String res = lqf + " " + operator + " " + rqf; + if (operator.equals("=")) + { // if (Type.isCollectionOrEntity(left.getType()) || Type.isCollectionOrEntity(right.getType())) + { res = "(*(" + lqf + ") == *(" + rqf + "))"; } + // else + // { res = "(" + lqf + " == " + rqf + ")"; } + } + else if (operator.equals("<>=")) + { res = "(" + lqf + " == " + rqf + ")"; } + else if (operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { // if (Type.isCollectionOrEntity(left.getType()) || Type.isCollectionOrEntity(right.getType())) + { res = "(*(" + lqf + ") != *(" + rqf + "))"; } + // else + // { res = "(" + lqf + " != " + rqf + ")"; } + } + else if (operator.equals(":") || operator.equals("<:")) + { res = "UmlRsdsLib<" + lcet + ">::isSubset(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->includesAll")) + { if (left.isMap() && right.isMap()) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + res = "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::includesAllMap(" + lqf + "," + rqf + ")"; + } + else + { res = "UmlRsdsLib<" + lcet + ">::isSubset(" + rqf + ", " + lqf + ")"; } + } + else if (operator.equals("-")) + { if (left.isMap() && right.isMap()) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + res = "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::excludeAllMap(" + lqf + "," + rqf + ")"; + } + else + { res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + ", " + rqf + ")"; } + } + else if (operator.equals("->excluding")) + { // String rss = makeSetCPP(rqf); + res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + ", " + rqf + ")"; + } + else if (operator.equals("->including")) + { // String rss = makeSetCPP(rqf); + if (left.isOrdered()) + { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + ", " + rqf + ")"; } + else + { res = "UmlRsdsLib<" + lcet + ">::unionSet(" + lqf + ", " + rqf + ")"; } + } + else if (operator.equals("\\/") || operator.equals("->union")) + { if (left.isMap() && right.isMap()) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + res = "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::unionMap(" + lqf + "," + rqf + ")"; + } + else if (left.isOrdered()) + { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + ", " + rqf + ")"; } + else // left is a set + { res = "UmlRsdsLib<" + lcet + ">::unionSet(" + lqf + ", " + rqf + ")"; } + } + else if (operator.equals("/\\") || operator.equals("->intersection")) + { if (left.isMap() && right.isMap()) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + res = "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::intersectionMap(" + lqf + "," + rqf + ")"; + } + else + { res = "UmlRsdsLib<" + lcet + ">::intersection(" + lqf + ", " + rqf + ")"; } + } + else if (operator.equals("/:") || operator.equals("/<:")) + { res = "!(UmlRsdsLib<" + lcet + ">::isSubset(" + lqf + ", " + rqf + "))"; } + else if (operator.equals("->excludesAll")) + { if (left.isMap() && right.isMap()) + { Type lkeyt = left.getType().getKeyType(); + String lkeytype = Type.getCPPtype(lkeyt); + res = "UmlRsdsOcl<" + lkeytype + ", " + lcet + ", " + lcet + ">::excludesAllMap(" + lqf + "," + rqf + ")"; + } + else + { res = "(UmlRsdsLib<" + lcet + ">::intersection(" + rqf + ", " + lqf + ")->size() == 0)"; } + } + else if (operator.equals("^") || operator.equals("->concatenate")) + { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->symmetricDifference")) + { res = "UmlRsdsLib<" + lcet + ">::symmetricDifference(" + lqf + "," + rqf + ")"; } + else if (operator.equals("->prepend")) + { res = "UmlRsdsLib<" + lcet + ">::prepend(" + lqf + ", " + rqf + ")"; } + else if (operator.equals("->append")) + { res = "UmlRsdsLib<" + lcet + ">::append(" + lqf + ", " + rqf + ")"; } + return res; + } // what about comparitors? + + public String updateForm(java.util.Map env, boolean local) + { String val2; + if (operator.equals("#") || operator.equals("#1")) + { return updateFormExists(env,local); } + // For #1 test qf first: if (qf) { } else { uf } + // Special case of ( x : E ) #1 ( x.id = v & P ) Should also check P before doing it + + if (operator.equals("#LC")) + { return updateFormExistsLC(env,local); } + + if (operator.equals("!")) // Only version with variable is ok + { BinaryExpression beleft = (BinaryExpression) left; + String lqf1 = beleft.right.queryForm(env,local); + if (beleft.right.umlkind == CLASSID) + { lqf1 = ((BasicExpression) beleft.right).classExtentQueryForm(env,local); } + String eleftname = ""; + String evarname = beleft.left + ""; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + Type eleft = beleft.right.getElementType(); // Must be an entity type + // System.out.println(">>>>>eleft is>>> " + eleft); + + String tname = ""; + if (eleft == null || "null".equals(eleft + "")) + { eleftname = "Object"; + tname = "Object"; + } + else + { eleftname = eleft.getName(); + // System.out.println(">>>>>eleftname is>>> " + eleftname); + tname = eleftname; // entities and String + + if ("int".equals(eleftname)) + { eleftname = "Integer"; + tname = "int"; + } + else if ("long".equals(eleftname)) + { eleftname = "Long"; + tname = "long"; + } + else if ("double".equals(eleftname)) + { eleftname = "Double"; + tname = "double"; + } + else if ("boolean".equals(eleftname)) + { eleftname = "Boolean"; + tname = "boolean"; + } + else if (eleftname.startsWith("Set") || eleftname.startsWith("Sequence")) + { eleftname = "List"; tname = "List"; } + else if (eleft != null && eleft.isEntity()) + { newenv.put(eleftname,evarname); } + } // not really needed to have E |-> ex in environment. + + String ufr1 = right.updateForm(newenv,false); + + String elist = Identifier.nextIdentifier("_" + tname.toLowerCase() + "_list"); + String indvar = Identifier.nextIdentifier("_ind"); + + + if ("Integer".equals(eleftname) && (left instanceof BasicExpression)) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryForm(env,false); + String endexpqf = endexp.queryForm(env,false); + return + " for (int " + evarname + " = " + startexpqf + "; " + evarname + " <= " + endexpqf + "; " + evarname + "++)\n" + + " { " + ufr1 + "\n" + + " }\n"; + } + else + { return " List " + elist + " = new Vector();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { int " + evarname + " = ((" + eleftname + ") " + elist + + ".get(" + indvar + ")).intValue();\n" + + " " + ufr1 + "\n" + + " }\n"; + } + } + else if (eleft != null && Type.isPrimitiveType(eleft)) + { return " List " + elist + " = new Vector();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { " + tname + " " + evarname + + " = ((" + eleftname + ") " + elist + + ".get(" + indvar + "))." + tname + "Value();\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + return + " List " + elist + " = new Vector();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { " + eleftname + " " + evarname + " = (" + eleftname + ") " + elist + + ".get(" + indvar + ");\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + + // Analyse if-then-else structure + if (operator.equals("&")) + { String ufl = left.updateForm(env,local); + String ufr = right.updateForm(env,local); + return ufl + "\n " + ufr; + } + + if (operator.equals("let")) + { // { var acc : T := e; ... E ... } + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getJava(); + String val = left.queryForm(env,local); + java.util.Map env1 = new java.util.HashMap(); + env1.putAll(env); + String stats = right.updateForm(env1,local); + return "\n { final " + lett + " " + acc + " = " + val + ";\n" + stats + "\n }"; + } + + if (operator.equals("or")) + { String ufl = left.updateForm(env,local); + String qfl = left.queryForm(env,local); + String ufr = right.updateForm(env,local); + return ufl + "\n if (" + qfl + ") {}\n else\n { " + ufr + " }"; + } + + if (operator.equals("xor")) + { Expression notleft = negate(left); + Expression notright = negate(right); + Statement stat1 = left.statLC(env,local); + Statement stat2 = notright.statLC(env,local); + String ufl = stat1.updateForm(env,local,new Vector(), new Vector(), new Vector()) + + "\n " + stat2.updateForm(env,local,new Vector(), new Vector(), new Vector()); + + String qfl1 = left.queryForm(env,local); + String qfl2 = notright.queryForm(env,local); + String ufr1 = right.updateForm(env,local); + String ufr2 = notleft.updateForm(env,local); + return ufl + "\n if (" + qfl1 + " && " + qfl2 + ") {}\n else\n { " + ufr1 + + "\n " + ufr2 + " }"; + } + + if (operator.equals("=>")) + { String ufl = left.queryForm(env,local); + String ufr = right.updateForm(env,local); + if ("true".equals(ufl)) + { return ufr; } + return " if (" + ufl + ") \n" + + " { " + ufr + "}"; + } // accumulate the cases + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opjava = Expression.getOperatorJava(op); + String lqf = left.queryForm(env,local); + String rqf = right.queryForm(env,local); + + if (opjava != null && opjava.length() > 0) + { return opjava.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + if (operator.equals("=") && left instanceof BasicExpression) + { val2 = right.queryForm(env,local); + return ((BasicExpression) left).updateFormEq(env,val2,right,local); + } + else if (operator.equals("=") && left instanceof UnaryExpression) + { val2 = right.queryForm(env,local); + return ((UnaryExpression) left).updateFormEq("Java4",env,((UnaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof BinaryExpression) + { val2 = right.queryForm(env,local); + return ((BinaryExpression) left).updateFormEq("Java4",env,((BinaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof SetExpression) + { val2 = right.queryForm(env,local); + return ((SetExpression) left).updateForm("Java4",env,operator,val2,right,local); + } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { val2 = right.queryForm(env,local); + return ((BasicExpression) left).updateForm(env,"<:",val2,right,local); + } + else if (operator.equals("->includesAll") && left instanceof BinaryExpression) + { return ((BinaryExpression) left).updateFormSubset("Java4", env, right, local); } + else if (operator.equals("->includesAll") && left instanceof UnaryExpression) + { return ((UnaryExpression) left).updateFormSubset("Java4", env, right, local); } + else if (operator.equals("->includes") && left instanceof BinaryExpression) + { return ((BinaryExpression) left).updateFormIn("Java4", env, right, local); } + else if (operator.equals("->includes") && left instanceof UnaryExpression) + { return ((UnaryExpression) left).updateFormIn("Java4", env, right, local); } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { val2 = right.queryForm(env,local); + return ((BasicExpression) left).updateForm(env,"-",val2,right,local); + } + else if (operator.equals("->excludesAll") && left instanceof UnaryExpression) + { return ((UnaryExpression) left).updateFormSubtract("Java4", env,right,local); } + else if (operator.equals("->excludesAll") && left instanceof BinaryExpression) + { return ((BinaryExpression) left).updateFormSubtract("Java4", env,right,local); } + else if (operator.equals("->excludes") && left instanceof UnaryExpression) + { return ((UnaryExpression) left).updateFormNotIn("Java4", env,right,local); } + else if (operator.equals("->excludes") && left instanceof BinaryExpression) + { return ((BinaryExpression) left).updateFormNotIn("Java4", env,right,local); } + else if ((operator.equals(":") || + operator.equals("<:") || + operator.equals("/<:") || + operator.equals("/:")) && + (right instanceof BasicExpression)) + { String val1 = left.queryForm(env,local); + BasicExpression ber = (BasicExpression) right; // Why cast? + /* boolean lmult = left.isMultiple(); + if (lmult) + { if (operator.equals(":") || operator.equals("<:")) + { return ber.updateForm(env,"<:",val1,left,local); } + if (operator.equals("/:") || operator.equals("/<:")) + { return ber.updateForm(env,"-",val1,left,local); } + } */ + if (left.isPrimitive()) + { val1 = left.wrap(val1); } + return ber.updateForm(env,operator,val1,left,local); + } + else if ((operator.equals("->includes") || + operator.equals("->excludes")) && (left instanceof BasicExpression)) + { String val3 = right.queryForm(env,local); + BasicExpression bel = (BasicExpression) left; + /* boolean rmult = right.isMultiple(); + if (rmult) + { if (operator.equals("->includes")) + { return bel.updateForm(env,"<:",val3,right,local); } + if (operator.equals("->excludes")) + { return bel.updateForm(env,"-",val3,right,local); } + } */ + + if (right.isPrimitive()) + { val3 = right.wrap(val3); } + if (operator.equals("->includes")) + { return bel.updateForm(env,":",val3,right,local); } + else + { return bel.updateForm(env,"/:",val3,right,local); } + } + else + { String qf = queryForm(env,local); + return "if (" + qf + ") { } else { System.err.println(\"Assertion " + qf + " fails:\"); System.err.println(this); }\n"; + } + } + +public String updateFormIn(String language, java.util.Map env, Expression var, boolean local) +{ if ("->union".equals(operator)) + { BinaryExpression test1 = new BinaryExpression("->includes", left, var); + BinaryExpression test2 = new BinaryExpression("->includes", right, var); + BinaryExpression test = new BinaryExpression("or", test1, test2); + BinaryExpression add2a = new BinaryExpression(":", var, left); + BinaryExpression add2b = new BinaryExpression(":", var, right); + String addleft = add2a.updateForm(language,env,local); + String addright = add2b.updateForm(language,env,local); + String testfull = addleft; + if (left instanceof BasicExpression && ((BasicExpression) left).isZeroOneRole()) + { Expression test3 = new UnaryExpression("->size", left); + Expression atcap = new BinaryExpression("=", test3, new BasicExpression(0)); + testfull = "if (" + atcap.queryForm(language, env, local) + ") { " + addright + " }\n " + + " else { " + addleft + " } "; + } + return " if (" + test.queryForm(language, env, local) + ") { }\n" + + " else " + testfull; + } + else if ("->intersection".equals(operator)) + { Expression e1 = new BinaryExpression(":", var, left); + Expression e2 = new BinaryExpression(":", var, right); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("^".equals(operator) || "->concatenate".equals(operator)) + { BinaryExpression test1 = new BinaryExpression("->includes", left, var); + BinaryExpression test2 = new BinaryExpression("->includes", right, var); + BinaryExpression test = new BinaryExpression("or", test1, test2); + Expression addb = new BinaryExpression(":", var, right); + return " if (" + test.queryForm(language,env,local) + ") { }\n" + + " else { " + addb.updateForm(language,env,local) + " } "; + } + else if ("-".equals(operator)) + { Expression e1 = new BinaryExpression(":", var, left); + Expression e2 = new BinaryExpression("/:", var, right); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("->sortedBy".equals(operator)) + { Expression e1 = new BinaryExpression(":", var, left); + return e1.updateForm(language,env,local); + } + else if ("->select".equals(operator) && (var instanceof BasicExpression)) + { Expression e1 = new BinaryExpression(":", var, left); + Expression e2 = right.addReference((BasicExpression) var, left.elementType); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("->reject".equals(operator) && (var instanceof BasicExpression)) + { Expression e1 = new BinaryExpression(":", var, left); + Expression e2 = right.addReference((BasicExpression) var, left.elementType); + Expression e3 = Expression.negate(e2); + Expression e = new BinaryExpression("&", e1, e3); + return e.updateForm(language,env,local); + } + else if ("->excluding".equals(operator)) + { Expression test = new BinaryExpression("=", var, right); + Expression adda = new BinaryExpression(":", var, left); + return " if (" + test.queryForm(language, env, local) + ") { }\n" + + " else { " + adda.updateForm(language, env, local) + " }"; + } + else if ("->including".equals(operator)) + { Expression test = new BinaryExpression("=", var, right); + Expression adda = new BinaryExpression(":", var, left); + return " if (" + test.queryForm(language, env, local) + ") { }\n" + + " else { " + adda.updateForm(language, env, local) + " }"; + } + else + { String qf = queryForm(env,local); + return "if (" + qf + ") { } else { System.err.println(\"Assertion " + qf + " fails:\"); System.err.println(this); }\n"; + } +} + +public String updateFormNotIn(String language, java.util.Map env, Expression var, boolean local) +{ if ("->union".equals(operator) || "^".equals(operator) || + "->concatenate".equals(operator)) + { BinaryExpression test1 = new BinaryExpression("/:", var, left); + BinaryExpression test2 = new BinaryExpression("/:", var, right); + BinaryExpression e = new BinaryExpression("&", test1, test2); + return e.updateForm(language, env, local); + } + else if ("->intersection".equals(operator)) + { Expression test = new BinaryExpression(":", var, left); + Expression rema = new BinaryExpression("/:", var, left); + Expression remb = new BinaryExpression("/:", var, right); + return " if (" + test.queryForm(language, env, local) + ") { " + rema.updateForm(language, env, local) + " } \n" + + " else { " + remb.updateForm(language, env, local) + " }"; + } + else if ("-".equals(operator)) + { Expression e1 = new BinaryExpression("/:", var, left); + return e1.updateForm(language,env,local); + } + else if ("->collect".equals(operator)) + { Expression e1 = new BinaryExpression("=", var, right); + Expression e2 = new BinaryExpression("->reject", left, e1); + Expression e = new BinaryExpression("=", left, e2); + return e.updateForm(language,env,local); + } + else if ("->sortedBy".equals(operator)) + { Expression e1 = new BinaryExpression("/:", var, left); + return e1.updateForm(language,env,local); + } + else if ("->select".equals(operator) && (var instanceof BasicExpression)) + { Expression e1 = new BinaryExpression("/:", var, left); + return e1.updateForm(language,env,local); + } + else if ("->reject".equals(operator) && (var instanceof BasicExpression)) + { Expression e1 = new BinaryExpression("/:", var, left); + return e1.updateForm(language,env,local); + } + else if ("->including".equals(operator) || "->excluding".equals(operator)) + { Expression test = new BinaryExpression("=", var, right); + Expression adda = new BinaryExpression("/:", var, left); + return " if (" + test.queryForm(language, env, local) + ") { }\n" + + " else { " + adda.updateForm(language, env, local) + " }"; + } + return "/* No update form for " + var + " : " + this + " */"; +} + +public String updateFormSubset(String language, java.util.Map env, Expression var, boolean local) +{ if ("->union".equals(operator)) + { BinaryExpression test = new BinaryExpression("->includesAll", this, var); + BinaryExpression add2a = new BinaryExpression("<:", var, left); + BinaryExpression add2b = new BinaryExpression("<:", var, right); + String addleft = add2a.updateForm(language,env,local); + String addright = add2b.updateForm(language,env,local); + String testfull = addleft; + if (left instanceof BasicExpression && ((BasicExpression) left).isZeroOneRole()) + { testfull = addright; } + return " if (" + test.queryForm(language, env, local) + ") { }\n" + + " else { " + testfull + " } "; + } + else if ("->intersection".equals(operator)) + { Expression e1 = new BinaryExpression("<:", var, left); + Expression e2 = new BinaryExpression("<:", var, right); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("^".equals(operator) || "->concatenate".equals(operator)) + { BinaryExpression test = new BinaryExpression("->includes", this, var); + Expression addb = new BinaryExpression("<:", var, right); + return " if (" + test.queryForm(language,env,local) + ") { }\n" + + " else { " + addb.updateForm(language,env,local) + " } "; + } + else if ("-".equals(operator)) + { Expression e1 = new BinaryExpression("<:", var, left); + Expression e2 = new BinaryExpression("->excludesAll", right, var); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("->sortedBy".equals(operator)) + { Expression e1 = new BinaryExpression("<:", var, left); + return e1.updateForm(language,env,local); + } + else if ("->select".equals(operator)) + { Expression e1 = new BinaryExpression("<:", var, left); + Expression e2 = new BinaryExpression("->forAll", var, right); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("->reject".equals(operator)) + { Expression e1 = new BinaryExpression("<:", var, left); + Expression e3 = Expression.negate(right); + Expression e2 = new BinaryExpression("->forAll", var, e3); + Expression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language,env,local); + } + else if ("->excluding".equals(operator) || "->including".equals(operator)) + { Expression subb = new BinaryExpression("->excluding", var, right); + Expression adda = new BinaryExpression("<:", subb, left); + return adda.updateForm(language, env, local); + } + return "/* No update form for " + var + " <: " + this + " */"; +} + +public String updateFormSubtract(String language, java.util.Map env, Expression var, boolean local) +{ if ("->union".equals(operator) || "^".equals(operator) + || "->concatenate".equals(operator)) + { BinaryExpression e1 = new BinaryExpression("->excludesAll", left, var); + BinaryExpression e2 = new BinaryExpression("->excludesAll", right, var); + BinaryExpression e = new BinaryExpression("&", e1, e2); + return e.updateForm(language, env, local); + } + else if ("->intersection".equals(operator)) + { Expression inter = new BinaryExpression("->intersection", var, right); + inter.setBrackets(true); + Expression rema = new BinaryExpression("-", left, inter); + Expression remb = new BinaryExpression("=", left, rema); + return rema.updateForm(language, env, local); + } + else if ("-".equals(operator)) + { Expression e1 = new BinaryExpression("-", var, right); + e1.setBrackets(true); + Expression e2 = new BinaryExpression("-", left, e1); + Expression e3 = new BinaryExpression("=", left, e2); + return e3.updateForm(language,env,local); + } + else if ("->collect".equals(operator)) + { Expression e1 = new BinaryExpression(":", right, var); + Expression e2 = new BinaryExpression("->reject", left, e1); + Expression e = new BinaryExpression("=", left, e2); + return e.updateForm(language,env,local); + } + else if ("->sortedBy".equals(operator)) + { Expression e1 = new BinaryExpression("->excludesAll", left, var); + return e1.updateForm(language,env,local); + } + else if ("->select".equals(operator)) + { Expression selfv = new BasicExpression("self", 0); + Expression e1 = new BinaryExpression(":", selfv, var); + Expression pred = new BinaryExpression("&", e1, right); + Expression rej = new BinaryExpression("->reject", left, pred); + Expression assign = new BinaryExpression("=", left, rej); + + return assign.updateForm(language,env,local); + } + else if ("->reject".equals(operator)) + { Expression selfv = new BasicExpression("self", 0); + Expression e1 = new BinaryExpression(":", selfv, var); + Expression nright = Expression.negate(right); + Expression pred = new BinaryExpression("&", e1, nright); + Expression rej = new BinaryExpression("->reject", left, pred); + Expression assign = new BinaryExpression("=", left, rej); + return assign.updateForm(language,env,local); + } + else if ("->including".equals(operator)) + { Expression rema = new BinaryExpression("->excludesAll", left, var); + return rema.updateForm(language, env, local); + } + else if ("->excluding".equals(operator)) + { Expression remb = new BinaryExpression("->excluding", var, right); + remb.setBrackets(true); + Expression suba = new BinaryExpression("-", left, remb); + Expression assign = new BinaryExpression("=", left, suba); + return assign.updateForm(language, env, local); + } + return "/* No update form for " + this + "->excludesAll(" + var + ") */"; +} + + public boolean isTestable() + { if ("result".equals("" + left)) + { return false; } + + if ("result".equals("" + right)) + { return false; } + return true; + } + + public boolean isExecutable() + { if ("#LC".equals(operator) || operator.equals("#") || operator.equals("#1")) + { return left.isExecutable() && right.isExecutable(); } // should be or + + if (operator.equals("!") || operator.equals("=>")) // Only version with variable is ok + { return right.isExecutable(); } + + if (operator.equals("&")) + { return left.isExecutable() || right.isExecutable(); } + + if (operator.equals("or")) + { return left.isExecutable() || right.isExecutable(); } + + if (operator.equals("=") && left instanceof BasicExpression) + { return ((BasicExpression) left).isAssignable(); } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { return ((BasicExpression) left).isAssignable(); } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { return ((BasicExpression) left).isAssignable(); } + else if (operator.equals(":") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.isAssignable(); + } + else if (operator.equals("<:") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.isAssignable(); + } + else if (operator.equals("/<:") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.isAssignable(); + } + else if (operator.equals("/:") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.isAssignable(); + } + else if (operator.equals("->includes") && left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + return lbe.isAssignable(); + } + else if (operator.equals("->excludes") && left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + return lbe.isAssignable(); + } + + return false; + } + + public String updateFormExistsLC(java.util.Map env, boolean local) + { Statement stat = statLC(env,local); + if (stat != null) + { return stat.updateForm(env,local,new Vector(), new Vector(), new Vector()); } + else + { return "/* Invalid expression: " + this + " */"; } + } + + public String updateFormExistsLCJava6(java.util.Map env, boolean local) + { Statement stat = statLC(env,local); + if (stat != null) + { return stat.updateFormJava6(env,local); } + else + { return "/* Invalid expression: " + this + " */"; } + } + + public String updateFormExistsLCJava7(java.util.Map env, boolean local) + { Statement stat = statLC(env,local); + if (stat != null) + { return stat.updateFormJava7(env,local); } + else + { return "/* Invalid expression: " + this + " */"; } + } + + public String updateFormExistsLCCSharp(java.util.Map env, boolean local) + { Statement stat = statLC(env,local); + if (stat != null) + { return stat.updateFormCSharp(env,local); } + else + { return "/* Invalid expression: " + this + " */"; } + } + + public String updateFormExistsLCCPP(java.util.Map env, boolean local) + { Statement stat = statLC(env,local); + if (stat != null) + { return stat.updateFormCPP(env,local); } + else + { return "/* Invalid expression: " + this + " */"; } + } + +public Statement statLC(java.util.Map env, boolean local) +{ String val2; + + if (operator.equals("#") || operator.equals("#1")) + { return generateDesignExists(env,local); } + + if (operator.equals("#LC")) + { return statLCExists(env,local); } + + if (operator.equals("or")) + { SequenceStatement skip = new SequenceStatement(); + if (left.isExecutable()) + { Statement leftdesign = left.statLC(env,local); + if (right.isExecutable()) + { Statement rightdesign = right.statLC(env,local); + SequenceStatement res = new SequenceStatement(); + res.addStatement(leftdesign); + res.addStatement(new ConditionalStatement(this, skip, rightdesign)); + return res; + } + return new ConditionalStatement(this, skip, leftdesign); + } + else + { Statement rightdesign = right.statLC(env,local); + return new ConditionalStatement(this, skip, rightdesign); + } + } + + if (operator.equals("!")) + { Statement body = right.statLC(env,local); + BinaryExpression bel = (BinaryExpression) left; + return iterationLoop(bel.left, bel.right, body); + } + + if (operator.equals("&")) + { Statement ufl = left.statLC(env,local); + Statement ufr = right.statLC(env,local); + if (ufl instanceof SequenceStatement) + { ((SequenceStatement) ufl).addStatement(ufr); + return ufl; + } + SequenceStatement sstat = new SequenceStatement(); + sstat.addStatement(ufl); + sstat.addStatement(ufr); + return sstat; + } + + if (operator.equals("=>")) + { Statement ufr = right.statLC(env,local); + if ("true".equals(left + "")) + { return ufr; } + ConditionalStatement istat = new ConditionalStatement(left,ufr); + return istat; + } + + if (operator.equals("=") && (left instanceof BasicExpression)) + { return new AssignStatement(left,right); } + + if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if (operator.equals("->includesAll")) + { Statement upd = lbe.generateDesignSubset(right); + if (lbe.isOrdered()) + { Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(this, skip, upd); + } + return upd; + } // but ->forAll in fact + else if (operator.equals("->excludesAll")) + { Statement upd = lbe.generateDesignSubtract(right); + Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(this, skip, upd); + } + else if (operator.equals("->includes")) + { Statement upd = lbe.generateDesignIn(right); + if (lbe.isOrdered()) + { Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(this, skip, upd); + } + return upd; + } + else if (operator.equals("->excludes")) + { Statement upd = lbe.generateDesignNotIn(right); + Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(this, skip, upd); + } + } + + if (right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + if (operator.equals("<:")) + { Statement upd = rbe.generateDesignSubset(left); + BinaryExpression test = new BinaryExpression("->includesAll",right,left); + test.setType(type); + test.setElementType(elementType); + if (rbe.isOrdered()) + { Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(test, skip, upd); + } + return upd; + } // but ->forAll in fact + else if (operator.equals("/<:")) + { Statement upd = rbe.generateDesignSubtract(left); + Statement skip = new SequenceStatement(); + BinaryExpression test = new BinaryExpression("->excludesAll",right,left); + test.setType(type); + test.setElementType(elementType); + upd.setBrackets(true); + return new ConditionalStatement(test, skip, upd); + } + else if (operator.equals(":")) + { Statement upd = rbe.generateDesignIn(left); + BinaryExpression test = new BinaryExpression("->includes",right,left); + test.setType(type); + test.setElementType(elementType); + + if (rbe.isOrdered()) + { Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(test, skip, upd); + } + return upd; + } + else if (operator.equals("/:")) + { Statement upd = rbe.generateDesignNotIn(left); + BinaryExpression test = new BinaryExpression("->excludes",right,left); + test.setType(type); + test.setElementType(elementType); + Statement skip = new SequenceStatement(); + upd.setBrackets(true); + return new ConditionalStatement(test, skip, upd); + } + } + + return new ImplicitInvocationStatement("/* No LC update form for : " + this + " */"); +} + +public Statement statLCExists(java.util.Map env, boolean local) +{ BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + + Expression evar = (Expression) lvar.clone(); + evar.umlkind = VARIABLE; + + Statement res = new InvocationStatement("/* No LC update form for : " + this + " */"); + + Expression ltype = lexp.right; + Type etype = ltype.getElementType(); + if (etype == null) + { return res; } + Entity ent = etype.getEntity(); + if (ent == null) + { return res; } + evar.setType(new Type(ent)); + + // Case of non-writable ltype + // is var evar : ltype; stat(right) + + Vector preds = right.getConjuncts(); + + System.out.println(">->-> Conjuncts of " + right + " are: " + preds); + + String ename = ent.getName(); + Expression eset = new BasicExpression(ename.toLowerCase() + "$set"); + eset.umlkind = VARIABLE; + eset.setType(new Type("Set",null)); + eset.setElementType(etype); + + Expression etest = new UnaryExpression("->isEmpty", eset); + Expression eany = new UnaryExpression("->any", eset); + Expression eexp = new BasicExpression(ent); + BasicExpression einstances = new BasicExpression("allInstances"); + einstances.setObjectRef(eexp); + einstances.umlkind = FUNCTION; + einstances.setType(new Type("Set", null)); + einstances.setElementType(etype); + + Statement assigneset = new AssignStatement(eset, einstances); + Statement eassign = new AssignStatement(evar, eany); + Vector remainder = new Vector(); + + Attribute pk = Expression.hasPrimaryKey(ltype); + if (pk != null) + { Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) + { String kvqf = keyval.queryForm(env,local); + BasicExpression invokecreent = new BasicExpression("createByPK" + ename); + invokecreent.umlkind = UPDATEOP; + invokecreent.type = new Type(ent); + invokecreent.elementType = new Type(ent); + invokecreent.addParameter(keyval); + AssignStatement assgn = new AssignStatement(evar,invokecreent); + assgn.setType(etype); + if (ltype.umlkind == CLASSID) + { if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + Statement remstat = rem.statLC(env,local); + SequenceStatement sts = new SequenceStatement(); + sts.addStatement(assgn); + sts.addStatement(remstat); + return sts; + } + else // no remainder + { return assgn; } + } + else // ltype not class + { Statement add2ltype = left.statLC(env,local); + SequenceStatement sts = new SequenceStatement(); + sts.addStatement(assgn); + sts.addStatement(add2ltype); + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + Statement remstat = rem.statLC(env,local); + sts.addStatement(remstat); + return sts; + } + else // no remainder + { return sts; } + } + } + else // no keyval + { if (preds.size() > 0) + { Expression p1 = (Expression) preds.get(0); + BinaryExpression erange = new BinaryExpression(":", evar, eset); + erange.setType(new Type("Set",null)); + erange.setElementType(etype); + Expression selp1 = new BinaryExpression("|", erange, p1); + Statement aselp1 = new AssignStatement(eset,selp1); + SequenceStatement sts = new SequenceStatement(); + CreationStatement createeset = new CreationStatement("Set(" + ename + ")", "" + eset); + createeset.setType(new Type("Set", null)); + createeset.setElementType(etype); + CreationStatement ini = new CreationStatement("" + ename, "" + evar); + ini.setType(etype); + ini.setElementType(etype); + sts.addStatement(createeset); + sts.addStatement(assigneset); + sts.addStatement(ini); + sts.addStatement(aselp1); + BasicExpression invokecreent1 = new BasicExpression("create" + ename); + invokecreent1.umlkind = UPDATEOP; + invokecreent1.type = new Type(ent); + invokecreent1.elementType = new Type(ent); + AssignStatement assgn1 = new AssignStatement(evar,invokecreent1); + // assgn1.setType(etype); + Statement ufr = right.statLC(env,local); + SequenceStatement ifcase = new SequenceStatement(); + ifcase.addStatement(assgn1); + ifcase.addStatement(ufr); + Vector prest = new Vector(); + prest.addAll(preds); + prest.remove(0); + Statement elsecase = existsLC(prest,eset,etest,evar,eassign,env,local); + ConditionalStatement cs = new ConditionalStatement(etest,ifcase,elsecase); + sts.addStatement(cs); + return sts; + } + } + } + else // no key + { if (preds.size() > 0) + { Expression p1 = (Expression) preds.get(0); + BinaryExpression erange = new BinaryExpression(":", evar, eset); + erange.setType(new Type("Set",null)); + erange.setElementType(etype); + Expression selp1 = new BinaryExpression("|", erange, p1); + Statement aselp1 = new AssignStatement(eset,selp1); + SequenceStatement sts = new SequenceStatement(); + CreationStatement createeset = new CreationStatement("Set(" + ename + ")", "" + eset); + createeset.setType(new Type("Set", null)); + createeset.setElementType(etype); + CreationStatement ini = new CreationStatement("" + ename, "" + evar); + ini.declarationOnly = true; + ini.setType(etype); + ini.setElementType(etype); + sts.addStatement(createeset); + sts.addStatement(assigneset); + sts.addStatement(ini); + sts.addStatement(aselp1); + BasicExpression invokecreent1 = new BasicExpression("create" + ename); + invokecreent1.umlkind = UPDATEOP; + invokecreent1.type = new Type(ent); + invokecreent1.elementType = new Type(ent); + AssignStatement assgn1 = new AssignStatement(evar,invokecreent1); + // assgn1.setType(etype); + Statement ufr = right.statLC(env,local); + SequenceStatement ifcase = new SequenceStatement(); + ifcase.addStatement(assgn1); + ifcase.addStatement(ufr); + Vector prest = new Vector(); + prest.addAll(preds); + prest.remove(0); + Statement elsecase = existsLC(prest,eset,etest,evar,eassign,env,local); + ConditionalStatement cs = new ConditionalStatement(etest,ifcase,elsecase); + sts.addStatement(cs); + return sts; + } + } + return res; +} + +public Statement existsLC(Vector preds, Expression eset, Expression etest, + Expression evar, Statement eassign, java.util.Map env, boolean local) +{ BinaryExpression erange = new BinaryExpression(":", evar, eset); + erange.setType(eset.getType()); + erange.setElementType(eset.getElementType()); + + if (preds.size() == 1) + { Expression pk = (Expression) preds.get(0); + Statement pkstat = pk.statLC(env,local); + + if (pk.isTestable()) + { Expression selpk = new BinaryExpression("|", erange, pk); + Statement stat2 = new AssignStatement(eset, selpk); + SequenceStatement res = new SequenceStatement(); + res.addStatement(eassign); + res.addStatement(stat2); + Statement ifst = new ConditionalStatement(etest, pkstat, eassign); + res.addStatement(ifst); + res.setBrackets(true); + return res; + } + else + { SequenceStatement r2 = new SequenceStatement(); + r2.addStatement(eassign); + r2.addStatement(pkstat); + r2.setBrackets(true); + return r2; + } + } + else if (preds.size() > 0) + { Expression pj = (Expression) preds.get(0); + Vector prem = new Vector(); + prem.addAll(preds); + prem.remove(0); + Statement remstat = existsLC(prem,eset,etest,evar,eassign,env,local); + if (pj.isTestable()) + { Expression selpj = new BinaryExpression("|", erange, pj); + Statement stat3 = new AssignStatement(eset, selpj); + SequenceStatement resg = new SequenceStatement(); + resg.addStatement(eassign); + resg.addStatement(stat3); + Statement doallpred = SequenceStatement.statLC(preds,env,local); + ConditionalStatement cs = new ConditionalStatement(etest, doallpred, remstat); + resg.addStatement(cs); + resg.setBrackets(true); + return resg; + } + else + { // just do pj and carry on + Statement pjstat = pj.statLC(env,local); + SequenceStatement rr = new SequenceStatement(); + rr.addStatement(eassign); + rr.addStatement(pjstat); + rr.addStatement(remstat); + rr.setBrackets(true); + return rr; + } + } + return new SequenceStatement(); // preds.size() == 0 +} + + + public Statement generateDesign(java.util.Map env, boolean local) + { String val2; + if (operator.equals("#") || operator.equals("#1")) + { return generateDesignExists(env,local); } + // For #1 test qf first: if (qf) { } else { uf } + // Special case of ( x : E ) #1 ( x.id = v & P ) Should also check P before doing it + + if (operator.equals("#LC")) + { return statLC(env,local); } + + if (operator.equals("!")) // Only version with variable is ok + { Statement body = right.generateDesign(env,local); + return iterationLoop(((BinaryExpression) left).left, ((BinaryExpression) left).right, body); + } + + if (operator.equals("->iterate")) + { // var acc : accType ; + // acc := acc.initialExpression ; + // for iteratorVariable : left + // do body + + SequenceStatement sstat = new SequenceStatement(); + CreationStatement cs = + new CreationStatement(accumulator); + BasicExpression acc = + new BasicExpression(accumulator); + AssignStatement asgn = + new AssignStatement(acc, + accumulator.getInitialExpression()); + AssignStatement body = + new AssignStatement(acc,right); + BasicExpression iterVar = + new BasicExpression(iteratorVariable); + iterVar.setType(left.getElementType()); + WhileStatement ws = + new WhileStatement(iterVar,left,body); + sstat.addStatement(cs); + sstat.addStatement(asgn); + sstat.addStatement(ws); + return ws; + } + + // Analyse if-then-else structure + if (operator.equals("&")) + { Statement ufl = left.generateDesign(env,local); + Statement ufr = right.generateDesign(env,local); + SequenceStatement sstat = new SequenceStatement(); + sstat.addStatement(ufl); sstat.addStatement(ufr); + return sstat; + } + + if (operator.equals("or")) + { Statement ufl = left.generateDesign(env,local); + Statement ufr = right.generateDesign(env,local); + SequenceStatement sstat = new SequenceStatement(); + sstat.addStatement(ufl); + SequenceStatement skip = new SequenceStatement(); + ConditionalStatement cs = new ConditionalStatement(left,skip,ufr); + sstat.addStatement(cs); + return sstat; + } + + // And for xor + + if (operator.equals("let") && accumulator != null) + { // let accumulator = left in right + + SequenceStatement sstat = new SequenceStatement(); + Type typ1 = accumulator.getType(); + String varname = accumulator.getName(); + CreationStatement cs1 = new CreationStatement(typ1 + "",varname); + cs1.setType(typ1); + if (left.getElementType() != null) + { cs1.setElementType(left.getElementType()); } + else if (accumulator.getElementType() != null) + { cs1.setElementType(accumulator.getElementType()); } + System.out.println(">>> Let element type is: " + cs1.getElementType()); + + // cs1.setInitialisation(left); + sstat.addStatement(cs1); + BasicExpression var = new BasicExpression(accumulator); + AssignStatement asgn = + new AssignStatement(var,left); + sstat.addStatement(asgn); + Statement ufr = right.generateDesign(env,local); + sstat.addStatement(ufr); + + System.out.println(">>> Design for let is: " + sstat); + System.out.println(); + + return sstat; + } + + if (operator.equals("=>")) + { Statement ufr = right.generateDesign(env,local); + if ("true".equals("" + left)) + { return ufr; } + ConditionalStatement istat = new ConditionalStatement(left, ufr); + return istat; + } // accumulate the cases + + if (operator.equals("=") && left instanceof BasicExpression) + { return new AssignStatement(left, right); } + else if (operator.equals("=") && left instanceof BinaryExpression) + { BinaryExpression leftbe = (BinaryExpression) left; + if ("+".equals(leftbe.operator) && left.isString() && + leftbe.left.isAssignable() && + leftbe.right.isAssignable()) + { UnaryExpression varsize = new UnaryExpression("->size",right); + UnaryExpression leftsize = new UnaryExpression("->size",leftbe.left); + + Vector spars1 = new Vector(); + spars1.add(new BasicExpression(1)); + spars1.add(leftsize); + + Vector spars2 = new Vector(); + spars2.add(new BinaryExpression("+", leftsize, + new BasicExpression(1))); + spars2.add(varsize); + + Expression newright1 = + BasicExpression.newFunctionBasicExpression( + "subrange",right,spars1); + Statement assign1 = new AssignStatement(leftbe.left, newright1); + Expression newright2 = + BasicExpression.newFunctionBasicExpression( + "subrange",right,spars2); + Statement assign2 = new AssignStatement(leftbe.right, newright2); + SequenceStatement sstat = new SequenceStatement(); + sstat.addStatement(assign1); + sstat.addStatement(assign2); + System.out.println("$$$ Design for " + this + " is " + sstat); + return sstat; + } + } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + return lbe.generateDesignSubset(right); + } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + return lbe.generateDesignSubtract(right); + } + else if (operator.equals(":") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.generateDesignIn(left); + } + else if (operator.equals("<:") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.generateDesignSubset(left); + } + else if (operator.equals("/<:") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.generateDesignSubtract(left); + } + else if (operator.equals("/:") && right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + return rbe.generateDesignNotIn(left); + } + else if (operator.equals("->includes") && left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + return lbe.generateDesignIn(right); + } + else if (operator.equals("->excludes") && left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + return lbe.generateDesignNotIn(right); + } + + return new ImplicitInvocationStatement(this); + } + + public String updateFormEq(String language, java.util.Map env, String op, + String val, Expression var, boolean local) + { // update this = var to this, val is + // query form of var. + + if ("->at".equals(operator)) + { // left->at(right) = val; + // left evaluates to a sequence or map or ref + + return BasicExpression.updateFormEqIndex( + language,left,right,val,var,env,local); + } + + if ("->select".equals(operator)) + { // (left - (left->select(right) - var))->union(var->select(right)) + BinaryExpression se = (BinaryExpression) clone(); + BinaryExpression subfg = new BinaryExpression("-", se, var ); + subfg.setBrackets(true); + BinaryExpression leftminus = new BinaryExpression("-", left, subfg); + BinaryExpression selectg = new BinaryExpression("->select", var, right); + BinaryExpression uniexp = new BinaryExpression("->union", leftminus, selectg); + BinaryExpression assign = new BinaryExpression("=", left, uniexp); + return assign.updateForm(language,env,local); + } + else if ("->reject".equals(operator)) + { // (left - var)->select(right)->union(var->reject(right)) + BinaryExpression subfg = new BinaryExpression("-", left, var ); + subfg.setBrackets(true); + BinaryExpression se = new BinaryExpression("->select", subfg, right); + BinaryExpression rejectg = new BinaryExpression("->reject", var, right); + BinaryExpression uniexp = new BinaryExpression("->union", se, rejectg); + BinaryExpression assign = new BinaryExpression("=", left, uniexp); + return assign.updateForm(language,env,local); + } + // else if ("->collect".equals(operator)) + // { // col->collect( e ) := var is + // for _i : Integer.subrange(1,col->size()) + // do (var _x : T := col->at(_i); _x.e := var->at(_i)) + // } + else if ("|C".equals(operator)) + { BinaryExpression lbe = (BinaryExpression) left; + BasicExpression vx = (BasicExpression) lbe.getLeft(); + Expression col = lbe.getRight(); + + if (col.isSequence()) { } + else + { System.err.println("!! Warning: can only update a sequence via a ->collect view, not other types of collections: " + col); } + + BasicExpression _ind = + BasicExpression.newVariableBasicExpression("_ind", + new Type("int", null)); + + Vector rangepars = new Vector(); + rangepars.add(new BasicExpression(1)); + rangepars.add(new UnaryExpression("->size", col)); + + Expression scope = + BasicExpression.newFunctionBasicExpression( + "subrange", "Integer", rangepars); + scope.setType(new Type("Sequence", null)); + scope.setElementType(new Type("int", null)); + + CreationStatement cs = new CreationStatement(vx, + col.getElementType()); + // Expression colclone = (Expression) col.clone(); + // colclone.setArrayIndex(_ind); + Expression iniExpr = new BinaryExpression("->at", col, _ind); + iniExpr.setType(col.getElementType()); + cs.setInitialisation(iniExpr); + + Expression rhs; + if (var.isNumeric() || var.isString() || + var.isBoolean()) + { rhs = var; } + else + { rhs = new BinaryExpression("->at", var, _ind); + rhs.setType(var.getElementType()); + } + + AssignStatement astat = + new AssignStatement(right, rhs); + + SequenceStatement ss = new SequenceStatement(); + ss.addStatement(cs); + ss.addStatement(astat); + ss.setBrackets(true); + + WhileStatement ws = + new WhileStatement(_ind, scope, ss); + return ws.updateForm(language, env, local); + } + else if ("->including".equals(operator) && Type.isSetType(type)) + { // left->intersection(var)->union(var - { right }) + BinaryExpression subfg = new BinaryExpression("->intersection", left, var ); + SetExpression se = new SetExpression(); + se.addElement(right); + BinaryExpression mins = new BinaryExpression("-", var, se); + BinaryExpression uniexp = new BinaryExpression("->union", subfg, mins); + BinaryExpression assign = new BinaryExpression("=", left, uniexp); + return assign.updateForm(language,env,local); + } + else if ("->union".equals(operator) && Type.isSetType(type)) + { // left->intersection(var)->union(var - right) + BinaryExpression subfg = new BinaryExpression("->intersection", left, var ); + BinaryExpression mins = new BinaryExpression("-", var, right); + BinaryExpression uniexp = new BinaryExpression("->union", subfg, mins); + BinaryExpression assign = new BinaryExpression("=", left, uniexp); + return assign.updateForm(language,env,local); + } + else if ("->excluding".equals(operator)) + { // left->intersection(var->including(right))->union(var) + BinaryExpression var1 = new BinaryExpression("->including", var, right ); + + BinaryExpression subfg = new BinaryExpression("->intersection", left, var1 ); + BinaryExpression uniong = new BinaryExpression("->union", subfg, var); + BinaryExpression assign = new BinaryExpression("=", left, uniong); + return assign.updateForm(language,env,local); + } + else if ("-".equals(operator) && Type.isCollectionType(type)) + { // left->intersection(var->union(right))->union(var) + BinaryExpression var1 = new BinaryExpression("->union", var, right ); + + BinaryExpression subfg = new BinaryExpression("->intersection", left, var1 ); + BinaryExpression uniong = new BinaryExpression("->union", subfg, var); + BinaryExpression assign = new BinaryExpression("=", left, uniong); + return assign.updateForm(language,env,local); + } + else if ("->intersection".equals(operator) || "/\\".equals(operator)) + { // (left - (right - var))->union(var) + BinaryExpression var1 = new BinaryExpression("-", right, var); + var1.setBrackets(true); + BinaryExpression subfg = new BinaryExpression("-", left, var1 ); + subfg.setBrackets(true); + BinaryExpression uniong = new BinaryExpression("->union", subfg, var); + BinaryExpression assign = new BinaryExpression("=", left, uniong); + return assign.updateForm(language,env,local); + } + else if ("->append".equals(operator) || + ("->including".equals(operator) && Type.isSequenceType(type))) + { // left := val->front() + UnaryExpression frg = new UnaryExpression("->front", var ); + BinaryExpression assign = new BinaryExpression("=", left, frg); + return assign.updateForm(language,env,local); + } + else if ("->prepend".equals(operator)) + { // left := val->tail() + UnaryExpression frg = new UnaryExpression("->tail", var ); + BinaryExpression assign = new BinaryExpression("=", left, frg); + return assign.updateForm(language,env,local); + } + else if ("^".equals(operator) || + "->concatenate".equals(operator) || + ("->union".equals(operator) && Type.isSequenceType(type))) + { // left := var.subrange(1, var.size - right.size) + UnaryExpression vsize = new UnaryExpression("->size", var ); + UnaryExpression gsize = new UnaryExpression("->size", right ); + BinaryExpression sdiff = new BinaryExpression("-", vsize, gsize); + BasicExpression subrg = new BasicExpression("subrange",0); + subrg.setObjectRef(var); + subrg.addParameter(new BasicExpression(1)); + subrg.addParameter(sdiff); + + BinaryExpression assign = new BinaryExpression("=", left, subrg); + return assign.updateForm(language,env,local); + } + else if ("->pow".equals(operator)) + { BinaryExpression dv = new BinaryExpression("/", new BasicExpression(1.0), right); + BinaryExpression newpow = new BinaryExpression("->pow", var, dv); + BinaryExpression assign = new BinaryExpression("=", left, newpow); + return assign.updateForm(language, env, local); + } + else if ("+".equals(operator) && Type.isNumericType(type)) + { // left = val - right if left is assignable + if (left.isAssignable()) + { BinaryExpression newright = new BinaryExpression("-", var, right); + BinaryExpression assign = new BinaryExpression("=", left, newright); + return assign.updateForm(language, env, local); + } + else if (right.isAssignable()) + { BinaryExpression newright = new BinaryExpression("-", var, left); + BinaryExpression assign = new BinaryExpression("=", right, newright); + return assign.updateForm(language, env, local); + } + } + else if ("+".equals(operator) && Type.isStringType(type)) + { // left = val.subrange(1,left.size); + // right = val.subrange(left.size+1); + + UnaryExpression varsize = new UnaryExpression("->size",var); + UnaryExpression leftsize = new UnaryExpression("->size",left); + + // Expression test = + // new BinaryExpression(">",varsize,leftsize); + + Vector spars1 = new Vector(); + spars1.add(new BasicExpression(1)); + spars1.add(leftsize); + + Vector spars2 = new Vector(); + spars2.add(new BinaryExpression("+", leftsize, + new BasicExpression(1))); + spars2.add(varsize); + + if (left.isAssignable() && right.isAssignable()) + { Expression newright1 = + BasicExpression.newFunctionBasicExpression( + "subrange",var,spars1); + BinaryExpression assign1 = new BinaryExpression("=", left, newright1); + Expression newright2 = + BasicExpression.newFunctionBasicExpression( + "subrange",var,spars2); + BinaryExpression assign2 = new BinaryExpression("=", right, newright2); + String astat1 = assign1.updateForm(language, env, local); + String astat2 = assign2.updateForm(language, env, local); + return astat1 + " " + astat2; + } + } + else if ("-".equals(operator) && Type.isNumericType(type)) + { // left = val + right if left is assignable + if (left.isAssignable()) + { BinaryExpression newright = new BinaryExpression("+", var, right); + BinaryExpression assign = new BinaryExpression("=", left, newright); + return assign.updateForm(language, env, local); + } + else if (right.isAssignable()) + { BinaryExpression newright = new BinaryExpression("-", left, var); + BinaryExpression assign = new BinaryExpression("=", right, newright); + return assign.updateForm(language, env, local); + } + } + else if ("*".equals(operator) && Type.isNumericType(type)) + { // left = val / right + if (left.isAssignable()) + { BinaryExpression newright = new BinaryExpression("/", var, right); + BinaryExpression assign = new BinaryExpression("=", left, newright); + return assign.updateForm(language, env, local); + } + else if (right.isAssignable()) + { BinaryExpression newright = new BinaryExpression("/", var, left); + BinaryExpression assign = new BinaryExpression("=", right, newright); + return assign.updateForm(language, env, local); + } + } + else if ("/".equals(operator) && Type.isNumericType(type)) + { // left = val * right + if (left.isAssignable()) + { BinaryExpression newright = new BinaryExpression("*", var, right); + BinaryExpression assign = new BinaryExpression("=", left, newright); + return assign.updateForm(language, env, local); + } + else if (right.isAssignable()) + { BinaryExpression newright = new BinaryExpression("/", left, var); + BinaryExpression assign = new BinaryExpression("=", right, newright); + return assign.updateForm(language, env, local); + } + + } + + return "/* No update form for: " + this + " = " + var + " */\n"; + } + + public String updateFormJava6(java.util.Map env, boolean local) + { String val2; + + if (operator.equals("#") || operator.equals("#1")) + { return updateFormExistsJava6(env,local); } + // For #1 test qf first: if (qf) { } else { uf } + // Special case of ( x : E ) #1 ( x.id = v & P ) Should also check P before doing it + + if (operator.equals("#LC")) + { return updateFormExistsLCJava6(env,local); } + + if (operator.equals("!")) // Only version with variable is ok + { BinaryExpression beleft = (BinaryExpression) left; + String lqf1 = beleft.right.queryFormJava6(env,local); + if (beleft.right.umlkind == CLASSID) + { lqf1 = ((BasicExpression) beleft.right).classExtentQueryFormJava6(env,local); } + String eleftname = ""; + String evarname = beleft.left + ""; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + String tname = ""; + Type eleft = beleft.right.getElementType(); // Must be an entity type + if (eleft == null || "null".equals(eleft + "")) + { eleftname = "Object"; tname = "Object"; } + else + { eleftname = eleft.getName(); + // System.out.println(">>>>>" + eleftname); + tname = eleftname; + + if ("int".equals(eleftname)) + { eleftname = "Integer"; tname = "int"; } + else if (eleftname.startsWith("Set")) + { eleftname = "HashSet"; } + else if (eleftname.startsWith("Sequence")) + { eleftname = "ArrayList"; } + else if ("long".equals(eleftname)) + { eleftname = "Long"; + tname = "long"; + } + else if ("double".equals(eleftname)) + { eleftname = "Double"; + tname = "double"; + } + else if ("boolean".equals(eleftname)) + { eleftname = "Boolean"; + tname = "boolean"; + } + else if (eleft != null && eleft.isEntity()) + { newenv.put(eleftname,evarname); } + } + + String ufr1 = right.updateFormJava6(newenv,false); + + String elist = Identifier.nextIdentifier("_" + tname.toLowerCase() + "_list"); + String indvar = Identifier.nextIdentifier("_ind"); + + if ("Integer".equals(eleftname)) + { return + " ArrayList " + elist + " = new ArrayList();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { int " + evarname + " = ((" + eleftname + ") " + elist + + ".get(" + indvar + ")).intValue();\n" + + " " + ufr1 + "\n" + + " }\n"; + } + else if (eleft != null && Type.isPrimitiveType(eleft)) + { return " ArrayList " + elist + " = new ArrayList();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { " + tname + " " + evarname + + " = ((" + eleftname + ") " + elist + + ".get(" + indvar + "))." + tname + "Value();\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + String ltypename = "HashSet"; + if (left.isOrdered()) + { ltypename = "ArrayList"; } + + return + " Collection " + elist + " = new " + ltypename + "();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (Object " + indvar + " : " + elist + ")\n" + + " { " + eleftname + " " + evarname + " = (" + eleftname + ") " + indvar + ";\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + + // Analyse if-then-else structure + if (operator.equals("&")) + { String ufl = left.updateFormJava6(env,local); + String ufr = right.updateFormJava6(env,local); + return ufl + "\n " + ufr; + } + + if (operator.equals("=>")) + { String ufl = left.queryFormJava6(env,local); + String ufr = right.updateFormJava6(env,local); + if ("true".equals(ufl)) + { return ufr; } + return " if (" + ufl + ") \n" + + " { " + ufr + "}"; + } // accumulate the cases + + if (operator.equals("let")) + { // { var acc : T := e; ... E ... } + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getJava6(); + String val = left.queryFormJava6(env,local); + java.util.Map env1 = new java.util.HashMap(); + env1.putAll(env); + String stats = right.updateFormJava6(env1,local); + return "\n { final " + lett + " " + acc + " = " + val + ";\n" + stats + "\n }"; + } + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opjava = Expression.getOperatorJava(op); + String lqf = left.queryFormJava6(env,local); + String rqf = right.queryFormJava6(env,local); + + if (opjava != null && opjava.length() > 0) + { return opjava.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + + if (operator.equals("=") && left instanceof BasicExpression) + { val2 = right.queryFormJava6(env,local); + return ((BasicExpression) left).updateFormEqJava6(env,val2,right,local); + } + else if (operator.equals("=") && left instanceof UnaryExpression) + { val2 = right.queryFormJava6(env,local); + return ((UnaryExpression) left).updateFormEq("Java6", env, ((UnaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof BinaryExpression) + { val2 = right.queryFormJava6(env,local); + return ((BinaryExpression) left).updateFormEq("Java6", env, ((BinaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof SetExpression) + { val2 = right.queryFormJava6(env,local); + return ((SetExpression) left).updateForm("Java6",env,operator,val2,right,local); + } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { val2 = right.queryFormJava6(env,local); + return ((BasicExpression) left).updateFormJava6(env,"<:",val2,right,local); + } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { val2 = right.queryFormJava6(env,local); + return ((BasicExpression) left).updateFormJava6(env,"-",val2,right,local); + } + else if ((operator.equals(":") || + operator.equals("<:") || operator.equals("/<:") || + operator.equals("/:")) && (right instanceof BasicExpression)) + { String val1 = left.queryFormJava6(env,local); + BasicExpression ber = (BasicExpression) right; + if (left.isPrimitive()) + { val1 = left.wrapJava6(val1); } + return ber.updateFormJava6(env,operator,val1,left,local); + } + else if ((operator.equals("->includes") || + operator.equals("->excludes")) && (left instanceof BasicExpression)) + { String val3 = right.queryFormJava6(env,local); + BasicExpression bel = (BasicExpression) left; + + if (right.isPrimitive()) + { val3 = right.wrapJava6(val3); } + if (operator.equals("->includes")) + { return bel.updateFormJava6(env,":",val3,right,local); } + else + { return bel.updateFormJava6(env,"/:",val3,right,local); } + } + else + { String qf = queryFormJava6(env,local); + return "if (" + qf + ") { } else { System.err.println(\"Assertion " + qf + " fails:\"); System.err.println(this); }\n"; + } + + // else + // { return "{} /* Cannot produce update code for: " + this + " */"; } + } + + public String updateFormJava7(java.util.Map env, boolean local) + { String val2; + + // System.out.println("UPDATE FORM JAVA7 of " + this); + + if (operator.equals("#") || operator.equals("#1")) + { return updateFormExistsJava7(env,local); } + // For #1 test qf first: if (qf) { } else { uf } + // Special case of ( x : E ) #1 ( x.id = v & P ) Should also check P before doing it + + if (operator.equals("#LC")) + { return updateFormExistsLCJava7(env,local); } + + if (operator.equals("!")) // Only version with variable is ok + { BinaryExpression beleft = (BinaryExpression) left; + String lqf1 = beleft.right.queryFormJava7(env,local); + if (beleft.right.umlkind == CLASSID) + { lqf1 = ((BasicExpression) beleft.right).classExtentQueryFormJava7(env,local); } + String eleftname = ""; + String evarname = beleft.left + ""; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + String tname = ""; + Type tleft = beleft.right.getType(); + Type eleft = beleft.right.getElementType(); // Must be an entity type + if (eleft == null || "null".equals(eleft + "")) + { eleftname = "Object"; tname = "Object"; + System.out.println("ERROR: null element type for quantifier: " + this); + } + else + { eleftname = eleft.getName(); + // System.out.println(">>>>>" + eleftname); + tname = eleftname; + + if ("int".equals(eleftname)) + { eleftname = "Integer"; tname = "int"; } + else if (eleftname.startsWith("Set")) + { eleftname = eleft.getJava7(eleft.getElementType()); } + else if (eleftname.startsWith("Sequence")) + { eleftname = eleft.getJava7(eleft.getElementType()); } + else if ("long".equals(eleftname)) + { eleftname = "Long"; + tname = "long"; + } + else if ("double".equals(eleftname)) + { eleftname = "Double"; + tname = "double"; + } + else if ("boolean".equals(eleftname)) + { eleftname = "Boolean"; + tname = "boolean"; + } + else if (eleft != null && eleft.isEntity()) + { newenv.put(eleftname,evarname); } + } // not needed + + String ufr1 = right.updateFormJava7(newenv,false); + + String elist = Identifier.nextIdentifier("_" + tname.toLowerCase() + "_list"); + String indvar = Identifier.nextIdentifier("_ind"); + + if ("Integer".equals(eleftname)) + { return + " ArrayList " + elist + " = new ArrayList();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { int " + evarname + " = ((Integer) " + elist + + ".get(" + indvar + ")).intValue();\n" + + " " + ufr1 + "\n" + + " }\n"; + } + else if (eleft != null && Type.isPrimitiveType(eleft)) + { return " ArrayList<" + eleftname + "> " + elist + " = new ArrayList<" + eleftname + ">();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".size(); " + indvar + "++)\n" + + " { " + tname + " " + evarname + + " = ((" + eleftname + ") " + elist + + ".get(" + indvar + "))." + tname + "Value();\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + String ltypename = tleft.getJava7(eleft); + // if (left.isOrdered()) + // { ltypename = "ArrayList"; } + // else if (left.isSorted()) + // { ltypename = "TreeSet"; } + // define the program type for sorted sets in Type. + + return + " " + ltypename + " " + elist + " = new " + ltypename + "();\n" + + " " + elist + ".addAll(" + lqf1 + ");\n" + + " for (" + eleftname + " " + evarname + " : " + elist + ")\n" + + " { " + ufr1 + "\n" + + " }\n"; + } + + + // Analyse if-then-else structure + if (operator.equals("&")) + { String ufl = left.updateFormJava7(env,local); + String ufr = right.updateFormJava7(env,local); + return ufl + "\n " + ufr; + } + + if (operator.equals("=>")) + { String ufl = left.queryFormJava7(env,local); + String ufr = right.updateFormJava7(env,local); + if ("true".equals(ufl)) + { return ufr; } + return " if (" + ufl + ") \n" + + " { " + ufr + "}"; + } // accumulate the cases + + if (operator.equals("let")) + { // { var acc : T := e; ... E ... } + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getJava7(); + String val = left.queryFormJava7(env,local); + java.util.Map env1 = new java.util.HashMap(); + env1.putAll(env); + String stats = right.updateFormJava7(env1,local); + return "\n { final " + lett + " " + acc + " = " + val + ";\n" + stats + "\n }"; + } + + if (extensionoperators.containsKey(operator)) + { String op = operator; + String opjava = Expression.getOperatorJava(op); + String lqf = left.queryFormJava7(env,local); + String rqf = right.queryFormJava7(env,local); + + if (opjava != null && opjava.length() > 0) + { return opjava.replaceAll("_1",lqf).replaceAll("_2",rqf); } + if (operator.startsWith("->")) + { op = operator.substring(2,operator.length()); } + return lqf + "." + op + "(" + rqf + ")"; + } + + + if (operator.equals("=") && left instanceof BasicExpression) + { val2 = right.queryFormJava7(env,local); + // System.out.println("QUERY FORM JAVA7: " + val2); + return ((BasicExpression) left).updateFormEqJava7(env,val2,right,local); + } + else if (operator.equals("=") && left instanceof UnaryExpression) + { val2 = right.queryFormJava7(env,local); + return ((UnaryExpression) left).updateFormEq("Java7", env, ((UnaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof BinaryExpression) + { val2 = right.queryFormJava7(env,local); + return ((BinaryExpression) left).updateFormEq("Java7", env, ((BinaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof SetExpression) + { val2 = right.queryFormJava7(env,local); + return ((SetExpression) left).updateForm("Java7",env,operator,val2,right,local); + } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { val2 = right.queryFormJava7(env,local); + return ((BasicExpression) left).updateFormJava7(env,"<:",val2,right,local); + } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { val2 = right.queryFormJava7(env,local); + return ((BasicExpression) left).updateFormJava7(env,"-",val2,right,local); + } + else if ((operator.equals(":") || + operator.equals("<:") || operator.equals("/<:") || + operator.equals("/:")) && (right instanceof BasicExpression)) + { String val1 = left.queryFormJava7(env,local); + BasicExpression ber = (BasicExpression) right; + if (left.isPrimitive()) + { val1 = left.wrap(val1); } + return ber.updateFormJava7(env,operator,val1,left,local); + } + else if ((operator.equals("->includes") || + operator.equals("->excludes")) && (left instanceof BasicExpression)) + { String val3 = right.queryFormJava7(env,local); + BasicExpression bel = (BasicExpression) left; + + if (right.isPrimitive()) + { val3 = right.wrap(val3); } + if (operator.equals("->includes")) + { return bel.updateFormJava7(env,":",val3,right,local); } + else + { return bel.updateFormJava7(env,"/:",val3,right,local); } + } + else + { String qf = queryFormJava7(env,local); + return "if (" + qf + ") { } else { System.err.println(\"Assertion " + qf + " fails: \"); System.err.println(this); }\n"; + } + + // else + // { return "{} /* Cannot produce update code for: " + this + " */"; } + } + + public String updateFormCSharp(java.util.Map env, boolean local) + { String val2; + if (operator.equals("#") || operator.equals("#1")) + { return updateFormExistsCSharp(env,local); } + // For #1 test qf first: if (qf) { } else { uf } + // Special case of ( x : E ) #1 ( x.id = v & P ) Should also check P before doing it + + if (operator.equals("#LC")) + { return updateFormExistsLCCSharp(env,local); } + + if (operator.equals("!")) // Only version with variable is ok + { BinaryExpression beleft = (BinaryExpression) left; + String lqf1 = beleft.right.queryFormCSharp(env,local); + if (beleft.right.umlkind == CLASSID) + { lqf1 = ((BasicExpression) beleft.right).classExtentQueryFormCSharp(env,local); } + String eleftname = ""; + String evarname = beleft.left + ""; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + String tname = ""; + Type eleft = beleft.right.getElementType(); // Must be an entity type + if (eleft == null || "null".equals(eleft + "")) + { eleftname = "object"; tname = "object"; } + else + { eleftname = eleft.getName(); + // System.out.println(">>>>>" + eleftname); + tname = eleftname; + + if (eleftname.startsWith("Set") || eleftname.startsWith("Sequence")) + { eleftname = "ArrayList"; + tname = "ArrayList"; + } + else if ("int".equals(eleftname)) + { eleftname = "Integer"; tname = "int"; } + else if ("long".equals(eleftname)) + { eleftname = "Long"; + tname = "long"; + } + else if ("double".equals(eleftname)) + { eleftname = "Double"; + tname = "double"; + } + else if ("boolean".equals(eleftname)) + { eleftname = "Boolean"; + tname = "bool"; + } + else if ("String".equals(eleftname)) + { tname = "string"; + eleftname = "string"; + } + else if (eleft != null && eleft.isEntity()) + { newenv.put(eleftname,evarname); } + } // not necessary + + String ufr1 = right.updateFormCSharp(newenv,false); + + String elist = Identifier.nextIdentifier("_" + tname.toLowerCase() + "_list"); + String indvar = Identifier.nextIdentifier("_ind"); + + if ("Integer".equals(eleftname)) + { return + " ArrayList " + elist + " = new ArrayList();\n" + + " " + elist + ".AddRange(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".Count; " + indvar + "++)\n" + + " { int " + evarname + " = (int) " + elist + "[" + indvar + "];\n" + + " " + ufr1 + "\n" + + " }\n"; + } + else if (eleft != null && Type.isBasicType(eleft)) + { return " ArrayList " + elist + " = new ArrayList();\n" + + " " + elist + ".AddRange(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".Count; " + indvar + "++)\n" + + " { " + tname + " " + evarname + + " = ((" + tname + ") " + elist + "[" + indvar + "]);\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + return + " ArrayList " + elist + " = new ArrayList();\n" + + " " + elist + ".AddRange(" + lqf1 + ");\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + ".Count; " + indvar + "++)\n" + + " { " + eleftname + " " + evarname + " = (" + eleftname + ") " + elist + + "[" + indvar + "];\n" + + " " + ufr1 + "\n" + + " }\n"; + } + + + // Analyse if-then-else structure + if (operator.equals("&")) + { String ufl = left.updateFormCSharp(env,local); + String ufr = right.updateFormCSharp(env,local); + return ufl + "\n " + ufr; + } + + if (operator.equals("=>")) + { String ufl = left.queryFormCSharp(env,local); + String ufr = right.updateFormCSharp(env,local); + if ("true".equals(ufl)) + { return ufr; } + return " if (" + ufl + ") \n" + + " { " + ufr + "}"; + } // accumulate the cases + + if (operator.equals("let")) + { // { var acc : T := e; ... E ... } + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + String lett = acct.getCSharp(); + String val = left.queryFormCSharp(env,local); + java.util.Map env1 = new java.util.HashMap(); + env1.putAll(env); + String stats = right.updateFormCSharp(env1,local); + return "\n { const " + lett + " " + acc + " = " + val + ";\n" + stats + "\n }"; + } + + if (operator.equals("=") && left instanceof BasicExpression) + { val2 = right.queryFormCSharp(env,local); + return ((BasicExpression) left).updateFormEqCSharp(env,val2,right,local); + } + else if (operator.equals("=") && left instanceof UnaryExpression) + { val2 = right.queryFormCSharp(env,local); + return ((UnaryExpression) left).updateFormEq("CSharp", env, ((UnaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof BinaryExpression) + { val2 = right.queryFormCSharp(env,local); + return ((BinaryExpression) left).updateFormEq("CSharp", env, ((BinaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof SetExpression) + { val2 = right.queryFormCSharp(env,local); + return ((SetExpression) left).updateForm("CSharp",env,operator,val2,right,local); + } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { val2 = right.queryFormCSharp(env,local); + return ((BasicExpression) left).updateFormCSharp(env,"<:",val2,right,local); + } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { val2 = right.queryFormCSharp(env,local); + return ((BasicExpression) left).updateFormCSharp(env,"-",val2,right,local); + } + else if ((operator.equals(":") || + operator.equals("<:") || operator.equals("/<:") || + operator.equals("/:")) && (right instanceof BasicExpression)) + { String val1 = left.queryFormCSharp(env,local); + BasicExpression ber = (BasicExpression) right; + // if (left.isPrimitive()) + // { val1 = ((BasicExpression) left).wrap(val1); } + return ber.updateFormCSharp(env,operator,val1,left,local); + } + else if ((operator.equals("->includes") || operator.equals("->excludes")) && + (left instanceof BasicExpression)) + { String val3 = right.queryFormCSharp(env,local); + BasicExpression bel = (BasicExpression) left; + + // if (right.isPrimitive()) + // { val3 = ((BasicExpression) right).wrap(val3); } + if (operator.equals("->includes")) + { return bel.updateFormCSharp(env,":",val3,right,local); } + else + { return bel.updateFormCSharp(env,"/:",val3,right,local); } + } + else + { return "{} /* Cannot produce update code for: " + this + " */"; } + } + + public String updateFormCPP(java.util.Map env, boolean local) + { String val2; + if (operator.equals("#") || operator.equals("#1")) + { return updateFormExistsCPP(env,local); } + // For #1 test qf first: if (qf) { } else { uf } + // Special case of ( x : E ) #1 ( x.id = v & P ) Should also check P before doing it + + if (operator.equals("#LC")) + { return updateFormExistsLCCPP(env,local); } + + if (operator.equals("!")) // Only version with variable is ok + { BinaryExpression beleft = (BinaryExpression) left; + String lqf1 = beleft.right.queryFormCPP(env,local); + if (beleft.right.umlkind == CLASSID) + { lqf1 = ((BasicExpression) beleft.right).classExtentQueryFormCPP(env,local); } + String eleftname = ""; + String evarname = beleft.left + ""; + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + Type eleft = beleft.right.getElementType(); + String tname = ""; + + if (eleft == null || "null".equals(eleft + "")) + { eleftname = "void*"; tname = "void"; } + else + { eleftname = eleft.getName(); + Type eelemt = eleft.getElementType(); + tname = eleftname; + + if ("int".equals(eleftname)) + { eleftname = "Integer"; tname = "int"; } + else if (eleftname.startsWith("Set")) + { eleftname = eleft.getCPP(eelemt); + tname = "List"; + } + else if (eleftname.startsWith("Sequence")) + { eleftname = eleft.getCPP(eelemt); + tname = "List"; + } + else if ("String".equals(eleftname)) + { tname = "string"; + eleftname = "string"; + } + else if ("boolean".equals(eleftname)) + { tname = "bool"; } + else if (eleft != null && eleft.isEntity()) + { eleftname = eleftname + "*"; + newenv.put(eleftname,evarname); + } + } // not necessary + + String ufr1 = right.updateFormCPP(newenv,false); + + String elist = Identifier.nextIdentifier("_" + tname.toLowerCase() + "_list"); + String indvar = Identifier.nextIdentifier("_ind"); + + if ("Integer".equals(eleftname)) + { return " vector* " + elist + " = " + lqf1 + ";\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + "->size(); " + indvar + "++)\n" + + " { int " + evarname + " = (*" + elist + ")[" + indvar + "];\n" + + " " + ufr1 + "\n" + + " }\n"; + } + else if (eleft != null && Type.isBasicType(eleft)) + { return " vector<" + tname + ">* " + elist + " = " + lqf1 + ";\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + "->size(); " + indvar + "++)\n" + + " { " + tname + " " + evarname + " = (*" + elist + ")[" + indvar + "];\n" + + " " + ufr1 + "\n" + + " }\n"; + } + return + " vector<" + eleftname + ">* " + elist + " = new vector<" + eleftname + ">();\n" + + " " + elist + "->insert(" + elist + "->end(), " + lqf1 + "->begin(), " + + lqf1 + "->end());\n" + + " for (int " + indvar + " = 0; " + indvar + " < " + elist + "->size(); " + indvar + "++)\n" + + " { " + eleftname + " " + evarname + " = (*" + elist + ")[" + indvar + "];\n" + + " " + ufr1 + "\n" + + " }\n" + + " delete " + elist + ";\n"; + } // could copy and delete in the other cases also. + + + // Analyse if-then-else structure + if (operator.equals("&")) + { String ufl = left.updateFormCPP(env,local); + String ufr = right.updateFormCPP(env,local); + return ufl + "\n " + ufr; + } + + if (operator.equals("=>")) + { String ufl = left.queryFormCPP(env,local); + String ufr = right.updateFormCPP(env,local); + if ("true".equals(ufl)) + { return ufr; } + return " if (" + ufl + ") \n" + + " { " + ufr + "}"; + } // accumulate the cases + + if (operator.equals("let")) + { // { var acc : T := e; ... E ... } + String acc = accumulator.getName(); + Type acct = accumulator.getType(); + if (acct == null) + { acct = left.getType(); } + Type lcet = accumulator.getElementType(); + if (lcet == null) + { lcet = left.getElementType(); } + String lett = acct.getCPP(lcet); + String val = left.queryFormCPP(env,local); + java.util.Map env1 = new java.util.HashMap(); + env1.putAll(env); + String stats = right.updateFormCPP(env1,local); + return "\n { const " + lett + " " + acc + " = " + val + ";\n" + stats + "\n }"; + } + + if (operator.equals("=") && left instanceof BasicExpression) + { val2 = right.queryFormCPP(env,local); + return ((BasicExpression) left).updateFormEqCPP(env,val2,local); + } + else if (operator.equals("=") && left instanceof UnaryExpression) + { val2 = right.queryFormCPP(env,local); + return ((UnaryExpression) left).updateFormEq("CPP",env,((UnaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof BinaryExpression) + { val2 = right.queryFormCPP(env,local); + return ((BinaryExpression) left).updateFormEq("CPP", env, ((BinaryExpression) left).operator,val2,right,local); + // return left.updateForm("CPP",env,((BinaryExpression) left).operator,val2,right,local); + } + else if (operator.equals("=") && left instanceof SetExpression) + { val2 = right.queryFormCPP(env,local); + return ((SetExpression) left).updateForm("CPP",env,operator,val2,right,local); + } + else if (operator.equals("->includesAll") && left instanceof BasicExpression) + { val2 = right.queryFormCPP(env,local); + return ((BasicExpression) left).updateFormCPP(env,"<:",val2,right,local); + } + else if (operator.equals("->excludesAll") && left instanceof BasicExpression) + { val2 = right.queryFormCPP(env,local); + return ((BasicExpression) left).updateFormCPP(env,"-",val2,right,local); + } + else if ((operator.equals(":") || + operator.equals("<:") || operator.equals("/<:") || + operator.equals("/:")) && (right instanceof BasicExpression)) + { String val1 = left.queryFormCPP(env,local); + BasicExpression ber = (BasicExpression) right; + /* boolean lmult = left.isMultiple(); + if (lmult) + { if (operator.equals(":") || operator.equals("<:")) + { return ber.updateFormCPP(env,"<:",val1,left,local); } + if (operator.equals("/:") || operator.equals("/<:")) + { return ber.updateFormCPP(env,"-",val1,left,local); } + } */ + // if (left.isPrimitive()) + // { val1 = ((BasicExpression) left).wrap(val1); } + return ber.updateFormCPP(env,operator,val1,left,local); + } + else if ((operator.equals("->includes") || operator.equals("->excludes")) && + (left instanceof BasicExpression)) + { String val3 = right.queryFormCPP(env,local); + BasicExpression bel = (BasicExpression) left; + /* boolean rmult = right.isMultiple(); + if (rmult) + { if (operator.equals("->includes")) + { return bel.updateFormCPP(env,"<:",val3,right,local); } + if (operator.equals("->excludes")) + { return bel.updateFormCPP(env,"-",val3,right,local); } + } */ + + // if (right.isPrimitive()) + // { val3 = ((BasicExpression) right).wrap(val3); } + if (operator.equals("->includes")) + { return bel.updateFormCPP(env,":",val3,right,local); } + else + { return bel.updateFormCPP(env,"/:",val3,right,local); } + } + else + { return "{} /* disallowed operator: " + + operator + " */"; + } + } + + public Statement generateDesignExists(java.util.Map env, boolean local) + { + // Statement ufl = left.generateDesign(env,local); + BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + Expression ltype = lexp.right; + String lqf = ltype.queryForm(env,local); + + + Statement ufr = right.generateDesign(env,local); + // Check completeness: + Vector wr = right.writeFrame(); + System.out.println(">>> Object creation for " + lvar + " sets features " + wr); + Type t = lvar.getType(); + if (t != null) + { Entity e = t.getEntity(); + if (e != null) + { Vector feats = e.allDefinedFeatures(); + if (feats.containsAll(wr)) + { if (wr.containsAll(feats)) + { System.out.println(">>> Creation is complete"); } + else + { System.out.println("??? Creation may be incomplete: not all of " + feats + + " are set"); + } + System.out.println(); + } + else + { System.out.println("!!! Some features set are not in entity features " + + feats); + System.out.println(); + } + } + } + + if (ltype.elementType == null || !ltype.elementType.isEntity()) + { System.err.println("!!! TYPE ERROR, no entity element type in exists: " + this); + JOptionPane.showMessageDialog(null, "no element type for LHS of " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return new SequenceStatement(); + } + + Entity ent = ltype.elementType.getEntity(); + + if (operator.equals("#1") || operator.equals("#")) + { Attribute pk = Expression.hasPrimaryKey(ltype); + + if (pk == null) + { // lvar : T := createT() ; where T is type of ltype + // ufr + BasicExpression invokecreent1; + if ((ltype + "").startsWith("Set(")) + { invokecreent1 = new BasicExpression("createSet"); + invokecreent1.setParameters(new Vector()); // I'm sure this is correct + invokecreent1.type = new Type("Set", null); + } + else if ((ltype + "").startsWith("Sequence(")) + { invokecreent1 = new BasicExpression("createSequence"); + invokecreent1.setParameters(new Vector()); // I'm sure this is correct + invokecreent1.type = new Type("Sequence", null); + } + else + { invokecreent1 = new BasicExpression("create" + ent); + invokecreent1.setParameters(new Vector()); // I'm sure this is correct + invokecreent1.type = new Type(ent); + } + + invokecreent1.umlkind = UPDATEOP; + // invokecreent.entity = ent; + invokecreent1.elementType = new Type(ent); + // and Controller as an objectRef + AssignStatement assgn1 = new AssignStatement(lvar, invokecreent1); + assgn1.setType(ltype.elementType); + SequenceStatement res = new SequenceStatement(); + // res.addStatement(ini); + res.addStatement(assgn1); + res.addStatement(ufr); + return res; + } + else + { // lvar : ent := createent(keyval); ufr + + Vector remainder = new Vector(); + Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) // Special case, matching on id first + { String kvqf = keyval.queryForm(env,local); + if (ltype.umlkind == CLASSID) + { // CreationStatement cre = new CreationStatement("" + ent, "" + lvar); + // cre.setType(ltype.elementType); + // cre.setElementType(ltype.elementType); + // cre.setEntity(ent); + BasicExpression invokecreent = new BasicExpression("createByPK" + ent); + invokecreent.umlkind = UPDATEOP; + // invokecreent.entity = ent; + invokecreent.type = new Type(ent); + invokecreent.elementType = new Type(ent); + invokecreent.addParameter(keyval); + // and Controller as an objectRef + AssignStatement assgn = new AssignStatement(lvar, invokecreent); + assgn.setType(ltype.elementType); + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + Statement remstat = rem.generateDesign(env,local); + + SequenceStatement res = new SequenceStatement(); + // res.addStatement(cre); + res.addStatement(assgn); res.addStatement(remstat); + return res; + } + else // just E->exists( x ! true ) + { return assgn; } + } + return new SequenceStatement(); + } + else // pkey != null but no pkey = val in the rhs. + { // CreationStatement ini = new CreationStatement("" + ent, "" + lvar); + // ini.setType(ltype.elementType); + // ini.setElementType(ltype.elementType); + // ini.setEntity(ent); + BasicExpression invokecreent2 = new BasicExpression("create" + ent); + invokecreent2.umlkind = UPDATEOP; + // invokecreent.entity = ent; + invokecreent2.type = new Type(ent); + invokecreent2.elementType = new Type(ent); + invokecreent2.setParameters(new Vector()); // I'm sure this is correct + // and Controller as an objectRef + AssignStatement assgn2 = new AssignStatement(lvar, invokecreent2); + assgn2.setType(ltype.elementType); + SequenceStatement res = new SequenceStatement(); + // res.addStatement(ini); + res.addStatement(assgn2); + res.addStatement(ufr); + return res; + } + } + } + + if (operator.equals("#1")) + { BinaryExpression test = new BinaryExpression("#", left, right); + CreationStatement ini2 = new CreationStatement("" + ent, "" + lvar); + ini2.setType(ltype.elementType); + ini2.setElementType(ltype.elementType); + ini2.setEntity(ent); + BasicExpression invokecreent3 = new BasicExpression("create" + ent); + invokecreent3.umlkind = UPDATEOP; + // invokecreent.entity = ent; + invokecreent3.setParameters(new Vector()); // I'm sure this is correct + invokecreent3.type = new Type(ent); + invokecreent3.elementType = new Type(ent); + // and Controller as an objectRef + AssignStatement assgn3 = new AssignStatement(lvar, invokecreent3); + SequenceStatement seq = new SequenceStatement(); + seq.addStatement(ini2); + seq.addStatement(assgn3); + seq.addStatement(ufr); + ConditionalStatement queryform = new ConditionalStatement(test, new SequenceStatement(), seq); + return queryform; + } // assume no primary key in this case - redundant. + + return new SequenceStatement(); + } + + public String updateFormExists(java.util.Map env, boolean local) + { String cont = "Controller.inst()"; + + String ufl = left.updateForm(env,local); + BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + Expression ltype = lexp.right; + String lqf = ltype.queryForm(env,local); + + + // java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + // newenv.put(ltype + "",lvar + ""); + String ufr = right.updateForm(env,local); + // Check completeness: + Vector wr = right.writeFrame(); + System.out.println(">>> Object creation for " + lvar + " sets features " + wr + + " in update " + ufr); + Type t = lvar.getType(); + if (t != null) + { Entity e = t.getEntity(); + if (e != null) + { Vector feats = e.allDefinedFeatures(); + if (feats.containsAll(wr)) + { if (wr.containsAll(feats)) + { System.out.println(">>> Creation is complete"); } + else + { System.out.println("??? Creation may be incomplete: not all of " + feats + + " are set"); + } + } + else + { System.out.println("!!! Some features set are not in entity features " + + feats); + } + System.out.println(); + } + } + + String res = ""; + String searchcode = ""; + + if (ltype.elementType == null || !ltype.elementType.isEntity()) + { System.err.println("!!! TYPE ERROR, no entity element type in exists: " + this); + JOptionPane.showMessageDialog(null, "no element type for LHS of " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return " /* Invalid ->exists */ {}\n"; + } + Entity ent = ltype.elementType.getEntity(); + + if (operator.equals("#1") || operator.equals("#")) + { Attribute pk = Expression.hasPrimaryKey(ltype); + if (pk != null) + { // System.out.println(); + // System.out.println("Exists with primary key " + pk); + + + Vector remainder = new Vector(); + Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) // Special case, matching on id first + { String kvqf = keyval.queryForm(env,local); + if (ltype.umlkind == CLASSID) + { searchcode = " if (" + cont + ".get" + ent + "ByPK(" + kvqf + ") != null)\n"; } + else + { searchcode = " if (" + lqf + ".contains(" + cont + ".get" + ent + "ByPK(" + kvqf + ")))\n"; } + + res = res + searchcode; + res = res + " { " + ent + " " + lvar + " = " + cont + ".get" + ent + "ByPK(" + kvqf + ");\n "; + + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + // System.out.println("REMAINDER == " + remainder); + res = res + " " + rem.updateForm(env,local) + "\n"; + } + res = res + " }\n"; + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { return res; } + + res = res + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + return res; + } + } + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { if (ltype.umlkind == CLASSID) + { lqf = ((BasicExpression) ltype).classExtentQueryForm(env,local); } + // System.err.println("Must ensure " + lqf + " nonempty!"); + return " if ((" + lqf + ").size() > 0)\n" + + " { " + ent + " " + lvar + " = (" + ent + ") (" + lqf + ").get(0);\n" + + " " + ufr + "\n" + + " }\n"; + } + + if (operator.equals("#1")) + { String queryform = existsQueryForm(env,local); // op is actually #1 here + return " if (" + queryform + ") { }\n" + + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + } + else + { return ufl + "\n " + ufr; } + } + + return res; + } + + public String updateFormExistsJava6(java.util.Map env, boolean local) + { String cont = "Controller.inst()"; + + String ufl = left.updateFormJava6(env,false); + BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + Expression ltype = lexp.right; + String lqf = ltype.queryFormJava6(env,local); + + + // java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + // newenv.put(ltype + "",lvar + ""); + String ufr = right.updateFormJava6(env,local); + // Check completeness: + Vector wr = right.writeFrame(); + System.out.println(">>> Object creation for " + lvar + " sets features " + wr); + Type t = lvar.getType(); + if (t != null) + { Entity e = t.getEntity(); + if (e != null) + { Vector feats = e.allDefinedFeatures(); + if (feats.containsAll(wr)) + { if (wr.containsAll(feats)) + { System.out.println(">> Creation is complete"); } + else + { System.out.println("! Creation may be incomplete: not all of " + feats + + " are set"); + } + } + else + { System.out.println("! Some features set are not in entity features " + + feats); + } + } + } + String res = ""; + String searchcode = ""; + if (ltype.elementType == null || !ltype.elementType.isEntity()) + { System.err.println("!! TYPE ERROR: no element type in exists: " + this); + JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return " {}\n"; + } + Entity ent = ltype.elementType.getEntity(); + + if (operator.equals("#1") || operator.equals("#")) + { Attribute pk = Expression.hasPrimaryKey(ltype); + if (pk != null) + { System.out.println(); + // System.out.println("Exists with primary key " + pk); + + + Vector remainder = new Vector(); + Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) // Special case, matching on id first + { String kvqf = keyval.queryFormJava6(env,local); + if (ltype.umlkind == CLASSID) + { searchcode = " if (" + cont + ".get" + ent + "ByPK(" + kvqf + ") != null)\n"; } + else + { searchcode = " if (" + lqf + ".contains(" + cont + ".get" + ent + "ByPK(" + kvqf + ")))\n"; } + + res = res + searchcode; + res = res + " { " + ent + " " + lvar + " = " + cont + ".get" + ent + "ByPK(" + kvqf + ");\n "; + + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + // System.out.println("REMAINDER == " + remainder); + res = res + " " + rem.updateFormJava6(env,false) + "\n"; + } + res = res + " }\n"; + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { return res; } + + res = res + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + return res; + } + } + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { if (ltype.umlkind == CLASSID) + { lqf = ((BasicExpression) ltype).classExtentQueryFormJava6(env,local); } + // System.err.println("Must ensure " + lqf + " nonempty!"); + return " if ((" + lqf + ").size() > 0)\n" + + " { " + ent + " " + lvar + " = (" + ent + ") (" + lqf + ").get(0);\n" + + " " + ufr + "\n" + + " }\n"; + } + + if (operator.equals("#1")) + { String queryform = existsQueryFormJava6(env,local); // op is actually #1 here + return " if (" + queryform + ") { }\n" + + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + } + else + { return ufl + "\n " + ufr; } + } + + return res; + } + + public String updateFormExistsJava7(java.util.Map env, boolean local) + { String cont = "Controller.inst()"; + + String ufl = left.updateFormJava7(env,local); + BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + Expression ltype = lexp.right; + String lqf = ltype.queryFormJava7(env,local); + + + // java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + // newenv.put(ltype + "",lvar + ""); + String ufr = right.updateFormJava7(env,local); + // Check completeness: + Vector wr = right.writeFrame(); + System.out.println(">>> Object creation for " + lvar + " sets features " + wr); + Type t = lvar.getType(); + if (t != null) + { Entity e = t.getEntity(); + if (e != null) + { Vector feats = e.allDefinedFeatures(); + if (feats.containsAll(wr)) + { if (wr.containsAll(feats)) + { System.out.println(">>> Creation is complete"); } + else + { System.out.println("! Creation may be incomplete: not all of " + feats + + " are set"); + } + } + else + { System.out.println("! Some features set are not in entity features " + + feats); + } + } + } + String res = ""; + String searchcode = ""; + if (ltype.elementType == null || !ltype.elementType.isEntity()) + { System.err.println("!! TYPE ERROR: no element type in exists: " + this); + JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return " {}\n"; + } + Entity ent = ltype.elementType.getEntity(); + + if (operator.equals("#1") || operator.equals("#")) + { Attribute pk = Expression.hasPrimaryKey(ltype); + if (pk != null) + { System.out.println(); + // System.out.println("Exists with primary key " + pk); + + + Vector remainder = new Vector(); + Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) // Special case, matching on id first + { String kvqf = keyval.queryFormJava7(env,local); + if (ltype.umlkind == CLASSID) + { searchcode = " if (" + cont + ".get" + ent + "ByPK(" + kvqf + ") != null)\n"; } + else + { searchcode = " if (" + lqf + ".contains(" + cont + ".get" + ent + "ByPK(" + kvqf + ")))\n"; } + + res = res + searchcode; + res = res + " { " + ent + " " + lvar + " = " + cont + ".get" + ent + "ByPK(" + kvqf + ");\n "; + + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + // System.out.println("REMAINDER == " + remainder); + res = res + " " + rem.updateFormJava7(env,local) + "\n"; + } + res = res + " }\n"; + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { return res; } + + res = res + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + return res; + } + } + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { if (ltype.umlkind == CLASSID) + { lqf = ((BasicExpression) ltype).classExtentQueryFormJava7(env,local); } + // System.err.println("Must ensure " + lqf + " nonempty!"); + return " if ((" + lqf + ").size() > 0)\n" + + " { " + ent + " " + lvar + " = (" + ent + ") (" + lqf + ").get(0);\n" + + " " + ufr + "\n" + + " }\n"; + } + + if (operator.equals("#1")) + { String queryform = quantifierQueryFormJava7(env,local); // op is actually #1 here + return " if (" + queryform + ") { }\n" + + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + } + else + { return ufl + "\n " + ufr; } + } + + return res; + } + + public String updateFormExistsCSharp(java.util.Map env, boolean local) + { String cont = "Controller.inst()"; + + String ufl = left.updateFormCSharp(env,local); + BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + Expression ltype = lexp.right; + String lqf = ltype.queryFormCSharp(env,local); + + + // java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + // newenv.put(ltype + "",lvar + ""); + String ufr = right.updateFormCSharp(env,local); + // Check completeness: + Vector wr = right.writeFrame(); + System.out.println(">> Object creation for " + lvar + " sets features " + wr); + Type t = lvar.getType(); + if (t != null) + { Entity e = t.getEntity(); + if (e != null) + { Vector feats = e.allDefinedFeatures(); + if (feats.containsAll(wr)) + { if (wr.containsAll(feats)) + { System.out.println(">> Creation is complete"); } + else + { System.out.println("! Creation may be incomplete: not all of " + feats + + " are set"); + } + } + else + { System.out.println("! Some features set are not in entity features " + + feats); + } + } + } + String res = ""; + String searchcode = ""; + if (ltype.elementType == null || !ltype.elementType.isEntity()) + { System.err.println("!! ERROR: no element type in exists: " + this); + JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return " {}\n"; + } + Entity ent = ltype.elementType.getEntity(); + + if (operator.equals("#1") || operator.equals("#")) + { Attribute pk = Expression.hasPrimaryKey(ltype); + if (pk != null) + { System.out.println(); + // System.out.println("Exists with primary key " + pk); + + + Vector remainder = new Vector(); + Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) // Special case, matching on id first + { String kvqf = keyval.queryFormCSharp(env,local); + if (ltype.umlkind == CLASSID) + { searchcode = " if (" + cont + ".get" + ent + "ByPK(" + kvqf + ") != null)\n"; } + else + { searchcode = " if (" + lqf + ".Contains(" + cont + ".get" + ent + "ByPK(" + kvqf + ")))\n"; } + + res = res + searchcode; + res = res + " { " + ent + " " + lvar + " = " + cont + ".get" + ent + "ByPK(" + kvqf + ");\n "; + + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + // System.out.println("REMAINDER == " + remainder); + res = res + " " + rem.updateFormCSharp(env,local) + "\n"; + } + res = res + " }\n"; + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { return res; } + + res = res + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + return res; + } + } + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { if (ltype.umlkind == CLASSID) + { lqf = ((BasicExpression) ltype).classExtentQueryFormCSharp(env,local); } + // System.err.println("Must ensure " + lqf + " nonempty!"); + return " if ((" + lqf + ").Count > 0)\n" + + " { " + ent + " " + lvar + " = (" + ent + ") " + lqf + "[0];\n" + + " " + ufr + "\n" + + " }\n"; + } + + if (operator.equals("#1")) + { String queryform = existsQueryFormCSharp(env,local); // op is actually #1 here + return " if (" + queryform + ") { }\n" + + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + } + else + { return ufl + "\n " + ufr; } + } + + return res; + } + + public String updateFormExistsCPP(java.util.Map env, boolean local) + { String cont = "Controller::inst->"; + + String ufl = left.updateFormCPP(env,local); + BinaryExpression lexp = (BinaryExpression) left; + Expression lvar = lexp.left; + Expression ltype = lexp.right; + String lqf = ltype.queryFormCPP(env,local); + + + // java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + // newenv.put(ltype + "",lvar + ""); + String ufr = right.updateFormCPP(env,local); + // Check completeness: + Vector wr = right.writeFrame(); + System.out.println(">> Object creation for " + lvar + " sets features " + wr); + Type t = lvar.getType(); + if (t != null) + { Entity e = t.getEntity(); + if (e != null) + { Vector feats = e.allDefinedFeatures(); + if (feats.containsAll(wr)) + { if (wr.containsAll(feats)) + { System.out.println(">> Creation is complete"); } + else + { System.out.println("! Creation may be incomplete: not all of " + feats + + " are set"); + } + } + else + { System.out.println("! Some features set are not in entity features " + feats); } + } + } + + String res = ""; + String searchcode = ""; + if (ltype.elementType == null || !ltype.elementType.isEntity()) + { System.err.println("!! ERROR: no element type in exists: " + this); + JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + return " {}\n"; + } + + Entity ent = ltype.elementType.getEntity(); + String ename = ent.getName(); + + if (operator.equals("#1") || operator.equals("#")) + { Attribute pk = Expression.hasPrimaryKey(ltype); + if (pk != null) + { System.out.println(); + // System.out.println("Exists with primary key " + pk); + + + Vector remainder = new Vector(); + Expression keyval = right.featureSetting2("" + lvar, "" + pk, remainder); + if (keyval != null) // Special case, matching on id first + { String kvqf = keyval.queryFormCPP(env,local); + if (ltype.umlkind == CLASSID) + { searchcode = " if (" + cont + "get" + ename + "ByPK(" + kvqf + ") != 0)\n"; } + else + { searchcode = " if (UmlRsdsLib<" + ename + "*>::isIn(" + + cont + "get" + ename + "ByPK(" + kvqf + "), " + lqf + "))\n"; + } + + res = res + searchcode; + res = res + " { " + ename + "* " + lvar + " = " + cont + "get" + ename + "ByPK(" + kvqf + ");\n"; + + if (remainder.size() > 0) + { Expression rem = (Expression) remainder.get(0); + // System.out.println("REMAINDER == " + remainder); + res = res + " " + rem.updateFormCPP(env,local) + "\n"; + } + res = res + " }\n"; + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { return res; } + + res = res + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + return res; + } + } + + if ((ltype + "").equals(ent + "@pre") || ltype.umlkind != CLASSID || + (ent != null && ent.isAbstract())) + { if (ltype.umlkind == CLASSID) + { lqf = ((BasicExpression) ltype).classExtentQueryFormCPP(env,local); } + // System.err.println("Must ensure " + lqf + " nonempty!"); + return " if ((" + lqf + ")->size() > 0)\n" + + " { " + ename + "* " + lvar + " = (*" + lqf + ")[0];\n" + + " " + ufr + "\n" + + " }\n"; + } + + if (operator.equals("#1")) + { String queryform = existsQueryFormCPP(env,local); // op is actually #1 here + return " if (" + queryform + ") { }\n" + + " else\n" + + " { " + ufl + "\n " + ufr + " }\n"; + } + else + { return ufl + "\n " + ufr; } + } + + return res; + } + + public BExpression bqueryForm(java.util.Map env) + { BExpression le = left.bqueryForm(env); + BExpression les = le.simplify(); + + if (operator.equals("#") || operator.equals("#LC")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + // BExpression lll = lexp.left.bqueryForm(env); + // String t = lexp.right + ""; + // env1.put(t,lll); + BExpression rrr = right.bqueryForm(env); + BExpression res = new BQuantifierExpression("exists",x, + new BBinaryExpression("&",les,rrr)); + return res; + } + + if (operator.equals("!")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + // BExpression lll = lexp.left.bqueryForm(env); + // String t = lexp.right + ""; + // env1.put(t,lll); + BExpression rrr = right.bqueryForm(env); + BExpression res = new BQuantifierExpression("forall",x, + new BBinaryExpression("=>",les,rrr)); + return res; + } + + if (operator.equals("#1")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + BExpression rng = lexp.right.bqueryForm(env); + BExpression rrr = right.bqueryForm(env); + BExpression sel = new BSetComprehension(x,rng,rrr); + BExpression selsize = new BUnaryExpression("card",sel); + BExpression res = new BBinaryExpression("=",selsize, + new BBasicExpression("1")); + return res; + } + + + BExpression re = right.bqueryForm(env); + boolean lmult = left.isMultiple(); + boolean rmult = right.isMultiple(); + + if (operator.equals("|") || operator.equals("->select") || + operator.equals("|R") || operator.equals("->reject")) + { return selectBinvariantForm(le,re,env,true); } + + if (operator.equals("->collect") || operator.equals("->unionAll") || + operator.equals("|C") || operator.equals("->intersectAll")) + { return collectBinvariantForm(le,re,env,true); } + + if (operator.equals("->forAll") || operator.equals("->exists") || + "->existsLC".equals(operator) || operator.equals("->exists1")) + { return quantifierBinvariantForm(le,re,env,true); } + + if (operator.equals("=")) + { if (lmult && !rmult) + { BSetExpression se; + if (re instanceof BSetExpression) + { se = (BSetExpression) re; } + else + { se = new BSetExpression(); + se.addElement(re); + } + BExpression res = new BBinaryExpression("<:",le,se); + res.setBrackets(needsBracket); + return res; + } + if (!lmult && rmult) + { return new BBinaryExpression(":",le,re); } + } // and other cases, and for /= + + String op = operator; + if (operator.equals("!=") || operator.equals("<>")) + { op = "/="; } + else if (operator.equals("->union")) + { op = "\\/"; } + else if (operator.equals("->intersection")) + { op = "/\\"; } + else if (operator.equals("->oclIsKindOf") || operator.equals("->oclIsTypeOf")) + { op = ":"; } + + // System.out.println(left + " b form is " + le + " " + le.setValued()); + les = BExpression.unSet(les); + // System.out.println("simplified is: " + les); + BExpression res = re.simplify(); + + BExpression result; + if (operator.equals("->excludesAll")) + { result = new BBinaryExpression("=", + new BBinaryExpression("/\\",les,res), + new BSetExpression()); + result.setBrackets(true); + } + else if (operator.equals("->includesAll")) + { BExpression ll = les; + if (left.isOrderedB()) + { ll = new BUnaryExpression("ran",les); } + result = new BBinaryExpression("<:",res,ll); + } + else if (operator.equals("->includes")) + { BExpression ll = les; + if (left.isOrderedB()) + { ll = new BUnaryExpression("ran",les); } + result = new BBinaryExpression(":",res,ll); + } + else if (operator.equals("->excludes")) + { BExpression ll = les; + if (left.isOrderedB()) + { ll = new BUnaryExpression("ran",les); } + result = new BBinaryExpression("/:",res,ll); + } + else if (operator.equals("->including")) + { BSetExpression bset = new BSetExpression(); + bset.addElement(res); + result = new BBinaryExpression("\\/",les,bset); + result.setBrackets(true); + } // and case for ordered, but should use ->prepend, ->append in such cases + else if (operator.equals("->excluding")) + { BSetExpression bset = new BSetExpression(); + bset.addElement(res); + result = new BBinaryExpression("-",les,bset); + result.setBrackets(true); + } + else if (operator.equals("->prepend")) + { result = new BBinaryExpression("->",res,les); + result.setBrackets(true); + } + else if (operator.equals("->append")) + { result = new BBinaryExpression("<-",les,res); + result.setBrackets(true); + } + else if (operator.equals("->indexOf")) // min(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(res); + BExpression func = new BPostfixExpression("~", les); + BExpression res1 = new BApplySetExpression(func,img); + result = new BUnaryExpression("min",res1); + } + else if (operator.equals("->lastIndexOf")) // max(bel~[{ber}]) + { BSetExpression limg = new BSetExpression(); + limg.addElement(res); + BExpression func = new BPostfixExpression("~", les); + BExpression res1 = new BApplySetExpression(func,limg); + result = new BUnaryExpression("max",res1); + } + else if (operator.equals("->count")) // card(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(res); + BExpression func = new BPostfixExpression("~", les); + BExpression res1 = new BApplySetExpression(func,img); + result = new BUnaryExpression("card",res); + } + else + { result = new BBinaryExpression(op,les,res); } + + if (operator.equals("/\\") || operator.equals("\\/") || + operator.equals("->union") || operator.equals("->intersection") || + operator.equals("->excludesAll") || operator.equals("->includesAll") || + operator.equals("^") || + "->concatenate".equals(operator) || operator.equals("-")) + { if (les.setValued() || res.setValued()) + { result.setMultiplicity(ModelElement.MANY); } + result.setBrackets(needsBracket); + } + + if (objectRef != null) + { BExpression ref = objectRef.bqueryForm(env); + result.setBrackets(true); + if (result.multiplicity == ModelElement.MANY) + { return new BApplySetExpression(result,ref); } + return new BApplyExpression(result,ref); + } + return result.simplify(); + } + // isPrefix, isSuffix? + + public BExpression bqueryForm() + { BExpression le = left.bqueryForm(); + BExpression les = le.simplify(); + + if (operator.equals("#") || operator.equals("#LC")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + // BExpression lll = lexp.left.bqueryForm(env); + // String t = lexp.right + ""; + // env1.put(t,lll); + BExpression rrr = right.bqueryForm(); + BExpression res = new BQuantifierExpression("exists",x, + new BBinaryExpression("&",les,rrr)); + return res; + } + + if (operator.equals("!")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + // BExpression lll = lexp.left.bqueryForm(env); + // String t = lexp.right + ""; + // env1.put(t,lll); + BExpression rrr = right.bqueryForm(); + BExpression res = new BQuantifierExpression("forall",x, + new BBinaryExpression("=>",les,rrr)); + return res; + } + + if (operator.equals("#1")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + BExpression rng = lexp.right.bqueryForm(); + BExpression rrr = right.bqueryForm(); + BExpression sel = new BSetComprehension(x,rng,rrr); + BExpression selsize = new BUnaryExpression("card",sel); + BExpression res = new BBinaryExpression("=",selsize, + new BBasicExpression("1")); + return res; + } + + BExpression re = right.bqueryForm(); + + String op = operator; + if (operator.equals("!=") || operator.equals("<>")) + { op = "/="; } + else if (operator.equals("->union")) + { op = "\\/"; } + else if (operator.equals("->intersection")) + { op = "/\\"; } + else if (operator.equals("->oclIsKindOf") || operator.equals("->oclIsTypeOf")) + { op = ":"; } + + // System.out.println(left + " b form is " + le + " " + le.setValued()); + les = BExpression.unSet(les); + // System.out.println("simplified is: " + les); + BExpression res = re.simplify(); + + java.util.Map env0 = new java.util.HashMap(); + + if (operator.equals("|") || operator.equals("->select") || + operator.equals("|R") || operator.equals("->reject")) + { return selectBinvariantForm(le,re,env0,true); } + + if (operator.equals("->collect") || operator.equals("->unionAll") || + operator.equals("|C") || operator.equals("->intersectAll")) + { return collectBinvariantForm(le,re,env0,true); } + + if (operator.equals("->forAll") || operator.equals("->exists") || + "->existsLC".equals(operator) || operator.equals("->exists1")) + { return quantifierBinvariantForm(le,re,env0,true); } + + BExpression result; + if (operator.equals("->excludesAll")) + { result = new BBinaryExpression("=", + new BBinaryExpression("/\\",les,res), + new BSetExpression()); + result.setBrackets(true); + } + else if (operator.equals("->includesAll")) + { result = new BBinaryExpression("<:",res,les); } + else if (operator.equals("->including")) + { BSetExpression bset = new BSetExpression(); + bset.addElement(res); + result = new BBinaryExpression("\\/",les,bset); + result.setBrackets(true); + } + else if (operator.equals("->excluding")) + { BSetExpression bset = new BSetExpression(); + bset.addElement(res); + result = new BBinaryExpression("-",les,bset); + result.setBrackets(true); + } + else if (operator.equals("->includes")) + { result = new BBinaryExpression(":",res,les); } + else if (operator.equals("->excludes")) + { result = new BBinaryExpression("/:",res,les); } + else if (operator.equals("->prepend")) + { result = new BBinaryExpression("->",res,les); + result.setBrackets(true); + } + else if (operator.equals("->append")) + { result = new BBinaryExpression("<-",les,res); + result.setBrackets(true); + } + else if (operator.equals("->indexOf")) // min(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(res); + BExpression func = new BPostfixExpression("~", les); + BExpression res1 = new BApplySetExpression(func,img); + result = new BUnaryExpression("min",res1); + } + else if (operator.equals("->lastIndexOf")) // max(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(res); + BExpression func = new BPostfixExpression("~", les); + BExpression res1 = new BApplySetExpression(func,img); + result = new BUnaryExpression("max",res1); + } + else if (operator.equals("->count")) // card(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(res); + BExpression func = new BPostfixExpression("~", les); + BExpression res1 = new BApplySetExpression(func,img); + result = new BUnaryExpression("card",res); + } + else + { result = new BBinaryExpression(op,les,res); } + + if (operator.equals("/\\") || operator.equals("\\/") || + operator.equals("->union") || operator.equals("->intersection") || + operator.equals("->includesAll") || operator.equals("->excludesAll") || + operator.equals("^") || + "->concatenate".equals(operator) + || operator.equals("-")) + { if (les.setValued() || res.setValued()) + { result.setMultiplicity(ModelElement.MANY); } + result.setBrackets(needsBracket); + } + + if (objectRef != null) + { BExpression ref = objectRef.bqueryForm(); + result.setBrackets(true); + if (result.multiplicity == ModelElement.MANY) + { return new BApplySetExpression(result,ref); } + return new BApplyExpression(result,ref); + } + + return result; + } // select, reject, includes, excludes, collect, exists, forall, exists1 + + public BStatement bupdateForm(java.util.Map env, boolean local) + { BExpression val2; + String s; + if (operator.equals("#") || operator.equals("#1") || operator.equals("#LC")) + { BinaryExpression lexp = (BinaryExpression) left; + String dvar = lexp.left + ""; + Expression typ = lexp.right; + + // Only makes sense for entities typ: + if (typ.umlkind != CLASSID) { return new BBasicStatement("skip"); } + + String dvars = ("" + typ).toLowerCase() + "s"; + String tname = objectType(typ,env,local); + BExpression dexp = new BBasicExpression(dvar); + dexp.setKind(VARIABLE); + BExpression texp = new BBasicExpression(tname); + texp.setKind(VARIABLE); + BExpression objs = new BBasicExpression(dvars); + objs.setKind(VARIABLE); + + BExpression tobjs = + new BBasicExpression(tname.substring(0,tname.length()-4).toLowerCase() + "s"); + tobjs.setKind(VARIABLE); + BExpression mns = new BBinaryExpression("-",texp,tobjs); + BExpression exp = new BBinaryExpression(":",dexp,mns); + + // BExpression s1 = BExpression.unSet(s); + // String snme = s1 + ""; + // BStatement assgn = + // constructLocalBOp("set",snme,null,dexp,null); + BStatement addst = + ((BasicExpression) lexp.right).constructLocalBOp("add",dvars,null,dexp,null,null); + BParallelStatement stat = new BParallelStatement(); + stat.addStatement(addst); + // and add same for each ancestor of typ, if an entity. + stat.addStatements(ancestorAddStatements(typ,dexp)); + BStatement stat2 = right.bupdateForm(env,local); + stat.addStatement(stat2); + BStatement bodystat = stat.seq2parallel(); + // BStatement.separateUpdates(stat.getStatements()); + + Vector vars = new Vector(); + vars.add(dvar); + // + // IF #x(x:T & right) THEN skip + // ELSE ANY snmex WHERE snmex : data.toUpperCase() - + // data.toLowerCase() + "s" THEN snme(datax) := snmex || + // datas := datas \/ {snmex} END END + + BStatement res1 = new BAnyStatement(vars,exp,bodystat); + + if (operator.equals("#1")) + { BExpression test = binvariantForm(env,local); + BStatement res = new BIfStatement(test,new BBasicStatement("skip"),res1); + return res; + } + else + { return res1; } + } + + if (operator.equals("&")) + { BParallelStatement bp = new BParallelStatement(); + BStatement sl = left.bupdateForm(env,local); + BStatement sr = right.bupdateForm(env,local); + bp.addStatement(sl); + bp.addStatement(sr); + Vector rd2 = right.allFeaturesUsedIn(); // but some are only written + Vector wrf1 = sl.wr(); + Vector wrf2 = sr.wr(); + // if (inters1.size() > 0 || inters2.size() > 0) + // { sl = sl.normalise(); + // sr = sr.normalise(); + // } FROM bOpUpdateform??? + return bp.sequence2parallel(sl,sr,wrf1,wrf2,rd2); + // combine the updates + } + + if (operator.equals("or")) + { BStatement sl = left.bupdateForm(env,local); + BStatement sr = right.bupdateForm(env,local); + return new BChoiceStatement(sl,sr); + } + + if (operator.equals("=>")) + { BExpression cond = left.binvariantForm(env,local); + BStatement code = right.bupdateForm(env,local); + BExpression conds = cond.simplify(); + if (conds.equals("TRUE") || conds.equals("true")) + { return code; } + return new BIfStatement(conds,code,null); + } + + if (operator.equals("=")) + { val2 = right.binvariantForm(env,local); + // right.bqueryForm(env); // binvariantForm is sufficient + // if its a singleton set just take the single element. + boolean lmultiple = left.isMultiple(); + + BExpression val3 = val2.simplify(); + if (!lmultiple && (val3 instanceof BSetExpression)) + { BSetExpression bset = (BSetExpression) val3; + if (bset.isSingleton()) + { val3 = bset.getElement(0); } // but could be intended? + } + return ((BasicExpression) left).bEqupdateForm(env,val3,local); + } + else if (operator.equals(":") || // if rhs not basic do ANY lx WHERE lx:rhs ... + operator.equals("<:") || + operator.equals("/:") || + operator.equals("/<:")) + { // if (right instanceof BasicExpression) + val2 = left.binvariantForm(env,local); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + // BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) right).bupdateForm(env,operator,val3,local); + } // If right.isOrderedB() then : means append, etc. + else if (operator.equals("->includes")) + { // if (right instanceof BasicExpression) + val2 = right.binvariantForm(env,local); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + // BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,":",val3,local); + } + else if (operator.equals("->excludes")) + { // if (right instanceof BasicExpression) + val2 = right.binvariantForm(env,local); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + // BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,"/:",val3,local); + } + else if (operator.equals("->includesAll")) + { // if (right instanceof BasicExpression) + val2 = right.bqueryForm(env); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,"<:",val4,local); + } + else if (operator.equals("->excludesAll")) + { // if (right instanceof BasicExpression) + val2 = right.bqueryForm(env); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,"/<:",val4,local); + } + else + { return new BBasicStatement("skip"); } + } + + public BStatement bOpupdateForm(java.util.Map env, boolean local) + { BExpression val2; + String s; + if (operator.equals("#") || operator.equals("#1") || operator.equals("#LC")) + // assume (x : C) # P, where C is a class name + { BinaryExpression lexp = (BinaryExpression) left; + String dvar = lexp.left + ""; + Expression typ = lexp.right; + if (typ.umlkind != CLASSID) { return new BBasicStatement("skip"); } + + String dvars = ("" + typ).toLowerCase() + "s"; + String tname = objectType(typ,env,local); + BBasicExpression dexp = new BBasicExpression(dvar); + dexp.setKind(VARIABLE); + BBasicExpression texp = new BBasicExpression(tname); + texp.setKind(VARIABLE); + BBasicExpression objs = new BBasicExpression(dvars); + objs.setKind(VARIABLE); + BBasicExpression tobjs = + new BBasicExpression(tname.substring(0,tname.length()-4).toLowerCase() + "s"); + tobjs.setKind(VARIABLE); + BExpression mns = new BBinaryExpression("-",texp,tobjs); + // BExpression mns = new BBinaryExpression("-",texp,objs); + BExpression exp = new BBinaryExpression(":",dexp,mns); + // BExpression s1 = BExpression.unSet(s); + // String snme = s1 + ""; + // BStatement assgn = + // constructLocalBOp("set",snme,null,dexp,null); + BStatement addst = + ((BasicExpression) lexp.right).constructLocalBOp("add",dvars,null,dexp,null,null); + BParallelStatement stat = new BParallelStatement(); + stat.addStatement(addst); + stat.addStatements(ancestorAddStatements(typ,dexp)); + BStatement stat2 = right.bupdateForm(env,local); + stat.addStatement(stat2); + + BStatement bodystat = stat.seq2parallel(); + // BStatement.separateUpdates(stat.getStatements()); + + Vector vars = new Vector(); + vars.add(dvar); + // IF #x(x:T & right) THEN skip + // ELSE ANY snmex WHERE snmex : data.toUpperCase() - + // data.toLowerCase() + "s" THEN snme(datax) := snmex || + // datas := datas \/ {snmex} END END + BStatement res1 = new BAnyStatement(vars,exp,bodystat); + if (operator.equals("#1")) + { BExpression test = binvariantForm(env,local); + BStatement res = new BIfStatement(test,new BBasicStatement("skip"),res1); + return res; + } + else + { return res1; } + } + + + if (operator.equals("&")) + { BParallelStatement bp = new BParallelStatement(); + BStatement sl = left.bupdateForm(env,local); + BStatement sr = right.bupdateForm(env,local); + // BStatement bodystat = BStatement.separateUpdates(bp.getStatements()); + // return bodystat; // use separate updates + Vector rd2 = right.allFeaturesUsedIn(); // but some are only written + Vector wrf1 = sl.wr(); + Vector wrf2 = sr.wr(); + Vector inters1 = VectorUtil.intersection(wrf1,wrf2); + Vector inters2 = VectorUtil.intersection(wrf1,rd2); + if (inters1.size() > 0 || inters2.size() > 0) + { sl = sl.normalise(); + sr = sr.normalise(); + } + bp.addStatement(sl); + bp.addStatement(sr); + return bp.sequence2parallel(sl,sr,wrf1,wrf2,rd2); + } // Should this be in bupdateForm also?? + + if (operator.equals("or")) + { BStatement sl = left.bupdateForm(env,local); + BStatement sr = right.bupdateForm(env,local); + return new BChoiceStatement(sl,sr); + } + + if (operator.equals("=>")) + { BExpression cond = left.binvariantForm(env,local); + BStatement code = right.bupdateForm(env,local); + BExpression conds = cond.simplify(); + if (conds.equals("TRUE") || conds.equals("true")) + { return code; } + return new BIfStatement(conds,code,null); + } + + if (operator.equals("=")) + { val2 = right.binvariantForm(env,local); // is sufficient + // if its a singleton set just take the single element. + boolean lmultiple = left.isMultiple(); + + BExpression val3 = val2.simplify(); + if (!lmultiple && (val3 instanceof BSetExpression)) + { BSetExpression bset = (BSetExpression) val3; + if (bset.isSingleton()) + { val3 = bset.getElement(0); } // or make left a set? + } + return ((BasicExpression) left).bEqupdateForm(env,val3,local); + } + else if (operator.equals(":") || // if rhs not basic do ANY lx WHERE lx:rhs ... + operator.equals("<:") || + operator.equals("/:") || + operator.equals("/<:")) + { // if (right instanceof BasicExpression) + val2 = left.binvariantForm(env,local); // sufficient + BExpression val3 = val2.simplify(); + BExpression val4 = BExpression.unSet(val3); // Should never be needed + return ((BasicExpression) right).bupdateForm(env,operator,val4,local); + } // Special cases if right.isOrderedB() + else if (operator.equals("->includes")) + { // if (right instanceof BasicExpression) + val2 = right.binvariantForm(env,local); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + // BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,":",val3,local); + } + else if (operator.equals("->excludes")) + { // if (right instanceof BasicExpression) + val2 = right.binvariantForm(env,local); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + // BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,"/:",val3,local); + } + else if (operator.equals("->includesAll")) + { // if (right instanceof BasicExpression) + val2 = right.bqueryForm(env); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,"<:",val4,local); + } + else if (operator.equals("->excludesAll")) + { // if (right instanceof BasicExpression) + val2 = right.bqueryForm(env); // binvariantForm sufficient + BExpression val3 = val2.simplify(); + BExpression val4 = BExpression.unSet(val3); + return ((BasicExpression) left).bupdateForm(env,"/<:",val4,local); + } + else + { System.out.println("No update form for " + this); + return new BBasicStatement("skip"); + } + } + + public boolean isMultiple() + { if (operator.equals("\\/") || operator.equals("->union") || + operator.equals("->intersection") || operator.equals("->prepend") || + operator.equals("->including") || operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("/\\") || operator.equals("^") || "->concatenate".equals(operator) || operator.equals("->append") || + (operator.equals("-") && left.isMultiple())) + { return true; } + + if (operator.equals("->select") || operator.equals("->reject") || + operator.equals("->closure") || operator.equals("->sortedBy") || + operator.equals("|") || operator.equals("|R") || operator.equals("|C") || + operator.equals("->collect") || operator.equals("->selectMinimals") || + operator.equals("->selectMaximals") || operator.equals("->unionAll") || operator.equals("->concatenateAll") || + operator.equals("->intersectAll") || operator.equals("->symmetricDifference") || + operator.equals("->split") || operator.equals("->allMatches")) + { return true; } + + // And map operators: + if (operator.equals("->restrict") || operator.equals("->antirestrict")) + { return true; } + + if (operator.equals("->at") || operator.equals("->any") || operator.equals("|A")) + { return Type.isCollectionType(left.elementType); } + + if (operator.equals("let")) + { return right.isMultiple(); } + + return false; + } + + public boolean isSorted() + { if (operator.equals("->sortedBy") || + operator.equals("|sortedBy")) + { return false; } + + if (operator.equals("\\/") || operator.equals("->union")) + { return left.isSorted(); } + // Union of two sorted collections uses a merge sort + // merging. + + if (operator.equals("->intersection") || + operator.equals("->including") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("/\\") || + (operator.equals("-") && left.isMultiple()) ) + { return left.isSorted(); } + + if (operator.equals("|") || operator.equals("|R")) + { return ((BinaryExpression) left).right.isSorted(); } + + if (operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->restrict") || + operator.equals("->antirestrict")) + { return left.isSorted(); } + + if (operator.equals("let")) + { return right.isSorted(); } + + + // if (operator.equals("->at")) + // { return Type.isSequenceType(left.elementType); } + + return false; + } + + public boolean isOrdered() + { if (operator.equals("->sortedBy") || + operator.equals("->collect") || + operator.equals("|C") || + "|sortedBy".equals(operator) || + "|concatenateAll".equals(operator)) + { return true; } + + if (operator.equals("\\/") || operator.equals("->union")) + { return left.isOrdered() && right.isOrdered(); } + + if (operator.equals("->intersection") || + operator.equals("->prepend") || + operator.equals("->including") || + operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("/\\") || + operator.equals("^") || "->concatenate".equals(operator) || + operator.equals("->append") || + (operator.equals("-") && left.isMultiple())) + { return left.isOrdered(); } + + if (operator.equals("|") || + operator.equals("|R") || + "|selectMinimals".equals(operator) || + "|selectMaximals".equals(operator)) + { return ((BinaryExpression) left).right.isOrdered(); } + + if (operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->selectMinimals") || + operator.equals("->selectMaximals")) + { return left.isOrdered(); } + + if (operator.equals("->at") || operator.equals("->any")) + { return Type.isSequenceType(left.elementType); } + + if (operator.equals("|A")) + { return Type.isSequenceType(((BinaryExpression) left).right.elementType); } + + if (operator.equals("let")) + { return right.isOrdered(); } + + return false; + } + + public boolean isOrderedB() + { + if (operator.equals("->sortedBy") || + "|sortedBy".equals(operator) || + operator.equals("->collect") || + operator.equals("|C")) + { return true; } + + if (operator.equals("\\/") || operator.equals("->union")) + { return left.isOrderedB() && right.isOrderedB(); } + + if (operator.equals("->intersection") || operator.equals("->prepend") || + operator.equals("->including") || operator.equals("->excluding") || + operator.equals("->excludingAt") || + operator.equals("->excludingFirst") || + operator.equals("/\\") || operator.equals("^") || + "->concatenate".equals(operator) || + operator.equals("->append") || + (operator.equals("-") && left.isMultiple())) + { return left.isOrderedB(); } + + if (operator.equals("|") || operator.equals("|R")) + { return ((BinaryExpression) left).right.isOrderedB(); } + + if (operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->selectMinimals") || + operator.equals("->selectMaximals")) + { return left.isOrderedB(); } + + if (operator.equals("->at")) + { return Type.isSequenceType(left.elementType); } + + return false; + } + + + public BExpression binvariantForm(java.util.Map env, boolean local) + { BExpression bel = left.binvariantForm(env,local); + BExpression ber = right.binvariantForm(env,local); + boolean lmultiple = left.isMultiple(); + boolean rmultiple = right.isMultiple(); + + if (operator.equals("#")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + if (lexp.right.isOrderedB()) + { BExpression belr = lexp.right.binvariantForm(env,local); + BExpression newl = new BUnaryExpression("ran",belr); + bel = new BBinaryExpression(":", new BBasicExpression(x), newl); + } + BExpression res = new BQuantifierExpression("exists",x, + new BBinaryExpression("&",bel,ber)); + return res; + } + + if (operator.equals("!")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + // BExpression lll = lexp.left.bqueryForm(env); + // String t = lexp.right + ""; + // env1.put(t,lll); + if (lexp.right.isOrderedB()) + { BExpression belr = lexp.right.binvariantForm(env,local); + BExpression newl = new BUnaryExpression("ran",belr); + bel = new BBinaryExpression(":", new BBasicExpression(x), newl); + } + BExpression res = new BQuantifierExpression("forall",x, + new BBinaryExpression("=>",bel,ber)); + return res; + } + + if (operator.equals("#1")) + { BinaryExpression lexp = (BinaryExpression) left; + String x = lexp.left + ""; + BExpression rng = lexp.right.binvariantForm(env,local); + if (lexp.right.isOrderedB()) + { rng = new BUnaryExpression("ran", rng); } + + BExpression sel = new BSetComprehension(x,rng,ber); + BExpression selsize = new BUnaryExpression("card",sel); + BExpression res = new BBinaryExpression("=",selsize, + new BBasicExpression("1")); + return res; + } + + if (operator.equals("|") || operator.equals("->select") || + operator.equals("|R") || operator.equals("->reject")) + { return selectBinvariantForm(bel,ber,env,local); } + + if (operator.equals("->collect") || operator.equals("->unionAll") || + operator.equals("|C") || operator.equals("->intersectAll")) + { return collectBinvariantForm(bel,ber,env,local); } + + if (operator.equals("->forAll") || operator.equals("->exists") || + "->existsLC".equals(operator) || operator.equals("->exists1")) + { return quantifierBinvariantForm(bel,ber,env,local); } + + if (operator.equals("=")) + { if (lmultiple && !rmultiple) + { BSetExpression se; + if (ber instanceof BSetExpression) + { se = (BSetExpression) ber; } + else + { se = new BSetExpression(); + se.addElement(ber); + se.setOrdered(left.isOrderedB()); + } + BExpression res = new BBinaryExpression("=",bel,se); // promote right to a set + res.setBrackets(needsBracket); + } + } // and other cases, rmult && !lmult, and for /= + + if (operator.equals(":") || operator.equals("/:")) + { if (!lmultiple && rmultiple && right.isOrderedB()) + { BExpression rr = new BUnaryExpression("ran",ber); + BExpression res = new BBinaryExpression(operator,bel,rr); + res.setBrackets(needsBracket); + return res; + } + else if ("String".equals(right.type + "")) + { BExpression rr = new BUnaryExpression("ran",ber); + BExpression res = new BBinaryExpression(operator,bel,rr); + res.setBrackets(needsBracket); + return res; + } + } + // also for <: and /<: if one of left or right is ordered. + + if (operator.equals("<:") || operator.equals("/<:")) + { BExpression newl = bel; + BExpression newr = ber; + if (lmultiple && left.isOrderedB()) + { newl = new BUnaryExpression("ran",bel); } + if (rmultiple && right.isOrderedB()) + { newr = new BUnaryExpression("ran",ber); } + BExpression res = new BBinaryExpression(operator,newl,newr); + res.setBrackets(needsBracket); + return res; + } + + if (operator.equals("->includes")) + { if (lmultiple && !rmultiple) + { BExpression ll = bel; + if (left.isOrderedB()) + { ll = new BUnaryExpression("ran",bel); } + BExpression res = new BBinaryExpression(":",ber,ll); + res.setBrackets(needsBracket); + return res; + } + else if ("String".equals(left.type + "")) + { BExpression ll = new BUnaryExpression("ran",bel); + BExpression res = new BBinaryExpression(":",ber,ll); + res.setBrackets(needsBracket); + return res; + } + } + + if (operator.equals("->oclIsKindOf") || operator.equals("->oclIsTypeOf")) + { BExpression es = new BBasicExpression((right + "").toLowerCase() + "s"); + BExpression res = new BBinaryExpression(":",bel,es); + res.setBrackets(needsBracket); + return res; + } + + if (operator.equals("->at")) + { BExpression res = new BApplyExpression(bel,ber); + return res; + } + + if (operator.equals("->excludes")) + { if (lmultiple && !rmultiple) + { BExpression ll = bel; + if (left.isOrderedB()) + { ll = new BUnaryExpression("ran",bel); } + BExpression res = new BBinaryExpression("/:",ber,ll); + res.setBrackets(needsBracket); + return res; + } + else if ("String".equals(left.type + "")) + { BExpression ll = new BUnaryExpression("ran",bel); + BExpression res = new BBinaryExpression("/:",ber,ll); + res.setBrackets(needsBracket); + return res; + } + } + + if (operator.equals("->isUnique")) + { // card(r(l)) = card(l) + BApplySetExpression rapplyl = new BApplySetExpression(ber,bel); + BUnaryExpression ll = new BUnaryExpression("card",rapplyl); + BUnaryExpression rr = new BUnaryExpression("card",bel); + return new BBinaryExpression("=",ll,rr); + } + + String op = operator; + if (operator.equals("!=") || operator.equals("<>")) + { op = "/="; } + else if (operator.equals("->union") && left.isOrderedB() && right.isOrderedB()) + { op = "^"; } + else if (operator.equals("\\/") && left.isOrderedB() && right.isOrderedB()) + { op = "^"; } + else if (operator.equals("->union")) + { op = "\\/"; } + else if (operator.equals("->intersection")) + { op = "/\\"; } + + if (operator.equals("->prepend")) + { BExpression res = new BBinaryExpression("->",ber,bel); + res.setBrackets(needsBracket); + return res; + } + else if (operator.equals("->append")) + { BExpression res = new BBinaryExpression("<-",bel,ber); + res.setBrackets(needsBracket); + return res; + } + else if (operator.equals("->indexOf")) // min(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(ber); + BExpression func = new BPostfixExpression("~", bel); + BExpression res = new BApplySetExpression(func,img); + res = new BUnaryExpression("min",res); + return res; + } + else if (operator.equals("->lastIndexOf")) // max(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(ber); + BExpression func = new BPostfixExpression("~", bel); + BExpression res1 = new BApplySetExpression(func,img); + BExpression result = new BUnaryExpression("max",res1); + return result; + } + else if (operator.equals("->count")) // card(bel~[{ber}]) + { BSetExpression img = new BSetExpression(); + img.addElement(ber); + BExpression func = new BPostfixExpression("~", bel); + BExpression res = new BApplySetExpression(func,img); + res = new BUnaryExpression("card",res); + return res; + } + else if (operator.equals("->including")) + { BSetExpression bset = new BSetExpression(); + bset.addElement(ber); + if (left.isOrderedB()) + { BExpression resord = new BBinaryExpression("<-", bel, ber); + return resord; + } + BExpression res = new BBinaryExpression("\\/",bel,bset); + res.setBrackets(needsBracket); + return res; + } + else if (operator.equals("->excluding")) + { BSetExpression bset = new BSetExpression(); + bset.addElement(ber); + BExpression res = new BBinaryExpression("-",bel,bset); + res.setBrackets(needsBracket); + return res; + } + else if (operator.equals("=") || operator.equals("-") || + operator.equals("\\/") || operator.equals("/\\") || + operator.equals("^") || "->concatenate".equals(operator) || operator.equals("->union") || + operator.equals("->intersection") || + operator.equals("/=") || operator.equals("!=") || operator.equals("<>")) + { // if one of bel, ber are sets and other isn't, + // promote the non-set to be a set: + if (operator.equals("->union") || operator.equals("\\/")) + { if (left.isOrderedB() && right.isOrderedB()) + { operator = "^"; } + } + + if (lmultiple == rmultiple) + { if (operator.equals("/\\") || operator.equals("\\/") || + operator.equals("->intersection") || operator.equals("->union") || + operator.equals("-") || "->concatenate".equals(operator) || operator.equals("^")) + { BExpression result = new BBinaryExpression(op,bel,ber); + if (lmultiple) + { result.setMultiplicity(ModelElement.MANY); } + result.setBrackets(needsBracket); + return result; + } + } // cases of sequences not handled. + else if (rmultiple) + { BExpression newbel = BExpression.makeSet(bel); + BExpression res = new BBinaryExpression(op,newbel,ber); + res.setBrackets(needsBracket); + return res; + } + else if (lmultiple) + { BExpression newber = BExpression.makeSet(ber); + BExpression res = new BBinaryExpression(op,bel,newber); + res.setBrackets(needsBracket); + return res; + } + } + else if (operator.equals(":")) + { if (lmultiple) + { BExpression res = new BBinaryExpression("<:",bel,ber); + res.setBrackets(needsBracket); + return res; + } + } + else if (operator.equals("/:")) + { if (lmultiple) // bel intersection ber = {} + { BExpression empty = + new BSetExpression(new Vector()); + BExpression res = + new BBinaryExpression("=", + new BBinaryExpression("/\\",bel,ber),empty); + res.setBrackets(needsBracket); + return res; + } + } + else if (comparitors.contains(operator)) + { return comparitorsBinvariantForm(op,bel,ber,lmultiple,rmultiple); } + BExpression res = new BBinaryExpression(op,bel,ber); + if (objectRef != null) + { BExpression func = objectRef.binvariantForm(env,local); + res.setBrackets(true); + return new BApplyExpression(res,func); + } // or ApplySet if objectRef.isMultiple() + res.setBrackets(needsBracket); + return res; + } // ->excludingAt, ->restrict, etc. + + private BExpression selectBinvariantForm(BExpression bel, BExpression ber, + java.util.Map env, boolean local) + { // { var | var : bel & right.binvariantForm(env <+ { e |-> var }, false) } + // Assume that left is not ordered. Ordered version needs to be treated. + + Type etype = left.getElementType(); + String ename; + String var; + Expression predicate = right; + + if (operator.equals("|") || operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + var = beleft.left + ""; + etype = beleft.right.getElementType(); + ename = "" + etype; + bel = beleft.right.binvariantForm(env,local); + } + else if (etype == null) + { System.err.println("Warning -- null element type in select: " + this); + ename = "Object"; + var = "object_xx"; + } + else + { ename = "" + etype; // should be a class + // System.out.println("Element type of " + left + " is " + ename); + var = ename.toLowerCase() + "_xx"; + } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (operator.equals("|") || operator.equals("|R")) { } + else { newenv.put(ename,new BBasicExpression(var)); } + + BExpression pred = predicate.binvariantForm(newenv,false); + + if (operator.equals("->reject") || operator.equals("|R")) + { pred = new BUnaryExpression("not",pred); } + + if (left.isOrdered()) + { return seqselectBinvariantForm(var, bel, pred, newenv); } + + return new BSetComprehension(var,bel,pred); + } // need same kind of thing with exists, forall, reject, collect, |R + + private BExpression collectBinvariantForm(BExpression bel, BExpression ber, + java.util.Map env, boolean local) + { // { var,y | var : bel & y = right.binvariantForm(env <+ { e |-> var }, false) } + // left not ordered: + // { i,y | var = bel(i) & y = right.binvariantForm(env <+ { e |-> var }, false) } + + Type etype = left.getElementType(); + String ename; + String var; + Expression collectleft = left; + + if (operator.equals("|C")) + { collectleft = ((BinaryExpression) left).right; + var = ((BinaryExpression) left).left + ""; + etype = collectleft.getElementType(); + } + else + { var = (etype + "").toLowerCase() + "_xx"; } + + if (etype == null) + { System.err.println("ERROR -- null element type in collect: " + this); + ename = "Object"; + var = "object_xx"; + } + else + { ename = "" + etype; // should be a class + // System.out.println("Element type of " + left + " is " + ename); + } + + BBasicExpression varbe = new BBasicExpression(var); + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|C")) { } + else + { newenv.put(ename,varbe); } + + BExpression pred = right.binvariantForm(newenv,false); + String var2 = "xx_value"; + BBasicExpression var2be = new BBasicExpression(var2); + + Vector vars = new Vector(); + vars.add(var); + vars.add(var2); + + pred = new BBinaryExpression("=", var2be, pred); + BExpression collvalue; + + if (collectleft.isOrderedB()) + { String var0 = "xx_index"; + Vector vars2 = new Vector(); + vars2.add(var0); + vars2.add(var2); + BBasicExpression var0be = new BBasicExpression(var0); + + BExpression dombel = new BUnaryExpression("dom",bel); + BExpression indombel = new BBinaryExpression(":", var0be, dombel); + BExpression belapply = new BApplyExpression(bel, var0be); + BExpression eqbelapply = new BBinaryExpression("=", varbe, belapply); + BQuantifierExpression existsvarb = + new BQuantifierExpression("exists", var, + new BBinaryExpression("&", eqbelapply, pred)); + collvalue = new BSetComprehension(vars, + new BBinaryExpression("&",indombel,existsvarb)); + } + else + { BExpression rng = new BBinaryExpression(":",varbe,bel); + pred = new BBinaryExpression("&",rng,pred); + BSetComprehension collexp = new BSetComprehension(vars,pred); + collvalue = new BUnaryExpression("ran", collexp); + } + + if (operator.equals("->collect") || operator.equals("|C")) + { return collvalue; } + else if (operator.equals("->unionAll") & left.isOrderedB() && + (right.isOrderedB() || "self".equals(right + ""))) + { return new BUnaryExpression("dcat",collvalue); } + else if (operator.equals("->unionAll")) + { if (left.isOrderedB()) + { collvalue = new BUnaryExpression("ran", collvalue); } + return new BUnaryExpression("union",collvalue); + } + else + { if (left.isOrderedB()) + { collvalue = new BUnaryExpression("ran", collvalue); } + return new BUnaryExpression("inter",collvalue); + } + } // need same kind of thing with exists, forall, reject, collect, |C + + + private BExpression quantifierBinvariantForm(BExpression bel, BExpression ber, + java.util.Map env, boolean local) + { // { var | var : bel & right.binvariantForm(env <+ { e |-> var }, false) } = ? + // for ordered use ran(bel) + + Type etype = left.getElementType(); + String ename; + String var; + if (etype == null) + { System.err.println("Warning -- null element type in quantifier: " + this); + ename = "Object"; + var = "object_xx"; + } + else + { ename = "" + etype; // should be a class + System.out.println("Element type of " + left + " is " + ename); + var = ename.toLowerCase() + "_xx"; + } + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + newenv.put(ename,new BBasicExpression(var)); + BExpression pred = right.binvariantForm(newenv,false); + + if (left.isOrderedB()) + { bel = new BUnaryExpression("ran",bel); } + + BSetComprehension satisfiesPred = new BSetComprehension(var,bel,pred); + + BExpression result; + + if (operator.equals("->forAll")) + { result = new BBinaryExpression("=",satisfiesPred,bel); } + else + { BExpression cardset = new BUnaryExpression("card",satisfiesPred); + if ("->existsLC".equals(operator) || operator.equals("->exists")) + { result = new BBinaryExpression(">",cardset,new BBasicExpression("0")); } + else + { result = new BBinaryExpression("=",cardset,new BBasicExpression("1")); } + } + + return result; + } + + private BExpression comparitorsBinvariantForm(String op, + BExpression bel, BExpression ber, + boolean lmult, boolean rmult) + { if (!lmult && !rmult) + { return new BBinaryExpression(op,bel,ber); } + if (lmult && !rmult) + { // !xx.(xx: bel => xx operator ber) Gen new variable xx + String xx = Identifier.nextIdentifier("xx_var"); + BExpression bxx = new BBasicExpression(xx); + BExpression compar = new BBinaryExpression(op,bxx,ber); + BExpression inexp = new BBinaryExpression(":",bxx,bel); + BExpression pred = new BBinaryExpression("=>",inexp,compar); + return new BQuantifierExpression("forall",xx,pred); + } + if (rmult && !lmult) + { // !xx.(xx: ber => bel operator xx) Gen new variable xx + String xx = Identifier.nextIdentifier("xx_var"); + BExpression bxx = new BBasicExpression(xx); + BExpression compar = new BBinaryExpression(op,bel,bxx); + BExpression inexp = new BBinaryExpression(":",bxx,ber); + BExpression pred = new BBinaryExpression("=>",inexp,compar); + return new BQuantifierExpression("forall",xx,pred); + } + // !(xx,yy).(xx: bel & yy : ber => xx operator yy) Gen xx, yy + String xx = Identifier.nextIdentifier("xx_var"); + String yy = Identifier.nextIdentifier("xx_var"); + BExpression bxx = new BBasicExpression(xx); + BExpression byy = new BBasicExpression(yy); + BExpression compar = new BBinaryExpression(op,bxx,byy); + BExpression inexp1 = new BBinaryExpression(":",bxx,bel); + BExpression inexp2 = new BBinaryExpression(":",byy,ber); + BExpression pred1 = new BBinaryExpression("=>",inexp2,compar); + BExpression pred2 = new BQuantifierExpression("forall",yy,pred1); + BExpression pred3 = new BBinaryExpression("=>",inexp1,pred2); + return new BQuantifierExpression("forall",xx,pred3); + } + + public int typeCheckEq(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) // Assume bel is the component/att. + { leftcat = lcat; + bel.kind = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + bel.mult = lmult; + rightcat = sm.getCategory(ber.data); + ber.kind = rightcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + ber.mult = rmult; + break; + } + } + + if (leftcat == Statemachine.STATEMACHINE && + rightcat == Statemachine.STATE) + { modality = leftsm.cType; + if (lmult <= 1 && bel.objectRef != null) + { System.err.println("Object ref specified " + + "for non-multiple component: " + + bel); + modality = ERROR; + return ERROR; + } + return modality; + } + + // swap left and right if rightcat == ATTRIBUTE + if (leftcat == Statemachine.ATTRIBUTE && + leftsm.getRange(bel.data).contains(ber.data)) + { modality = leftsm.cType; + if (lmult <= 1 && bel.objectRef != null) + { System.err.println("Object ref specified " + + "for non-multiple component: " + + bel); + modality = ERROR; + return ERROR; + } // also check ber.data is an integer in range + return modality; + } + + if (leftsm == null) + { System.err.println("I can't find a component " + + "for: " + bel); + } + else + { System.err.println("Strange combination in equality " + + toString()); + } + modality = ERROR; + return ERROR; + } + + + public int typeCheckAnd(Vector sms) + { int tal = left.typeCheck(sms); + int tar = right.typeCheck(sms); + if ((tal == ERROR) || (tar == ERROR)) + { modality = ERROR; + return ERROR; + } + if ((tal == HASEVENT && tar != HASEVENT) || + (tal != HASEVENT && tar == HASEVENT)) + { modality = HASEVENT; + return HASEVENT; + } + if (tal != HASEVENT && tal == tar) + { modality = tal; + return tal; + } + else + { modality = MIXED; + return MIXED; + } + } + + public Expression createActionForm(final Vector sms) + { if ((left instanceof BasicExpression) && + (right instanceof BasicExpression) && + operator.equals("=")) + { return createEqActionForm(sms); } + else if (operator.equals("&")) // should never happen + { Expression lact = left.createActionForm(sms); + Expression ract = right.createActionForm(sms); + Expression actionForm = + new BinaryExpression("||",lact,ract); + javaForm = + new BinaryExpression(";",lact.javaForm, + ract.javaForm); + actionForm.javaForm = javaForm; + return actionForm; + } + return this; + } + + private Expression createEqActionForm(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) + { leftcat = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + } + int rcat = sm.getCategory(ber.data); + if (rcat >= 0) + { rightcat = rcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + } + } + if (rightcat == Statemachine.STATEMACHINE) + { int temp = rightcat; // swap left and right -- + rightcat = leftcat; // should already have happened in + leftcat = temp; // normalisation. + temp = rmult; + rmult = lmult; + lmult = temp; + Statemachine stemp = rightsm; + rightsm = leftsm; + leftsm = stemp; + } + + if (leftcat == Statemachine.STATEMACHINE && + rightcat == Statemachine.STATE) + { String acts = bel.data + "Set" + ber.data; + BasicExpression act = new BasicExpression(acts); + if (lmult <= 1) + { javaForm = + new BasicExpression("Actuator" + bel.data + + "." + acts + "()"); + act.javaForm = javaForm; + return act; + } + else if (bel.objectRef != null) + { act.objectRef = + (Expression) bel.objectRef.clone(); + // act1 = new BasicExpression(act.toB()); + javaForm = new BasicExpression(act.toJava() + "()"); // act + // javaForm.objectRef = + // (Expression) bel.objectRef.clone(); + act.javaForm = javaForm; // act1 + return act; // act1 + } + else // shouldn't happen + { return new BasicExpression(bel.data + + "SetAll(" + ber.data + ")"); + } // in Java ; of each Set. + } + + // swap left and right if rightcat == ATTRIBUTE + if (leftcat == Statemachine.ATTRIBUTE && + leftsm.getRange(bel.data).contains(ber.data)) + { String attset = "set" + bel.data + + "(" + ber.data + ")"; + if (lmult <= 1) + { BasicExpression act2 = + new BasicExpression(attset); + javaForm = + new BasicExpression("M" + leftsm.label + + "." + attset); + act2.javaForm = javaForm; + return act2; + } + else if (bel.objectRef != null) + { BasicExpression act3 = + new BasicExpression("set" + bel.data + + "(" + bel.objectRef.toB() + "," + + ber.data + ")"); + BasicExpression jf = new BasicExpression(attset); + jf.objectRef = + (Expression) bel.objectRef.clone(); + javaForm = new BasicExpression(jf.toJava()); + act3.javaForm = javaForm; + return act3; + } + else // shouldn't happen + { return new BasicExpression("setAll" + + bel.data + "(" + ber.data + ")"); + } + } + + System.err.println("I can't produce a sensible " + + "action form from: " + bel + " = " + ber); + return this; + } + + public Scope resultScope() + { if (left.equalsString("result") && + operator.equals(":")) + { return new Scope("in",this); } // this formula then ignored + // in update. + if (right.equalsString("result") && + operator.equals("->includes")) + { return new Scope("in",new BinaryExpression(":",right,left)); } + + if (left.equalsString("result") && + operator.equals("<:")) + { return new Scope("subset",this); } + + if (right.equalsString("result") && + operator.equals("->includesAll")) + { return new Scope("subset", new BinaryExpression("subset",right,left)); } + + if (left.equalsString("result") && + operator.equals("=")) + { return new Scope("eq",this); } + if (right.equalsString("result") && + operator.equals("=")) + { return new Scope("eq",reverse()); } + // removeExpression must remove these as well + if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if ("result".equals(lbe.arrayIndex + "")) + { return new Scope("array",this,lbe); } + } + if (right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + if ("result".equals(rbe.arrayIndex + "")) + { return new Scope("array",this,rbe); } + } + if (operator.equals("&")) + { Scope res1 = left.resultScope(); + Scope res2 = right.resultScope(); + if (res1 != null) + { // return (BinaryExpression) Expression.simplify("&",res1,res2, + // + return res1; + } + else + { return res2; } + } + if (operator.equals("=>") || + operator.equals("#") || operator.equals("#1") || + operator.equals("#LC") || operator.equals("!")) + { return right.resultScope(); } // this ? + return null; + } + // also case where result occurs as an array index: + // be[result] + + public Expression simplify(final Vector vars) + { Expression lsimp = left.simplify(vars); + Expression rsimp = right.simplify(vars); + return simplify(operator,lsimp,rsimp,vars); + } + + public Expression simplify() + { Expression lsimp = left.simplify(); + Expression rsimp = right.simplify(); + return simplify(operator,lsimp,rsimp,needsBracket); + } + + public Expression substitute(final Expression oldE, + final Expression newE) + { if (operator.equals("#") || operator.equals("#1") || operator.equals("!") || operator.equals("|A") || + operator.equals("#LC") || operator.equals("|") || operator.equals("|C") || operator.equals("|R")) + { Expression var = ((BinaryExpression) left).left; + Vector vars = oldE.getVariableUses(); + Vector vars1 = newE.getVariableUses(); + if (VectorUtil.containsEqualString(var + "",vars) || + VectorUtil.containsEqualString(var + "",vars1)) + { return this; } + else + { Expression newR = right.substitute(oldE,newE); + Expression newL = left.substitute(oldE,newE); // Added 9.1.2016 + Expression result = new BinaryExpression(operator,newL,newR); + result.formalParameter = formalParameter; + result.setBrackets(needsBracket); + return result; + } // Surely should substitute in left.right ??? + } + + if (oldE == left) + { Expression newR = right.substitute(oldE,newE); + BinaryExpression result = + new BinaryExpression(operator,newE,newR); + result.formalParameter = formalParameter; + result.setBrackets(needsBracket); + result.iteratorVariable = iteratorVariable; + result.accumulator = accumulator; + return result; + } + else if (oldE == right) + { Expression newL = left.substitute(oldE,newE); + BinaryExpression result = + new BinaryExpression(operator,newL,newE); + result.formalParameter = formalParameter; + result.setBrackets(needsBracket); + result.iteratorVariable = iteratorVariable; + result.accumulator = accumulator; + return result; + } + else + { Expression newLeft = left.substitute(oldE,newE); + Expression newRight = right.substitute(oldE,newE); + BinaryExpression result = + new BinaryExpression(operator, newLeft, newRight); + result.formalParameter = formalParameter; + result.iteratorVariable = iteratorVariable; + result.accumulator = accumulator; + result.setBrackets(needsBracket); + return result; + } + } // What if oldE == left and right? + + public Expression substituteEq(final String oldVar, + final Expression newVal) + { // if (oldVar.equals(left.toString())) + // { return new BinaryExpression(operator,newVal,right); } + // else if (oldVar.equals(right.toString())) + // { return new BinaryExpression(operator,left,newVal); } + // else + // { System.out.println("left is: " + left); + + // System.out.println("SUBSTITUTING " + oldVar + " BY " + newVal + " IN " + this); + + if (oldVar.equals(this + "")) + { return newVal; } + + Expression newLeft = null; + if (left != null) + { newLeft = left.substituteEq(oldVar,newVal); } + // System.out.println("after substitution: " + newLeft); + // System.out.println("right is: " + right); + Expression newRight = null; + if (right != null) + { newRight = right.substituteEq(oldVar,newVal); } + + /* if (operator.equals("#") || operator.equals("#1") || operator.equals("!") || + operator.equals("|") || operator.equals("|R") || operator.equals("|C")) + { Expression var = ((BinaryExpression) left).left; + Vector vars1 = newVal.getVariableUses(); + if (VectorUtil.containsEqualString(var + "",vars1)) + { return this; } + else if ((var + "").equals(oldVar)) + { Expression scope = ((BinaryExpression) left).right; + Expression scopesub = scope.substituteEq(oldVar,newVal); + Expression res1 = new BinaryExpression(":",var,scopesub); + return new BinaryExpression(operator,res1,right); + } + else + { Expression result = new BinaryExpression(operator,newLeft,newRight); + if (needsBracket) + { result.setBrackets(true); } + return result; + } + } */ + + BinaryExpression res = + new BinaryExpression(operator,newLeft,newRight); + res.formalParameter = formalParameter; + + res.iteratorVariable = iteratorVariable; // if not renamed + res.accumulator = accumulator; // if not renamed + if (accumulator != null && + accumulator.getInitialExpression() != null) + { Attribute newacc = new Attribute(accumulator.getName(), + accumulator.getType(), + ModelElement.INTERNAL); + Expression init = accumulator.getInitialExpression(); + Expression newInit = init.substituteEq(oldVar,newVal); + newacc.setInitialExpression(newInit); + res.setAccumulator(newacc); + } + + res.setBrackets(needsBracket); + // System.out.println("***** " + this + " after substitution = " + res); + return res; + // } + } // what if oldVar equals left and right? + + public Expression removeSlicedParameters( + BehaviouralFeature op, Vector fpars) + { Expression newLeft = null; + if (left != null) + { newLeft = left.removeSlicedParameters(op,fpars); } + Expression newRight = null; + if (right != null) + { newRight = right.removeSlicedParameters(op,fpars); } + + BinaryExpression res = + new BinaryExpression(operator,newLeft,newRight); + res.formalParameter = formalParameter; + // Do this for Unary, Conditional, Set, etc + + res.iteratorVariable = iteratorVariable; // if not renamed + res.accumulator = accumulator; // if not renamed + if (accumulator != null && + accumulator.getInitialExpression() != null) + { Attribute newacc = new Attribute(accumulator.getName(), + accumulator.getType(), + ModelElement.INTERNAL); + Expression init = accumulator.getInitialExpression(); + Expression newInit = + init.removeSlicedParameters(op,fpars); + newacc.setInitialExpression(newInit); + res.setAccumulator(newacc); + } + + res.setBrackets(needsBracket); + return res; + } + + + public boolean hasVariable(final String s) + { boolean res = false; + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res = expr.hasVariable(s); } + } + return (res || left.hasVariable(s) || + right.hasVariable(s)); + } + // Cases of ->iterate, let + + public boolean selfReferential(final Vector vars) + { Vector res1 = left.variablesUsedIn(vars); + Vector res2 = right.variablesUsedIn(vars); + + for (int i = 0; i < res1.size(); i++) + { Object x = res1.get(i); + if (res2.contains(x)) + { return true; } + } + + Vector res3 = left.allAttributesUsedIn(); + Vector res4 = right.allAttributesUsedIn(); + + // System.out.println(">> " + res3 + " ---- " + res4); + + for (int i = 0; i < res3.size(); i++) + { Object x = res3.get(i); + if (res4.contains(x)) + { return true; } + } + + return false; + } + + public Vector variablesUsedIn(final Vector vars) + { Vector res1 = left.variablesUsedIn(vars); + Vector res2 = right.variablesUsedIn(vars); + + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res1.addAll(expr.variablesUsedIn(vars)); } + } + + return VectorUtil.vector_merge(res1,res2); + } // Cases of ->iterate, let + + public Vector componentsUsedIn(final Vector sms) + { Vector res1 = left.componentsUsedIn(sms); + Vector res2 = right.componentsUsedIn(sms); + if ("->iterate".equals(operator) && accumulator != null) + { Expression expr = accumulator.getInitialExpression(); + if (expr != null) + { res1.addAll(expr.componentsUsedIn(sms)); } + } + return VectorUtil.union(res1,res2); + } + + public boolean selfConsistent(final Vector vars) + { Vector res1 = left.variablesUsedIn(vars); + // System.out.println("Lefts are: " + res1); + Vector res2 = right.variablesUsedIn(vars); + // System.out.println("Rights are: " + res2); + Vector inter = VectorUtil.intersection(res1, res2); + // System.out.println("Intersection: " + inter); + if (inter.size() > 0) + { System.out.println("Duplicate variables in operands of " + toString()); + return false; + } + return true; + } + + public Maplet findSubexp(final String var) + { if (operator.equals("=")) + { if ((left instanceof BasicExpression) && + left.toString().equals(var)) + { return new Maplet(this,null); } + if ((right instanceof BasicExpression) && + right.toString().equals(var)) + { return new Maplet(this,null); } + else + { return new Maplet(null,this); } + } + else /* Operator is & */ + { Maplet f1 = left.findSubexp(var); + Maplet f2 = right.findSubexp(var); + Expression exp = simplify(operator,(Expression) f1.dest, + (Expression) f2.dest, null); + if (f1.source == null) + { return new Maplet(f2.source, exp); } + else + { return new Maplet(f1.source, exp); } + } + /* Don't expect to find more than one! */ + } + + public Expression filter(final Vector vars) + { if (operator.equals("=")) + { return filterEquality(left,right,this,vars); } + else if (operator.equals("&")) + { Expression e1 = left.filter(vars); + Expression e2 = right.filter(vars); + return simplify("&",e1,e2, vars); + } /* vars should be redundant */ + else { return this; } + } + + + + public Vector splitAnd(Vector sms) + { Vector res = new Vector(); + if (operator.equals("&")) + { Vector res1 = left.splitAnd(sms); + Vector res2 = right.splitAnd(sms); + res = VectorUtil.vector_merge(res1,res2); + return res; + } + else if (operator.equals("=")) + { return expandEqSucc(sms); } + else + { System.out.println("!! Expression in succedent without = or &"); + return res; + } + } + + // Also deals with operator being "<", etc + private Vector expandEqAnte(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + Vector res = new Vector(); + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) + { leftcat = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + } + int rcat = sm.getCategory(ber.data); + if (rcat >= 0) + { rightcat = rcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + } + } + + if ((leftcat == Statemachine.ATTRIBUTE || + leftcat == Statemachine.STATEMACHINE) && + (rightcat == Statemachine.ATTRIBUTE || + rightcat == Statemachine.STATEMACHINE)) + { Vector range1 = leftsm.getRange(bel.data); + Vector range2 = rightsm.getRange(ber.data); + Vector inter = + // VectorUtil.intersection(range1,range2); + VectorUtil.satisfies(operator,range1,range2); + for (int i = 0; i < inter.size(); i++) + { Maplet val = (Maplet) inter.get(i); + BasicExpression bsc1 = + new BasicExpression((String) val.source); + BasicExpression bsc2 = + new BasicExpression((String) val.dest); + BinaryExpression be1 = + new BinaryExpression("=",bel,bsc1); + BinaryExpression be2 = + new BinaryExpression("=",ber,bsc2); + BinaryExpression andexp = + new BinaryExpression("&",be1,be2); + res.add(andexp); + } + } + else if ((leftcat == Statemachine.ATTRIBUTE || + leftcat == Statemachine.STATEMACHINE) && + Expression.isNumber(ber.data)) + { // it is var < val, etc. + Vector range1 = leftsm.getRange(bel.data); + Vector range2 = new Vector(); + range2.add(ber.data); + Vector inter = VectorUtil.satisfies(operator,range1,range2); + for (int i = 0; i < inter.size(); i++) + { Maplet val = (Maplet) inter.get(i); + BasicExpression bsc1 = + new BasicExpression((String) val.source); + BinaryExpression be1 = + new BinaryExpression("=",bel,bsc1); + res.add(be1); + } + } + else if (leftcat != Statemachine.ATTRIBUTE && + leftcat != Statemachine.STATEMACHINE) + { res.add(reverse()); } + else + { res.add(clone()); } + return res; + } // splitOr, for antecedent. + // Danger in that bel, ber are not cloned? + + public Vector splitOr(final Vector components) + { Vector res = new Vector(); + if (operator.equals("&")) + { Vector lefts = left.splitOr(components); + Vector rights = right.splitOr(components); + for (int i = 0; i < lefts.size(); i++) + { Expression e1 = (Expression) lefts.get(i); + for (int j = 0; j < rights.size(); j++) + { Expression e2 = (Expression) rights.get(j); + Expression e = new BinaryExpression("&",e1,e2); + res.add(e); + } + } + } + else if (operator.equals("or")) + { Vector lefts = left.splitOr(components); + Vector rights = right.splitOr(components); + res = VectorUtil.union(lefts,rights); + } + else if (operator.equals("!=")) + { Expression be = new BinaryExpression("=",left,right); + res = be.computeNegation4ante(components); + /* if (res == null || res.size() == 0) + issue warning. */ + } + else if (comparitors.contains(operator)) + { res = expandEqAnte(components); } + return res; + } + + public Expression expandMultiples(Vector sms) + { if (operator.equals("=")) + { return expandEqMultiples(sms); } + if (operator.equals("&")) + { Expression newleft = + left.expandMultiples(sms); + Expression newright = + right.expandMultiples(sms); + return simplifyAnd(newleft,newright); + } + else + { return this; } + } + + private Vector expandEqSucc(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + Vector res = new Vector(); + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) + { leftcat = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + } + int rcat = sm.getCategory(ber.data); + if (rcat >= 0) + { rightcat = rcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + } + } + if ((leftcat == Statemachine.ATTRIBUTE || + leftcat == Statemachine.STATEMACHINE) && + (rightcat == Statemachine.ATTRIBUTE || + rightcat == Statemachine.STATEMACHINE)) + { Vector range1 = leftsm.getRange(bel.data); + Vector range2 = rightsm.getRange(ber.data); + Vector inter = + VectorUtil.intersection(range1,range2); + for (int i = 0; i < inter.size(); i++) + { String val = (String) inter.get(i); + BasicExpression bsc1 = + new BasicExpression(val); + BasicExpression bsc2 = + new BasicExpression(val); + BinaryExpression be1 = + new BinaryExpression("=",bel,bsc1); + BinaryExpression be2 = + new BinaryExpression("=",ber,bsc2); + BinaryExpression andexp; + if (leftsm.cType == DCFDArea.SENSOR) + { andexp = new BinaryExpression("=>",be1,be2); } + else if (rightsm.cType == DCFDArea.SENSOR) + { andexp = new BinaryExpression("=>",be2,be1); } + else // ACTACT + { andexp = new BinaryExpression("=>",be1,be2); } + res.add(andexp); + } // Only correct if ranges are actually the same + } + else if (leftcat != Statemachine.ATTRIBUTE && + leftcat != Statemachine.STATEMACHINE) + { res.add(reverse()); } + else + { res.add(clone()); } + return res; + } // splitAnd, for succedent. + + private Expression expandEqMultiples(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + Expression res = null; + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) + { leftcat = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + } + int rcat = sm.getCategory(ber.data); + if (rcat >= 0) + { rightcat = rcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + } + } + if ((leftcat == Statemachine.ATTRIBUTE || + leftcat == Statemachine.STATEMACHINE) && + leftsm.getMultiplicity() > 1 && + bel.objectRef == null) + { Vector insts = leftsm.getInstances(); + for (int i = 0; i < insts.size(); i++) + { String val = (String) insts.get(i); + BasicExpression bsc1 = + (BasicExpression) bel.clone(); + bsc1.objectRef = new BasicExpression(val); + BasicExpression bsc2 = + (BasicExpression) ber.clone(); + BinaryExpression be1 = + new BinaryExpression("=",bsc1,bsc2); + if (res == null) + { res = be1; } + else + { res = + new BinaryExpression("&",res,be1); + } + } + } + else + { res = this; } + return res; + } + + + public Expression removeExpression(final Expression e) + { /* Assumes e is of form v = x */ + if (e == null) + { return this; } + if (("" + this).equals("" + e)) + { return null; } + if (operator.equals("=>") || "->existsLC".equals(operator) || + operator.equals("->exists") || operator.equals("->exists1") || + operator.equals("->forAll") || operator.equals("#") || + operator.equals("#1") || operator.equals("#LC") || operator.equals("!")) + { Expression succ = right.removeExpression(e); + return new BinaryExpression(operator,left,succ); + } + + if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (be.operator.equals("&")) + { Expression rleft = removeExpression(be.left); + Expression rright = removeExpression(be.right); + return simplify("&",rleft,rright,new Vector()); + } + // if (be.operator.equals("=")) + // { Expression rem1 = removeExpression(be); + // return rem1.removeExpression(be.reverse()); + // return rem1; // endless loop if be is its own reverse + // } + } + if (e.equals(left)) + { return right.removeExpression(e); } + else if (e.equals(right)) + { return left.removeExpression(e); } + else + { Expression res1 = left.removeExpression(e); + Expression res2 = right.removeExpression(e); + return simplify(operator,res1,res2, new Vector()); + } /* or null? */ + } + + public boolean implies(final Expression e) + { if (equals(e)) + { return true; } + + if (e.isTrueString()) + { return true; } + + if (this.isFalseString()) + { return true; } + + if (operator.equals("&")) + { if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (comparitors.contains(be.operator)) // or other non-logical ops + { boolean res1 = left.implies(be); + boolean res2 = right.implies(be); + return (res1 || res2); + } + else if (be.operator.equals("&")) + { boolean res1 = implies(be.left); + boolean res2 = implies(be.right); + return (res1 && res2); + } + else if (be.operator.equals("or")) + { boolean res1 = implies(be.left); + boolean res2 = implies(be.right); + return (res1 || res2); + } + else if (be.operator.equals("=>")) + { return implies(be.right); } + else + { return false; } + } + else if (e instanceof BasicExpression) + { return (left.implies(e) || right.implies(e)); } + else + { return false; } + } + else if (operator.equals("=") || operator.equals("<>=")) + { if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (comparitors.contains(be.operator) || + be.operator.equals("<:") || + be.operator.equals("->includesAll")) + { return impliesEq(be.operator,be); } + else if (be.operator.equals("&")) + { return (implies(be.left) && implies(be.right)); } + } + else if (e instanceof BasicExpression) + { return false; } + else + { return false; } + } + else if (operator.equals("<") || operator.equals(">")) + { if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (comparitors.contains(be.operator)) + { return impliesLG(be.operator,be); } + else if (be.operator.equals("&")) + { return (implies(be.left) && implies(be.right)); } + } + return false; + } + else { return false; } + return false; + } // and cases of x > y => x >= y etc + + private boolean impliesEq(String op, BinaryExpression be) + { if (op.equals("=") || op.equals("<>=")) + { return (equals(be) || equals(be.reverse())); } + + if (op.equals("<=") || op.equals(">=") || + op.equals("<:") || + op.equals("->includesAll")) + { return (left.equals(be.left) && right.equals(be.right)) || + (right.equals(be.left) && left.equals(be.right)); + } + + return false; + } + + private boolean impliesLG(String op, BinaryExpression be) + { if (operator.equals("<")) + { if (op.equals("/=") || op.equals("!=") || + operator.equals("<>")) + { return ((left.equals(be.left) && + right.equals(be.right)) || + (right.equals(be.left) && + left.equals(be.right))); + } + + if (op.equals("<=")) + { return left.equals(be.left) && right.equals(be.right); } + + if (op.equals(">=")) + { return left.equals(be.right) && right.equals(be.left); } + + return false; + } + + if (operator.equals(">")) + { if (op.equals("/=") || op.equals("!=") || + operator.equals("<>")) + { return ((left.equals(be.left) && right.equals(be.right)) || + (right.equals(be.left) && left.equals(be.right))); + } + + if (op.equals(">=")) + { return left.equals(be.left) && right.equals(be.right); } + + if (op.equals("<=")) + { return left.equals(be.right) && right.equals(be.left); } + + return false; + } + + return false; + } + + private BinaryExpression reverse() + { return new BinaryExpression(operator,right,left); } + + public boolean consistentWith(Expression e) + { if (equals(e)) { return true; } + if (operator.equals("&")) + { return (left.consistentWith(e) || + right.consistentWith(e)); } + else if (operator.equals("=")) + { return subformulaOf(e); } + else if (comparitors.contains(operator) && e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (left.equals(be.left) && right.equals(be.right)) + { return consistentOps(operator,be.operator); } + if (left.equals(be.right) && right.equals(be.left)) + { return consistentOps(operator,negateOp(be.operator)); } // ?? + } + { return false; } + } // and cases of x > y cw x >= y etc, = with <: + + // private boolean consistentWithEq(Expression e) + // { if + + private boolean consistentOps(String op1, String op2) + { if (op1.equals("<")) + { return (op2.equals("<=") || op2.equals("/=") || + op2.equals("!=")); + } + if (op1.equals(">")) + { return (op2.equals(">=") || op2.equals("/=") || + op2.equals("!=")); + } + if (op1.equals("=")) + { return (op2.equals("<=") || op2.equals(">=") || + op2.equals("<:") || op2.equals("->includesAll")); + } + if (op1.equals("/=") || op1.equals("!=") || operator.equals("<>")) + { return (op2.equals("<") || op2.equals("/=") || + op2.equals("/<:") || op2.equals("->excludesAll") || // added 9.1.2016 + op2.equals(">") || op2.equals("!=") || op2.equals("<>")); + } + if (op1.equals("<=")) + { return (op2.equals("<") || op2.equals(">=") || + op2.equals("=")); + } + if (op1.equals(">=")) + { return (op2.equals(">") || op2.equals("<=") || + op2.equals("=")); + } + if (op1.equals("<:") || op1.equals("->includesAll")) + { return op2.equals("="); } + if (op1.equals("/<:") || op1.equals("->excludesAll")) + { return op2.equals("/=") || op2.equals("!=") || op2.equals("<>"); } + return false; + } + + + public boolean subformulaOf(final Expression e) + { /* Assume operator is "=" */ // if (e.equals(this)) return true; + if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (be.operator.equals("=")) + { return (equals(be) || equals(be.reverse())); } + else if (be.operator.equals("&")) + { return (subformulaOf(be.left) || subformulaOf(be.right)); } + else if (be.operator.equals("#") || "->existsLC".equals(operator) || + be.operator.equals("->exists") || operator.equals("#LC") || + be.operator.equals("#1") || be.operator.equals("->exists1") || + be.operator.equals("->forAll") || be.operator.equals("!")) + { return subformulaOf(be.right); } // and if be.operator.equals("=>") ??? + else { return false; } + } + else + { return false; } + } + + public Expression computeNegation4succ() + { if (operator.equals("=")) + { return computeEqNegation4succ(); } + if (operator.equals("&")) + { // System.err.println("Can't negate: " + toString() + + // " for succ."); + Expression notB = right.computeNegation4succ(); + Expression res = new BinaryExpression("=>",left,notB); + res.setBrackets(needsBracket); + return res; + } // not(A & B) is A => not(B) + else if (operator.equals("=>")) + { Expression notB = right.computeNegation4succ(); + Expression res = new BinaryExpression("&",left,notB); + res.setBrackets(needsBracket); + return res; + } // not(A => B) is A & not(B) + else if (operator.equals("#") || operator.equals("!") || + operator.equals("->existsLC") || "->exists".equals(operator) || + operator.equals("->forAll")) + { Expression rneg = right.computeNegation4succ(); + String op = invertOp(operator); + Expression result = new BinaryExpression(op,left,rneg); + result.setBrackets(needsBracket); + return result; + } + else if (operator.equals("->includesAll")) + { Expression result = new BinaryExpression("/<:",right,left); + result.setBrackets(needsBracket); + return result; + } + else if (operator.equals("->excludesAll")) + { Expression inter = new BinaryExpression("/\\",left,right); + Expression result = new UnaryExpression("->notEmpty",inter); + result.setBrackets(needsBracket); + return result; + } + else if (operator.equals("or")) // added 9.1.2016 + { Expression notA = left.computeNegation4succ(); + Expression notB = right.computeNegation4succ(); + Expression res = new BinaryExpression("&",notA,notB); + res.setBrackets(needsBracket); + return res; + } + + Expression result; + if (comparitors.contains(operator) || ":".equals(operator) || + "/:".equals(operator) || "<:".equals(operator) || "/<:".equals(operator) || + "->includes".equals(operator) || "->excludes".equals(operator)) + { String op = negateOp(operator); + result = new BinaryExpression(op,left,right); + } + else + { result = new UnaryExpression("not", this); } + result.setBrackets(needsBracket); + return result; + } // but not for +, -, etc + + private Expression computeEqNegation4succ() + { if (right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + if (rbe.umlkind == VALUE) + { if (rbe.data.equals("true")) + { Expression newright = new BasicExpression("false"); + return new BinaryExpression("=",left,newright); + } + if (rbe.data.equals("false")) + { Expression newright = new BasicExpression("true"); + return new BinaryExpression("=",left,newright); + } + Type rt = rbe.getType(); + Vector vals = rt.getValues(); + if (vals != null) + { Vector newvals = (Vector) vals.clone(); + newvals.remove(rbe.data); + if (newvals.size() == 1) + { String other = (String) newvals.get(0); + BasicExpression otherbe = new BasicExpression(other); + if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if (lbe.objectRef != null && + lbe.objectRef.isMultiple()) + { return new BinaryExpression(":",otherbe,left); } + } + return new BinaryExpression("=",left,otherbe); + } + else + { SetExpression se = + new SetExpression(newvals); + if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if (lbe.objectRef != null && + lbe.objectRef.isMultiple()) + { SetExpression empty = new SetExpression(); + Expression inter = new BinaryExpression("/\\",left,se); + return new BinaryExpression("/=",inter,empty); + } + } + return new BinaryExpression(":",left,se); + } + } + } + } + return new BinaryExpression("/=",left,right); + } // But non-basics can also be multiple ... + + public Vector computeNegation4ante() + { if (operator.equals("=")) + { return computeEqNegation4ante(); } + else if (operator.equals("&")) + { Vector res1 = left.computeNegation4ante(); + Vector res2 = right.computeNegation4ante(); + return VectorUtil.vector_merge(res1,res2); + } + else if (operator.equals("!=") || operator.equals("/=") || operator.equals("<>")) + { Vector res = new Vector(); + res.add(new BinaryExpression("=",left,right)); + return res; + } + Vector res = new Vector(); + + // negate the op. + Expression result; + if (comparitors.contains(operator) || ":".equals(operator) || + "/:".equals(operator) || "<:".equals(operator) || "/<:".equals(operator) || + "->includes".equals(operator) || "->excludes".equals(operator)) + { String op = negateOp(operator); + result = new BinaryExpression(op,left,right); + } + else + { result = new UnaryExpression("not", this); } + result.setBrackets(needsBracket); + res.add(result); + + return res; + } + + private Vector computeEqNegation4ante() + { Vector res = new Vector(); + if (right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + if (rbe.umlkind == VALUE) + { if (rbe.data.equals("true")) + { Expression newright = new BasicExpression("false"); + res.add(new BinaryExpression("=",left,newright)); + return res; + } + if (rbe.data.equals("false")) + { Expression newright = new BasicExpression("true"); + res.add(new BinaryExpression("=",left,newright)); + return res; + } + Type rt = rbe.getType(); + Vector vals = rt.getValues(); + if (vals != null) + { Vector newvals = (Vector) vals.clone(); + newvals.remove(rbe.data); + if (newvals.size() == 1) + { String other = (String) newvals.get(0); + BasicExpression otherbe = new BasicExpression(other); + if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if (lbe.objectRef != null && + lbe.objectRef.isMultiple()) + { res.add(new BinaryExpression(":",otherbe,left)); + return res; + } + } + res.add(new BinaryExpression("=",left,otherbe)); + return res; + } + else + { if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if (lbe.objectRef != null && + lbe.objectRef.isMultiple()) + { for (int i = 0; i < newvals.size(); i++) + { String val = (String) newvals.get(i); + BasicExpression valbe = new BasicExpression(val); + res.add(new BinaryExpression(":",valbe,left)); + } + return res; + } + } + for (int j = 0; j < newvals.size(); j++) + { String val = (String) newvals.get(j); + BasicExpression valbe = new BasicExpression(val); + res.add(new BinaryExpression("=",left,valbe)); + } + return res; + } + } + } + } + res.add(new BinaryExpression("/=",left,right)); + return res; + } + + + public Expression computeNegation4succ(final Vector sms) + { if (operator.equals("=")) + { return computeEqNegation4succ(sms); } + else if (operator.equals("&")) + { System.err.println("Can't compute negation for succ of " + + toString()); + return new BasicExpression("false"); + } + else if (operator.equals("!=")) + { return new BinaryExpression("=",left,right); } + // clone them? + return new BasicExpression("false"); + } + + public Expression computeEqNegation4succ(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + Expression newsucc = null; + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) + { leftcat = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + } + int rcat = sm.getCategory(ber.data); + if (rcat >= 0) + { rightcat = rcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + } + } + if (rightcat == Statemachine.STATEMACHINE) + { int temp = rightcat; // swap left and right + rightcat = leftcat; + leftcat = temp; + temp = rmult; + rmult = lmult; + lmult = temp; + Statemachine stemp = rightsm; + rightsm = leftsm; + leftsm = stemp; + } + // String lvalue = bel.toString(); + + if (leftcat == Statemachine.STATEMACHINE && + rightcat == Statemachine.STATE) + { Vector otherstates = + (Vector) leftsm.getStateNames().clone(); + otherstates.remove(ber.data); + if (otherstates.size() == 1) + { String otherstate = (String) otherstates.get(0); + newsucc = + new BinaryExpression("=", + (Expression) bel.clone(), + new BasicExpression(otherstate)); + return newsucc; + } + else // otherstates.size() > 1 + { newsucc = + new BinaryExpression("!=", + (Expression) bel.clone(), + (Expression) ber.clone()); + return newsucc; + } + } + // swap left and right if rightcat == ATTRIBUTE + if (leftcat == Statemachine.ATTRIBUTE) + { Vector othervals = leftsm.getRange(bel.data); + othervals.remove(ber.data); + if (othervals.size() == 1) + { String otherval = (String) othervals.get(0); + newsucc = + new BinaryExpression("=", + (Expression) bel.clone(), + new BasicExpression(otherval)); + return newsucc; + } + else if (othervals.size() > 1) + { newsucc = + new BinaryExpression("!=", + (Expression) bel.clone(), + (Expression) ber.clone()); + return newsucc; + } + else // shouldn't happen + { newsucc = new BasicExpression("false"); } + } + + System.err.println("I can't produce a sensible " + + "negation for succ of: " + bel + " = " + ber); + return newsucc; + } + + + public Vector computeNegation4ante(final Vector sms) + { if (operator.equals("=")) + { return computeEqNegation4ante(sms); } + else if (operator.equals("&")) + { Vector res1 = left.computeNegation4ante(sms); + Vector res2 = right.computeNegation4ante(sms); + return VectorUtil.vector_merge(res1,res2); + } + else if (operator.equals("!=")) + { Vector res = new Vector(); + res.add(new BinaryExpression("=",left,right)); + return res; + } + // clone them? + return new Vector(); + } + + public Vector computeEqNegation4ante(final Vector sms) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + int leftcat = Statemachine.NONE; + int rightcat = Statemachine.NONE; + Statemachine leftsm = null; + Statemachine rightsm = null; + int lmult = 0; + int rmult = 0; + Vector newante = new Vector(); + + for (int i = 0; i < sms.size(); i++) + { Statemachine sm = (Statemachine) sms.get(i); + int lcat = sm.getCategory(bel.data); + if (lcat >= 0) + { leftcat = lcat; + leftsm = sm; + lmult = sm.getMultiplicity(); + } + int rcat = sm.getCategory(ber.data); + if (rcat >= 0) + { rightcat = rcat; + rightsm = sm; + rmult = sm.getMultiplicity(); + } + } + if (rightcat == Statemachine.STATEMACHINE) + { int temp = rightcat; // swap left and right + rightcat = leftcat; + leftcat = temp; + temp = rmult; + rmult = lmult; + lmult = temp; + Statemachine stemp = rightsm; + rightsm = leftsm; + leftsm = stemp; + } + // String lvalue = bel.toString(); + + if (leftcat == Statemachine.STATEMACHINE && + rightcat == Statemachine.STATE) + { Vector otherstates = + (Vector) leftsm.getStateNames().clone(); + otherstates.remove(ber.data); + for (int i = 0; i < otherstates.size(); i++) + { String otherstate = (String) otherstates.get(i); + newante.add( + new BinaryExpression("=", + (Expression) bel.clone(), + new BasicExpression(otherstate))); + } + return newante; + } + // swap left and right if rightcat == ATTRIBUTE + if (leftcat == Statemachine.ATTRIBUTE) + { Vector othervals = leftsm.getRange(bel.data); + othervals.remove(ber.data); + for (int i = 0; i < othervals.size(); i++) + { String otherval = (String) othervals.get(i); + newante.add( + new BinaryExpression("=", + (Expression) bel.clone(), + new BasicExpression(otherval))); + } + return newante; + } + + System.err.println("I can't produce a sensible " + + "negation for ante of: " + bel + " = " + ber); + return newante; + } + + public DataDependency getDataItems() + { DataDependency res = left.getDataItems(); + res.union(right.getDataItems()); + return res; + } + + public DataDependency rhsDataDependency() + { // if p.f = val then val, p --> f + + if (operator.equals("&")) + { DataDependency dd1 = left.rhsDataDependency(); + DataDependency dd2 = right.rhsDataDependency(); + dd1.union(dd2); + return dd1; + } + else if (operator.equals("#")) + { DataDependency dd2 = right.rhsDataDependency(); + return dd2; + } + else if (operator.equals("=")) + { if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + DataDependency dr = right.getDataItems(); + // if (bel.objectRef != null || bel.arrayIndex != null) + // { DataDependency pr = bel.getDataItems(); + // dr.union(pr); + // } + dr.addTarget(new BasicExpression(bel.data)); + System.out.println(">>> Data dependency of: " + this + " is: " + dr); + return dr; + } + else if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + DataDependency dl = left.getDataItems(); + if (ber.objectRef != null || ber.arrayIndex != null) + { DataDependency pr = ber.getDataItems(); + dl.union(pr); + } + dl.addTarget(new BasicExpression(ber.data)); + return dl; + } + else // assume both are changed? -- no, neither, surely? + { DataDependency ddl = left.getDataItems(); + DataDependency ddr = right.getDataItems(); + DataDependency dd = new DataDependency(); + dd.addTargets(ddl); + dd.addTargets(ddr); + return dd; + } + } + if (operator.equals(":") || operator.equals("/:") || + operator.equals("/<:") || operator.equals("<:")) + { DataDependency ddr = new DataDependency(); + DataDependency ddl = left.getDataItems(); + if (right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + if (rbe.objectRef != null || rbe.arrayIndex != null) + { ddr = rbe.getDataItems(); } + + ddl.union(ddr); + ddl.addTarget(new BasicExpression(rbe.data)); + return ddl; + } + else // it is the left that is the updated thing? + { ddr = right.getDataItems(); + ddl.addTargets(ddr); + return ddl; + } + } + if (operator.equals("->includes") || operator.equals("->excludes") || + operator.equals("->excludesAll") || operator.equals("->includesAll")) + { DataDependency ddl = new DataDependency(); + DataDependency ddr = right.getDataItems(); + if (left instanceof BasicExpression) + { BasicExpression lbe = (BasicExpression) left; + if (lbe.objectRef != null || lbe.arrayIndex != null) + { ddl = lbe.getDataItems(); } + + ddr.union(ddl); + ddr.addTarget(new BasicExpression(lbe.data)); + return ddr; + } + else // it is the left that is the updated thing? + { ddl = left.getDataItems(); + ddr.addTargets(ddl); + return ddr; + } + } + return new DataDependency(); + } + + public UpdateFeatureInfo updateFeature(String feature) + { UpdateFeatureInfo res = null; + if (operator.equals("&")) + { // chain together UFI's? + if (left instanceof BinaryExpression) + { BinaryExpression beleft = (BinaryExpression) left; + UpdateFeatureInfo ufi1 = beleft.updateFeature(feature); + if (ufi1 != null) { ufi1.newexp = this; } + return ufi1; + } + if (right instanceof BinaryExpression) + { BinaryExpression beright = (BinaryExpression) right; + UpdateFeatureInfo ufi2 = beright.updateFeature(feature); + if (ufi2 != null) { ufi2.newexp = this; } + return ufi2; + } + return null; + } + if (operator.equals("#")) + { if (right instanceof BinaryExpression) + { UpdateFeatureInfo ufi1 = ((BinaryExpression) right).updateFeature(feature); + if (ufi1 != null) { ufi1.newexp = this; } + return ufi1; + } + else + { UpdateFeatureInfo ufi2 = ((BinaryExpression) left).updateFeature(feature); + if (ufi2 != null) { ufi2.newexp = this; } + return ufi2; + } + } + if (operator.equals("=")) + { if (left instanceof BasicExpression) + { BasicExpression be = (BasicExpression) left; + String f = be.getData(); + if (f.equals(feature) && be.objectRef == null) // try rhs instead + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + String f2 = ber.getData(); + if (f2.equals(feature) && ber.objectRef == null) + { return null; } // give up + Entity e2 = ber.getEntity(); + if (ber.umlkind == ATTRIBUTE) + { Attribute att2 = e2.getAttribute(f2); + if (att2 != null) + { if (att2.isAssignable()) + { return new UpdateFeatureInfo(f2,left,ber.objectRef,reverse()); } + } + } + else if (ber.umlkind == ROLE) + { return new UpdateFeatureInfo(f2,left,ber.objectRef,reverse()); } + } + } + else + { Entity e = be.getEntity(); + if (be.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) + { return new UpdateFeatureInfo(f,right,be.objectRef,this); } + } + } + else if (be.umlkind == ROLE) + { return new UpdateFeatureInfo(f,right,be.objectRef,this); } + // roles can be frozen however + } + } + else if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + String f = ber.getData(); + if (f.equals(feature) && ber.objectRef == null) // give up + { return null; } + Entity e = ber.getEntity(); + if (ber.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) + { return new UpdateFeatureInfo(f,left,ber.objectRef,reverse()); } + } + } + else if (ber.umlkind == ROLE) + { return new UpdateFeatureInfo(f,left,ber.objectRef,reverse()); } + } + return null; + } + else if (operator.equals(":") || + operator.equals("/:") || operator.equals("/<:") || + operator.equals("<:")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + // must be a role + String f = ber.getData(); // and swap exp? + if (f.equals(feature) && ber.objectRef == null) + // return left, if a basic expression? + { return null; } + return new UpdateFeatureInfo(f,left,ber.objectRef,this); + } + else if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if ("result".equals(bel.getData())) + { return new UpdateFeatureInfo("result",right,bel.objectRef,this); } + } + } + return null; + } // cases of ->includes, etc + + + public Expression updateExpression() + { if (operator.equals("=") || operator.equals("->includes") || + operator.equals("->excludes") || operator.equals("->includesAll") || + operator.equals("->excludesAll")) + { if (left instanceof BasicExpression) + { BasicExpression be = (BasicExpression) left; + String f = be.getData(); + Entity e = be.getEntity(); + if (be.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) { return right; } } + } + else if (be.umlkind == ROLE) + { return right; } // roles can be frozen however + } + else if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + String f = ber.getData(); + Entity e = ber.getEntity(); + if (ber.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) { return left; } } + } + else if (ber.umlkind == ROLE) + { return left; } // roles can be frozen however + } + return null; + } + else if (operator.equals(":") || + operator.equals("/:") || operator.equals("/<:") || + operator.equals("<:")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + // must be a role + return left; // and swap exp? + } + else if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if ("result".equals(bel.getData())) + { return right; } + } + } + return null; + } // cases of ->includes, etc + + public Expression updateReference() + { if (operator.equals("=") || operator.equals("->includes") || + operator.equals("->excludes") || operator.equals("->includesAll") || + operator.equals("->excludesAll")) + { if (left instanceof BasicExpression) + { BasicExpression be = (BasicExpression) left; + String f = be.getData(); + Entity e = be.getEntity(); + if (be.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) { return be.objectRef; } } + } + else if (be.umlkind == ROLE) + { return be.objectRef; } // roles can be frozen however + } + else if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + String f = ber.getData(); + Entity e = ber.getEntity(); + if (ber.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) { return ber.objectRef; } } + } + else if (ber.umlkind == ROLE) + { return ber.objectRef; } // roles can be frozen however + } + return null; + } + else if (operator.equals(":") || + operator.equals("/:") || + operator.equals("<:")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + // must be a role + return ber.objectRef; // and swap exp? + } + else if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if ("result".equals(bel.getData())) + { return null; } + } + } + return null; + } + + public boolean isUpdateable() // true if can be used to generate update code + { boolean res = false; + if (operator.equals("&")) + { // chain together UFI's? + if (left instanceof BinaryExpression) + { BinaryExpression beleft = (BinaryExpression) left; + return beleft.isUpdateable(); + } + if (right instanceof BinaryExpression) + { BinaryExpression beright = (BinaryExpression) right; + return beright.isUpdateable(); + } + return false; + } + if (operator.equals("=>") || operator.equals("!")) + { if (right instanceof BinaryExpression) + { return ((BinaryExpression) right).isUpdateable(); } + return false; + } + if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { if (right instanceof BinaryExpression) + { if (((BinaryExpression) right).isUpdateable()) + { return true; } + } + if (left instanceof BinaryExpression) + { BinaryExpression beleft = (BinaryExpression) left; + return beleft.isUpdateable(); + } + return false; + } + if (operator.equals("=")) + { if (left instanceof BasicExpression) + { return left.isAssignable(); } + // must be assignable - a VARIABLE, ROLE or ATTRIBUTE + else if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + String f = ber.getData(); + Entity e = ber.getEntity(); + if (ber.umlkind == ATTRIBUTE) + { Attribute att = e.getAttribute(f); + if (att != null) + { if (att.isAssignable()) + { return true; } + } + return false; + } + return true; + } + } + else if (operator.equals(":") || + operator.equals("/:") || operator.equals("/<:") || + operator.equals("<:")) + { if (right instanceof BasicExpression) + { return right.isAssignable(); } // and assignable + else if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if ("result".equals(bel.getData())) + { return true; } + } + } + else if (operator.equals("->includes") || operator.equals("->excludes") || + operator.equals("->includesAll") || + operator.equals("->excludesAll")) + { if (left instanceof BasicExpression) + { return left.isAssignable(); } // and assignable + else if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if ("result".equals(ber.getData())) + { return true; } + } + } + return false; + } + + public Vector allBinarySubexpressions() + { // returns new Vector() by default. + Vector res = new Vector(); + if (left instanceof BasicExpression && + right instanceof BasicExpression) + { res.add(clone()); } + else if (operator.equals("&")) + { res.addAll(left.allBinarySubexpressions()); + res.addAll(right.allBinarySubexpressions()); + } + else if (operator.equals("#") || operator.equals("#1") || operator.equals("#LC") || + operator.equals("!")) + { res.addAll(right.allBinarySubexpressions()); } + return res; + } // case of => ? + + public Vector allConjuncts() + { // returns new Vector() by default. + Vector res = new Vector(); + if (operator.equals("&")) + { Vector map1 = left.allConjuncts(); + Vector map2 = right.allConjuncts(); + // (conj,x & right) for each (conj,x) : map1, etc: + for (int i = 0; i < map1.size(); i++) + { Vector conjx = (Vector) map1.get(i); + Expression x = (Expression) conjx.get(1); + Expression newx = Expression.simplify("&",x,right,new Vector()); + Vector newconjx = new Vector(); + newconjx.add(conjx.get(0)); + newconjx.add(newx); + res.add(newconjx); + } + for (int i = 0; i < map2.size(); i++) + { Vector conjx = (Vector) map2.get(i); + Expression x = (Expression) conjx.get(1); + Expression newx = Expression.simplify("&",left,x,new Vector()); + Vector newconjx = new Vector(); + newconjx.add(conjx.get(0)); + newconjx.add(newx); + res.add(newconjx); + } + } + else + { Vector map = new Vector(); + map.add(this); + map.add(null); + res.add(map); + } + return res; + } + + public Vector getConjuncts() + { // returns new Vector() by default. + Vector res = new Vector(); + if (operator.equals("&")) { } + else + { res.add(this); + return res; + } + + + Vector map1 = left.getConjuncts(); + Vector map2 = right.getConjuncts(); + res = VectorUtil.union(map1, map2); + return res; + } + + public Vector allDisjuncts() + { // returns new Vector() by default. + Vector res = new Vector(); + if (operator.equals("or")) { } + else + { res.add(this); + return res; + } + + + Vector map1 = left.allDisjuncts(); + Vector map2 = right.allDisjuncts(); + res = VectorUtil.union(map1, map2); + return res; + } + + public String updatedData() + { return left.updatedData(); } + // when this := val is a valid update + + public Vector allReadBasicExpressionData() + { Vector res = new Vector(); + res = VectorUtil.union(res, + left.allReadBasicExpressionData()); + res = VectorUtil.union(res, + right.allReadBasicExpressionData()); + return res; + } + + + // The set of features in writable mode in the expression + public Vector writeFrame() + { Vector res = new Vector(); + if (operator.equals("=")) + { if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + res.add(bel.getData()); + } + return res; + } + + if (operator.equals("&") || operator.equals("xor")) + { res = left.writeFrame(); + res.addAll(right.writeFrame()); + return res; + } + + if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { res = right.writeFrame(); + if (left instanceof BinaryExpression) + { BinaryExpression leftbe = (BinaryExpression) left; + if (leftbe.right.umlkind != CLASSID) + { return res; } + Entity e = leftbe.right.entity; + if (e == null) + { return res; } + if (e.isAbstract()) + { return res; } + if ((leftbe.right + "").endsWith("@pre")) + { return res; } + // all superclasses of e, and e. + Vector supers = e.getAllSuperclasses(); + Vector wrleft = new Vector(); + wrleft.add(e + ""); + for (int i = 0; i < supers.size(); i++) + { Entity esup = (Entity) supers.get(i); + wrleft.add(esup + ""); + } + return VectorUtil.union(res,wrleft); + } + return res; + } + + if (operator.equals("=>") || operator.equals("!") || + operator.equals("->forAll")) + // || operator.equals(":") || + // operator.equals("<:")) + { return right.writeFrame(); } + + if (operator.equals("->select") || // Only for implicit + operator.equals("->reject") || // updates + operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("->excludesAll") || + operator.equals("->includesAll")) + { return left.writeFrame(); } + + return res; + } + + public Vector wr(Vector assocs) + { Vector res = new Vector(); + if (operator.equals("=") || + operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("->includesAll") || + operator.equals("->excludesAll")) + { return left.wr(assocs); } // just the left.data + + if (operator.equals(":") || operator.equals("<:") || + operator.equals("/:") || operator.equals("/<:")) + { return right.wr(assocs); } + + if (operator.equals("&") || operator.equals("xor")) + { return VectorUtil.union(left.wr(assocs),right.wr(assocs)); } + + if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { // left is not written if it is preform, abstract class or not a class + res = right.wr(assocs); + if (left instanceof BinaryExpression) + { BinaryExpression leftbe = (BinaryExpression) left; + if (leftbe.right.umlkind != CLASSID) + { return res; } + Entity e = leftbe.right.entity; + if (e == null) + { return res; } + if (e.isAbstract()) + { return res; } + if ((leftbe.right + "").endsWith("@pre")) + { return res; } + return VectorUtil.union(res,left.wr(assocs)); + } + } + + if (operator.equals("=>") || operator.equals("!") || + operator.equals("->forAll")) // surely? + { return right.wr(assocs); } + + if (operator.equals("->select") || + operator.equals("->reject") || // for isDeleted + operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("->excludesAll") || + operator.equals("->includesAll")) + { return left.wr(assocs); } + + return res; + } + + public Vector cwr(Vector assocs) + { // The data which is completely over-written + + Vector res = new Vector(); + + if (operator.equals("=")) + { return left.wr(assocs); } // just the left.data + + if (operator.equals(":") || operator.equals("<:") || + operator.equals("/:") || operator.equals("/<:")) + { return res; } + + if (operator.equals("&") || operator.equals("xor")) + { return VectorUtil.union(left.cwr(assocs),right.cwr(assocs)); } + + if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { // left is not written if it is preform, abstract class or not a class + return right.cwr(assocs); + } + + if (operator.equals("=>") || operator.equals("!") || + operator.equals("->forAll")) + { return right.cwr(assocs); } + + return res; + } + + // cases of /:, /<: ?? ->exists, ->exists1, ->forAll? + /* + public Vector wrdel(Vector assocs) + { Vector res = new Vector(); + if (operator.equals("->select") || operator.equals("->reject") || + operator.equals("->excluding")) + { return left.wrdel(assocs); } + if (operator.equals("->including") || + operator.equals("->union") || operator.equals("->intersection") || + operator.equals("\\/") || operator.equals("/\\")) + { res = left.wrdel(assocs); + return VectorUtil.union(res,right.wrdel(assocs)); + } + return res; + } */ + + + public Vector allReadFrame() + { Vector res = new Vector(); + res = left.allReadFrame(); + return VectorUtil.union(res,right.allReadFrame()); + } + + public Vector readFrame() + { Vector res = new Vector(); + if (operator.equals("=") || + operator.equals("->excludes") || + operator.equals("->includes") || + operator.equals("->excludesAll") || + operator.equals("->includesAll")) + { if (left instanceof BasicExpression) + { BasicExpression beleft = (BasicExpression) left; + if (beleft.arrayIndex != null) + { res.addAll(beleft.arrayIndex.allReadFrame()); } + if (beleft.objectRef != null) + { res.addAll(beleft.objectRef.allReadFrame()); } + res.addAll(right.allReadFrame()); + return res; + } + res = left.allReadFrame(); + res.addAll(right.allReadFrame()); + return res; + } + + if (operator.equals(":") || operator.equals("<:") || + operator.equals("/:") || operator.equals("/<:")) + { if (right instanceof BasicExpression) + { BasicExpression beright = (BasicExpression) right; + if (beright.arrayIndex != null) + { res.addAll(beright.arrayIndex.allReadFrame()); } + if (beright.objectRef != null) + { res.addAll(beright.objectRef.allReadFrame()); } + res.addAll(left.allReadFrame()); + return res; + } + res = left.allReadFrame(); + res.addAll(right.allReadFrame()); + return res; + } + + if (operator.equals("=>")) + { Vector lrf = left.allReadFrame(); + return VectorUtil.union(lrf,right.readFrame()); + } + + if (operator.equals("!")) + { Vector rfscope = + ((BinaryExpression) left).right.allReadFrame(); + return VectorUtil.union(rfscope,right.readFrame()); + } // some cases of #, #1 are also like this + + // special treatment of #, #1 needed, eg, t.f = a & t.g = t.f*2 & + + // Added 27/2/2023: + + if (operator.equals("|C") || operator.equals("|") || + operator.equals("|R") || operator.equals("|A") || + operator.equals("|sortedBy") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|selectMaximals") || + operator.equals("|selectMinimals")) + { Vector rfscope = + ((BinaryExpression) left).right.allReadFrame(); + return VectorUtil.union(rfscope,right.readFrame()); + } + + return VectorUtil.union(left.readFrame(),right.readFrame()); + } + + public Vector internalReadFrame() + { Vector res = new Vector(); + + if (operator.equals("=") || + operator.equals("->excludes") || + operator.equals("->includes") || + operator.equals("->excludesAll") || + operator.equals("->includesAll")) + { if (left instanceof BasicExpression) + { BasicExpression beleft = (BasicExpression) left; + if (beleft.arrayIndex != null) + { res.addAll(beleft.arrayIndex.allReadFrame()); } + if (beleft.objectRef != null) + { res.addAll(beleft.objectRef.allReadFrame()); } + res.addAll(right.allReadFrame()); + return res; + } + res = left.allReadFrame(); + res.addAll(right.allReadFrame()); + return res; + } + + if (operator.equals(":") || operator.equals("<:") || + operator.equals("/:") || operator.equals("/<:")) + { if (right instanceof BasicExpression) + { BasicExpression beright = (BasicExpression) right; + if (beright.arrayIndex != null) + { res.addAll(beright.arrayIndex.allReadFrame()); } + if (beright.objectRef != null) + { res.addAll(beright.objectRef.allReadFrame()); } + res.addAll(left.allReadFrame()); + return res; + } + res = left.allReadFrame(); + res.addAll(right.allReadFrame()); + return res; + } + + if (operator.equals("=>")) + { Vector lrf = left.allReadFrame(); + return VectorUtil.union(lrf,right.internalReadFrame()); + } + + if (operator.equals("!")) + { Vector rfscope = ((BinaryExpression) left).right.allReadFrame(); + return VectorUtil.union(rfscope,right.internalReadFrame()); + } // some cases of #, #1 are also like this + + // special treatment of #, #1 needed, eg, t.f = a & t.g = t.f*2 & + + if (operator.equals("&")) + { Vector lrf = left.internalReadFrame(); + Vector assocs = new Vector(); + Vector wf = left.cwr(assocs); + Vector rrf = right.readFrame(); + Vector resr = new Vector(); + resr.addAll(rrf); + resr.removeAll(wf); // read elements that were not over-written in left. + + Vector rr = VectorUtil.union(lrf, resr); + // System.out.println("INTERNAL READ FRAME OF " + this + " IS: " + rr); + return rr; + } + + // Added 27/2/2023: + + if (operator.equals("|C") || operator.equals("|") || + operator.equals("|R") || operator.equals("|A") || + operator.equals("|sortedBy") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|selectMaximals") || + operator.equals("|selectMinimals")) + { Vector rfscope = ((BinaryExpression) left).right.allReadFrame(); + // Vector rfscope = left.allReadFrame(); + return VectorUtil.union(rfscope, + right.internalReadFrame()); + } + + return VectorUtil.union(left.internalReadFrame(),right.internalReadFrame()); + } + + public boolean confluenceCheck(Vector iterated, Vector created) + { // true if the only assignments are c.f = e for c in created, or c : s + // where neither s or s@pre are read + // Local assignments are also ok. + + // assignments c.cId = e for created c and cId an identify must have: + // (i) e is a variable, or an identity attribute of an iterated element, or + // a 1-1 function of such an attribute; (ii) e cannot be a constant and + // should not be a many-1 function. + + boolean res = false; + + if (operator.equals("=")) + { if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if (created.contains(bel.objectRef + "")) + { return checkIdentityAssignment(bel,iterated,created); } + else + { Vector vleft = new Vector(); + vleft.add(bel.objectRef + ""); + Vector vright = right.innermostVariables(); + if (vleft.contains("self")) + { if (vright.size() == 0) + { return true; } // assigning a value to feature of self + else if (vright.size() == 1 && vright.contains("self")) + { return true; } // updating self by its own data + } + else if (vleft.contains("null")) + { if (vright.size() == 0) + { return true; } + else if (vright.size() == 1 && vright.contains("self")) + { return true; } + } + System.out.println(">>> Confluence warning: assignment not to new object or iterated source object: " + this); + return false; + } + } + return false; // not a valid assignment + } + else if (operator.equals(":")) + { if (created.contains(left + "")) // and right.data is unordered + { if (right.entity != null && right instanceof BasicExpression && + right.entity.isOrderedRole(((BasicExpression) right).getData())) + { System.err.println(">>> Potentially fails confluence, addition to ordered role: " + this); + return false; + } + return true; + } + else if (right instanceof BasicExpression) + { BasicExpression re = (BasicExpression) right; + if (created.contains(re.objectRef + "")) + { return true; } + System.out.println("May fail confluence: addition to not newly created object " + this); + return false; + } + return true; // not an update + } + else if (operator.equals("->includes")) + { if (created.contains(right + "")) // and left.data is unordered + { if (left.entity != null && left instanceof BasicExpression && + left.entity.isOrderedRole(((BasicExpression) left).getData())) + { System.err.println(">>> Potentially fails confluence, addition to ordered role: " + this); + return false; + } + return true; + } + else if (left instanceof BasicExpression) + { BasicExpression le = (BasicExpression) left; + if (created.contains(le.objectRef + "")) + { return true; } + System.out.println("May fail confluence: addition to not newly created object " + this); + return false; + } + return true; // not an update + } + else if (operator.equals("<:")) + { if (right instanceof BasicExpression) + { if (right.isOrdered()) + { System.out.println(">>> Potentially fails confluence: addition to ordered collection: " + this); + return false; + } + else + { BasicExpression re = (BasicExpression) right; + if (created.contains(re.objectRef + "")) + { return true; } + System.out.println(">>> Confluence warning: adds objects not newly created: " + this); + return false; + } + } + return true; // not an update + } + else if (operator.equals("->includesAll")) + { if (left instanceof BasicExpression) + { if (left.isOrdered()) + { System.out.println(">>> Confluence warning: addition to ordered collection: " + this); + return false; + } + else + { BasicExpression le = (BasicExpression) left; + if (created.contains(le.objectRef + "")) + { return true; } + System.out.println(">>> Confluence warning: adds objects not newly created: " + this); + return false; + } + } + return true; // not an update + } + else if (operator.equals("&")) + { res = left.confluenceCheck(iterated, created); + if (res) + { return right.confluenceCheck(iterated, created); } + else + { return false; } + } + else if (operator.equals("=>")) + { return right.confluenceCheck(iterated, created); } + else if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { if (left instanceof BinaryExpression && ((BinaryExpression) left).right.entity != null) + { BinaryExpression lbe = (BinaryExpression) left; + Vector cr = new Vector(); + cr.addAll(created); + + Vector ukeys = lbe.right.entity.getUniqueAttributes(); + + if (("" + lbe.right).endsWith("@pre") || lbe.right.entity.isAbstract()) + { } + else if (iterated.size() <= 1 || ukeys.size() == 0) + { cr.add(lbe.left + ""); } + return right.confluenceCheck(iterated, cr); + } + else + { return right.confluenceCheck(iterated, created); } + } + else if (operator.equals("->exists") || + operator.equals("->exists1")) + { return right.confluenceCheck(iterated, created); } + else if (operator.equals("!")) + { if (left instanceof BinaryExpression && ((BinaryExpression) left).right.entity != null) + { BinaryExpression lbe = (BinaryExpression) left; + Vector cr = new Vector(); + cr.addAll(iterated); + cr.add(lbe.left); + return right.confluenceCheck(cr, created); + } + return right.confluenceCheck(iterated, created); + } + else + { return false; } + } + + public boolean checkIdentityAssignment(BasicExpression bel, Vector iterated, Vector created) + { // assignments c.cId = e for created c and cId an identify must have: + // (i) e is a variable, or an identity attribute of an iterated element, or + // a 1-1 function of such an attribute; (ii) e cannot be a constant and + // should not be a many-1 function. + + boolean res = false; + if (bel.umlkind != ATTRIBUTE) + { return true; } + + Entity lefte = left.getEntity(); + if (bel.objectRef != null) + { Type lot = bel.objectRef.getElementType(); + if (lot.isEntity()) + { lefte = lot.getEntity(); } + } + + if (lefte == null) // not a feature of an entity + { return true; } + + Attribute key = lefte.getUniqueAttribute(bel.data); + if (key == null) + { return true; } + + System.out.println(); + // System.out.println(">>> Checking assignment to key attribute " + bel.data + " of " + lefte); + + if (right instanceof BasicExpression) + { BasicExpression rbe = (BasicExpression) right; + if (rbe.umlkind == CONSTANT && iterated.size() > 0) + { System.err.println(">>> Confluence error: assigning constant to key of created object within an iteration: " + this); + return false; + } + else if (rbe.umlkind == VALUE && iterated.size() == 0) + { System.err.println(">>> Warning, possible confluence error: assigning value to key of created object: " + this); + return false; + } + else if (rbe.umlkind == VALUE && iterated.size() > 0) + { System.err.println(">>> Confluence error: assigning value to key of created object within an iteration: " + this); + return false; + } + else if (rbe.umlkind == CONSTANT && iterated.size() == 0) + { System.err.println(">>> Warning, possible confluence error: assigning constant to key of created object: " + this); + return false; + } + else if (rbe.umlkind == VARIABLE) + { System.out.println(">>> Assignment of variable to identity attribute, error if variable is not value of a source primary key or 1-1 function of value: " + this); + return true; + } + else if (rbe.umlkind == ATTRIBUTE) + { Expression ror = rbe.objectRef; + Entity rent = right.getEntity(); + if (ror != null) + { rent = ror.getElementType().getEntity(); } + + Attribute ratt = rent.getUniqueAttribute(rbe.data); + if (ratt == null) + { System.out.println("Possible confluence error: Assignment of non-identity attribute to identity attribute: " + this); + return true; + } + } + else if (rbe.umlkind == FUNCTION) // ok for reverse, dubious for front, tail, subrange, etc + { if (rbe.data.equals("reverse")) + { return true; } + if (rbe.data.equals("front") || "tail".equals(rbe.data) || "subrange".equals(rbe.data) + || "toLowerCase".equals(rbe.data) || "toUpperCase".equals(rbe.data)) + { System.out.println(">>> Possible confluence error: Assignment of many-one function value to identity attribute: " + this); + return true; + } + } + else if (right instanceof UnaryExpression) + { UnaryExpression rune = (UnaryExpression) right; + if (rune.operator.equals("front") || "tail".equals(rune.operator) || + "subrange".equals(rune.operator) || "toLowerCase".equals(rune.operator) || + "toUpperCase".equals(rune.operator)) + { System.out.println(">>> Possible confluence error: Assignment of many-one function value to identity attribute: " + this); + return true; + } + } // reverse is ok again. + else if (right instanceof BinaryExpression) + { BinaryExpression rbin = (BinaryExpression) right; + if (rbin.operator.equals("+")) + { if (rbin.left.umlkind == VALUE && rbin.right.umlkind == VALUE) + { System.err.println(">>> Confluence error: Assignment of constant value to an identity attribute: " + this); + return false; + } + else if (rbin.left.umlkind == VALUE || rbin.right.umlkind == VALUE) + { return true; } + } + else if (rbin.operator.equals("-")) + { System.out.println(">>> Possible confluence error: Assignment of many-one function value to identity attribute: " + this); + return true; + } + } + } + return true; + + } + + + // returns true if opf(val) can possibly make expression true + public boolean relevantOccurrence(String op, Entity ent, + String val, + String f) + { boolean rel1 = left.relevantOccurrence(op,ent,val,f); + boolean rel2 = right.relevantOccurrence(op,ent,val,f); + if (!rel1 && !rel2) { return false; } + + if (operator.equals("=") && op.equals("set")) + { if (left instanceof BasicExpression && + right instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + if (bel.data.equals(f) && + !ber.data.equals(val) && + ber.getType().getValues() != null && + ber.getType().getValues().contains(val)) + { return false; } + if (ber.data.equals(f) && + !bel.data.equals(val) && + bel.getType().getValues() != null && + bel.getType().getValues().contains(val)) + { return false; } + } + return true; // only if f occurs in this? + } + else if (operator.equals("/=") && op.equals("set")) + { if (left instanceof BasicExpression && + right instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + BasicExpression ber = (BasicExpression) right; + if (bel.data.equals(f) && + ber.data.equals(val) && + ber.getType().getValues() != null && + bel.getType().getValues().contains(val)) + { return false; } + } + return true; + } + else if (operator.equals("<:") && op.equals("add")) // also for : + { if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if (bel.data.equals(f) && !rel2) + { return false; } + } + return true; + } + else if (operator.equals("/:") && op.equals("add")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if (ber.data.equals(f) && !rel1) + { return false; } + } + return true; + } + else if (operator.equals("<:") && op.equals("remove")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if (ber.data.equals(f) && !rel1) + { return false; } + } + return true; + } + else if (operator.equals(":") && op.equals("remove")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if (ber.data.equals(f) && !rel1) + { return false; } + } + return true; + } + return true; + } + + // returns true if opf(val) can possibly make expression false + public boolean canFalsify(String op, Entity ent, + String val, String f) + { boolean rel1 = left.allFeaturesUsedIn().contains(f); + boolean rel2 = right.allFeaturesUsedIn().contains(f); + if (!rel1 && !rel2) { return false; } // a change to f cannot affect this + // if no data-dependent feature of f + // occurs in this. + + if (operator.equals("<:") && op.equals("add")) // also for : + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if (ber.data.equals(f) && !rel1) + { return false; } + } + return true; + } + else if (operator.equals("/:") && op.equals("remove")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if (ber.data.equals(f) && !rel1) + { return false; } + } + return true; + } + else if (operator.equals("<:") && op.equals("remove")) + { if (left instanceof BasicExpression) + { BasicExpression bel = (BasicExpression) left; + if (bel.data.equals(f) && !rel2) + { return false; } + } + return true; + } + else if (operator.equals(":") && op.equals("add")) + { if (right instanceof BasicExpression) + { BasicExpression ber = (BasicExpression) right; + if (ber.data.equals(f) && !rel1) + { return false; } + } + return true; + } + return true; + } + + public Expression matchCondition(String op, String f, + Expression exbe) + { // any special rules based on op? + Expression lmc = left.matchCondition(op,f,exbe); + Expression rmc = right.matchCondition(op,f,exbe); + return simplifyOr(lmc,rmc); + } + + + public Expression featureSetting(String var, String feat, Vector remainder) + { // if (left instanceof BasicExpression) + // { BasicExpression beleft = (BasicExpression) left; + // if (beleft.data.equals(feat)) + // { + if ((left + "").equals(var + "." + feat)) + { return right; } + if (operator.equals("&")) + { Vector remainder1 = new Vector(); + Expression lfs = left.featureSetting(var,feat,remainder1); + if (lfs == null) + { remainder.add(left); + return right.featureSetting(var,feat,remainder); + } + remainder.add(right); // remainder1.add(right) ?? + return lfs; + } + if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { Vector rem = new Vector(); + Expression res = right.featureSetting(var,feat,rem); + if (rem.size() > 0) + { Expression rempred = (Expression) rem.get(0); + remainder.add(new BinaryExpression(operator,left,rempred)); + return res; + } + } + return null; + } + + public Expression featureSetting2(String var, String feat, Vector remainder) + { if ((left + "").equals(var + "." + feat)) // operator.equals("=") + { // remainder = new Vector(); + return right; + } + + + if (operator.equals("&")) + { Vector remainder1 = new Vector(); + Vector remainder2 = new Vector(); + Expression lfs = left.featureSetting2(var,feat,remainder1); + if (lfs == null) + { Expression res = right.featureSetting2(var,feat,remainder2); + Vector rem = (Vector) simplifyAnd(remainder1,remainder2); + if (rem != null && rem.size() > 0) + { remainder.add(rem.get(0)); } // remainder.size() == 0 + return res; + } + remainder2.add(right); + Vector rem = (Vector) simplifyAnd(remainder1,remainder2); + if (rem != null && rem.size() > 0) + { remainder.add(rem.get(0)); } // remainder.size() == 0 + return lfs; + } + + if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { Vector rem = new Vector(); + Expression res = right.featureSetting2(var,feat,rem); + if (rem.size() > 0) // res could be null + { Expression rempred = (Expression) rem.get(0); + remainder.add(new BinaryExpression(operator,left,rempred)); + return res; + } + } + + remainder.add(this); + return null; + } + + public Expression featureAdding2(String var, Vector remainder) + { if (":".equals(operator) && (left + "").equals(var + "")) + { + return right; + } + + if ("->includes".equals(operator) && (right + "").equals(var + "")) + { + return left; + } + + if (operator.equals("&")) + { Vector remainder1 = new Vector(); + Vector remainder2 = new Vector(); + Expression lfs = left.featureAdding2(var,remainder1); + if (lfs == null) + { Expression res = right.featureAdding2(var,remainder2); + Vector rem = (Vector) simplifyAnd(remainder1,remainder2); + if (rem != null && rem.size() > 0) + { remainder.add(rem.get(0)); } // remainder.size() == 0 + return res; + } + remainder2.add(right); + Vector rem = (Vector) simplifyAnd(remainder1,remainder2); + if (rem != null && rem.size() > 0) + { remainder.add(rem.get(0)); } // remainder.size() == 0 + return lfs; + } + + /* if (operator.equals("#") || operator.equals("#1")) + { Vector rem = new Vector(); + Expression res = right.featureAdding2(var,rem); + if (rem.size() > 0) // res could be null + { Expression rempred = (Expression) rem.get(0); + remainder.add(new BinaryExpression(operator,left,rempred)); + return res; + } + } */ + + remainder.add(this); + return null; + } + + public Expression simplifyOCL() + { // Double iterations ->select(...)->select(...) + // replaced + + Expression lexpr = left.simplifyOCL(); + Expression rexpr = right.simplifyOCL(); + + if ("->union".equals(operator) && + lexpr instanceof SetExpression && + rexpr instanceof SetExpression) + { // merge the literal sets/sequences/maps + SetExpression res = + SetExpression.mergeSetExpressions((SetExpression) lexpr, + (SetExpression) rexpr); + return res; + } + + if (operator.equals("|")) + { BinaryExpression arg = (BinaryExpression) left; + Expression domain = arg.getRight(); + if (domain instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) domain; + + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyAnd( + newright.addReference(ref, ref.getType()), right); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|", newdomain, newpred); + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested select: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyAnd( + Expression.negate(newright.addReference(ref, + ref.getType())), + right); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|", newdomain, newpred); + } + } + } + else if (operator.equals("|R")) + { BinaryExpression arg = (BinaryExpression) left; + Expression domain = arg.getRight(); + if (domain instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) domain; + + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select/reject: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyAnd( + newright.addReference(ref, ref.getType()), + Expression.negate(right)); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|", newdomain, newpred); + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested reject: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyOr( + newright.addReference(ref, + ref.getType()), + right); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|R", newdomain, newpred); + } + } + } + else if (operator.equals("->select")) + { + if (left instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) left; + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression combinedPred = + new BinaryExpression("&", predicate1, right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->select"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression pred2 = + Expression.negate(predicate1); + Expression combinedPred = + new BinaryExpression("&", pred2, right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->select"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + } + } + else if (operator.equals("->reject")) + { + if (left instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) left; + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression combinedPred = + new BinaryExpression("&", + Expression.negate(predicate1), right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->select"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression pred2 = + Expression.negate(predicate1); + pred2.setBrackets(true); + right.setBrackets(true); + Expression combinedPred = + new BinaryExpression("or", pred2, right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->reject"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + } + } + + BinaryExpression res = (BinaryExpression) clone(); + res.left = lexpr; + res.right = rexpr; + return res; + } + + + public Map energyUse(Map res, Vector rUses, Vector aUses) + { // Double iterations ->select(...)->select(...) + // are amber flags. + // ->select(...)->any() is a red flag. + + left.energyUse(res, rUses, aUses); + right.energyUse(res, rUses, aUses); + + if (operator.equals("|") || + operator.equals("|R")) + { BinaryExpression arg = (BinaryExpression) left; + Expression domain = arg.getRight(); + if (domain instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) domain; + + if (lbe.operator.equals("|") || + lbe.operator.equals("|R") || + lbe.operator.equals("->select") || + lbe.operator.equals("->reject")) + { aUses.add("! Nested select/reject iterators (loops) in " + this + " : more efficient to combine conditions"); + int ascore = (int) res.get("amber"); + res.set("amber", ascore+1); + } + } + } + else if (operator.equals("->select") || + operator.equals("->reject")) + { + if (left instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) left; + + if (lbe.operator.equals("|") || + lbe.operator.equals("|R") || + lbe.operator.equals("->select") || + lbe.operator.equals("->reject")) + { aUses.add("! Nested select/reject iterators (loops) in " + this + " : more efficient to combine conditions"); + int ascore = (int) res.get("amber"); + res.set("amber", ascore+1); + } + } + } + else if ("->sortedBy".equals(operator) || + "|sortedBy".equals(operator)) + { aUses.add("! n*log(n) sorting algorithm used for " + this); + + int ascore = (int) res.get("amber"); + res.set("amber", ascore+1); + } + else if ("->unionAll".equals(operator) || + "|unionAll".equals(operator) || + "->concatenateAll".equals(operator) || + "|concatenateAll".equals(operator) || + "->intersectAll".equals(operator) || + "|intersectAll".equals(operator)) + { aUses.add("! High-cost operator in: " + this); + int ascore = (int) res.get("amber"); + res.set("amber", ascore+1); + } + else if ("->at".equals(operator) && + left instanceof BasicExpression && + ((BasicExpression) left).isOperationCall()) + { // redundant results computation + aUses.add("! Redundant results computation in: " + this); + int ascore = (int) res.get("amber"); + res.set("amber", ascore+1); + } + + return res; + } + + public java.util.Map collectionOperatorUses(int level, + java.util.Map res, + Vector vars) + { // level |-> [x.setAt(i,y), etc] + + left.collectionOperatorUses(level,res,vars); + + if (operator.equals("->including") || + operator.equals("->prepend") || + operator.equals("->append") || + operator.equals("->excluding") || + operator.equals("->excludingFirst") || + operator.equals("->includes") || + operator.equals("->excludes") || + operator.equals("->includesAll") || + operator.equals("->excludesAll") || + operator.equals("<:") || + operator.equals(":") || + operator.equals("/:") || + operator.equals("->intersection") || + operator.equals("->union") || + operator.equals("->restrict") || + operator.equals("->antirestrict")) + { Vector opers = (Vector) res.get(level); + if (opers == null) + { opers = new Vector(); } + opers.add(this); + res.put(level, opers); + + Vector vuses = variablesUsedIn(vars); + if (level > 1 && vuses.size() == 0) + { JOptionPane.showInputDialog(">> The expression " + this + " is independent of the iterator variables " + vars + "\n" + + "Use Extract local variable to optimise."); + refactorELV = true; + } + + return res; + } + + if (operator.equals("->count") || + operator.equals("->at")) + { Vector opers = (Vector) res.get(level); + if (opers == null) + { opers = new Vector(); } + opers.add(this); + res.put(level, opers); + + Vector vuses = variablesUsedIn(vars); + if (level > 1 && vuses.size() == 0) + { JOptionPane.showInputDialog(">> The expression " + this + " is independent of the iterator variables " + vars + "\n" + + "Use Extract local variable to optimise."); + refactorELV = true; + } + + return res; + } + + if (operator.equals("->select") || + operator.equals("->reject") || + operator.equals("->collect") || + operator.equals("->forall") || + operator.equals("->exists") || + operator.equals("->exists1") || + operator.equals("->isUnique") || + operator.equals("->iterate") || + operator.equals("->sortedBy")) + { Vector opers = (Vector) res.get(level); + if (opers == null) + { opers = new Vector(); } + opers.add(this); + res.put(level, opers); + + Vector vuses = variablesUsedIn(vars); + if (level > 1 && vuses.size() == 0) + { JOptionPane.showInputDialog(">> The expression " + this + " is independent of the iterator variables " + vars + "\n" + + "Use Extract local variable to optimise."); + refactorELV = true; + } + + Vector newvars = new Vector(); + newvars.addAll(vars); + newvars.add("self"); + + right.collectionOperatorUses(level+1, res, newvars); + return res; + } + + if (operator.equals("|") || + operator.equals("|R") || + operator.equals("|C") || + operator.equals("!") || + operator.equals("#") || + operator.equals("#1") || + operator.equals("|unionAll") || + operator.equals("|intersectAll") || + operator.equals("|concatenateAll") || + operator.equals("|sortedBy")) + { Vector opers = (Vector) res.get(level); + if (opers == null) + { opers = new Vector(); } + opers.add(this); + res.put(level, opers); + + BinaryExpression iter = (BinaryExpression) left; + String var = "" + iter.getLeft(); + + Vector newvars = new Vector(); + newvars.addAll(vars); + newvars.add(var); + + right.collectionOperatorUses(level+1, res, newvars); + return res; + } + + right.collectionOperatorUses(level,res,vars); + + return res; + } // and the left and right. + + + public int syntacticComplexity() + { int res = left.syntacticComplexity(); + res = res + right.syntacticComplexity(); + if (operator.equals("#") || operator.equals("#1") || + operator.equals("#LC") || operator.equals("!") || + operator.equals("|") || operator.equals("|R") || + operator.equals("|C") || + operator.equals("|A") || + operator.equals("|intersectAll") || + operator.equals("|unionAll") || + operator.equals("|selectMinimals") || + operator.equals("|selectMaximals") + ) + { return res; } + + if (operator.equals("->iterate")) + { if (accumulator != null) + { Expression init = accumulator.getInitialExpression(); + if (init != null) + { res = res + init.syntacticComplexity(); } + } + res = res + 2; + } + + return res + 1; + } + + public int cyclomaticComplexity() + { if (operator.equals("#") || operator.equals("#1") || + operator.equals("#LC") || operator.equals("!")) + { return right.cyclomaticComplexity(); } + else if (operator.equals("&") || + operator.equals("or") || operator.equals("=>")) + { return left.cyclomaticComplexity() + right.cyclomaticComplexity(); } + + if (operator.equals("->iterate")) + { int res = left.cyclomaticComplexity() + right.cyclomaticComplexity(); + if (accumulator != null) + { Expression init = accumulator.getInitialExpression(); + if (init != null) + { res = res + init.cyclomaticComplexity(); } + } + return res; + } + + return 1; + } + + // assume outermost operator is an exists + public Expression isExistsForall(Vector foralls, Expression tracest) + { if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) + { Expression rem = right.isExistsForall(foralls, tracest); + if (rem == null) { return null; } + else + { return new BinaryExpression(operator,left,rem); } + } + else if (operator.equals("&")) + { Expression lrem = left.isForall(foralls, tracest); + Expression rrem = right.isForall(foralls, tracest); + if (lrem == null && rrem == null) + { return null; } + else if (lrem == null) + { return Expression.simplifyAnd(left,rrem); } + else if (rrem == null) + { return Expression.simplifyAnd(lrem,right); } + return null; + } + else if (operator.equals("!")) + { foralls.add(this); + return tracest; // new BasicExpression("$$"); + } // for the trace + else + { return null; } + } + + public Expression isForall(Vector foralls, Expression tracest) + { if (operator.equals("&")) + { Expression lrem = left.isForall(foralls, tracest); + Expression rrem = right.isForall(foralls, tracest); + if (lrem == null && rrem == null) + { return null; } + else if (lrem == null) + { return Expression.simplifyAnd(left,rrem); } + else if (rrem == null) + { return Expression.simplifyAnd(lrem,right); } + return null; + } + else if (operator.equals("!")) + { foralls.add(this); + return tracest; + } // for the trace + else + { return null; } + } + +private BExpression seqselectBinvariantForm(String var, BExpression bsimp, BExpression pexp, + java.util.Map env) +{ String i = Identifier.nextIdentifier("i"); + String j = Identifier.nextIdentifier("j"); + String k = var; // Identifier.nextIdentifier("k"); + String f = Identifier.nextIdentifier("f"); + BExpression fbe = new BBasicExpression(f); + BExpression ibe = new BBasicExpression(i); + BExpression jbe = new BBasicExpression(j); + BExpression kbe = new BBasicExpression(k); + String ssq = Identifier.nextIdentifier("sqxx"); + BExpression ssqe = new BBasicExpression(ssq); + String n = Identifier.nextIdentifier("n"); + BExpression nbe = new BBasicExpression(n); + BExpression domsq = new BUnaryExpression("dom", bsimp); + // env1 maps left.elementType + "" to new BApplyExpression(left.binvariantForm(env,local), kbe) + + BExpression predk = pexp; // right.binvariantForm(env,local); + BExpression setcomp = new BSetComprehension(k, domsq, predk); + BExpression eqcard = new BBinaryExpression("=", new BUnaryExpression("card", ssqe), nbe); + BExpression ileqj = new BBinaryExpression("<=", ibe, jbe); + BExpression fileqfj = + new BBinaryExpression("<=", new BApplyExpression(f,ibe), new BApplyExpression(f,jbe)); + BExpression leq = new BBinaryExpression("=>", ileqj, fileqfj); + Vector vars = new Vector(); + vars.add(i); vars.add(j); + BExpression domf = new BUnaryExpression("dom", fbe); + BExpression indomfi = new BBinaryExpression(":", ibe, domf); + BExpression indomfj = new BBinaryExpression(":", jbe, domf); + BExpression indomf = new BBinaryExpression("&", indomfi, indomfj); + BExpression indomfleq = new BBinaryExpression("&", indomf, leq); + + BExpression ord = new BQuantifierExpression("forall", vars, indomfleq); + BExpression ransq = new BUnaryExpression("ran", bsimp); + BExpression ssqrange = // new BBinaryExpression(":", ssqe, + new BUnaryExpression("seq", ransq); + String ii = Identifier.nextIdentifier("ix"); + BExpression iibe = new BBasicExpression(ii); + BExpression align = new BBinaryExpression("=>", + new BBinaryExpression(":", iibe, + new BUnaryExpression("dom", ssqe)), + new BBinaryExpression("=", new BApplyExpression(ssqe, iibe), + new BApplyExpression(bsimp, new BApplyExpression(fbe, iibe)))); + // i : dom(sq) => sq(i) = left(f(i)) + + BExpression pred2 = new BQuantifierExpression("forall", ii, align); + BExpression rpred = new BBinaryExpression("&", eqcard, pred2); + // BExpression rpred = new BBinaryExpression("&", ssqrange, rpred1); + BExpression pred = new BBinaryExpression("&", ord, rpred); + BExpression frange = new BBinaryExpression(":", fbe, new BUnaryExpression("seq", setcomp)); + BExpression qf = new BQuantifierExpression("exists", f, + new BBinaryExpression("&", frange, pred)); + + BExpression nrange = new BBinaryExpression(":", nbe, domsq); + BExpression qn = new BQuantifierExpression("exists",n, + new BBinaryExpression("&", nrange, qf)); + BExpression res = new BSetComprehension(ssq, ssqrange, qn); + return new BUnaryExpression("union",res); +} + // union({ sq | sq : seq(ran(left)) & #n.(n : dom(left) & + // #f.(f : seq({ k | k : dom(left) & right }) & align & + // !(i,j).(i : dom(f) & j : dom(f) & i <= j => f(i) <= f(j)) & + // card(sq) = n))}) + +// BSetComprehension(var, rng, e) +// is { var | var : rng & e } + + public void changedEntityName(String oldN, String newN) + { left.changedEntityName(oldN, newN); + right.changedEntityName(oldN, newN); + } + + public boolean isRuleCallDisjunction(Vector rules) + { if (operator.equals("or")) { } + else + { return false; } + + if (left instanceof BasicExpression) + { BasicExpression bleft = (BasicExpression) left; + if (bleft.isRuleCall(rules)) { } + else + { return false; } + } + else if (left instanceof BinaryExpression) + { BinaryExpression binleft = (BinaryExpression) left; + if (binleft.isRuleCallDisjunction(rules)) { } + else + { return false; } + } + else + { return false; } + + if (right instanceof BasicExpression) + { BasicExpression bright = (BasicExpression) right; + if (bright.isRuleCall(rules)) { } + else + { return false; } + } + else if (right instanceof BinaryExpression) + { BinaryExpression binright = (BinaryExpression) right; + if (binright.isRuleCallDisjunction(rules)) { } + else + { return false; } + } + else + { return false; } + + return true; + } + + public String cg(CGSpec cgs) + { String etext = this + ""; + if (needsBracket) + { etext = "(" + etext + ")"; } + + Vector args = new Vector(); + Vector eargs = new Vector(); + + if ("->iterate".equals(operator)) + { System.out.println(">>> Trying to match rule for ->iterate " + iteratorVariable + " " + accumulator); + System.out.println(etext); + System.out.println(); + } + + if ("|C".equals(operator) || "|R".equals(operator) || + "|".equals(operator) || "#".equals(operator) || + "#1".equals(operator) || "|sortedBy".equals(operator) || + "|intersectAll".equals(operator) || "|unionAll".equals(operator) || + "|concatenateAll".equals(operator) || "|isUnique".equals(operator) || + "|selectMaximals".equals(operator) || "|selectMinimals".equals(operator) || + "!".equals(operator) || "|A".equals(operator)) + { BinaryExpression beleft = (BinaryExpression) getLeft(); + args.add(beleft.getRight().cg(cgs)); + args.add(beleft.getLeft().cg(cgs)); + args.add(right.cg(cgs)); + eargs.add(beleft.getRight()); + eargs.add(beleft.getLeft()); + eargs.add(right); + } + else if ("let".equals(operator)) + { BasicExpression varbe = + new BasicExpression(accumulator); + Type vartype = + accumulator.getType(); + args.add(varbe.cg(cgs)); + args.add(vartype.cg(cgs)); + args.add(left.cg(cgs)); + args.add(right.cg(cgs)); + eargs.add(varbe); + eargs.add(vartype); + eargs.add(left); + eargs.add(right); + } + else if ("->iterate".equals(operator)) + { args.add(left.cg(cgs)); + if (iteratorVariable != null) + { args.add(iteratorVariable); } + else + { args.add("self"); } + + if (accumulator != null) + { args.add(accumulator.getName()); } + else + { args.add("_acc"); } + if (accumulator != null) + { Expression initval = + accumulator.getInitialExpression(); + if (initval == null) + { args.add("null"); } + else + { args.add(initval.cg(cgs)); } + } + else + { args.add("null"); } + + args.add(right.cg(cgs)); + + System.out.println(">>> Trying to match rule for ->iterate " + args); + + eargs.add(left); + + if (iteratorVariable != null) + { BasicExpression iterVar = + new BasicExpression(iteratorVariable); + iterVar.setType(left.getElementType()); + eargs.add(iterVar); + } + else + { BasicExpression iterVar = + new BasicExpression("self"); + iterVar.setType(left.getElementType()); + eargs.add(iterVar); + } + + if (accumulator != null) + { eargs.add(new BasicExpression(accumulator)); + Expression initval = + accumulator.getInitialExpression(); + eargs.add(initval); + } + else + { eargs.add(new BasicExpression("_acc")); + eargs.add(new BasicExpression("null")); + } + eargs.add(right); + + System.out.println(">>> Trying to match rule for ->iterate " + args + " " + eargs); + } + else if ("->collect".equals(operator) || "->reject".equals(operator) || + "->select".equals(operator) || "->exists".equals(operator) || + "->exists1".equals(operator) || "->forAll".equals(operator) || + "->intersectAll".equals(operator) || "->unionAll".equals(operator) || + "->selectMaximals".equals(operator) || "->selectMinimals".equals(operator) || + "->isUnique".equals(operator) || "->sortedBy".equals(operator) || + "->any".equals(operator)) + { String id = Identifier.nextIdentifier("var"); + args.add(left.cg(cgs)); + eargs.add(left); + BasicExpression v = new BasicExpression(id); + v.setType(left.getElementType()); + args.add(v.cg(cgs)); + eargs.add(v); + Expression newright = right.addReference(v,left.getElementType()); + newright.setType(right.getType()); + newright.setElementType(right.getElementType()); + args.add(newright.cg(cgs)); + eargs.add(newright); + } + else + { args.add(left.cg(cgs)); + args.add(right.cg(cgs)); + eargs.add(left); + eargs.add(right); + } + + CGRule r = cgs.matchedBinaryExpressionRule(this,etext); + + if (r != null) + { System.out.println(">> Found rule " + r + " for: " + etext); + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + return etext; + } + +} + + diff --git a/version24/Binding.class b/version24/Binding.class new file mode 100644 index 0000000000000000000000000000000000000000..a6104ca60652beb7306168d45437e1f49dd77ecd GIT binary patch literal 3248 zcmb7G`F9)D75<*Lk;cypc8n1TL}3Y9;+U;zkWE5t>=2?PuCp~^9ZO?p5?Lc=Mj>v2 z7P^;xC+yI@P0wk28kvL7;YWVpZ=!|oj>fiRiyt^gy7T6~d+)o;cki38{{Q(G0Pe;= zO=NK*jxJCQ6It&7%Z$to|59uGXHyfCI<+LtPx?fZ^f zrb2#d?TvdqZlSc!Q0N+W%1*FPVMl7SsYccGDTR(nx5z{L@=n=4T3wv8y%W}4NjM93 zFw^ANmQ;GPJ%w1{*4jefnOT<6`^6^*9LyW6!>n{ zE7;g|!qkI;Sw`_y>I7EjU)d0-dZBnFD4cm7gjHPOvnVKFbOg+{H@CzQlKh z_Eh>1treCEC3lfZg~^7^enCTM$!843L#(*LVsPy%>}-*>s4UGsnSOQ7=jl~(CEY@+ zF)iu*gi|g?P&*z*J?#hzbj05+nAErfzty-MqZ+#~qOlvJ3d0-WI#G2>McdQ(9ez)M zCC5jSvVLCUhuFicGF8q(c?}t2^-i)UEZ-@t14P&_XuK##^oK_@#K#J0yo8roIE`2E zs>W-0-M||fZ{jVDw}rfe%Npjx>Qd*!f?H9o;X1D|UA z0e@8Jm69jtJvL?1oli<6j-NE}CyhUgXMe$8HU5Uf8hIgq$3cywIHvIrTw%qc#H~6X zw)3&M^Tcx#YqfPc1Z70$dZdIX%|s|Bei}X2N7%KcsZ!KwgcDo2%c@lDGEq9xqS~8V zH!2ewvq`@0BfI81%1Zg6R`%&Y+zsQKwdc7G7|-N6yKq6_a3tSQ!0+49(HxLQiaCD0 zt->}UBhKbn<(Ql~QPVLYtK1<<+;7iw#1*G)E2w&5Pb*yCDv*3QgA}%HQi}3juhg(- zS4vjFW+kd6n=#v-T`owA4yV3r_VgDdA(L+TqV35jr!YG+JTIb6<=;5EbjfuuR4WtF zMR9iv?>CRmbiNTQtX{WOEY5iLwCgSM{A3Fw8zyEGJfa(^ad&&jDL6n3@9M^k`}FWA9LJj)M}cK$gLNg+cqd~!_ksi9=Pk>16( zakPc9TQbW~8FdwHne0`xXLemh$G^F+_(=m?%TEVT zDAk$yFWUdLrrH%U6QrEAq;lvU9x9?YuAuYGGP*>g24f&b!gWUt@fysHHnve`FYbwK zr09&;=wCti88IM=%g`IOwo@vHvAUMp%|Lpo^`XkeR4%@Po=|rgy*V>s%4?SEtLR%n zKRvr9*DYp85*>-|L}v{Hr+3vbcp2OI*pkx;EeF>yl#8t{ug%3pBVp7qoYR?vPQ()N zL{|;hF}2x5=VwUddJ;WfqAx?awrma8b7KWt&kSr!n8I4d4H83JnD_~P1_HOTL_5)i z6qBAol7&sPw0l|D{VeGe@4p$A^daVTo>{JP=V|8YImZ1GBOj*)X8aopXan~e*k@qB zf%{f}2MkPv95N@#1pbFR4cu?gvcfbD)^o?t$#!}L?2B@f7jM6WWT>r%8}t9c_Nbl% z$$BBljt}hMnqf*sYq%-99$Ot$`w`=jeK>$&OwiZK(BBx;*BBOO6du5#$b-E+Up(l` z@=WIa=F8~pxYB-wta`e7Lo6TU2lWH|jy@EcYKQ8f{)0FiSxH4!v>=sOyXEomtzx1M zbu&ES2uxm`N-ok!YbT#_w$zA9w{F&%WhBQbb!07LNxlh2V|AUK8?kwsyS$)Dr7Lzs zeuV&H#%|jvewKnW_)#Q&7aO31YQthYOF*WMt{@%4d1M)xb>(_Qk1(P~sX9xQHXQ#J Di#H9- literal 0 HcmV?d00001 diff --git a/version24/Binding.java b/version24/Binding.java new file mode 100644 index 00000000..d26c4bca --- /dev/null +++ b/version24/Binding.java @@ -0,0 +1,96 @@ +import java.util.Vector; + +/****************************** +* Copyright (c) 2003,2020 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ +/* Package: ATL */ + + +public class Binding +{ String propertyName; + Expression expression; + Expression oclExpression = null; + + public Binding(String att, Expression exp) + { propertyName = att; + expression = exp; + } + + public String getPropertyName() + { return propertyName; } + + public String toString() + { return propertyName + " <- " + expression; } + + public Statement toStatement() + { return new AssignStatement(propertyName,expression); } + + public Expression toExpression(String nme, Type typ, Vector types, Vector ents, Vector env, + java.util.Map interp, UseCase uc) + { // nme.propertyName = expression, with conversions of thisModule + + Type propType = null; // Target type of the output variable being instantiated. + Type propElemType = null; + + BasicExpression lhs = new BasicExpression(propertyName); + + lhs.objectRef = new BasicExpression(nme); + + Vector contexts = new Vector(); + expression.typeCheck(types,ents,contexts,env); + if (typ.isEntity()) + { Entity e = typ.getEntity(); + propType = e.getDefinedFeatureType(propertyName); + propElemType = e.getDefinedFeatureElementType(propertyName); + // System.out.println("DEFINED FEATURE TYPE OF " + propertyName + " IS " + propType + "(" + + // propElemType + ")"); + } + + Expression replacedModule = expression.replaceModuleReferences(uc); + oclExpression = replacedModule.checkConversions(propType,propElemType,interp); + ModelElement met = ModelElement.lookupByName(nme, env); + if (met != null) + { oclExpression = oclExpression.addPreForms(nme); } + return new BinaryExpression("=",lhs,oclExpression); + } + + public Vector sourceTypesRead() + { Vector res = new Vector(); + if (oclExpression != null) + { res = oclExpression.allReadFrame(); } + System.out.println("Read frame of " + oclExpression + " is " + res); + return res; + } + + public boolean isAssociationUpdate(Entity ent) + { if (ent.hasRole(propertyName)) + { return true; } + return false; + } + + public int complexity() + { int result = 2 + expression.syntacticComplexity(); + return result; + } + + public int cyclomaticComplexity() + { int result = expression.cyclomaticComplexity(); + return result; + } + + public Vector operationsUsedIn() + { return expression.allOperationsUsedIn(); } + + public Vector getUses(String data) + { return expression.getUses(data); } + + public Binding substitute(String v, Expression expr) + { Expression newexpr = expression.substituteEq(v,expr); + return new Binding(propertyName,newexpr); + } +} \ No newline at end of file diff --git a/version24/BreakStatement.class b/version24/BreakStatement.class new file mode 100644 index 0000000000000000000000000000000000000000..47ca8f32bddbc896b9bf40110fabeda6daed7a6d GIT binary patch literal 5529 zcmb`KYit}>703VM*X+)2?9_R<&a0ac+;yBs+my7}O-jA7gWGi+vU!m3DC5~1XOh`R zW@nw46dDSYwiF750^wDlP-q(Jv5)yoX4}t%kncclR zyJ;PX54qmC_jk@c=iGD7z4_I(AN>Ttow#CP2*gyj3<;SBjd_>1%F+6Ud4^J5QC@x6;NjZEhhL0O~3ZKyNNdp5?VgOIa z@G1HC(=j{~!)GM-Svh=8PF{@R^9H_vFUIht7`|-aS$svuS2gt9V;602kA}|l@DUAN znNnV8=*!wgvAr6R?emuF^A3CrVh%qs;bNw0KY?vRF6R;lQjcCnJH&WdwoS5zu?sYp}O z*@^n+*zj=;%PQQ%5z|%AEP54XkE&-oJC1ONlFL03v(<9m^u%PzEoj(~4$SnKX|p_b zd^kIv^SE9RMQPH_Az+tw9H0~4QP=i_J0^pY2z|ewe$vnoR2`PomNxUjo^4bnE7jSG zXM0soOq|g$(oR-&JFA+y+7*S;yvRAWCGrPM*DMH{%1G=?XUD}!bKWjhUDKHqrdM^v znBsUCoZ%*QtIT{p69iwl2gM2DilW7{8>cq2Vq1zGtw;TO%9FK|4uZ$ip70!bhUUDO zX0ADVO^-nxzE1R8H`H)@dp0{!WIz|j+U8^2TPTanNnxGV@IWZ9rc0|EOPTSrQEHwl z)}wa(|E68BKqjo*tn+Ny(y*qvB-HxQFx0fDt_`an8hTkA=3Y@2#XKv3*>m@jEDyu0 z2G36wzX_>(!VSU5J~;-^+qKNxTYJG~{#v+9U?L!h$N z>FnW($e0zuDpNbsipm0;x8>PZrc@|9;v5Unzfz{yo~;F51_d*^$W1h?FdZkjOr*I~ zo}XgRze${_+ViF(^RhO#j7^Rw;o9;(qAeZPoQ8GjY-V4sEUflbzl=6or|F@8iRt(n zZ(1GCX-HagWu@Az(jjNKZ#|OTcuiO{OhJv_UwXP z5i^-AbA=bI8tS+x3U_XSVet>Qp;#@JK(RVA?AINS&?-3&uSkZwc8OCJ-QJm=Ql#3e zRm)ZqOurnj8cR&t@{Q12w{yG9uOx0oTF2Lu_y(Tmou5k0GI39j>G)<6-@+*Get&|3 z<8q-cEwA($%c*|{a>Fd8M%o4~g{dNMF1uJ2bvlU`@S+AS#bO-y3#q=u_f6%rU6zK8 z>Ub%M5v1jCH&Ne|O6@`LppHvPd>h}zK=x>amAq^BuaAfNtfAokdn1<1#1fxzI0fUrK-pN8k}_PUBaiBFbh1*6~3#@ z(|r1s<$K6sU3T)N(CE&-;_yi)yK}R2@P1;3Ov&rTK4A;K7JG~097EEW;B6HRZ~Id2 zG0XC%(y(nw65$!qrzXB;ZOf(&p3##Hg*nKUB@d(?>>#MOrj>GR(L>{d=yT^dO?DOn zshXe7CE4OSQhcxv@qZ1#9sI}o0pCXawVr>OG3efM1=`E}!S^P|9yw_Uj?83^65WUn zIg9u!=;-fUL{}7_OIA;?byLl>P>}uV^`60>4erSS-*chya6_|V%hEC~6dK6qES*(NHX z8W>m6cdUQ;72Fi%A1BE^6Y{svH0iTGA`hrPdO%MSdoxBuSRTC}pe>775k;T!(XkNS zKv3Gzvt{cdRz}&UN!^3pAu9tZ*^VtyTc6>|9^Cu7+(i;^!F>wX)mGoLB-r&rt`XGE z=*G_x$t(qYo*uJj^l6U}Fg_GIPq2zF|?+<-$TH*ZTZQ*`QVn1f0oZ^3=@25U@K;e8pTDYH)cpDBX zoNr%Ceg2$84u?WcX0`OUn^}EJG=#t8;$a+7Q0Yor^w)%rE)D$+(YG%R{VmaBOGAH0 z^f=zZvDPG|``2rdzbE(3dXpLo`vCh!*rXbf2pZrY*qHuEnRnfQ%%3RpXUe=A4=Ps4 z!@HhUe=ku*xOJe+;oLB<)4{|4NAP)az9R5X_ zxf_uAH)Z}qnUgmlbB!|prHl=EVahDH$c`lAeK>4I%<)wJ#-Pqt~FuW