Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 1 | <!DOCTYPE html |
| 2 | PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "../xhtml1-strict.dtd"> |
| 3 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
| 4 | <head> |
| 5 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 6 | <link rel="stylesheet" type="text/css" href="../css/ot.css" /> |
| 7 | <link rel="stylesheet" type="text/css" href="../css/otjld.css" /> |
| 8 | <title>OT/J Language Definition v1.3</title> |
| 9 | </head> |
| 10 | <body class="otdt"> |
| 11 | <div id="content"> |
| 12 | <table class="nav"> |
| 13 | <tr> |
| 14 | <td class="back"><a id="top"></a><a href="s4.html" rel="prev"><< §4 Callin Binding</a></td> |
| 15 | <td class="top"><a href="index.html" rel="contents">↑ Table of Contents ↑</a></td> |
| 16 | <td class="next"><a href="s6.html" rel="next">§6 Object Teams API >></a></td> |
| 17 | </tr> |
| 18 | </table> |
| 19 | <div class="chapter" id="s5"> |
| 20 | <div class="headl"> |
| 21 | <div class="headr"> |
| 22 | <h1>§5 Team Activation</h1> |
| 23 | </div> |
| 24 | </div> |
| 25 | <div id="toc-box"> |
| 26 | <ul class="toc-box"> |
| 27 | <li><a href="s5.html">§5 Team Activation</a></li> |
| 28 | <li><a href="#s5.1">§5.1 Effect of team activation</a></li> |
| 29 | <li><a href="#s5.2">§5.2 Explicit team activation</a></li> |
| 30 | <li><a href="#s5.3">§5.3 Implicit team activation</a></li> |
| 31 | <li><a href="#s5.4">§5.4 Guard predicates</a></li> |
| 32 | <li><a href="#s5.5">§5.5 Unanticipated team activation</a></li> |
| 33 | </ul> |
| 34 | </div> |
| 35 | <div class="intro"> |
| 36 | <h3>The concept of Activation</h3> |
| 37 | <div class="line"></div> |
| 38 | <div class="term">Binding activation</div> |
| 39 | <div class="termdesc">All <strong>callin</strong> bindings of a team only have effect if |
| 40 | the team is <strong>active</strong>. Activation may be caused by explicit |
| 41 | statements and also happens implicitly at certain points |
| 42 | during program execution. |
| 43 | </div> |
| 44 | <div class="line"></div> |
| 45 | <div class="term">Guard predicates</div> |
| 46 | <div class="termdesc">Callin bindings can further be controlled using guard predicates, |
| 47 | which can be attached to roles and teams at different levels. If a guard |
| 48 | predicate evaluates to <code>false</code>, all affected callin bindings |
| 49 | are disabled. |
| 50 | </div> |
| 51 | <div class="line"></div> |
| 52 | </div> |
| 53 | <div class="sect depth2" id="s5.1"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 54 | <h2 class="sect">§5.1 Effect of team activation<a class="img" href="s5.html#s5.1" |
| 55 | title="PermaLink to §5.1 Effect of team activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 56 | alt="" /></a><span class="toplink"><a href="#top">↑ §5</a></span></h2> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 57 | <p>Activating a team instance has the effect of enabling all its callin bindings. |
| 58 | All effects defined in <a href="s4.html" title="§4 Callin Binding" class="sect">§4</a> apply only if a corresponding |
| 59 | team instance is active.<br /> |
| 60 | The <strong>order</strong> of team activation controls the order of callin executions. |
| 61 | If more than one team intercepts calls to the same base method, the most recently activated |
| 62 | team has highest priority in that its before or replace callins are executed first while its after |
| 63 | callins are executed last. |
| 64 | |
| 65 | </p> |
| 66 | <div class="sect depth3" id="s5.1.1"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 67 | <h3 class="sect">§5.1.1 Global vs. thread local team activation<a class="img" href="s5.html#s5.1.1" |
| 68 | title="PermaLink to §5.1.1 Global vs. thread local team activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 69 | alt="" /></a><span class="toplink"><a href="#s5.1">↑ §5.1</a></span></h3> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 70 | <p>While <strong>thread local</strong> activation only enables the callin bindings of |
| 71 | a team instance for a certain thread, <strong>global</strong> activation activates the |
| 72 | team instance for all threads of the application. |
| 73 | |
| 74 | </p> |
| 75 | </div> |
| 76 | <div class="sect depth3" id="s5.1.2"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 77 | <h3 class="sect">§5.1.2 Effect on garbage collection<a class="img" href="s5.html#s5.1.2" |
| 78 | title="PermaLink to §5.1.2 Effect on garbage collection"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 79 | alt="" /></a><span class="toplink"><a href="#s5.1">↑ §5.1</a></span></h3> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 80 | <p>Any active team is referenced by internal infrastructure. |
| 81 | Thus, a team cannot be reclaimed by the garbage collector while it is active. |
| 82 | |
| 83 | </p> |
| 84 | </div> |
| 85 | </div> |
| 86 | <div class="sect depth2" id="s5.2"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 87 | <h2 class="sect">§5.2 Explicit team activation<a class="img" href="s5.html#s5.2" |
| 88 | title="PermaLink to §5.2 Explicit team activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 89 | alt="" /></a><span class="toplink"><a href="#top">↑ §5</a></span></h2> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 90 | <div class="subsect depth3" id="s5.2.a"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 91 | <h4 class="subsect">(a) <span class="title">Activation block</span><a class="img" href="s5.html#s5.2.a" |
| 92 | title="PermaLink to (a) Activation block"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 93 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 94 | <p>A team can be activated thread local by the block construct</p> |
| 95 | <div class="listing plain"><pre><b>within</b> (myTeam) { <i>stmts</i> }</pre></div> |
| 96 | <p>If <em>stmts</em> has only one statement this can be abbreviated to |
| 97 | </p> |
| 98 | <div class="listing plain"><pre><b>within</b> (myTeam) <i>stmt</i></pre></div> |
| 99 | <p>In these statements, <code>myTeam</code> must denote a team instance. |
| 100 | For the time of executing this block, this team instance is activated for the current thread, |
| 101 | which has entered the within block. |
| 102 | |
| 103 | </p> |
| 104 | <p>The <code>within</code> block statement guarantees that it leaves |
| 105 | the team in exactly the same activation state as it was in when |
| 106 | entering this block. This includes the cases of exceptions, meaning |
| 107 | that deactivation will also occur if the execution of the block |
| 108 | terminates abnormally. |
| 109 | |
| 110 | </p> |
| 111 | </div> |
| 112 | <div class="subsect depth3" id="s5.2.b"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 113 | <h4 class="subsect">(b) <span class="title">Imperative activation</span><a class="img" href="s5.html#s5.2.b" |
| 114 | title="PermaLink to (b) Imperative activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 115 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 116 | <p>Each team class implicitly provides methods from the predefined interface |
| 117 | <code>org.objectteams.ITeam</code> (super interface of all team classes) to control team |
| 118 | activation disregarding the block structure of the program. The methods <code>activate()</code> |
| 119 | and <code>deactivate()</code> are used to activate and deactivate a team instance for |
| 120 | the current thread.<br /> |
| 121 | If a team should be de-/activated for another thread this can be done by the methods |
| 122 | <code>activate(Thread aThread)</code> and <code>deactivate(Thread aThread)</code>. |
| 123 | In order to achieve global activation for all threads the predefined constant |
| 124 | <code>org.objectteams.Team.ALL_THREADS</code> is passed to these methods (e.g. |
| 125 | <code>activate(Team.ALL_THREADS)</code>).<br /> |
| 126 | Note, that this methods make no guarantees with respect to exceptions. |
| 127 | |
| 128 | </p> |
| 129 | </div> |
| 130 | <div class="subsect depth3" id="s5.2.c"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 131 | <h4 class="subsect">(c) <span class="title">Multiple and mixed activations</span><a class="img" href="s5.html#s5.2.c" |
| 132 | title="PermaLink to (c) Multiple and mixed activations"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 133 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 134 | <ul> |
| 135 | <li>If <code>activate()</code> is invoked on a team instance |
| 136 | that has been explicitly activated before, this statement has |
| 137 | no effect at all (note the difference in <a href="#s5.3.a" title="§5.3.(a) Team level methods" class="sect">§5.3.(a)</a> below). |
| 138 | <br /> |
| 139 | The same applies to deactivating an inactive team. |
| 140 | </li> |
| 141 | <li>If a team was already active when entering a <code>within</code> |
| 142 | block, it will remain active after leaving the block. |
| 143 | </li> |
| 144 | <li>If the team was active on entry of a <code>within</code> block |
| 145 | and if <code>deactivate()</code> is invoked on the same team |
| 146 | instance from within the <code>within</code> block, |
| 147 | leaving the block will re-activate the team. |
| 148 | </li> |
| 149 | </ul> |
| 150 | </div> |
| 151 | </div> |
| 152 | <div class="sect depth2" id="s5.3"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 153 | <h2 class="sect">§5.3 Implicit team activation<a class="img" href="s5.html#s5.3" |
| 154 | title="PermaLink to §5.3 Implicit team activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 155 | alt="" /></a><span class="toplink"><a href="#top">↑ §5</a></span></h2> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 156 | <p>Implicit team activation is intended to ensure that |
| 157 | whenever the control flow is passed to a team or one of its roles, |
| 158 | the team is implicitly activated for the current thread. |
| 159 | Implicit activation can be configured at different levels (see <a href="#s5.3.d" title="§5.3.(d) Configuring implicit activation" |
| 160 | class="sect">§5.3.(d)</a>). |
| 161 | |
| 162 | </p> |
| 163 | <p>When implicit activation is enabled a programmer may assume, |
| 164 | that whenever a role forwards calls to its base object via callout, |
| 165 | the callin bindings of the same role will be active at that time. |
| 166 | Exceptions to this rule have to be programmed explicitly. |
| 167 | |
| 168 | </p> |
| 169 | <div class="subsect depth3" id="s5.3.a"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 170 | <h4 class="subsect">(a) <span class="title">Team level methods</span><a class="img" href="s5.html#s5.3.a" |
| 171 | title="PermaLink to (a) Team level methods"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 172 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 173 | <p>While executing a <strong>team level method</strong>, the target team |
| 174 | is always active. Activation is reset to the previous state |
| 175 | when leaving the team method, unless the team has been explicitly activated during |
| 176 | execution of the team method by a call to <code>activate()</code>. |
| 177 | Explicit activation is stronger than implicit activation and thus persists after the |
| 178 | team level method terminates. Ie., leaving a team level method will never reset |
| 179 | an explicit activation. |
| 180 | |
| 181 | </p> |
| 182 | </div> |
| 183 | <div class="subsect depth3" id="s5.3.b"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 184 | <h4 class="subsect">(b) <span class="title">Methods of externalized roles</span><a class="img" href="s5.html#s5.3.b" |
| 185 | title="PermaLink to (b) Methods of externalized roles"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 186 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 187 | <p>Invoking a method on an <strong>externalized role</strong> |
| 188 | (see <a href="s1.html#s1.2.2" title="§1.2.2 Externalized roles" |
| 189 | class="sect">§1.2.2</a>) also has the |
| 190 | effect of temporary activation of the team containing the role for the current thread. |
| 191 | Regarding deactivation the rule of <a href="#s5.3.a" title="§5.3.(a) Team level methods" class="sect">§5.3.(a)</a> above applies accordingly. |
| 192 | |
| 193 | </p> |
| 194 | </div> |
| 195 | <div class="subsect depth3" id="s5.3.c"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 196 | <h4 class="subsect">(c) <span class="title">Nested teams</span><a class="img" href="s5.html#s5.3.c" title="PermaLink to (c) Nested teams"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 197 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 198 | <p>Implicit activation has additional consequences for nested teams |
| 199 | (see <a href="s1.html#s1.5" title="§1.5 Team and role nesting" |
| 200 | class="sect">§1.5</a>): |
| 201 | |
| 202 | </p> |
| 203 | <ul> |
| 204 | <li>Implicit activation of a team causes the activation of its outer teams.</li> |
| 205 | <li>Implicit deactivation of a team causes the deactivation of its inner teams.</li> |
| 206 | </ul> |
| 207 | </div> |
| 208 | <div class="subsect depth3" id="s5.3.d"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 209 | <h4 class="subsect">(d) <span class="title">Configuring implicit activation</span><a class="img" href="s5.html#s5.3.d" |
| 210 | title="PermaLink to (d) Configuring implicit activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 211 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 212 | <p>Implicit activation is disabled by default and can be enabled by adding the annotation |
| 213 | <code>@org.objectteams.ImplicitTeamActivation</code>, which can be applied to a type or a method. |
| 214 | When applied to a method it is ensured that invoking this method will trigger implicit activation. |
| 215 | When the annotation is applied to a type this has the same effect as applying it to all externally |
| 216 | visible methods of the type. Member types are not affected and have to be annotated separately. |
| 217 | </p> |
| 218 | <p>The runtime environment can be configured globally by defining the system property |
| 219 | <code>ot.implicit.team.activation</code> to one of these values: |
| 220 | </p> |
| 221 | <dl> |
| 222 | <dt>NEVER</dt> |
| 223 | <dd>Implicit activation is completely disabled.</dd> |
| 224 | <dt>ANNOTATED</dt> |
| 225 | <dd>This is the default: implicit activation applies only where declared by <code>@ImplicitTeamActivation</code>. |
| 226 | </dd> |
| 227 | <dt>ALWAYS</dt> |
| 228 | <dd>Implicit activation applies to all externally visible methods (this was the default in OTJLD versions ≤1.2)</dd> |
| 229 | </dl> |
| 230 | </div> |
| 231 | <p>Note that among the different mechanisms for activation, <code>within</code> is strongest, |
| 232 | followed by <code>(de)activate()</code>, weakest is implicit activation. In this sense, |
| 233 | explicit imperative (de)activation may override the block structure of implicit activation |
| 234 | (by explicit activation within a team level method), but not that of a <code>within</code> |
| 235 | block (by deactivation from a within block). |
| 236 | |
| 237 | </p> |
| 238 | </div> |
| 239 | <div class="sect depth2" id="s5.4"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 240 | <h2 class="sect">§5.4 Guard predicates<a class="img" href="s5.html#s5.4" |
| 241 | title="PermaLink to §5.4 Guard predicates"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 242 | alt="" /></a><span class="toplink"><a href="#top">↑ §5</a></span></h2> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 243 | <div class="syntaxlink"><a href="sA.html#sA.7" title="§A.7 Guard predicates" class="syntax">→ Syntax §A.7</a></div> |
| 244 | <p>The effect of callins can further be controlled using so called guard predicates. |
| 245 | Guards appear at four different levels: |
| 246 | |
| 247 | </p> |
| 248 | <ul> |
| 249 | <li>callin method binding</li> |
| 250 | <li>role method</li> |
| 251 | <li>role class</li> |
| 252 | <li>team class</li> |
| 253 | </ul> |
| 254 | <p>Guards can be specified as <em>regular</em> guards or <code>base</code> guards, |
| 255 | which affects the exact point in the control flow, where the guard will be evaluated. |
| 256 | |
| 257 | </p> |
| 258 | <div class="subsect depth3" id="s5.4.a"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 259 | <h4 class="subsect">(a) <span class="title">General syntax for guards</span><a class="img" href="s5.html#s5.4.a" |
| 260 | title="PermaLink to (a) General syntax for guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 261 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 262 | <p>A guard is declared using the keyword <code>when</code> followed by a |
| 263 | boolean expression in parentheses: |
| 264 | |
| 265 | </p> |
| 266 | <div class="listing plain"><pre><em><b>when</b> (</em><i>predicateExpression</i><em>)</em></pre></div> |
| 267 | <p>Depending on the kind of guard different objects are in scope using |
| 268 | special identifiers like <code>this</code>, <code>base</code>.<br /> |
| 269 | Any predicate expression that evaluates to <code>true</code> enables |
| 270 | the callin binding(s) to which it applies. |
| 271 | Evaluation to <code>false</code> disables the callin binding(s). |
| 272 | |
| 273 | </p> |
| 274 | </div> |
| 275 | <div class="subsect depth3" id="s5.4.b"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 276 | <h4 class="subsect">(b) <span class="title">No side effects</span><a class="img" href="s5.html#s5.4.b" |
| 277 | title="PermaLink to (b) No side effects"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 278 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 279 | <p>A guard predicate should have no side effects. |
| 280 | A compiler should optionally check this condition, but inter-procedural analysis |
| 281 | actually depends on the availability of appropriate means to mark any method as side-effect free. |
| 282 | |
| 283 | </p> |
| 284 | </div> |
| 285 | <div class="subsect depth3" id="s5.4.c"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 286 | <h4 class="subsect">(c) <span class="title">Exceptions</span><a class="img" href="s5.html#s5.4.c" title="PermaLink to (c) Exceptions"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 287 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 288 | <p>A guard predicate should not throw any exceptions. |
| 289 | Yet, any exception thrown within a guard predicate cause the guard to evaluate to <code>false</code> |
| 290 | rather than propagating the exception, meaning that the evaluation of a guard predicate will never |
| 291 | interrupt the current base behaviour.<br /> |
| 292 | A compiler should flag any checked exception that is thrown within a guard. |
| 293 | Such diagnosis should by default be treated as an error, with the option of configuring |
| 294 | its severity to warning or ignore. |
| 295 | |
| 296 | </p> |
| 297 | </div> |
| 298 | <div class="sect depth3" id="s5.4.1"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 299 | <h3 class="sect">§5.4.1 Regular guards<a class="img" href="s5.html#s5.4.1" |
| 300 | title="PermaLink to §5.4.1 Regular guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 301 | alt="" /></a><span class="toplink"><a href="#s5.4">↑ §5.4</a></span></h3> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 302 | <p>This group of guards evaluates within the context of a given role. |
| 303 | These guards are evaluated <em>after</em> a callin target is lifted and |
| 304 | <em>before</em> a callin bound role method is invoked. |
| 305 | |
| 306 | </p> |
| 307 | <div class="subsect depth4" id="s5.4.1.a"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 308 | <h4 class="subsect">(a) <span class="title">Method binding guards</span><a class="img" href="s5.html#s5.4.1.a" |
| 309 | title="PermaLink to (a) Method binding guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 310 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 311 | <p>A guard may be attached to a callin method binding as in: |
| 312 | |
| 313 | </p> |
| 314 | <div class="listing plain"><pre><b>void</b> roleMethod(<b>int</b> ir) <b><-</b> <b>after</b> <b>void</b> baseMethod(<b>int</b> ib) |
| 315 | <b>when</b> (ir > MyTeam.this.threshold);</pre></div> |
| 316 | <p>Such a guard only affects the callin binding to which it is attached, |
| 317 | i.e., this specific callin binding is only effective, |
| 318 | if the predicate evaluates to <code>true</code>. |
| 319 | <br /> |
| 320 | The following values are within the scope of the predicate expression, |
| 321 | and thus can be used to express the condition: |
| 322 | |
| 323 | </p> |
| 324 | <ul> |
| 325 | <li>The role instance denoted by <code>this</code>.<br /> |
| 326 | Features of the role instance can also be accessed relative to |
| 327 | <code>this</code> with or without explicit qualifying <code>this</code>. |
| 328 | |
| 329 | </li> |
| 330 | <li>The team instance denoted by a qualified this reference as in |
| 331 | <code>MyTeam.this</code>. |
| 332 | |
| 333 | </li> |
| 334 | <li>If the callin binding includes signatures (as in the example above): |
| 335 | Parameters of the role method.<br /> |
| 336 | If parameter mappings are involved, they will be evaluated before evaluating the guard. |
| 337 | |
| 338 | </li> |
| 339 | </ul> |
| 340 | </div> |
| 341 | <div class="subsect depth4" id="s5.4.1.b"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 342 | <h4 class="subsect">(b) <span class="title">Method guards</span><a class="img" href="s5.html#s5.4.1.b" |
| 343 | title="PermaLink to (b) Method guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 344 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 345 | <p>A method guard is similar to a method binding guard, but it applies |
| 346 | to all callin method bindings of this method.<br /> |
| 347 | A method guard is declared between the method signature and the method body: |
| 348 | |
| 349 | </p> |
| 350 | <div class="listing plain"><pre><b>void</b> roleMethod(<b>int</b> ir) |
| 351 | <b>when</b> (ir > MyTeam.this.threshold) { <i>body statements</i> }</pre></div> |
| 352 | </div> |
| 353 | <div class="subsect depth4" id="s5.4.1.c"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 354 | <h4 class="subsect">(c) <span class="title">Role level guards</span><a class="img" href="s5.html#s5.4.1.c" |
| 355 | title="PermaLink to (c) Role level guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 356 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 357 | <p>When a guard is specified at the role level, i.e., directly before the |
| 358 | class body of a role class, it applies to all callin method bindings of |
| 359 | the role class: |
| 360 | |
| 361 | </p> |
| 362 | <div class="listing plain"><pre><b>protected</b> <b>class</b> MyRole |
| 363 | <b>when</b> (value > MyTeam.this.threshold) |
| 364 | { |
| 365 | <b>int</b> value; |
| 366 | <i>other <b>class</b> body declarations</i> |
| 367 | }</pre></div> |
| 368 | <p>The following values are within the scope of the predicate expression: |
| 369 | |
| 370 | </p> |
| 371 | <ul> |
| 372 | <li>The role instance denoted by <code>this</code> (explicit or implicit, see above). |
| 373 | Thus, in the example <code>value</code> will be interpreted as a field of the enclosing role. |
| 374 | |
| 375 | </li> |
| 376 | <li>The team instance denoted by a qualified this reference as in <code>MyTeam.this</code></li> |
| 377 | </ul> |
| 378 | </div> |
| 379 | <div class="subsect depth4" id="s5.4.1.d"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 380 | <h4 class="subsect">(d) <span class="title">Team level guards</span><a class="img" href="s5.html#s5.4.1.d" |
| 381 | title="PermaLink to (d) Team level guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 382 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 383 | <p>A guard specified in the header of a team class may disable the callin |
| 384 | bindings of all contained role classes. The syntax corresponds to the syntax |
| 385 | of role level guards.<br /> |
| 386 | The only value directly available within team level guard is the |
| 387 | team instance (denoted by <code>this</code>) and its features. |
| 388 | |
| 389 | </p> |
| 390 | </div> |
| 391 | <p>Of course all guards can also access any visible static feature of a visible class. |
| 392 | |
| 393 | </p> |
| 394 | <p>Even if a guard has no direct effect, because, e.g., a role class has no callin |
| 395 | bindings (maybe not even a role-base binding), predicates at such abstract |
| 396 | levels are useful, because all predicates are inherited by all sub classes |
| 397 | (explicit and implicit). |
| 398 | |
| 399 | </p> |
| 400 | </div> |
| 401 | <div class="sect depth3" id="s5.4.2"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 402 | <h3 class="sect">§5.4.2 Base guards<a class="img" href="s5.html#s5.4.2" |
| 403 | title="PermaLink to §5.4.2 Base guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 404 | alt="" /></a><span class="toplink"><a href="#s5.4">↑ §5.4</a></span></h3> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 405 | <p>The intention behind base guards is to prevent lifting of a callin-target |
| 406 | if a guard evaluates to <code>false</code> and thus refuses to invoke the |
| 407 | callin bound role method. Using base guards it is easier to prevent any |
| 408 | side-effects caused by a callin binding, because lifting could cause side-effects |
| 409 | at two levels: |
| 410 | |
| 411 | </p> |
| 412 | <ul> |
| 413 | <li>Creating a role on-demand already is a side-effect (observable e.g. |
| 414 | by the reflective function <code><a href="s6.html#s6.1" title="§6.1 Reflection" class="sect">hasRole (§6.1)</a></code>) |
| 415 | |
| 416 | </li> |
| 417 | <li>Role creation triggers execution of a role constructor |
| 418 | (see <a href="s2.html#s2.3.1.c" |
| 419 | title="§2.3.1.(c) Custom lifting constructor" |
| 420 | class="sect">custom lifting constructor (§2.3.1.(c))</a>) |
| 421 | which could produce arbitrary side-effects. |
| 422 | |
| 423 | </li> |
| 424 | </ul> |
| 425 | <p>Both kinds of side-effects can be avoided using a base guard which prevents |
| 426 | unnecessary lifting. |
| 427 | |
| 428 | </p> |
| 429 | <p>Any guard (5.4.1 (b)-(e)) can be turned into a base guard by adding |
| 430 | the modifier <code>base</code> as in: |
| 431 | |
| 432 | </p> |
| 433 | <div class="listing plain"><pre><b>protected</b> <b>class</b> MyRole <b>playedBy</b> MyBase |
| 434 | <em><b>base</b> when</em> (base.value > MyTeam.this.threshold) |
| 435 | { |
| 436 | <i><b>class</b> body declarations</i> |
| 437 | }</pre></div> |
| 438 | <p>However, different scoping rules apply for the identifiers |
| 439 | that can be used in a base guard: |
| 440 | |
| 441 | </p> |
| 442 | <div class="subsect depth4" id="s5.4.2.a"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 443 | <h4 class="subsect">(a) <span class="title">Base object reference</span><a class="img" href="s5.html#s5.4.2.a" |
| 444 | title="PermaLink to (a) Base object reference"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 445 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 446 | <p>In all base guard predicates the special identifier <code>base</code> |
| 447 | can be used to denote the base object that is about to be lifted. |
| 448 | |
| 449 | </p> |
| 450 | </div> |
| 451 | <div class="subsect depth4" id="s5.4.2.b"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 452 | <h4 class="subsect">(b) <span class="title">Method binding guards</span><a class="img" href="s5.html#s5.4.2.b" |
| 453 | title="PermaLink to (b) Method binding guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 454 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 455 | <p>A base method binding guard may access parameters as passed to the |
| 456 | base method. Parameter mappings are not considered.<br /> |
| 457 | Additionally, for <code>after</code> callin bindings, the identifier <code>result</code> |
| 458 | may be used to refer to the result of the base method (if any). |
| 459 | |
| 460 | </p> |
| 461 | <div class="note"> |
| 462 | <h5>Note:</h5> |
| 463 | <p>In order to achieve the same effect of accessing |
| 464 | the base method's result, a regular binding guard (not a base guard) |
| 465 | must use a suitable parameter mapping (see <a href="s4.html#s4.4.c" |
| 466 | title="§4.4.(c) Mapping the result of a base method" |
| 467 | class="sect">§4.4.(c)</a>). |
| 468 | |
| 469 | </p> |
| 470 | </div> |
| 471 | </div> |
| 472 | <div class="subsect depth4" id="s5.4.2.c"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 473 | <h4 class="subsect">(c) <span class="title">Method guards</span><a class="img" href="s5.html#s5.4.2.c" |
| 474 | title="PermaLink to (c) Method guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 475 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 476 | <p>In contrast to regular method guards, a <em>base</em> guard attached to a role method |
| 477 | cannot access any method parameters. See the next item (d) for values that are actually in scope. |
| 478 | |
| 479 | </p> |
| 480 | </div> |
| 481 | <div class="subsect depth4" id="s5.4.2.d"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 482 | <h4 class="subsect">(d) <span class="title">Role level guards</span><a class="img" href="s5.html#s5.4.2.d" |
| 483 | title="PermaLink to (d) Role level guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 484 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 485 | <p>Role level base guards may use these values: |
| 486 | |
| 487 | </p> |
| 488 | <ul> |
| 489 | <li>The base instance using the special identifier <code>base</code>. |
| 490 | </li> |
| 491 | <li>The team instance using a qualified this references (<code>MyTeam.this</code>). |
| 492 | </li> |
| 493 | </ul> |
| 494 | </div> |
| 495 | <div class="subsect depth4" id="s5.4.2.e"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 496 | <h4 class="subsect">(e) <span class="title">Team level guards</span><a class="img" href="s5.html#s5.4.2.e" |
| 497 | title="PermaLink to (e) Team level guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 498 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 499 | <p>Team level base guards have the same scope as role level base guards (d). |
| 500 | However, the type of the role instance is not known here, i.e., here <code>base</code> |
| 501 | has the static type <code>java.lang.Object</code>. |
| 502 | |
| 503 | </p> |
| 504 | </div> |
| 505 | <div class="subsect depth4" id="s5.4.2.f"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 506 | <h4 class="subsect">(f) <span class="title">Unbound roles</span><a class="img" href="s5.html#s5.4.2.f" |
| 507 | title="PermaLink to (f) Unbound roles"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 508 | alt="" /></a></h4> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 509 | <p>In contrast to regular guards, base guards cannot be attached to |
| 510 | unbound role classes nor to their methods.<br /> |
| 511 | Only team level base guards are independent of role binding. |
| 512 | |
| 513 | </p> |
| 514 | </div><img src="../images/guards.png" alt="Overview: Guard predicates" /></div> |
| 515 | <div class="sect depth3" id="s5.4.3"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 516 | <h3 class="sect">§5.4.3 Multiple guards<a class="img" href="s5.html#s5.4.3" |
| 517 | title="PermaLink to §5.4.3 Multiple guards"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 518 | alt="" /></a><span class="toplink"><a href="#s5.4">↑ §5.4</a></span></h3> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 519 | <p>Due to the different ranges of applicability different guards may affect the same method binding. |
| 520 | In that case all applicable guards are conjoined using a logical <code>and</code>.<br /> |
| 521 | Any guard is interpreted as the conjunction of these predicates (if present): |
| 522 | |
| 523 | </p> |
| 524 | <ul> |
| 525 | <li>The direct predicate expression of the guard.</li> |
| 526 | <li>The next outer guard along the chain |
| 527 | <em>method binding -> method -> role level -> team level</em></li> |
| 528 | <li>The guard at the same level that is inherited from the <em>implicit</em> super role. |
| 529 | </li> |
| 530 | <li>The guard at the same level that is inherited from the <em>explicit</em> super role. |
| 531 | </li> |
| 532 | </ul> |
| 533 | <h5 class="listing">Example code (Guard Predicates):</h5> |
| 534 | <div class="listing example frame"> |
| 535 | <table class="listing"> |
| 536 | <tr class="line odd"> |
| 537 | <td class="ln">1</td> |
| 538 | <td><pre><b>public</b> <b>team</b> <b>class</b> ATM {</pre></td> |
| 539 | </tr> |
| 540 | <tr class="line even"> |
| 541 | <td class="ln">2</td> |
| 542 | <td><pre> <b>private</b> Bank myBank;</pre></td> |
| 543 | </tr> |
| 544 | <tr class="line odd"> |
| 545 | <td class="ln">3</td> |
| 546 | <td><pre> <b>public</b> <b>class</b> ForeignAccount <b>playedBy</b> Account</pre></td> |
| 547 | </tr> |
| 548 | <tr class="line even"> |
| 549 | <td class="ln">4</td> |
| 550 | <td><pre> <em><b>base</b> when</em> (!ATM.this.myBank.equals(<em>base</em>.getBank()))</pre></td> |
| 551 | </tr> |
| 552 | <tr class="line odd"> |
| 553 | <td class="ln">5</td> |
| 554 | <td><pre> {</pre></td> |
| 555 | </tr> |
| 556 | <tr class="line even"> |
| 557 | <td class="ln">6</td> |
| 558 | <td><pre> <b>callin</b> <b>void</b> debitWithFee(<b>int</b> amount) {</pre></td> |
| 559 | </tr> |
| 560 | <tr class="line odd"> |
| 561 | <td class="ln">7</td> |
| 562 | <td><pre> base.debitWithFee(fee+amount);</pre></td> |
| 563 | </tr> |
| 564 | <tr class="line even"> |
| 565 | <td class="ln">8</td> |
| 566 | <td><pre> }</pre></td> |
| 567 | </tr> |
| 568 | <tr class="line odd"> |
| 569 | <td class="ln">9</td> |
| 570 | <td><pre> <b>void</b> debitWithFee(<b>int</b> i) <b><-</b> <b>replace</b> <b>void</b> debit(<b>int</b> amount)</pre></td> |
| 571 | </tr> |
| 572 | <tr class="line even"> |
| 573 | <td class="ln">10</td> |
| 574 | <td><pre> <em><b>base</b> when</em> (amount < 1000);</pre></td> |
| 575 | </tr> |
| 576 | <tr class="line odd"> |
| 577 | <td class="ln">11</td> |
| 578 | <td><pre> }</pre></td> |
| 579 | </tr> |
| 580 | <tr class="line even"> |
| 581 | <td class="ln">12</td> |
| 582 | <td><pre>}</pre></td> |
| 583 | </tr> |
| 584 | </table> |
| 585 | </div> |
| 586 | <div class="codecomment"> |
| 587 | <h5>Effects:</h5> |
| 588 | The team in this example causes that an additional fee has to be payed while debiting |
| 589 | less than 1000 Euros from a "foreign" account. |
| 590 | |
| 591 | <ul> |
| 592 | <li>The base guard in line 4 ensures that <code>Account</code> objects only get |
| 593 | <code>ForeignAccount</code> roles, if they belong to a different bank than the |
| 594 | surrounding <code>ATM</code> team.<br /> |
| 595 | It accesses the bank of the base via the <code>base</code> identifier. |
| 596 | |
| 597 | </li> |
| 598 | <li>The method binding guard in line 10 restricts the callin to |
| 599 | <code>debitWithFee</code> to calls where the base method argument |
| 600 | <code>amount</code> is lower than 1000. |
| 601 | |
| 602 | </li> |
| 603 | <li>A call to <code>Account.debit</code> causes a replace callin to |
| 604 | <code>debitWithFee</code><em> only</em> if <em>both</em> predicates evaluate to true. |
| 605 | |
| 606 | </li> |
| 607 | </ul> |
| 608 | </div> |
| 609 | </div> |
| 610 | </div> |
| 611 | <div class="sect depth2" id="s5.5"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 612 | <h2 class="sect">§5.5 Unanticipated team activation<a class="img" href="s5.html#s5.5" |
| 613 | title="PermaLink to §5.5 Unanticipated team activation"><img style="vertical-align:text-top;margin-left:5px;" src="../images/permalink.png" |
| 614 | alt="" /></a><span class="toplink"><a href="#top">↑ §5</a></span></h2> |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 615 | <p>If an application should be adapted unanticipatedly by one or more teams, |
| 616 | this can be achieved without explicitly changing the program code of this application. |
| 617 | |
| 618 | </p> |
| 619 | <p><span class="underline">General activation via config file:</span><br /> |
| 620 | Instead of adding the team initialization |
| 621 | and activation code to the main program, it is possible to add the respective teams via a config file. |
| 622 | Every line of this text file contains the fully qualified name of a compiled team, which has to be available |
| 623 | on the classpath. |
| 624 | For the instantiation of these teams the default constructor is used, which means adding a team to |
| 625 | an application this way requires the team to provide a default constructor. |
| 626 | The activation order (see <a href="#s5.1" title="§5.1 Effect of team activation" class="sect">§5.1</a>) for these teams corresponds to the order |
| 627 | in which they are listed in the config file.<br /> |
| 628 | Lines starting with a '#' denote comment lines. |
| 629 | |
| 630 | </p> |
| 631 | <h5 class="listing">Example config file:</h5> |
| 632 | <div class="listing config frame"><pre><span class="comment"># Config file for an ObjectTeams application:</span> |
| 633 | <em>mypackage1.MyTeam1</em> |
| 634 | <span class="comment"># ...</span> |
| 635 | <em>mypackageM.MyTeamN</em></pre></div> |
| 636 | <p>To get this config file recognized by the application the VM argument<br /><strong>'-Dot.teamconfig=<<em>config_file_name</em>>'</strong><br /> |
| 637 | has to be used when starting the application. |
| 638 | |
| 639 | </p> |
| 640 | <div class="note"> |
| 641 | <h5>Note:</h5> |
| 642 | In the ObjectTeams Development Tooling (OTDT) teams are activated unanticipatedly |
| 643 | via a special tab in the "Run-Configuration" (see <a href="http://www.objectteams.org/distrib/features.html#execution" class="ext">OTDT features</a>), instead. |
| 644 | |
| 645 | </div> |
| 646 | <p><span class="underline">Activation adjustment example:</span><br /> |
| 647 | Teams added via the config file mechanism are activated by default. Because no reference to them is |
| 648 | stored anywhere, it is not possible to deactivate them later. |
| 649 | If deactivation of unanticipated added teams is required, this can be achieved by adding a manager team |
| 650 | via config file and encapsulate the actual functionality in another team managed by the manager team. |
| 651 | This way a functional team can be activated and deactivated as needed. |
| 652 | |
| 653 | </p> |
| 654 | <h5 class="listing">Example code (Activation Adjustment):</h5> |
| 655 | <div class="listing example frame"> |
| 656 | <table class="listing"> |
| 657 | <tr class="line odd"> |
| 658 | <td class="ln">1</td> |
| 659 | <td><pre><b>public</b> <b>team</b> <b>class</b> MyManagerTeam {</pre></td> |
| 660 | </tr> |
| 661 | <tr class="line even"> |
| 662 | <td class="ln">2</td> |
| 663 | <td><pre> <b>private</b> FunctionalTeam myFunctionalTeam = <b>new</b> FunctionalTeam();</pre></td> |
| 664 | </tr> |
| 665 | <tr class="line odd"> |
| 666 | <td class="ln">3</td> |
| 667 | <td><pre> <b>protected</b> <b>class</b> MyRole <b>playedBy</b> MyApplication {</pre></td> |
| 668 | </tr> |
| 669 | <tr class="line even"> |
| 670 | <td class="ln">4</td> |
| 671 | <td><pre> <b>void</b> startAdaption() { myFunctionalTeam.activate(); }</pre></td> |
| 672 | </tr> |
| 673 | <tr class="line odd"> |
| 674 | <td class="ln">5</td> |
| 675 | <td><pre> startAdaption <b><-</b> <b>before</b> startMethod;</pre></td> |
| 676 | </tr> |
| 677 | <tr class="line even"> |
| 678 | <td class="ln">6</td> |
| 679 | <td><pre> <b>void</b> stopAdaption() { myFunctionalTeam.deactivate(); }</pre></td> |
| 680 | </tr> |
| 681 | <tr class="line odd"> |
| 682 | <td class="ln">7</td> |
| 683 | <td><pre> stopAdaption <b><-</b> <b>after</b> stopMethod;</pre></td> |
| 684 | </tr> |
| 685 | <tr class="line even"> |
| 686 | <td class="ln">8</td> |
| 687 | <td><pre> }</pre></td> |
| 688 | </tr> |
| 689 | <tr class="line odd"> |
| 690 | <td class="ln">9</td> |
| 691 | <td><pre>}</pre></td> |
| 692 | </tr> |
| 693 | </table> |
| 694 | </div> |
| 695 | <div class="listing config frame"><pre><span class="comment"># Config file for the manager team example:</span> |
| 696 | <em>MyManagerTeam</em></pre></div> |
| 697 | <div class="codecomment"> |
| 698 | <h5>Effects:</h5> |
| 699 | <ul> |
| 700 | <li><code>startMethod</code> and <code>stopMethod</code> are methods which demand |
| 701 | the activation and deactivation respectively. |
| 702 | |
| 703 | </li> |
| 704 | <li>If the activation/deactivation depends on other conditions these can be checked in addition. |
| 705 | |
| 706 | </li> |
| 707 | </ul> |
| 708 | </div> |
| 709 | </div> |
| 710 | </div> |
| 711 | <table class="nav"> |
| 712 | <tr> |
| 713 | <td class="back"><a href="s4.html" rel="prev"><< §4 Callin Binding</a></td> |
| 714 | <td class="top"><a href="index.html" rel="contents">↑ Table of Contents ↑</a></td> |
| 715 | <td class="next"><a href="s6.html" rel="next">§6 Object Teams API >></a></td> |
| 716 | </tr> |
| 717 | </table> |
| 718 | </div> |
| 719 | <div id="footer"> |
Stephan Herrmann | 109893e | 2010-05-18 22:02:53 +0000 | [diff] [blame] | 720 | <hr /><a class="w3c img" href="http://jigsaw.w3.org/css-validator/check/referer" |
| 721 | shape="rect"><img src="../images/valid-css2-blue.png" alt="Valid CSS!" height="31" width="88" /></a><a class="w3c img" href="http://validator.w3.org/check?uri=referer" shape="rect"><img src="../images/valid-xhtml10-blue.png" alt="Valid XHTML 1.0 Strict" height="31" |
| 722 | width="88" /></a><address>© Stephan Herrmann, Christine Hundt, Marco Mosconi</address> |
Stephan Herrmann | b7085ef | 2011-05-15 14:59:15 +0000 | [diff] [blame] | 723 | OT/J version 1.3 — last modified: 2011-05-15 |
Stephan Herrmann | 0166441 | 2010-04-01 20:28:43 +0000 | [diff] [blame] | 724 | </div> |
| 725 | </body> |
| 726 | </html> |