Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » determine containment of EObject
determine containment of EObject [message #1081491] Wed, 07 August 2013 05:39 Go to next message
Mauro Condarelli is currently offline Mauro Condarelli
Messages: 415
Registered: September 2009
Senior Member
I'm trying to write a PrettyPrinter for a generic Model.
There is such a thing floating around in the Internet, but it fails
miserably when model has circular references (including a simple
"opposite" construct). Problem is it does not differentiate between
containment and non-containment EReferences.
I am thus rewriting it almost from scratch.

I have problems determining the actual *containing* object of the target
of a non-containment EReference.

Relevant section of my code is:


EObject eo = <current object>;
EClass eClass = eo.eClass();

sb.append(eClass.getName());
sb.append(" [");
sb.append(eo.getClass().getCanonicalName());
sb.append("] {\n");
for (EStructuralFeature feature : eClass.getEAllStructuralFeatures()) {
sb.append(feature.getName());
Object value = eo.eGet(feature);
boolean done = false;
if (feature instanceof EReference) {
EReference er = (EReference) feature;
if (!er.isContainment()) {
sb.append(" => ");
EStructuralFeature cf = er.eContainingFeature();
Object ceo = er.eContainer().eGet(cf);
sb.append(ceo.getClass().getCanonicalName());
sb.append(".");
sb.append(cf.getName());
if (ceo instanceof EList<?>) {
EList<?> cl = (EList<?>) ceo;
int i = cl.indexOf(value);
sb.append("@");
sb.append(i);
}
done = true;
}
}

The test is ok, but I would like to print a non-containment reference as
" => <containing EClass>.<containing EFeature>".
If <containing EFeature> is a list I would add "@<index>"

I seem unable to get the right containing EClass/EFeature and extract
their names.

Can someone point me in the right direction in this maze?
TiA
Mauro
Re: determine containment of EObject [message #1081528 is a reply to message #1081491] Wed, 07 August 2013 06:30 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 25917
Registered: July 2009
Senior Member
Mauro,

Comments below.

On 07/08/2013 11:39 AM, Mauro Candarelli wrote:
> I'm trying to write a PrettyPrinter for a generic Model.
> There is such a thing floating around in the Internet, but it fails
> miserably when model has circular references (including a simple
> "opposite" construct). Problem is it does not differentiate between
> containment and non-containment EReferences.
That can't be good!
>
> I am thus rewriting it almost from scratch.
>
> I have problems determining the actual *containing* object of the
> target of a non-containment EReference.
>
> Relevant section of my code is:
>
>
> EObject eo = <current object>;
> EClass eClass = eo.eClass();
>
> sb.append(eClass.getName());
> sb.append(" [");
> sb.append(eo.getClass().getCanonicalName());
> sb.append("] {\n");
I'm not sure anyone would want to see the implementation class' name...
> for (EStructuralFeature feature : eClass.getEAllStructuralFeatures()) {
> sb.append(feature.getName());
> Object value = eo.eGet(feature);
> boolean done = false;
> if (feature instanceof EReference) {
> EReference er = (EReference) feature;
> if (!er.isContainment()) {
> sb.append(" => ");
> EStructuralFeature cf = er.eContainingFeature();
You're getting the containing feature of the reference itself?
> Object ceo = er.eContainer().eGet(cf);
The eContainer of a reference will be an EClass and this will fetch
that's class's getEStructuralFeatures.
> sb.append(ceo.getClass().getCanonicalName());
Keep in mind this could be a list class name.
> sb.append(".");
> sb.append(cf.getName());
> if (ceo instanceof EList<?>) {
> EList<?> cl = (EList<?>) ceo;
> int i = cl.indexOf(value);
> sb.append("@");
> sb.append(i);
> }
> done = true;
> }
> }
>
> The test is ok, but I would like to print a non-containment reference
> as " => <containing EClass>.<containing EFeature>".
So you want er.eContainer() (which could be null if it's a root object
> If <containing EFeature> is a list I would add "@<index>"
>
> I seem unable to get the right containing EClass/EFeature and extract
> their names.
I think you should be processing each EObject in "value", where "value"
is of course either an EObject or a list of EObject if the feature is an
EReference. Perhaps have a look at EcoreUtil.Copier for some insights...
>
> Can someone point me in the right direction in this maze?
> TiA
> Mauro
Re: determine containment of EObject [message #1081555 is a reply to message #1081528] Wed, 07 August 2013 07:25 Go to previous messageGo to next message
Mauro Condarelli is currently offline Mauro Condarelli
Messages: 415
Registered: September 2009
Senior Member
Thanks Ed.
I'm getting there.

On 07/08/2013 12:30, Ed Merks wrote:
> ...
>> sb.append(eo.getClass().getCanonicalName());
> I'm not sure anyone would want to see the implementation class' name...
You are absolutely right (as always).
How do I get the name of the Interface from the implementation?
I would like to avoid stupid tricks like editing the string to cut out the various "impl".
Should I filter result of eo.getESuperTypes() or is there a better way?

>> ...
>> The test is ok, but I would like to print a non-containment reference as " => <containing EClass>.<containing EFeature>".
> So you want er.eContainer() (which could be null if it's a root object
>> If <containing EFeature> is a list I would add "@<index>"
>>
>> I seem unable to get the right containing EClass/EFeature and extract their names.
> I think you should be processing each EObject in "value", where "value" is of course either an EObject or a list of EObject if the feature is an EReference. Perhaps have a look at EcoreUtil.Copier for some insights...

Code is now in a much better shape (not finished yet, as I still get some "???"):

if (feature instanceof EReference) {
EReference er = (EReference) feature;
String s;
if (!er.isContainment()) {
sb.append(" => ");
if (value == null) {
sb.append("(");
s = er.getEType().getName();
sb.append(s);
sb.append(") <null>");
} else {
if (value instanceof EObject) {
EObject evalue = (EObject) value;
EObject ceo = evalue.eContainer();
EStructuralFeature cf = evalue.eContainingFeature();
s = ceo.getClass().getCanonicalName();
sb.append(s);
sb.append(" . ");
s = cf.getName();
sb.append(s);
Object cr = ceo.eGet(cf);
if (cr instanceof EList<?>) {
EList<?> cl = (EList<?>) cr;
int i = cl.indexOf(value);
sb.append("@");
sb.append(i);
}
} else {
sb.append("???");
}
}
done = true;
}
}

Side question: should I post here (or somewhere else) resulting code, when complete and reasonably polished?
I have no problems sharing and it could be useful to someone else.
What is the recommended policy?
Re: determine containment of EObject [message #1081634 is a reply to message #1081555] Wed, 07 August 2013 09:36 Go to previous messageGo to next message
Mauro Condarelli is currently offline Mauro Condarelli
Messages: 415
Registered: September 2009
Senior Member
On 07/08/2013 13:25, Mauro Candarelli wrote:
> Thanks Ed.
> I'm getting there.
>
> On 07/08/2013 12:30, Ed Merks wrote:
>> ...
>>> sb.append(eo.getClass().getCanonicalName());
>> I'm not sure anyone would want to see the implementation class' name...
> You are absolutely right (as always).
> How do I get the name of the Interface from the implementation?
> I would like to avoid stupid tricks like editing the string to cut out the various "impl".
> Should I filter result of eo.getESuperTypes() or is there a better way?
>
Ok, found.
I needed to use getInstanceClassName().
Method names are not very meaningful to me :(

Side question remains:
>
> Side question: should I post here (or somewhere else) resulting code, when complete and reasonably polished?
> I have no problems sharing and it could be useful to someone else.
> What is the recommended policy?
Re: determine containment of EObject [message #1081664 is a reply to message #1081634] Wed, 07 August 2013 10:15 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 25917
Registered: July 2009
Senior Member
Mauro,

If you host it at github, it would be easily accessible and installable
for anyone.

On 07/08/2013 3:36 PM, Mauro Candarelli wrote:
> On 07/08/2013 13:25, Mauro Candarelli wrote:
>> Thanks Ed.
>> I'm getting there.
>>
>> On 07/08/2013 12:30, Ed Merks wrote:
>>> ...
>>>> sb.append(eo.getClass().getCanonicalName());
>>> I'm not sure anyone would want to see the implementation class' name...
>> You are absolutely right (as always).
>> How do I get the name of the Interface from the implementation?
>> I would like to avoid stupid tricks like editing the string to cut
>> out the various "impl".
>> Should I filter result of eo.getESuperTypes() or is there a better way?
>>
> Ok, found.
> I needed to use getInstanceClassName().
> Method names are not very meaningful to me :(
>
> Side question remains:
>>
>> Side question: should I post here (or somewhere else) resulting code,
>> when complete and reasonably polished?
>> I have no problems sharing and it could be useful to someone else.
>> What is the recommended policy?
>
Re: determine containment of EObject [message #1081749 is a reply to message #1081555] Wed, 07 August 2013 12:38 Go to previous message
Ed Merks is currently offline Ed Merks
Messages: 25917
Registered: July 2009
Senior Member
Mauro,

Oops, I forgot the hit send on this reply...


On 07/08/2013 1:25 PM, Mauro Candarelli wrote:
> Thanks Ed.
> I'm getting there.
>
> On 07/08/2013 12:30, Ed Merks wrote:
>> ...
>>> sb.append(eo.getClass().getCanonicalName());
>> I'm not sure anyone would want to see the implementation class' name...
> You are absolutely right (as always).
> How do I get the name of the Interface from the implementation?
> I would like to avoid stupid tricks like editing the string to cut out
> the various "impl".
> Should I filter result of eo.getESuperTypes() or is there a better way?
>
>>> ...
>>> The test is ok, but I would like to print a non-containment
>>> reference as " => <containing EClass>.<containing EFeature>".
>> So you want er.eContainer() (which could be null if it's a root object
>>> If <containing EFeature> is a list I would add "@<index>"
>>>
>>> I seem unable to get the right containing EClass/EFeature and
>>> extract their names.
>> I think you should be processing each EObject in "value", where
>> "value" is of course either an EObject or a list of EObject if the
>> feature is an EReference. Perhaps have a look at EcoreUtil.Copier
>> for some insights...
>
> Code is now in a much better shape (not finished yet, as I still get
> some "???"):
>
> if (feature instanceof EReference) {
> EReference er = (EReference) feature;
> String s;
> if (!er.isContainment()) {
> sb.append(" => ");
You probably should use feature.isMany to determine whether to expect a
single value or a list of values.
> if (value == null) {
> sb.append("(");
> s = er.getEType().getName();
> sb.append(s);
> sb.append(") <null>");
> } else {
> if (value instanceof EObject) {
> EObject evalue = (EObject) value;
> EObject ceo = evalue.eContainer();
> EStructuralFeature cf = evalue.eContainingFeature();
> s = ceo.getClass().getCanonicalName();
> sb.append(s);
> sb.append(" . ");
> s = cf.getName();
> sb.append(s);
> Object cr = ceo.eGet(cf);
> if (cr instanceof EList<?>) {
> EList<?> cl = (EList<?>) cr;
> int i = cl.indexOf(value);
> sb.append("@");
> sb.append(i);
> }
> } else {
This must be the list of values case.
> sb.append("???");
> }
> }
> done = true;
> }
> }
>
> Side question: should I post here (or somewhere else) resulting code,
> when complete and reasonably polished?
> I have no problems sharing and it could be useful to someone else.
> What is the recommended policy?
Previous Topic:Deserialization issue if attribute value is higher than 8000 characters
Next Topic:Error when I try generate GMF Editor
Goto Forum:
  


Current Time: Thu Jul 24 04:44:19 EDT 2014

Powered by FUDForum. Page generated in 0.03023 seconds