Home » Language IDEs » Objectteams » Lifting and Roles - Graph Product Line example(Lifting and Roles - Graph Product Line example)
Lifting and Roles - Graph Product Line example [message #1007183] |
Mon, 04 February 2013 19:58 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
Hello,
I have programmed part of the Graph Product Line (GPL) in Object-Teams. I have a question regarding my code, so I post here a simplified version of my example.
Background: The Graph Product Line (GPL) is a Software Product Line (SPL) about Graphs and features regarding different type of Graphs (weighted or unweighted edges, directed or undirected edges, colored or uncolored edges, etc.) and various graph algorithms.
Currently I am interested in the dynamic capabilities of Object Teams. Especially in adding roles to existing objects at runtime and managing the state of instance variables in that situation.
In my small example I have implemented a plain 'Graph' and also a 'WeightedGraph' (both team classes). It is setting, an edge is part of a graph and connects two nodes. This is implemented via the Role 'Graph.Edge' that consists of two instance variables 'from' and 'to', which are both of type 'Graph.Node'.
Here is a link to the full code example, a simplified version of the graph product line (GPL):
[h]ttps://gist.github.com/8cb1cd50bd5b832532c9
[h]ttp://wikisend.com/download/348874/simplified-gpl-example.zip
(Probably I am using object teams in a slightly different manner compared to the online code examples. If you know improvements to my code, please tell me.)
Information about the version of OT:
Eclipse SDK 4.3M4
Object Teams Development Tooling - 2.2.0.201212161846
Runtime - objectteams.runtime_2.1.0.201212161846.jar
Short information regarding the code example:
For a weighted edge a new instance variable 'weight' is needed, which is of type 'int'. The Role 'Weighted.Edge' that is part of 'WeightedGraph' and includes the instance variable 'weight'.
The goal for the example is:
How can I create an 'Edge' with the Role 'Graph.Edge' and how can I later lift this edge to also include the Role 'WeightedGraph.Edge'. After the lifting, I would like to access/print the instance variables defined in 'Graph.Edge', as well those defined in 'WeightedGraph.Edge'.
I have implemented the functionality using lifting, but unfortunately if I print the 'Edge' object, this result is a NullPointerException. (The call 'super.print()' within the method 'WeightedGraph.Edge.print()' of Role 'WeightedGraph.Edge' results in the exception.)
I am interested in:
a) Why does this exception happen?
b) Is there an alternative approach in object teams to solve the problem?
Best regards from Vienna,
Stephan
(aka Steve Mayer)
====== here is a copy of the source code (see also the linked zipfile above) ======
public class Edge { }
public class Node { }
public team class Graph {
// ArrayList<REdges> edges = new ArrayList<GEdge>();
// public void addEdge(Edge as REdge e) { edges.add(e); }
// (simplified example, this is commented out)
// new method
protected REdge newEdge(String name) {
return new REdge(name);
}
public class REdge playedBy Edge {
protected RNode from, to;
public REdge(Edge e) { System.out.println("Graph.REdge() -- custom lifting constructor"); }
public REdge(String name) {
base();
System.out.println("Graph.REdge() -- normal constructor");
from = new RNode("node-from -- name: "+name);
to = new RNode("node-to -- name: "+name);
}
public void print() {
System.out.println("Plain Edge with two nodes:");
from.print();
to.print();
}
}
public class RNode playedBy Node {
protected String name;
public RNode(String s) { base(); name = s;}
public void print() { System.out.println(name); }
}
}
public team class WeightedGraph extends Graph {
// lifting method
protected REdge liftDecorate(Edge as REdge e) { return e;}
public class REdge playedBy Edge {
int weight = -1;
public REdge(Edge e) { System.out.println("WeightedGraph.REdge() -- custom lifting constructor"); }
public void print() {
System.out.println("WeightedEdge with nodes:");
tsuper.print();
}
public int getWeight() { return weight; }
}
}
public class Main {
public static void main(String[] args) {
// note: simplified example, we don't do anything with the objects
// usually we would do 'g1.add( g1.newEdge() )' and so on
Graph g1 = new Graph();
g1.newEdge(" plain Edge A").print();
WeightedGraph g2 = new WeightedGraph();
System.out.println("======\n\n");
// we can lift the plain edge (i.e., it becomes a weighted edge) and get its weight:
int testWeight = g2.liftDecorate(g1.newEdge(" plain Edge B")).getWeight();
System.out.println("======\n\n");
// again lifting, but printing the edge results in a NullPointerException
// (i.e., the instance variables 'from' and 'to' are NullPointers!)
g2.liftDecorate(g1.newEdge(" plain Edge B")).print();
}
}
/**
* OUTPUT:
*
*
Graph.REdge() constructor
Plain Edge with nodes:
node-from -- name: plain Edge A
node-to -- name: plain Edge A
======
Graph.REdge() constructor
WeightedGraph.REdge() -- custom lifting constructor
======
Graph.REdge() constructor
WeightedGraph.REdge() -- custom lifting constructor
WeightedEdge with nodes:
Plain Edge with nodes:
Exception in thread "main" java.lang.NullPointerException
at WeightedGraph$__OT__REdge.print(WeightedGraph.java:35)
at WeightedGraph$__OT__REdge.print(WeightedGraph.java:22)
at Main.main(Main.java:25)
*/
|
|
|
Re: Lifting and Roles - Graph Product Line example [message #1007882 is a reply to message #1007183] |
Thu, 07 February 2013 22:19 |
Stephan Herrmann Messages: 1853 Registered: July 2009 |
Senior Member |
|
|
Hi Stephan,
sorry for the delay, here are some answers:
Quote: a) Why does this exception happen?
The core to understanding your program is in this method call:
g2.liftDecorate(g1.newEdge(" plain Edge B"))
the inner call (newEdge) causes two objects to be created:
(a) a role instance of Graph.REdge
(b) a base instanceof Edge (via the base() constructor call inside REdge's ctor)
Of these, the role instance (a) is the passed into the call to liftDecorate, but here double magic happens:
- This method requires an Edge instance. When seeing a Graph.REdge instead the compiler has to insert a lowering conversion, so actually the base instance (b) is passed into liftDecorate
- upon entering this method the base instance (b) is then lifted to a fresh role of type WeightedGraph.REdge, let's call this role (c).
As a result we have two independent roles (a) and (c) both connected to the same base (b):
When it comes to executing Graph.REdge.print() (via the tsuper call in WeightedGraph.REdge.print()), we find that role (c) has no 'to' and 'from' nodes associated. Both fields are null, hence the NPE.
Looking about I can see that these fields are properly initialized in role (a). I.e., we have one role that has the 'to'/'from' information and another role holding the 'weight' information. However, neither role can "see" the other role, they only share the common base (b).
The mismatch in your code is in the tsuper call: you are trying to delegate to the part that owns the 'to'/'from' information, but your calling this code on the role (c) which doesn't have that information.
Quote:b) Is there an alternative approach in object teams to solve the problem?
Let's focus on the capability to dynamically add 'weight' information to edges in an existing graph.
Your design actually does this already. To avoid the confusion underlying the NPE I'd suggest to remove the inheritance relation between Graph and WeightedGraph (once that is done, you'll no longer be tempted to make that bogus tsuper call).
At this point we'll see that the connection is solely defined by the runtime graph of roles and bases.
The only thing we have to fix now: how can a method invocation of role (c) trigger any behaviour sitting in role (a)?
I see two general schemes how this could be solved:
(A) change the structure so that WeightedGraph.REdge is not a role of Edge but of Graph.REdge. Then role (c) can invoke methods of role (a) via callout method binding.
(B) leave the structure as it is but work with a chain of callout-then-callin, which matches the lower-than-lift scheme explained above.
Approach (A) re-arranges the formerly independent roles into a chain. To make this possible you may refer to the Layering section in the OTJLD: http://www.objectteams.org/def/1.3/s2.html#s2.7.c
When expanding approach (B) as a general design, you may run into infinite recursion, if all roles intercept (via callin, which requires team activation) calls to the base object and also invoke the same base method as to let other roles jump in. If needed, temporarily deactivating a team will cut this infinite recursion.
Finally, an approach (C) might be to explicitly invoke slices of the behaviour by calling explicitly which team you want to be involved. This approach would apply the Team Component pattern (http://wiki.eclipse.org/OTPattern/TeamComponent). Instead of calling print() on a role you would call "print(Edge as REdge e)" on a particular team instance (or several of them).
OK, the design space is starting to get large
I'll let you choose which general direction you want to follow. Fell free to ask detailed questions on that way.
cheers,
Stephan
|
|
| |
Re: Lifting and Roles - Graph Product Line example [message #1008122 is a reply to message #1007883] |
Sun, 10 February 2013 03:15 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
Hello Stephan,
thank you for you reply, it helped me a lot.
I am perusing approach (A), the team layering approach.
Yesterday I tried to code the example "(c) Layering" in section §2.7 Advanced structures and I got the code working.
However, I think I would need more advanced structures.
So today, I tried to implement the two advanced examples in section "(d) Implicit playedBy specialization" in §2.7 Advanced structures.
I am interested in the second example:
Consider the case where a nested T1 as a role of TOuter is stacked on a base team TB1. Also, T1 is a layered team over TB1 because its role R adapts role TB1.B. In this situation the playedBy relation of role TOuter.T1.R is given by a base-anchored type B<@T1.base>. If furthermore TOuter.T1 is subclassed to TOuter.T2 which covariantly refines the inherited playedBy declaration to TB2, then TOuter.T2.R will automatically refine the inherited playedBy relation to TB2.B to follow the new interpretation of the base anchor.
Could you please write me the code for this example?
It's because as soon as I extend a team in a more complicate setting, I get various error messages, some perhaps refer to the generated code.
Like:
No enclosing instance of the type ... is accessible in scope
Exception in thread "main" java.lang.ClassFormatError: Duplicate method name&signature in class file Outer$__OT__SecondarySub$__OT__Role1
I would really need the second advance example, so I can fix the graph product line code (GPL) on Monday.
Also, I can give you the GPL code and perhaps a second SPL example, as soon as I am finished with the SPL examples.
All the best,
Stephan
Stephan Herrmann wrote on Thu, 07 February 2013 17:29PS: Reconsidering your inheritance between WeightedGraph and Graph you seem to be expressing a dependence between these two features.
This is an indication that the team layering approach (A) is closest to your intentions.
Either way, it should help to think of callout and callin bindings for wiring the interactions between the different slices of behaviour.
|
|
| | | |
Re: Lifting and Roles - Graph Product Line example [message #1008838 is a reply to message #1008139] |
Thu, 14 February 2013 00:07 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
Stephan Herrmann wrote on Sun, 10 February 2013 16:04Steve
[quote title=Quote:Exception in thread "main" java.lang.ClassFormatError: Duplicate method name&signature in class file Outer$__OT__SecondarySub$__OT__Role1
I didn't see this. If you see it again please file a bug (with your example, if possible), thanks.
Unfortunately, I did not read your last post on Sunday (from 16:00 ) when I wrote my last posting. I probably looked at a cached version of the forum page, without reloading the site, when I wrote the answer. So, please mind that! It must have appeared quite strange to you.
I am not sure if the error ('Duplicate method name&signature in class file...') is a bug in OT. It could be related to bug 400404 or another problem.
Because I don't yet fully understand, in OT, the concept of final instances and how 'base anchors' work in complex examples, so I maybe I am using OT in a semantically incorrect way. And I did not care about error messages in my code because of the bug 400404.
I tried to install OT from the staging repository as you said, but I got a download error:
My input in "Work with ('type or select a site')":
[h]ttp://build.eclipse.org/tools/objectteams/stagingRepo
This is the message of the pop-up:
An error occurred while collecting items to be installed
session context was:(profile=SDKProfile, phase=org.eclipse.equinox.internal.p2.engine.phases.Collect, operand=, action=).
Multiple problems occurred while downloading.
Artifact not found: http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar.pack.gz.
http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar.pack.gz
Artifact not found: http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar.
http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar
Multiple problems occurred while downloading.
Here is a link to the full error message:
[h]ttps://gist.github.com/stgit/36b9d28811e7ab758725
As soon as I manage to install the stageing version or the git version, I can file a bug report, if the error message still comes up.
I also looked at the git-repository. My attempts to build the compiler failed, but this is probably due the fact that I don't know anything about build tools for java. (personally I often use haskell; I understand and quite like the build tools as well as the package management functionality). I briefly looked on the website for information regarding the git repo.
I clone this git repo, hope that's the right one:
[h]ttp://git.eclipse.org/c/objectteams/org.eclipse.objectteams.git
Are there any instructions (including detailed prerequisites) on how to build OT from the git repository, or how to run the test suite? For me, building only the command line compiler would be enough.
A side note: Perhaps it would make sense to also mention the java version you are using to you develop object teams or a reference version for object teams. Maybe also, whether you use Win/Mac/Linux. This could rule out problems related to different java versions. I am using linux with "oracle java 6u37", but some windows users might use "oracle java 7u9", so this could theoretically lead to problems (that I would like to rule out). For instance, eclipse milestone m5 (kepler) does crash in certain situations.
Just in case you are interested about the error message (I could file a bug report too):
[h]ttps://gist.github.com/anonymous/34b22f70836d42c05163
In the meantime, I further tried to get my small example, from my last posting, working. But, no matter what, I still get:
The constructor TOuter.T2.R(B<tthis[TB2]> is undefined.
Thanks for any pointers.
I did already link to object teams in a posting on 'stackoverflow.com', simply because I think more people should know and be interested in object teams.
cheers,
Stephan
ps: I can't post links because of 'You can only use links to eclipse.org sites while you have fewer than 5 messages.'
|
|
|
Re: Lifting and Roles - Graph Product Line example [message #1009221 is a reply to message #1008838] |
Thu, 14 February 2013 17:39 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
I almost got the git version of OT to compile. First I did not notice that the sub folder in eclipse contain project files.
Currently I have imported the root folder in eclipse and selected all sub projects.
I started with a fresh version of eclipse M5 (kepler).
Some dependencies are probably still missing:
Require-Bundle: org.apache.bcel;bundle-version="[5.2.0,5.3.0)"
org.eclipse.test.performance;bundle-version="[3.1.0,4.0.0)",
org.eclipse.m2e.core;bundle-version="[1.0.0,2.0.0)",
org.eclipse.m2e.jdt;bundle-version="[1.0.0,2.0.0)",
org.eclipse.m2e.lifecyclemapping.defaults;bundle-version="[1.0.0,2.0.0)",
org.eclipse.m2e.maven.runtime;bundle-version="[1.0.0,2.0.0)",
org.eclipse.jdt.debug.tests,
org.eclipse.jdt.core.tests.builder,
|
|
| |
Re: Lifting and Roles - Graph Product Line example [message #1009233 is a reply to message #1008838] |
Thu, 14 February 2013 18:08 |
Stephan Herrmann Messages: 1853 Registered: July 2009 |
Senior Member |
|
|
Steve Mayer wrote on Thu, 14 February 2013 01:07
I tried to install OT from the staging repository as you said, but I got a download error:
My input in "Work with ('type or select a site')":
[h]ttp://build.eclipse.org/tools/objectteams/stagingRepo
This is the message of the pop-up:
An error occurred while collecting items to be installed
session context was:(profile=SDKProfile, phase=org.eclipse.equinox.internal.p2.engine.phases.Collect, operand=, action=).
Multiple problems occurred while downloading.
Artifact not found: http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar.pack.gz.
http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar.pack.gz
Artifact not found: http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar.
http://build.eclipse.org/tools/objectteams/stagingRepo/plugins/org.apache.bcel_5.2.0.v201005080400.jar
Multiple problems occurred while downloading.
This might happen if you install *only* from that site, perhaps without a prior install of OTDT. This problem *should* disappear if you additionally enable the milestone repository http://download.eclipse.org/objectteams/updates/ot2.2milestones
For this to take effect enable
[x] Contact all update sites during install to find required software
Background: bcel is a dependency of OTDT, which is missing in the staging repo, but can be found in the milestone repo.
HTH,
Stephan
|
|
| | |
Re: Lifting and Roles - Graph Product Line example [message #1019798 is a reply to message #1012310] |
Sat, 16 March 2013 17:48 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
Hello Stephan,
thank you for you last answers, they helped me to work further. I had to take a brief break from my work with Object Teams, but I just started the last 1-2 weeks to look again at the product line examples.
From now on I am using the unstable version of Object Teams ('eclipse.org/objectteams/updates/unstable' - I hope this is still the current unstable version).
I will split my text in three postings.
First, I am interested in the dynamic lifting capabilities, as I think the dynamic capabilites of object teams are one of the main advantages of using OT.
For the graph example (graph product line), I would like to use BasicGraphs and WeightedGraphs. But I subsequently would like to 'lift' existing BasicGraph instances to WeightedGraph instances.
...
public team class Features {
public team class BasicGraph playedBy BGraph { }
public team class WeightedGraph extends BasicGraph { }
protected BasicGraph liftBasicGraph (BGraph as BasicGraph g) { return g;}
protected WeightedGraph liftWeightedGraph (BGraph as WeightedGraph g) {return g;}
...
Here are my methods to create a new Graphs:
protected BasicGraph newBasicGraph() {
BasicGraph g = new BasicGraph (new BGraph());
return g;
}
// the above version would work, however leads to a warning and an exception at run time,
// when I lift a BasicGraph instance to a WeightedGraph instance.
// i.e., warning : Dangerous instantitation. To avoid a WrongRoleException at runtime ...
// alternative version:
protected BasicGraph newBasicGraphWorking() {
BasicGraph g = new WeightedGraph(new BGraph());
return g;
}
// this is the suggested version of the tool tip, however here an BasicGraph is esentially a WeightedGraph and lifiting is besides the point.
Note that I cannot define a constructor for BGraph (possible bug?).
public team class BasicGraph playedBy BGraph {
/* ERROR: I cannot define a constructor for BGraph
* this leads to 'The constructor Outer.BGraph() is undefined', which is wrong,
* as I have defined just that constructor.
*
public BasicGraph() {
base();
}
*/
The full code is posted at the end of this posting.
Would you have any tips on how I can implement 'liftable' graphs?
(I post the full code at the end of this posting.)
Stephan
Full code:
package features;
public team class Outer {
// empty classes that get refined
public class BGraph {
public BGraph() {
}
}
public class BNode { }
public class BEdge { }
public void test() {
final Features f = new Features();
/* VERSION 1 */
BasicGraph<@f> g = f.newBasicGraphWorking();
WeightedGraph<@f> g2 = f.liftWeightedGraph(g);
g.print();
g2.print();
/* However, 'Wrong' result printed: */
// I am a weighted graph ...
// I am a weighted graph ...
/* VERSION 2 (EXCEPTION) */
BasicGraph<@f> g3 = f.newBasicGraphException();
g3.print();
WeightedGraph<@f> g4 = f.liftWeightedGraph(g3);
/*
* The compiler has warned you about ambiguous role bindings.
Now lifting to class features.Outer$__OT__Features$__OT__WeightedGraph fails with the following objects
(see OT/J language definition para. 2.3.4(d)) */
}
public team class Features {
/* new methods */
protected BasicGraph newBasicGraphException() {
BasicGraph g = new BasicGraph (new BGraph());
/* warning :
Dangerous instantitation. To avoid a WrongRoleException at runtime role
WeightedGraph should be used instead (OTJLD 2.4.3).
*/
return g;
}
protected BasicGraph newBasicGraphWorking() {
BasicGraph g = new WeightedGraph(new BGraph());
return g;
}
/* lifting methods */
protected BasicGraph liftBasicGraph (BGraph as BasicGraph g) { return g;}
protected WeightedGraph liftWeightedGraph (BGraph as WeightedGraph g) {return g;}
public team class BasicGraph playedBy BGraph {
/* ERROR: I cannot define a constructor for BGraph
* this leads to 'The constructor Outer.BGraph() is undefined', which is wrong,
* as I have define just that constructor.
*
public BasicGraph() {
base();
}
*/
public void print() {
System.out.println("I am a basic graph ...");
}
public Node newNode(String s) {
Node n = new Node(new BNode());
return n;
}
public class Node playedBy BNode { }
}
public team class WeightedGraph extends BasicGraph {
@Override
public void print() {
System.out.println("I am a weighted graph ...");
}
}
}
public static void main(String[] args) {
new Outer().test();
}
}
|
|
| |
Re: Lifting and Roles - Graph Product Line example [message #1027948 is a reply to message #1019909] |
Wed, 27 March 2013 16:31 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
Hello Stephan,
just a short question:
is it possible to look at the generated java code in Object Teams?
I.e., I can access the generated class files, such as "Features$__OT__WeightedGraph.class", but I would like to look at the java code, which is compiled to those "OT class files".
In case another problem turns up, I can look at the java code. If there is an easy way in eclipse to to do that I must have missed it, as I look in almost all the menus.
In case someone is interested, there is an update in the bug report from my last message that states that the problem is now fixed.
regards from Vienna,
Stephan
|
|
| |
Re: Lifting and Roles - Graph Product Line example [message #1057730 is a reply to message #1030004] |
Wed, 08 May 2013 13:29 |
Hi-Tech ITO Messages: 2 Registered: May 2013 Location: Ahmedabad |
Junior Member |
|
|
Thank you for your recent response helped me to work. I have to take a break from my work with teams of subjects, but I just started in the last 1-2 weeks to see new examples of product lines.
From now on, I use the version command unstable objects ('eclipse.org / objectteams / Update / unstable "- I hope this is still the current stable version).
I will divide my text into three editions.
First of all, I am interested in basic dynamic load rating, I believe that the dynamic capabilities of the equipment items are one of the main advantages of using OT.
For example, graphics (graphics product line), I would like to use and BasicGraphs WeightedGraphs. But then it would be a "bump" of existing case WeightedGraph BasicGraph case.
public team class Features {
public team class BasicGraph playedBy BGraph { }
public team class WeightedGraph extends BasicGraph { }
protected BasicGraph liftBasicGraph (BGraph as BasicGraph g) { return g;}
protected WeightedGraph liftWeightedGraph (BGraph as WeightedGraph g) {return g;}
Here are my methods to create a new Graphs:
Code: [Select all] [Show/ hide]
protected BasicGraph newBasicGraph() {
BasicGraph g = new BasicGraph (new BGraph());
return g;
}
// the above version would work, however leads to a warning and an exception at run time,
// when I lift a BasicGraph instance to a WeightedGraph instance.
// i.e., warning : Dangerous instantitation. To avoid a WrongRoleException at runtime ...
// alternative version:
protected BasicGraph newBasicGraphWorking() {
BasicGraph g = new WeightedGraph(new BGraph());
return g;
}
// this is the suggested version of the tool tip, however here an BasicGraph is esentially a WeightedGraph and lifiting is besides the point.
Note that I cannot define a constructor for BGraph (possible bug?).
Code: [Select all] [Show/ hide]
public team class BasicGraph playedBy BGraph {
/* ERROR: I cannot define a constructor for BGraph
* this leads to 'The constructor Outer.BGraph() is undefined', which is wrong,
* as I have defined just that constructor.
*
public BasicGraph() {
base();
}
*/
The full code is posted at the end of this posting.
Would you have any tips on how I can implement 'liftable' graphs?
(I post the full code at the end of this posting.)
Stephan
Full code:
Code: [Select all] [Show/ hide]
package features;
public team class Outer {
// empty classes that get refined
public class BGraph {
public BGraph() {
}
}
public class BNode { }
public class BEdge { }
public void test() {
final Features f = new Features();
/* VERSION 1 */
BasicGraph<@f> g = f.newBasicGraphWorking();
WeightedGraph<@f> g2 = f.liftWeightedGraph(g);
g.print();
g2.print();
/* However, 'Wrong' result printed: */
// I am a weighted graph ...
// I am a weighted graph ...
/* VERSION 2 (EXCEPTION) */
BasicGraph<@f> g3 = f.newBasicGraphException();
g3.print();
WeightedGraph<@f> g4 = f.liftWeightedGraph(g3);
/*
* The compiler has warned you about ambiguous role bindings.
Now lifting to class features.Outer$__OT__Features$__OT__WeightedGraph fails with the following objects
(see OT/J language definition para. 2.3.4(d)) */
}
public team class Features {
/* new methods */
protected BasicGraph newBasicGraphException() {
BasicGraph g = new BasicGraph (new BGraph());
/* warning :
Dangerous instantitation. To avoid a WrongRoleException at runtime role
WeightedGraph should be used instead (OTJLD 2.4.3).
*/
return g;
}
protected BasicGraph newBasicGraphWorking() {
BasicGraph g = new WeightedGraph(new BGraph());
return g;
}
/* lifting methods */
protected BasicGraph liftBasicGraph (BGraph as BasicGraph g) { return g;}
protected WeightedGraph liftWeightedGraph (BGraph as WeightedGraph g) {return g;}
public team class BasicGraph playedBy BGraph {
/* ERROR: I cannot define a constructor for BGraph
* this leads to 'The constructor Outer.BGraph() is undefined', which is wrong,
* as I have define just that constructor.
*
public BasicGraph() {
base();
}
*/
public void print() {
System.out.println("I am a basic graph ...");
}
public Node newNode(String s) {
Node n = new Node(new BNode());
return n;
}
public class Node playedBy BNode { }
}
public team class WeightedGraph extends BasicGraph {
@Override
public void print() {
System.out.println("I am a weighted graph ...");
}
}
}
public static void main(String[] args) {
new Outer().test();
}
}
|
|
| |
Re: Lifting and Roles - Graph Product Line example [message #1060536 is a reply to message #1057730] |
Sun, 26 May 2013 12:20 |
Stephan Herrmann Messages: 1853 Registered: July 2009 |
Senior Member |
|
|
I was busy getting some last fixes into the Kepler release. A fix for "your" error regarding 'The constructor Outer.BGraph() is undefined' is among those [1]. It's currently in the staging area from where Kepler RC2 will be aggregated:
http://download.eclipse.org/objectteams/updates/ot2.2-staging
With this fix you no longer need to write "new BasicGraph (new BGraph())" but this should suffice: "new BasicGraph ()".
However, I couldn't fully understand your design with respect to lifting, it seems you are using lifting as something that it is not meant to be.
To set the background for all those issues of "dangerous instantiation" and "wrong role". it is important to know that
- lifting is designed as an implicit conversion, that can be inserted by the compiler mainly in callin and callout method bindings to lift base type parameters (return for callout) to expected role types.
- lifting always picks the best applicable role type based on three pieces of information: the base type, the team instance and the minimal required role type
- once created, each role is stored in an internal cache of the team, so that lifting the same base object again can re-use the existing role instance. Role caches are shared for each hierarchy of role types.
From this you should understand the business of WrongRoleException: lifting a BGraph to anything less-or-equal BasicGraph will find the role WeightedGraph to be the most specify applicable role. If, however, explicit role creation of a BasicGraph forced an instance of this exact type, any attempt to lift the same BGraph to a WeightedGraph will fail, because a BasicGraph will already be found in the corresponding cache, which is the "wrong role" for this request.
It is not possible to add two different role instances to the same base instance if the different role types are within the same role type hierarchy and if roles are bound to the same base class.
Some options how to resolve the problem in your example:
- remove class BasicGraph, if BGraph is the undecorated graph already, I don't see why you would want to lift BGraph to BasicGraph just to add *nothing*, or
- make BasicGraph and WeightedGraph independent roles, i.e., remove the inheritance relation (they could still have a common super type *without* a playedBy binding). That way each BGraph can have both roles independently, or
- avoid role instantiation via lifting, always explicitly create roles of either type. When after instantiation lifting is used, only require BasicGraph, such that whatever role is found in the cache is good enough.
These are quite technical discussions. Which approach is suitable depends of course on the exact requirements, which I don't know. I'm wonder if perhaps you are forcing things into an inheritance hierarchy, because other PL approaches do so, where a role based approach doesn't require this inheritance at all.
To contrast your design with the simplest thing that could possibly work, consider this:
public class Node { }
public class Edge { Node start, end; }
public team class Weight {
protected class WeightedEdge playedBy Edge {
public int weight;
}
public void setWeight(Edge as WeightedEdge edge, int weight) {
edge.weight = weight;
}
public int getWeight(Edge as WeightedEdge edge) {
return edge.weight;
}
}
This already adds the dynamic capability to add weights to any edge.
If weights should be respected in any graph operations, this could be achieved by callin bindings to the corresponding graph methods. In these callin bindings, Edge instances would be lifted to WeightedEdge and computations based on weights can be performed.
I'm perhaps oversimplifying things, but if you go for a more involved design, it's of course good to known, why exactly
I hope the GPL example is sufficiently specified so you know your requirements. But perhaps those requirements can only be discovered once you implement a set of actual applications rather than a library for graphs with not specific usage scenarii - just wondering.
HTH
Stephan
[1] https://bugs.eclipse.org/409075 - [compiler] base constructor call fails to resolve to role of an outer enclosing team
|
|
|
Re: Lifting and Roles - Graph Product Line example [message #1062280 is a reply to message #1060536] |
Thu, 06 June 2013 23:44 |
Steve Mayer Messages: 22 Registered: December 2012 |
Junior Member |
|
|
Today I read in the Object Teams Specification and I was thinking about lifting versus lowering.
It is written that "Lifting is the reverse translation of lowering."
However, there are small details that are different. Lifting can create new role objects, but lowering can never delete role objects.
For lifting, I can define a special purpose "lifting constructor", but for lowering there is no pendant.
Was there a special reson for this?
Also my quick look didn't reveal a method to remove role objects.
Just my thoughs of today.
Best,
Stephan A.
[Updated on: Thu, 06 June 2013 23:45] Report message to a moderator
|
|
|
Re: Lifting and Roles - Graph Product Line example [message #1062478 is a reply to message #1062280] |
Fri, 07 June 2013 22:26 |
Stephan Herrmann Messages: 1853 Registered: July 2009 |
Senior Member |
|
|
Steve Mayer wrote on Fri, 07 June 2013 01:44Today I read in the Object Teams Specification and I was thinking about lifting versus lowering.
It is written that "Lifting is the reverse translation of lowering."
However, there are small details that are different.
True, both operations cannot be 100% symmetric because the underlying playedBy relation is asymmetric to begin with.
Quote:Lifting can create new role objects, but lowering can never delete role objects.
Role creation is necessary for lifting (unless an existing role can be re-used), but deleting a role is not necessary, it actually works against re-using cached role instances (which would mean roles can't keep state between operations).
Quote:For lifting, I can define a special purpose "lifting constructor", but for lowering there is no pendant.
This is just a consequence of the above. An operation that is invoked by the infrastructure (role creation) can be intercepted by implementing a role constructor, the absence of an operation during lowering doesn't provide a good hook
Quote:Was there a special reson for this?
Let me step back one, and speak about the underlying motivation:
When working a lot with callin bindings, the on-demand creation of role instances provides the illusion that all base instances are actually adapted by a corresponding role instance -- even if none exists at a given point in time, it will be created early enough to perform its adaptation.
Think of lifting as "materializing" a virtual object.
Quote:
Also my quick look didn't reveal a method to remove role objects.
the ITeam.unregisterRole methods[1] do most of this. The rest is garbage collection (provided you don't hold a reference to the role). In fact, neither role nor base are referenced from client code, they will be garbage collected (although internally we hold some (weak) references).
Is this clearer now?
Stephan
[1] http://www.objectteams.org/def/1.3.1/s6.html#s6.1
|
|
| | | | | | | | | |
Re: Lifting and Roles - Graph Product Line example [message #1697885 is a reply to message #1697725] |
Tue, 09 June 2015 10:59 |
Stephan Herrmann Messages: 1853 Registered: July 2009 |
Senior Member |
|
|
aadhar card wrote on Sun, 07 June 2015 13:26It is written that "Lifting is the reverse translation of lowering."
However, there are small details that are different. Lifting can create new role objects, but lowering can never delete role objects.
You are right, the quoted statement generalizes the situation, disregarding details.
For the general intuition, you could even imagine that each base object has a virtual (immaterial) role (within each team instance), which is materialized upon first access. With this intuition, both lifting and lowering are only navigations from one instance to another.
Quote:
For lifting, I can define a special purpose "lifting constructor", but for lowering there is no pendant.
Right, as soon as a custom lifting constructor is defined, there's the possibility that lifting can cause side effects. There's no denying this fact, while OTOH one may still argue that constructors should never cause side effects outside the object being created.
Thinking about a possible inverse of a lifting constructor, we may ask two questions: (a) can base creation be triggered by lowering and (b) can object destruction cause side effects.
For (a) the obvious answer is "no", because a role cannot exist without its base.
For (b) roles behave like any object in Java: since Java has no explicit destructor calls, forgetting an instance is nothing more then deleting the last incoming reference. Roles are well integrated with the Java garbage collector (see http://www.objectteams.org/def/1.3.1/s2.html#s2.1.f ).
As another difference, lifting can fail for several reasons, whereas lowering always succeeds.
Summarizing: yes there is an inherent asymmetry between roles and bases and hence also between lifting and lowering. But looking just at the navigation, the following formula holds (disregarding exceptions):
Do you agree?
Stephan
|
|
|
Goto Forum:
Current Time: Mon Sep 23 09:09:50 GMT 2024
Powered by FUDForum. Page generated in 0.07663 seconds
|