Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » inserting model object into featuremap
inserting model object into featuremap [message #396714] Wed, 09 November 2005 00:28 Go to next message
Eclipse UserFriend
Originally posted by: dhurst.lisletech.com

Hello,

I have an ecore model that was generated from an XML Schema containing a
<choice> element. This causes the generator to create a FeatureMap in
the model. I've been trying to figure out how to insert a child element
into the FeatureMap as a sibling of another element in the FeatureMap
and I just can't seem to find a solution that works.

Here is an excerpt from my schema:

<xs:complexType name="Node">
<xs:complexContent>
<xs:extension base="Base">
<xs:choice maxOccurs="unbounded" minOccurs="0">
<xs:element ref="fork"/>
<xs:element ref="line"/>
<xs:element ref="flow"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>

This results in a MixerNode class with getFork(), getLine(), getFlow(),
and getGroup() methods. The getGroup returns a FeatureMap. What I'd
like to do is find an existing element of any type in the Node and add
another node of any type as its sibling. I know this is possible
because the EMF-generated editor provides menu operations that do it.
But I can't for the life of me figure out how to do it programmatically.

It seems like I should be able to use the indexOf() method to find the
location of the element and then use add() to insert the element at that
location. This approach fails to find the element. Some investigation
of BasicFeatureMap led me to try creating a FeatureMapUtil.EntryImpl
containing the object I'm searching for, but that caused a ClassCast
exception. I tried iterating through the FeatureMap using get(), but
that fails for other reasons.

It seems like there should be something obvious that I'm missing, but I
don't know what it is. Any help would be appreciated.

--DaveH "Be Excellent to each other!"
Re: inserting model object into featuremap [message #396719 is a reply to message #396714] Wed, 09 November 2005 11:39 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 29037
Registered: July 2009
Senior Member
David,

David, it's the repeating of the model group that generates a feature
map, not the choice itself. Note that doing node.getFork().add(fork)
will be equivalent to
node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so you
may not need to work with the feature map directly. You should be
able to use the features of the Node EClass, i.e.,
XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
feature map, or any element-based feature in one of those element's
substitution group (which will be in some package's document root, i.e.,
XyzPackage.eINSTANCE.getDocumentRoot_Abc()). To match some value, you
need to iterate over the feature map and check
getGroup().getValue(index) or use FeatureMapUtil.createEntry to create a
FeatureMap.Entry to search for directly.


David Hurst wrote:

> Hello,
>
> I have an ecore model that was generated from an XML Schema containing
> a <choice> element. This causes the generator to create a FeatureMap
> in the model. I've been trying to figure out how to insert a child
> element into the FeatureMap as a sibling of another element in the
> FeatureMap and I just can't seem to find a solution that works.
>
> Here is an excerpt from my schema:
>
> <xs:complexType name="Node">
> <xs:complexContent>
> <xs:extension base="Base">
> <xs:choice maxOccurs="unbounded" minOccurs="0">
> <xs:element ref="fork"/>
> <xs:element ref="line"/>
> <xs:element ref="flow"/>
> </xs:choice>
> </xs:extension>
> </xs:complexContent>
> </xs:complexType>
>
> This results in a MixerNode class with getFork(), getLine(),
> getFlow(), and getGroup() methods. The getGroup returns a
> FeatureMap. What I'd like to do is find an existing element of any
> type in the Node and add another node of any type as its sibling. I
> know this is possible because the EMF-generated editor provides menu
> operations that do it. But I can't for the life of me figure out how
> to do it programmatically.
>
> It seems like I should be able to use the indexOf() method to find the
> location of the element and then use add() to insert the element at
> that location. This approach fails to find the element. Some
> investigation of BasicFeatureMap led me to try creating a
> FeatureMapUtil.EntryImpl containing the object I'm searching for, but
> that caused a ClassCast exception. I tried iterating through the
> FeatureMap using get(), but that fails for other reasons.
>
> It seems like there should be something obvious that I'm missing, but
> I don't know what it is. Any help would be appreciated.
>
> --DaveH "Be Excellent to each other!"
Re: inserting model object into featuremap [message #396735 is a reply to message #396719] Wed, 09 November 2005 19:52 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: dhurst.lisletech.com

Ed,

Thanks for your suggestions. The problem is that I can't work with the
feature sublists directly. In this structure, I need a generic way to
add a feature element at a specific index in the overall group. So for
example, I might have the following structure:

<Node>
<fork .../>
<line .../>
<fork .../>
</Node>

And I want to insert a <flow> element after the first <fork> element. I
can't use node.getFork() to do this because this just returns the
sublist of <fork> elements. So I have to use node.getGroup(), which
returns a feature map. The problem is that in trying to do this
generically, I don't necessarily know what type of feature I'm going to
be adding in advance, so I can't give a specific feature type. If I try
to use XyzPackage.eINSTANCE.getNode_Group(), I get a ClassCastException
in FeatureMapUtil.createEntry() because the Group feature ID is
different from the feature ID of the actual element being used.

The only other approach I can think of is to have a huge case statement
that switches on the type of element being inserted and uses the
associated feature ID. But that doesn't seem very generic and will
break if I have to change the model.

The frustrating thing about this is that I know that the generated
editor does this because it provides an add sibling menu item which does
exactly what I want. But I've tried tracking down how the command is
implemented and can't make head or tail out of it.

--DaveH "Be Excellent to each other!"

Ed Merks wrote:
> David,
>
> David, it's the repeating of the model group that generates a feature
> map, not the choice itself. Note that doing node.getFork().add(fork)
> will be equivalent to
> node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so you
> may not need to work with the feature map directly. You should be
> able to use the features of the Node EClass, i.e.,
> XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
> feature map, or any element-based feature in one of those element's
> substitution group (which will be in some package's document root, i.e.,
> XyzPackage.eINSTANCE.getDocumentRoot_Abc()). To match some value, you
> need to iterate over the feature map and check
> getGroup().getValue(index) or use FeatureMapUtil.createEntry to create a
> FeatureMap.Entry to search for directly.
>
>
> David Hurst wrote:
>
>> Hello,
>>
>> I have an ecore model that was generated from an XML Schema containing
>> a <choice> element. This causes the generator to create a FeatureMap
>> in the model. I've been trying to figure out how to insert a child
>> element into the FeatureMap as a sibling of another element in the
>> FeatureMap and I just can't seem to find a solution that works.
>>
>> Here is an excerpt from my schema:
>>
>> <xs:complexType name="Node">
>> <xs:complexContent>
>> <xs:extension base="Base">
>> <xs:choice maxOccurs="unbounded" minOccurs="0">
>> <xs:element ref="fork"/>
>> <xs:element ref="line"/>
>> <xs:element ref="flow"/>
>> </xs:choice>
>> </xs:extension>
>> </xs:complexContent>
>> </xs:complexType>
>>
>> This results in a MixerNode class with getFork(), getLine(),
>> getFlow(), and getGroup() methods. The getGroup returns a
>> FeatureMap. What I'd like to do is find an existing element of any
>> type in the Node and add another node of any type as its sibling. I
>> know this is possible because the EMF-generated editor provides menu
>> operations that do it. But I can't for the life of me figure out how
>> to do it programmatically.
>>
>> It seems like I should be able to use the indexOf() method to find the
>> location of the element and then use add() to insert the element at
>> that location. This approach fails to find the element. Some
>> investigation of BasicFeatureMap led me to try creating a
>> FeatureMapUtil.EntryImpl containing the object I'm searching for, but
>> that caused a ClassCast exception. I tried iterating through the
>> FeatureMap using get(), but that fails for other reasons.
>>
>> It seems like there should be something obvious that I'm missing, but
>> I don't know what it is. Any help would be appreciated.
>>
>> --DaveH "Be Excellent to each other!"
>
>
Re: inserting model object into featuremap [message #396736 is a reply to message #396735] Wed, 09 November 2005 20:21 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 29037
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------020307020908040800060803
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

David,

There's just so little that I know about your application and I can't
provide specific help without that knowledge. If there are no
substitution groups for the global elements you've referenced then the
*only *valid features to use are those for fork, line, and flow.

Will you know which object you want to add but you need to choose an
appropriate feature? You can use feature.getEType().isInstance(object)
to see if the instance is appropriate for use in that feature. Or do
you need to figure out all subclasses of each features type? You need
to visit "all classes" to determine that since there is no way to go
from a super class to all it's subclasses. Looking at
ReflectiveItemProvider.collectNewChildDescriptors might help you
understand how we compute the information need for child creation
dynamically.


David Hurst wrote:

> Ed,
>
> Thanks for your suggestions. The problem is that I can't work with
> the feature sublists directly. In this structure, I need a generic
> way to add a feature element at a specific index in the overall
> group. So for example, I might have the following structure:
>
> <Node>
> <fork .../>
> <line .../>
> <fork .../>
> </Node>
>
> And I want to insert a <flow> element after the first <fork> element.
> I can't use node.getFork() to do this because this just returns the
> sublist of <fork> elements. So I have to use node.getGroup(), which
> returns a feature map. The problem is that in trying to do this
> generically, I don't necessarily know what type of feature I'm going
> to be adding in advance, so I can't give a specific feature type. If
> I try to use XyzPackage.eINSTANCE.getNode_Group(), I get a
> ClassCastException in FeatureMapUtil.createEntry() because the Group
> feature ID is different from the feature ID of the actual element
> being used.
>
> The only other approach I can think of is to have a huge case
> statement that switches on the type of element being inserted and uses
> the associated feature ID. But that doesn't seem very generic and
> will break if I have to change the model.
>
> The frustrating thing about this is that I know that the generated
> editor does this because it provides an add sibling menu item which
> does exactly what I want. But I've tried tracking down how the
> command is implemented and can't make head or tail out of it.
>
> --DaveH "Be Excellent to each other!"
>
> Ed Merks wrote:
>
>> David,
>>
>> David, it's the repeating of the model group that generates a feature
>> map, not the choice itself. Note that doing node.getFork().add(fork)
>> will be equivalent to
>> node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so you
>> may not need to work with the feature map directly. You should be
>> able to use the features of the Node EClass, i.e.,
>> XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
>> feature map, or any element-based feature in one of those element's
>> substitution group (which will be in some package's document root,
>> i.e., XyzPackage.eINSTANCE.getDocumentRoot_Abc()). To match some
>> value, you need to iterate over the feature map and check
>> getGroup().getValue(index) or use FeatureMapUtil.createEntry to
>> create a FeatureMap.Entry to search for directly.
>>
>>
>> David Hurst wrote:
>>
>>> Hello,
>>>
>>> I have an ecore model that was generated from an XML Schema
>>> containing a <choice> element. This causes the generator to create
>>> a FeatureMap in the model. I've been trying to figure out how to
>>> insert a child element into the FeatureMap as a sibling of another
>>> element in the FeatureMap and I just can't seem to find a solution
>>> that works.
>>>
>>> Here is an excerpt from my schema:
>>>
>>> <xs:complexType name="Node">
>>> <xs:complexContent>
>>> <xs:extension base="Base">
>>> <xs:choice maxOccurs="unbounded" minOccurs="0">
>>> <xs:element ref="fork"/>
>>> <xs:element ref="line"/>
>>> <xs:element ref="flow"/>
>>> </xs:choice>
>>> </xs:extension>
>>> </xs:complexContent>
>>> </xs:complexType>
>>>
>>> This results in a MixerNode class with getFork(), getLine(),
>>> getFlow(), and getGroup() methods. The getGroup returns a
>>> FeatureMap. What I'd like to do is find an existing element of any
>>> type in the Node and add another node of any type as its sibling. I
>>> know this is possible because the EMF-generated editor provides menu
>>> operations that do it. But I can't for the life of me figure out how
>>> to do it programmatically.
>>>
>>> It seems like I should be able to use the indexOf() method to find
>>> the location of the element and then use add() to insert the element
>>> at that location. This approach fails to find the element. Some
>>> investigation of BasicFeatureMap led me to try creating a
>>> FeatureMapUtil.EntryImpl containing the object I'm searching for,
>>> but that caused a ClassCast exception. I tried iterating through
>>> the FeatureMap using get(), but that fails for other reasons.
>>>
>>> It seems like there should be something obvious that I'm missing,
>>> but I don't know what it is. Any help would be appreciated.
>>>
>>> --DaveH "Be Excellent to each other!"
>>
>>
>>


--------------020307020908040800060803
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
David,<br>
<br>
There's just so little that I know about your application and I can't
provide specific help without that knowledge.&nbsp;&nbsp; If there are no
substitution groups for the global elements you've referenced then the <b>only
</b>valid features to use are those for fork, line, and flow.<br>
<br>
Will you know which object you want to add but you need to choose an
appropriate feature?&nbsp;&nbsp; You can use
feature.getEType().isInstance(object) to see if the instance is
appropriate for use in that feature.&nbsp; Or do you need to figure out all
subclasses of each features type?&nbsp; You need to visit "all classes" to
determine that since there is no way to go from a super class to all
it's subclasses.&nbsp; Looking at
ReflectiveItemProvider.collectNewChildDescriptors might help you
understand how we compute the information need for child creation
dynamically.<br>
<br>
<br>
David Hurst wrote:
<blockquote cite="middktk35$b3b$1@news.eclipse.org" type="cite">Ed,
<br>
<br>
Thanks for your suggestions.&nbsp; The problem is that I can't work with the
feature sublists directly.&nbsp; In this structure, I need a generic way to
add a feature element at a specific index in the overall group.&nbsp; So for
example, I might have the following structure:
<br>
<br>
&lt;Node&gt;
<br>
&nbsp; &lt;fork .../&gt;
<br>
&nbsp; &lt;line .../&gt;
<br>
&nbsp; &lt;fork .../&gt;
<br>
&lt;/Node&gt;
<br>
<br>
And I want to insert a &lt;flow&gt; element after the first
&lt;fork&gt; element.&nbsp; I can't use node.getFork() to do this because
this just returns the sublist of &lt;fork&gt; elements.&nbsp; So I have to
use node.getGroup(), which returns a feature map.&nbsp; The problem is that
in trying to do this generically, I don't necessarily know what type of
feature I'm going to be adding in advance, so I can't give a specific
feature type.&nbsp; If I try to use XyzPackage.eINSTANCE.getNode_Group(), I
get a ClassCastException in FeatureMapUtil.createEntry() because the
Group feature ID is different from the feature ID of the actual element
being used.
<br>
<br>
The only other approach I can think of is to have a huge case statement
that switches on the type of element being inserted and uses the
associated feature ID.&nbsp; But that doesn't seem very generic and will
break if I have to change the model.
<br>
<br>
The frustrating thing about this is that I know that the generated
editor does this because it provides an add sibling menu item which
does exactly what I want.&nbsp; But I've tried tracking down how the command
is implemented and can't make head or tail out of it.
<br>
<br>
--DaveH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&am p;nbsp;&nbsp; "Be Excellent to each other!"
<br>
<br>
Ed Merks wrote:
<br>
<blockquote type="cite">David,
<br>
<br>
David, it's the repeating of the model group that generates a feature
map, not the choice itself.&nbsp; Note that doing node.getFork().add(fork)
will be equivalent to
node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so you
may not need to work with the feature map directly.&nbsp;&nbsp;&nbsp; You should be
able to use the features of the Node EClass, i.e.,
XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
feature map, or any element-based feature in one of those element's
substitution group (which will be in some package's document root,
i.e., XyzPackage.eINSTANCE.getDocumentRoot_Abc()).&nbsp; To match some
value, you need to iterate over the feature map and check
getGroup().getValue(index) or use FeatureMapUtil.createEntry to create
a FeatureMap.Entry to search for directly.
<br>
<br>
<br>
David Hurst wrote:
<br>
<br>
<blockquote type="cite">Hello,
<br>
<br>
I have an ecore model that was generated from an XML Schema containing
a &lt;choice&gt; element.&nbsp; This causes the generator to create a
FeatureMap in the model.&nbsp; I've been trying to figure out how to insert
a child element into the FeatureMap as a sibling of another element in
the FeatureMap and I just can't seem to find a solution that works.
<br>
<br>
Here is an excerpt from my schema:
<br>
<br>
&lt;xs:complexType name="Node"&gt;
<br>
&nbsp; &lt;xs:complexContent&gt;
<br>
&nbsp;&nbsp;&nbsp; &lt;xs:extension base="Base"&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;xs:choice maxOccurs="unbounded" minOccurs="0"&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;xs:element ref="fork"/&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;xs:element ref="line"/&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;xs:element ref="flow"/&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/xs:choice&gt;
<br>
&nbsp;&nbsp;&nbsp; &lt;/xs:extension&gt;
<br>
&nbsp; &lt;/xs:complexContent&gt;
<br>
&lt;/xs:complexType&gt;
<br>
<br>
This results in a MixerNode class with getFork(), getLine(), getFlow(),
and getGroup() methods.&nbsp; The getGroup returns a FeatureMap.&nbsp; What I'd
like to do is find an existing element of any type in the Node and add
another node of any type as its sibling.&nbsp; I know this is possible
because the EMF-generated editor provides menu operations that do it.
But I can't for the life of me figure out how to do it
programmatically.
<br>
<br>
It seems like I should be able to use the indexOf() method to find the
location of the element and then use add() to insert the element at
that location.&nbsp; This approach fails to find the element.&nbsp; Some
investigation of BasicFeatureMap led me to try creating a
FeatureMapUtil.EntryImpl containing the object I'm searching for, but
that caused a ClassCast exception.&nbsp; I tried iterating through the
FeatureMap using get(), but that fails for other reasons.
<br>
<br>
It seems like there should be something obvious that I'm missing, but I
don't know what it is.&nbsp; Any help would be appreciated.
<br>
<br>
--DaveH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&am p;nbsp;&nbsp; "Be Excellent to each other!"
<br>
</blockquote>
<br>
<br>
</blockquote>
</blockquote>
<br>
</body>
</html>

--------------020307020908040800060803--
Re: inserting model object into featuremap [message #396738 is a reply to message #396736] Wed, 09 November 2005 21:19 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: dhurst.lisletech.com

Ed,

Actually the problem is fairly contained, in that I know the types of
all the objects involved, I just don't necessarily know them in advance.
I've managed to solve the problem by using a big case statement. So
my solution looks something like the following:

public class Node {

public void addSibling(Node sibling) {
Node parent = (Node)eContainer();
EStructuralFeature thisFeature = null;
switch (this.eClass().getClassifierID()) {
case XyzPackage.FLOW:
thisFeature = XyzPackage.eINSTANCE.getNode_Flow();
break;
case XyzPackage.FORK:
thisFeature = XyzPackage.eINSTANCE.getNode_Fork();
break;
case XyzPackage.LINE:
thisFeature = XyzPackage.eINSTANCE.getNode_Line();
break;
}
EStructuralFeature siblingFeature = null;
switch (sibling.eClass().getClassifierID()) {
case XyzPackage.FLOW:
siblingFeature = XyzPackage.eINSTANCE.getNode_Flow();
break;
case XyzPackage.FORK:
siblingFeature = XyzPackage.eINSTANCE.getNode_Fork();
break;
case XyzPackage.LINE:
siblingFeature = XyzPackage.eINSTANCE.getNode_Line();
break;
}
BasicFeatureMap group = (BasicFeatureMap)parent.getGroup();
int i = group.indexOf(thisFeature, this);
group.add(i+1, siblingFeature, sibling);
return;
}
}

I'd have prefered to avoid the case statements and do it in a way that
wouldn't break if I change the model. It's ugly, but it works.

Thanks for your help. I've been beating my head on this for too many
days and at least now I have a solution.

--DaveH "Be Excellent to each other!"

Ed Merks wrote:
> David,
>
> There's just so little that I know about your application and I can't
> provide specific help without that knowledge. If there are no
> substitution groups for the global elements you've referenced then the
> *only *valid features to use are those for fork, line, and flow.
>
> Will you know which object you want to add but you need to choose an
> appropriate feature? You can use feature.getEType().isInstance(object)
> to see if the instance is appropriate for use in that feature. Or do
> you need to figure out all subclasses of each features type? You need
> to visit "all classes" to determine that since there is no way to go
> from a super class to all it's subclasses. Looking at
> ReflectiveItemProvider.collectNewChildDescriptors might help you
> understand how we compute the information need for child creation
> dynamically.
>
>
> David Hurst wrote:
>
>> Ed,
>>
>> Thanks for your suggestions. The problem is that I can't work with
>> the feature sublists directly. In this structure, I need a generic
>> way to add a feature element at a specific index in the overall
>> group. So for example, I might have the following structure:
>>
>> <Node>
>> <fork .../>
>> <line .../>
>> <fork .../>
>> </Node>
>>
>> And I want to insert a <flow> element after the first <fork> element.
>> I can't use node.getFork() to do this because this just returns the
>> sublist of <fork> elements. So I have to use node.getGroup(), which
>> returns a feature map. The problem is that in trying to do this
>> generically, I don't necessarily know what type of feature I'm going
>> to be adding in advance, so I can't give a specific feature type. If
>> I try to use XyzPackage.eINSTANCE.getNode_Group(), I get a
>> ClassCastException in FeatureMapUtil.createEntry() because the Group
>> feature ID is different from the feature ID of the actual element
>> being used.
>>
>> The only other approach I can think of is to have a huge case
>> statement that switches on the type of element being inserted and uses
>> the associated feature ID. But that doesn't seem very generic and
>> will break if I have to change the model.
>>
>> The frustrating thing about this is that I know that the generated
>> editor does this because it provides an add sibling menu item which
>> does exactly what I want. But I've tried tracking down how the
>> command is implemented and can't make head or tail out of it.
>>
>> --DaveH "Be Excellent to each other!"
>>
>> Ed Merks wrote:
>>
>>> David,
>>>
>>> David, it's the repeating of the model group that generates a feature
>>> map, not the choice itself. Note that doing node.getFork().add(fork)
>>> will be equivalent to
>>> node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so you
>>> may not need to work with the feature map directly. You should be
>>> able to use the features of the Node EClass, i.e.,
>>> XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
>>> feature map, or any element-based feature in one of those element's
>>> substitution group (which will be in some package's document root,
>>> i.e., XyzPackage.eINSTANCE.getDocumentRoot_Abc()). To match some
>>> value, you need to iterate over the feature map and check
>>> getGroup().getValue(index) or use FeatureMapUtil.createEntry to
>>> create a FeatureMap.Entry to search for directly.
>>>
>>>
>>> David Hurst wrote:
>>>
>>>> Hello,
>>>>
>>>> I have an ecore model that was generated from an XML Schema
>>>> containing a <choice> element. This causes the generator to create
>>>> a FeatureMap in the model. I've been trying to figure out how to
>>>> insert a child element into the FeatureMap as a sibling of another
>>>> element in the FeatureMap and I just can't seem to find a solution
>>>> that works.
>>>>
>>>> Here is an excerpt from my schema:
>>>>
>>>> <xs:complexType name="Node">
>>>> <xs:complexContent>
>>>> <xs:extension base="Base">
>>>> <xs:choice maxOccurs="unbounded" minOccurs="0">
>>>> <xs:element ref="fork"/>
>>>> <xs:element ref="line"/>
>>>> <xs:element ref="flow"/>
>>>> </xs:choice>
>>>> </xs:extension>
>>>> </xs:complexContent>
>>>> </xs:complexType>
>>>>
>>>> This results in a MixerNode class with getFork(), getLine(),
>>>> getFlow(), and getGroup() methods. The getGroup returns a
>>>> FeatureMap. What I'd like to do is find an existing element of any
>>>> type in the Node and add another node of any type as its sibling. I
>>>> know this is possible because the EMF-generated editor provides menu
>>>> operations that do it. But I can't for the life of me figure out how
>>>> to do it programmatically.
>>>>
>>>> It seems like I should be able to use the indexOf() method to find
>>>> the location of the element and then use add() to insert the element
>>>> at that location. This approach fails to find the element. Some
>>>> investigation of BasicFeatureMap led me to try creating a
>>>> FeatureMapUtil.EntryImpl containing the object I'm searching for,
>>>> but that caused a ClassCast exception. I tried iterating through
>>>> the FeatureMap using get(), but that fails for other reasons.
>>>>
>>>> It seems like there should be something obvious that I'm missing,
>>>> but I don't know what it is. Any help would be appreciated.
>>>>
>>>> --DaveH "Be Excellent to each other!"
>>>
>>>
>>>
>
Re: inserting model object into featuremap [message #396739 is a reply to message #396738] Wed, 09 November 2005 21:57 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: dhurst.lisletech.com

Unfortunately, I was wrong. The code below does not work as I expected.
The indexOf() method filters out anything which does not match the
specified structure feature rather than simply giving me the index of
the element in the overall group. How do I get the index of an element,
regardless of feature type, in the group? And then how do I add an
element to the group at a given position, regardless of feature type?

--DaveH "Be Excellent to each other!"

David Hurst wrote:
> Ed,
>
> Actually the problem is fairly contained, in that I know the types of
> all the objects involved, I just don't necessarily know them in advance.
> I've managed to solve the problem by using a big case statement. So my
> solution looks something like the following:
>
> public class Node {
>
> public void addSibling(Node sibling) {
> Node parent = (Node)eContainer();
> EStructuralFeature thisFeature = null;
> switch (this.eClass().getClassifierID()) {
> case XyzPackage.FLOW:
> thisFeature = XyzPackage.eINSTANCE.getNode_Flow();
> break;
> case XyzPackage.FORK:
> thisFeature = XyzPackage.eINSTANCE.getNode_Fork();
> break;
> case XyzPackage.LINE:
> thisFeature = XyzPackage.eINSTANCE.getNode_Line();
> break;
> }
> EStructuralFeature siblingFeature = null;
> switch (sibling.eClass().getClassifierID()) {
> case XyzPackage.FLOW:
> siblingFeature = XyzPackage.eINSTANCE.getNode_Flow();
> break;
> case XyzPackage.FORK:
> siblingFeature = XyzPackage.eINSTANCE.getNode_Fork();
> break;
> case XyzPackage.LINE:
> siblingFeature = XyzPackage.eINSTANCE.getNode_Line();
> break;
> }
> BasicFeatureMap group = (BasicFeatureMap)parent.getGroup();
> int i = group.indexOf(thisFeature, this);
> group.add(i+1, siblingFeature, sibling);
> return;
> }
> }
>
> I'd have prefered to avoid the case statements and do it in a way that
> wouldn't break if I change the model. It's ugly, but it works.
>
> Thanks for your help. I've been beating my head on this for too many
> days and at least now I have a solution.
>
> --DaveH "Be Excellent to each other!"
>
> Ed Merks wrote:
>
>> David,
>>
>> There's just so little that I know about your application and I can't
>> provide specific help without that knowledge. If there are no
>> substitution groups for the global elements you've referenced then the
>> *only *valid features to use are those for fork, line, and flow.
>>
>> Will you know which object you want to add but you need to choose an
>> appropriate feature? You can use
>> feature.getEType().isInstance(object) to see if the instance is
>> appropriate for use in that feature. Or do you need to figure out all
>> subclasses of each features type? You need to visit "all classes" to
>> determine that since there is no way to go from a super class to all
>> it's subclasses. Looking at
>> ReflectiveItemProvider.collectNewChildDescriptors might help you
>> understand how we compute the information need for child creation
>> dynamically.
>>
>>
>> David Hurst wrote:
>>
>>> Ed,
>>>
>>> Thanks for your suggestions. The problem is that I can't work with
>>> the feature sublists directly. In this structure, I need a generic
>>> way to add a feature element at a specific index in the overall
>>> group. So for example, I might have the following structure:
>>>
>>> <Node>
>>> <fork .../>
>>> <line .../>
>>> <fork .../>
>>> </Node>
>>>
>>> And I want to insert a <flow> element after the first <fork>
>>> element. I can't use node.getFork() to do this because this just
>>> returns the sublist of <fork> elements. So I have to use
>>> node.getGroup(), which returns a feature map. The problem is that in
>>> trying to do this generically, I don't necessarily know what type of
>>> feature I'm going to be adding in advance, so I can't give a specific
>>> feature type. If I try to use XyzPackage.eINSTANCE.getNode_Group(),
>>> I get a ClassCastException in FeatureMapUtil.createEntry() because
>>> the Group feature ID is different from the feature ID of the actual
>>> element being used.
>>>
>>> The only other approach I can think of is to have a huge case
>>> statement that switches on the type of element being inserted and
>>> uses the associated feature ID. But that doesn't seem very generic
>>> and will break if I have to change the model.
>>>
>>> The frustrating thing about this is that I know that the generated
>>> editor does this because it provides an add sibling menu item which
>>> does exactly what I want. But I've tried tracking down how the
>>> command is implemented and can't make head or tail out of it.
>>>
>>> --DaveH "Be Excellent to each other!"
>>>
>>> Ed Merks wrote:
>>>
>>>> David,
>>>>
>>>> David, it's the repeating of the model group that generates a
>>>> feature map, not the choice itself. Note that doing
>>>> node.getFork().add(fork) will be equivalent to
>>>> node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so
>>>> you may not need to work with the feature map directly. You
>>>> should be able to use the features of the Node EClass, i.e.,
>>>> XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
>>>> feature map, or any element-based feature in one of those element's
>>>> substitution group (which will be in some package's document root,
>>>> i.e., XyzPackage.eINSTANCE.getDocumentRoot_Abc()). To match some
>>>> value, you need to iterate over the feature map and check
>>>> getGroup().getValue(index) or use FeatureMapUtil.createEntry to
>>>> create a FeatureMap.Entry to search for directly.
>>>>
>>>>
>>>> David Hurst wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> I have an ecore model that was generated from an XML Schema
>>>>> containing a <choice> element. This causes the generator to create
>>>>> a FeatureMap in the model. I've been trying to figure out how to
>>>>> insert a child element into the FeatureMap as a sibling of another
>>>>> element in the FeatureMap and I just can't seem to find a solution
>>>>> that works.
>>>>>
>>>>> Here is an excerpt from my schema:
>>>>>
>>>>> <xs:complexType name="Node">
>>>>> <xs:complexContent>
>>>>> <xs:extension base="Base">
>>>>> <xs:choice maxOccurs="unbounded" minOccurs="0">
>>>>> <xs:element ref="fork"/>
>>>>> <xs:element ref="line"/>
>>>>> <xs:element ref="flow"/>
>>>>> </xs:choice>
>>>>> </xs:extension>
>>>>> </xs:complexContent>
>>>>> </xs:complexType>
>>>>>
>>>>> This results in a MixerNode class with getFork(), getLine(),
>>>>> getFlow(), and getGroup() methods. The getGroup returns a
>>>>> FeatureMap. What I'd like to do is find an existing element of any
>>>>> type in the Node and add another node of any type as its sibling.
>>>>> I know this is possible because the EMF-generated editor provides
>>>>> menu operations that do it. But I can't for the life of me figure
>>>>> out how to do it programmatically.
>>>>>
>>>>> It seems like I should be able to use the indexOf() method to find
>>>>> the location of the element and then use add() to insert the
>>>>> element at that location. This approach fails to find the
>>>>> element. Some investigation of BasicFeatureMap led me to try
>>>>> creating a FeatureMapUtil.EntryImpl containing the object I'm
>>>>> searching for, but that caused a ClassCast exception. I tried
>>>>> iterating through the FeatureMap using get(), but that fails for
>>>>> other reasons.
>>>>>
>>>>> It seems like there should be something obvious that I'm missing,
>>>>> but I don't know what it is. Any help would be appreciated.
>>>>>
>>>>> --DaveH "Be Excellent to each other!"
>>>>
>>>>
>>>>
>>>>
>>
Re: inserting model object into featuremap [message #396748 is a reply to message #396739] Thu, 10 November 2005 13:13 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 29037
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------060206030607080004050103
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

David,

Switching on the classifier ID is not such a great idea. You can't be
sure you aren't looking at a derived instance from another package? I'd
use something like this to ensure that derived instances are properly
taken into account:

if (XyzPackage.eINSTANCE.getNode().isInstance(this))

Even just doing "instanceof Node" seems fine and safer than the code you
have.

Something like this should work better for insertion:

FeatureMap group = parent.getGroup();
for (int i = 0, size = group.size(); i < size; ++i)
{
if (group.getValue() == this)
{
group.add(i + i, siblingFeature, sibling);
break;
}
}

Since all the features are containments, "this" can be in at most one
place and you don't need to know the feature for it ahead of time. You
could use FeatureMapUtil.createEntry(thisFeature, this) and do an
indexOf on that, if you feel the need.


David Hurst wrote:

> Unfortunately, I was wrong. The code below does not work as I
> expected. The indexOf() method filters out anything which does not
> match the specified structure feature rather than simply giving me the
> index of the element in the overall group. How do I get the index of
> an element, regardless of feature type, in the group? And then how do
> I add an element to the group at a given position, regardless of
> feature type?
>
> --DaveH "Be Excellent to each other!"
>
> David Hurst wrote:
>
>> Ed,
>>
>> Actually the problem is fairly contained, in that I know the types of
>> all the objects involved, I just don't necessarily know them in
>> advance. I've managed to solve the problem by using a big case
>> statement. So my solution looks something like the following:
>>
>> public class Node {
>>
>> public void addSibling(Node sibling) {
>> Node parent = (Node)eContainer();
>> EStructuralFeature thisFeature = null;
>> switch (this.eClass().getClassifierID()) {
>> case XyzPackage.FLOW:
>> thisFeature = XyzPackage.eINSTANCE.getNode_Flow();
>> break;
>> case XyzPackage.FORK:
>> thisFeature = XyzPackage.eINSTANCE.getNode_Fork();
>> break;
>> case XyzPackage.LINE:
>> thisFeature = XyzPackage.eINSTANCE.getNode_Line();
>> break;
>> }
>> EStructuralFeature siblingFeature = null;
>> switch (sibling.eClass().getClassifierID()) {
>> case XyzPackage.FLOW:
>> siblingFeature = XyzPackage.eINSTANCE.getNode_Flow();
>> break;
>> case XyzPackage.FORK:
>> siblingFeature = XyzPackage.eINSTANCE.getNode_Fork();
>> break;
>> case XyzPackage.LINE:
>> siblingFeature = XyzPackage.eINSTANCE.getNode_Line();
>> break;
>> }
>> BasicFeatureMap group = (BasicFeatureMap)parent.getGroup();
>> int i = group.indexOf(thisFeature, this);
>> group.add(i+1, siblingFeature, sibling);
>> return;
>> }
>> }
>>
>> I'd have prefered to avoid the case statements and do it in a way
>> that wouldn't break if I change the model. It's ugly, but it works.
>>
>> Thanks for your help. I've been beating my head on this for too many
>> days and at least now I have a solution.
>>
>> --DaveH "Be Excellent to each other!"
>>
>> Ed Merks wrote:
>>
>>> David,
>>>
>>> There's just so little that I know about your application and I
>>> can't provide specific help without that knowledge. If there are
>>> no substitution groups for the global elements you've referenced
>>> then the *only *valid features to use are those for fork, line, and
>>> flow.
>>>
>>> Will you know which object you want to add but you need to choose an
>>> appropriate feature? You can use
>>> feature.getEType().isInstance(object) to see if the instance is
>>> appropriate for use in that feature. Or do you need to figure out
>>> all subclasses of each features type? You need to visit "all
>>> classes" to determine that since there is no way to go from a super
>>> class to all it's subclasses. Looking at
>>> ReflectiveItemProvider.collectNewChildDescriptors might help you
>>> understand how we compute the information need for child creation
>>> dynamically.
>>>
>>>
>>> David Hurst wrote:
>>>
>>>> Ed,
>>>>
>>>> Thanks for your suggestions. The problem is that I can't work with
>>>> the feature sublists directly. In this structure, I need a generic
>>>> way to add a feature element at a specific index in the overall
>>>> group. So for example, I might have the following structure:
>>>>
>>>> <Node>
>>>> <fork .../>
>>>> <line .../>
>>>> <fork .../>
>>>> </Node>
>>>>
>>>> And I want to insert a <flow> element after the first <fork>
>>>> element. I can't use node.getFork() to do this because this just
>>>> returns the sublist of <fork> elements. So I have to use
>>>> node.getGroup(), which returns a feature map. The problem is that
>>>> in trying to do this generically, I don't necessarily know what
>>>> type of feature I'm going to be adding in advance, so I can't give
>>>> a specific feature type. If I try to use
>>>> XyzPackage.eINSTANCE.getNode_Group(), I get a ClassCastException in
>>>> FeatureMapUtil.createEntry() because the Group feature ID is
>>>> different from the feature ID of the actual element being used.
>>>>
>>>> The only other approach I can think of is to have a huge case
>>>> statement that switches on the type of element being inserted and
>>>> uses the associated feature ID. But that doesn't seem very generic
>>>> and will break if I have to change the model.
>>>>
>>>> The frustrating thing about this is that I know that the generated
>>>> editor does this because it provides an add sibling menu item which
>>>> does exactly what I want. But I've tried tracking down how the
>>>> command is implemented and can't make head or tail out of it.
>>>>
>>>> --DaveH "Be Excellent to each other!"
>>>>
>>>> Ed Merks wrote:
>>>>
>>>>> David,
>>>>>
>>>>> David, it's the repeating of the model group that generates a
>>>>> feature map, not the choice itself. Note that doing
>>>>> node.getFork().add(fork) will be equivalent to
>>>>> node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so
>>>>> you may not need to work with the feature map directly. You
>>>>> should be able to use the features of the Node EClass, i.e.,
>>>>> XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
>>>>> feature map, or any element-based feature in one of those
>>>>> element's substitution group (which will be in some package's
>>>>> document root, i.e., XyzPackage.eINSTANCE.getDocumentRoot_Abc()).
>>>>> To match some value, you need to iterate over the feature map and
>>>>> check getGroup().getValue(index) or use FeatureMapUtil.createEntry
>>>>> to create a FeatureMap.Entry to search for directly.
>>>>>
>>>>>
>>>>> David Hurst wrote:
>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> I have an ecore model that was generated from an XML Schema
>>>>>> containing a <choice> element. This causes the generator to
>>>>>> create a FeatureMap in the model. I've been trying to figure out
>>>>>> how to insert a child element into the FeatureMap as a sibling of
>>>>>> another element in the FeatureMap and I just can't seem to find a
>>>>>> solution that works.
>>>>>>
>>>>>> Here is an excerpt from my schema:
>>>>>>
>>>>>> <xs:complexType name="Node">
>>>>>> <xs:complexContent>
>>>>>> <xs:extension base="Base">
>>>>>> <xs:choice maxOccurs="unbounded" minOccurs="0">
>>>>>> <xs:element ref="fork"/>
>>>>>> <xs:element ref="line"/>
>>>>>> <xs:element ref="flow"/>
>>>>>> </xs:choice>
>>>>>> </xs:extension>
>>>>>> </xs:complexContent>
>>>>>> </xs:complexType>
>>>>>>
>>>>>> This results in a MixerNode class with getFork(), getLine(),
>>>>>> getFlow(), and getGroup() methods. The getGroup returns a
>>>>>> FeatureMap. What I'd like to do is find an existing element of
>>>>>> any type in the Node and add another node of any type as its
>>>>>> sibling. I know this is possible because the EMF-generated
>>>>>> editor provides menu operations that do it. But I can't for the
>>>>>> life of me figure out how to do it programmatically.
>>>>>>
>>>>>> It seems like I should be able to use the indexOf() method to
>>>>>> find the location of the element and then use add() to insert the
>>>>>> element at that location. This approach fails to find the
>>>>>> element. Some investigation of BasicFeatureMap led me to try
>>>>>> creating a FeatureMapUtil.EntryImpl containing the object I'm
>>>>>> searching for, but that caused a ClassCast exception. I tried
>>>>>> iterating through the FeatureMap using get(), but that fails for
>>>>>> other reasons.
>>>>>>
>>>>>> It seems like there should be something obvious that I'm missing,
>>>>>> but I don't know what it is. Any help would be appreciated.
>>>>>>
>>>>>> --DaveH "Be Excellent to each other!"
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>


--------------060206030607080004050103
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
David,<br>
<br>
Switching on the classifier ID is not such a great idea.&nbsp; You can't be
sure you aren't looking at a derived instance from another package?&nbsp;
I'd use something like this to ensure that derived instances are
properly taken into account:<br>
<blockquote>&nbsp; if (XyzPackage.eINSTANCE.getNode().isInstance(this))<br>
</blockquote>
Even just doing "instanceof Node" seems fine and safer than the code
you have.<br>
<br>
Something like this should work better for insertion:<br>
<blockquote>&nbsp; FeatureMap group = parent.getGroup();<br>
&nbsp; for (int i = 0, size = group.size(); i &lt; size; ++i)<br>
&nbsp; {<br>
&nbsp;&nbsp;&nbsp; if (group.getValue() == this)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; group.add(i + i, siblingFeature, sibling);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp; }<br>
</blockquote>
Since all the features are containments, "this" can be in at most one
place and you don't need to know the feature for it ahead of time.&nbsp; You
could use FeatureMapUtil.createEntry(thisFeature, this) and do an
indexOf on that, if you feel the need.<br>
<br>
<br>
David Hurst wrote:
<blockquote cite="middktrds$lap$1@news.eclipse.org" type="cite">Unfortunately,
I was wrong.&nbsp; The code below does not work as I expected. &nbsp;The
indexOf() method filters out anything which does not match the
specified structure feature rather than simply giving me the index of
the element in the overall group.&nbsp; How do I get the index of an
element, regardless of feature type, in the group?&nbsp; And then how do I
add an element to the group at a given position, regardless of feature
type?
<br>
<br>
--DaveH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&am p;nbsp;&nbsp; "Be Excellent to each other!"
<br>
<br>
David Hurst wrote:
<br>
<blockquote type="cite">Ed,
<br>
<br>
Actually the problem is fairly contained, in that I know the types of
all the objects involved, I just don't necessarily know them in
advance. &nbsp;I've managed to solve the problem by using a big case
statement.&nbsp; So my solution looks something like the following:
<br>
<br>
public class Node {
<br>
<br>
public void addSibling(Node sibling) {
<br>
&nbsp; Node parent = (Node)eContainer();
<br>
&nbsp; EStructuralFeature thisFeature = null;
<br>
&nbsp; switch (this.eClass().getClassifierID()) {
<br>
&nbsp;&nbsp;&nbsp; case XyzPackage.FLOW:
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisFeature = XyzPackage.eINSTANCE.getNode_Flow();
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
<br>
&nbsp;&nbsp;&nbsp; case XyzPackage.FORK:
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisFeature = XyzPackage.eINSTANCE.getNode_Fork();
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
<br>
&nbsp;&nbsp;&nbsp; case XyzPackage.LINE:
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisFeature = XyzPackage.eINSTANCE.getNode_Line();
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
<br>
&nbsp; }
<br>
&nbsp; EStructuralFeature siblingFeature = null;
<br>
&nbsp; switch (sibling.eClass().getClassifierID()) {
<br>
&nbsp;&nbsp;&nbsp; case XyzPackage.FLOW:
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; siblingFeature = XyzPackage.eINSTANCE.getNode_Flow();
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
<br>
&nbsp;&nbsp;&nbsp; case XyzPackage.FORK:
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; siblingFeature = XyzPackage.eINSTANCE.getNode_Fork();
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
<br>
&nbsp;&nbsp;&nbsp; case XyzPackage.LINE:
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; siblingFeature = XyzPackage.eINSTANCE.getNode_Line();
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
<br>
&nbsp; }
<br>
&nbsp; BasicFeatureMap group = (BasicFeatureMap)parent.getGroup();
<br>
&nbsp; int i = group.indexOf(thisFeature, this);
<br>
&nbsp; group.add(i+1, siblingFeature, sibling);
<br>
&nbsp; return;
<br>
}
<br>
}
<br>
<br>
I'd have prefered to avoid the case statements and do it in a way that
wouldn't break if I change the model.&nbsp; It's ugly, but it works.
<br>
<br>
Thanks for your help.&nbsp; I've been beating my head on this for too many
days and at least now I have a solution.
<br>
<br>
--DaveH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&am p;nbsp;&nbsp; "Be Excellent to each other!"
<br>
<br>
Ed Merks wrote:
<br>
<br>
<blockquote type="cite">David,
<br>
<br>
There's just so little that I know about your application and I can't
provide specific help without that knowledge.&nbsp;&nbsp; If there are no
substitution groups for the global elements you've referenced then the
*only *valid features to use are those for fork, line, and flow.
<br>
<br>
Will you know which object you want to add but you need to choose an
appropriate feature?&nbsp;&nbsp; You can use
feature.getEType().isInstance(object) to see if the instance is
appropriate for use in that feature.&nbsp; Or do you need to figure out all
subclasses of each features type?&nbsp; You need to visit "all classes" to
determine that since there is no way to go from a super class to all
it's subclasses.&nbsp; Looking at
ReflectiveItemProvider.collectNewChildDescriptors might help you
understand how we compute the information need for child creation
dynamically.
<br>
<br>
<br>
David Hurst wrote:
<br>
<br>
<blockquote type="cite">Ed,
<br>
<br>
Thanks for your suggestions.&nbsp; The problem is that I can't work with the
feature sublists directly.&nbsp; In this structure, I need a generic way to
add a feature element at a specific index in the overall group.&nbsp; So for
example, I might have the following structure:
<br>
<br>
&lt;Node&gt;
<br>
&nbsp; &lt;fork .../&gt;
<br>
&nbsp; &lt;line .../&gt;
<br>
&nbsp; &lt;fork .../&gt;
<br>
&lt;/Node&gt;
<br>
<br>
And I want to insert a &lt;flow&gt; element after the first
&lt;fork&gt; element.&nbsp; I can't use node.getFork() to do this because
this just returns the sublist of &lt;fork&gt; elements.&nbsp; So I have to
use node.getGroup(), which returns a feature map.&nbsp; The problem is that
in trying to do this generically, I don't necessarily know what type of
feature I'm going to be adding in advance, so I can't give a specific
feature type.&nbsp; If I try to use XyzPackage.eINSTANCE.getNode_Group(), I
get a ClassCastException in FeatureMapUtil.createEntry() because the
Group feature ID is different from the feature ID of the actual element
being used.
<br>
<br>
The only other approach I can think of is to have a huge case statement
that switches on the type of element being inserted and uses the
associated feature ID.&nbsp; But that doesn't seem very generic and will
break if I have to change the model.
<br>
<br>
The frustrating thing about this is that I know that the generated
editor does this because it provides an add sibling menu item which
does exactly what I want.&nbsp; But I've tried tracking down how the command
is implemented and can't make head or tail out of it.
<br>
<br>
--DaveH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&am p;nbsp;&nbsp; "Be Excellent to each other!"
<br>
<br>
Ed Merks wrote:
<br>
<br>
<blockquote type="cite">David,
<br>
<br>
David, it's the repeating of the model group that generates a feature
map, not the choice itself.&nbsp; Note that doing node.getFork().add(fork)
will be equivalent to
node.getGroup().add(XyzPackage.eINSTANCE.getNode_Fork(), fork) so you
may not need to work with the feature map directly.&nbsp;&nbsp;&nbsp; You should be
able to use the features of the Node EClass, i.e.,
XyzPackage.eINSTANCE.getNode_Fork/Line/Flow, as the feature in the
feature map, or any element-based feature in one of those element's
substitution group (which will be in some package's document root,
i.e., XyzPackage.eINSTANCE.getDocumentRoot_Abc()).&nbsp; To match some
value, you need to iterate over the feature map and check
getGroup().getValue(index) or use FeatureMapUtil.createEntry to create
a FeatureMap.Entry to search for directly.
<br>
<br>
<br>
David Hurst wrote:
<br>
<br>
<blockquote type="cite">Hello,
<br>
<br>
I have an ecore model that was generated from an XML Schema containing
a &lt;choice&gt; element.&nbsp; This causes the generator to create a
FeatureMap in the model.&nbsp; I've been trying to figure out how to insert
a child element into the FeatureMap as a sibling of another element in
the FeatureMap and I just can't seem to find a solution that works.
<br>
<br>
Here is an excerpt from my schema:
<br>
<br>
&lt;xs:complexType name="Node"&gt;
<br>
&nbsp; &lt;xs:complexContent&gt;
<br>
&nbsp;&nbsp;&nbsp; &lt;xs:extension base="Base"&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;xs:choice maxOccurs="unbounded" minOccurs="0"&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;xs:element ref="fork"/&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;xs:element ref="line"/&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &lt;xs:element ref="flow"/&gt;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/xs:choice&gt;
<br>
&nbsp;&nbsp;&nbsp; &lt;/xs:extension&gt;
<br>
&nbsp; &lt;/xs:complexContent&gt;
<br>
&lt;/xs:complexType&gt;
<br>
<br>
This results in a MixerNode class with getFork(), getLine(), getFlow(),
and getGroup() methods.&nbsp; The getGroup returns a FeatureMap.&nbsp; What I'd
like to do is find an existing element of any type in the Node and add
another node of any type as its sibling.&nbsp; I know this is possible
because the EMF-generated editor provides menu operations that do it.
But I can't for the life of me figure out how to do it
programmatically.
<br>
<br>
It seems like I should be able to use the indexOf() method to find the
location of the element and then use add() to insert the element at
that location.&nbsp; This approach fails to find the element.&nbsp; Some
investigation of BasicFeatureMap led me to try creating a
FeatureMapUtil.EntryImpl containing the object I'm searching for, but
that caused a ClassCast exception.&nbsp; I tried iterating through the
FeatureMap using get(), but that fails for other reasons.
<br>
<br>
It seems like there should be something obvious that I'm missing, but I
don't know what it is.&nbsp; Any help would be appreciated.
<br>
<br>
--DaveH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&am p;nbsp;&nbsp; "Be Excellent to each other!"
<br>
</blockquote>
<br>
<br>
<br>
<br>
</blockquote>
</blockquote>
<br>
</blockquote>
</blockquote>
</blockquote>
<br>
</body>
</html>

--------------060206030607080004050103--
Previous Topic:Adding unique field validation?
Next Topic:How to define stereo type in omondo eclipseUML?
Goto Forum:
  


Current Time: Fri Dec 15 20:09:13 GMT 2017

Powered by FUDForum. Page generated in 0.02469 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software