Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » Getting the name of an element which is itself an attribute value
Getting the name of an element which is itself an attribute value [message #44675] Fri, 25 April 2008 10:05 Go to next message
Georges Bachelier is currently offline Georges BachelierFriend
Messages: 8
Registered: July 2009
Junior Member
Hello everyone,

We want to use JET in a project involving a test program flow editor based
on EMF and GMF. The GMF flow editor produces an output file on which we
want to apply a JET transformation to get an XML file with a particular
structure.

The GMF output file is this one (simplified):

<?xml version="1.0" encoding="UTF-8"?>
<Flow flowName="myFlow">
<BinTable name="myBin" />
<nodes xsi:type="TestBlock" nodeName="N0"
group="g1" subGroup="sg1">
<outputLinks targetNode="//@nodes.1" />
<outputLinks targetNode="//@nodes.2" />
</nodes>
<nodes xsi:type="SubFlow" inputLabel="SF1" nodeName="N1" flowName="SF0" >
<outputLinks targetNode="//@nodes.3" />
</nodes>
<nodes xsi:type="SubFlow" inputLabel="SF2" nodeName="N2" flowName="SF1" >
<outputLinks targetNode="//@nodes.3" />
</nodes>
<nodes xsi:type="TestBlock" inputLabel="TB2" nodeName="N3"
group="g2" subGroup="sg2" binning="b0" />
</Flow>

and the XML ouput file is this one (simplified, too):

<?xml version="1.0" encoding="utf-8"?>
<tns:flow name="myFlow" >
<bin_table>myBin</bin_table>
<node name="N0">
<output_label_1>SF1</output_label_1>
<output_label_2>SF2</output_label_2>
</node>
<node name="N1">
<input_label>SF1</input_label>
<output_label_1>TB2</output_label_1>
</node>
<node name="N2">
<input_label>SF2</input_label>
<output_label_1>TB2</output_label_1>
</node>
<node name="N3">
<input_label>TB2</input_label>
</node>
</tns:flow>

In the output file, the output_label_<x> element value must be the
inputLabel attribute value of the node which reference is the value of the
targetNode attribute of the outputLinks element. Hum... I guess the files
will be more helpful than this long explanation ;-)

I don't know how to manage this "//@nodes.x" expression.
Could you please tell me how to perform this transformation by using JET
tags?

Thanks a lot in advance for your time,

Georges
Re: Getting the name of an element which is itself an attribute value [message #44706 is a reply to message #44675] Sat, 26 April 2008 15:19 Go to previous messageGo to next message
Paul Elder is currently offline Paul ElderFriend
Messages: 849
Registered: July 2009
Senior Member
Georges:

The GMF editor is producing a file that has an EMF meta-model. Provided that
meta model is registered correctly (via the
org.eclipse.emf.ecore.generated_package extension point in the EMF project
defining the model), JET should be able to read that model.

Note that if JET recognizes a file as being produced by EMF, JET DOES NOT
parse it as an XML document. Instead, it uses EMF to load the model, and
then uses EMF's reflective APIs to navigate the document. When using this
API, XPath steps will match elements in the model as follows:

* an initial / corresonds to the EMF Resource containing the model.
* a child-step (syntax /foo or /child::foo) will try to find objects in two
ways:
* First, it will look for an EReference feature on the current context
object with name 'foo'. If found, it will match all the objects refered to
by the feature.
* Seond, it will look in the eContents collection of the current object
for an object whose eClass().getName() equals foo (case sensitive).
* an attribute step (syntax /@name or /attribute::name) is matched as
follows:
* JET will look for an EAttribute feature on the current context object
with name 'name'. If found, it returns that object.

So, some examples form you model (I'm assuming is serialized in XMI, so
though, I'm not quite sure...

* To get the flowName of the root object:

<c:get select="/Flow/@flowName"/>

* To traverse all the nodes in Flow:

<c:iterate select="/Flow/nodes" var="node">
<c:get select="$node/@nodeName"/>
</c:iterate>

* To find all the nodes output linked from each node...

<c:iterate select="/Flow/nodes" var="node">
Node: <c:get select="$node/@nodeName"/>
<c:iterate select="$node/outputLinks" var="link">
</c:iterate>
<%-- I'm assuming SubFlow has a reference feature
outputLinks (type OutputLinks) and the targetNode is a reference feature,
too --%>
<c:get select="$link/targetNode/@nodeName"/>
</c:iterate>

So, assuming my guesses about the EMF model are correct, the JET template
for the XML document would look like this:

<%-- templates/outputFile.xml.jet --%>
<?xml version="1.0" encoding="utf-8"?>
<tns:flow name="<c:get select=/Flow/@flowName/>" >
<bin_table><c:get select="/Flow/BinTable/@name"/></bin_table>
<c:iterate select="/Flow/nodes" var="node">
<c:if test="$node/@inputLabel">
<input_label><c:get select="$node/@inputLabel"/></input_label>
</c:if>
<node name="<c:get select="$node/@nodeName"/>">
<c:iterate select="$node/outputLinks" var="link">
<output_label_<c:get select="$link/@ordinal"/>><c:get
select="$link/@inputLabel"/></output_label_<c:get select="$link/@ordinal"/>>
</c:iterate>
</node>
</c:iterate>
</tns:flow>

You may have noticed that I used an attribute (@ordinal) which is not
defined on your GMF-produced model.. It's created in main.jet:

<%-- templates/main.jet --%>
<c:iterate select="/Flow/nodes" var="node">
<c:setVariable var="nextOrdinal" select="1"/>
<c:iterate select="$node/outputLinks" var="link">
<c:set select="$link" name="ordinal"><c:get
select="$nextOrdinal"/></c:set>
<c:setVariable var="nextOrdinal" select="$nextOrdinal + 1"/>
</c:iterate>
</c:iterate>

<%-- Don't know what method you will use to get the name of the output file.
Here, I'm assuming
that it is set in a JET variable. You could set it a number of ways,
depending on how the transformation is invoked --%>
<ws:file template="templates/outputfile.xml.jet" path="{$outputFilePath}" />

Paul
Re: Getting the name of an element which is itself an attribute value [message #44744 is a reply to message #44706] Sun, 27 April 2008 08:47 Go to previous messageGo to next message
Georges Bachelier is currently offline Georges BachelierFriend
Messages: 8
Registered: July 2009
Junior Member
Hi Paul,

thank you so much for this detailed answer; it helped me to progress.
Unfortunately the solution you suggest to map outputLinks to inputLabels
does not work, but I understand from your remarks that providing you with
the XML output from my GMF flow editor is not sufficient; you also need
the EMF model stucture. This is a tough point for someone not familiar
with JET, like me. Some more questions before giving you the files built
with your help as well as the EMF file :

* What is the purpose of the loop you suggest me to include in the
main.jet file?
Is it here to add an "ordinal" attribute to every "link"? Does this mean
that I can manipulate an in-memory structure which is an image of the XML
input file one?

* I understand from this that we could use the main.jet file to prepare
things in order to make the transformation easier to code. Is this correct?

* The JET transformation produces errors :

templates/flow_template2.jet(11,22): <c:get select="$link/@ordinal">
Error: XPath expression returned no result
templates/flow_template2.jet(11,55): <c:get select="$link/@inputLabel">

Do you see why?




Here are my files built with your help ; main.jet first:


<%@taglib prefix="ws" id="org.eclipse.jet.workspaceTags" %>

<ws:file template="templates/flow_template2.jet"
path="{$org.eclipse.jet.resource.project.name}/flow.xml"/>

<c:iterate select="/Flow/nodes" var="node">
<c:setVariable var="nextOrdinal" select="1"/>
<c:iterate select="$node/outputLinks" var="link">
<c:set select="$link" name="ordinal"><c:get
select="$nextOrdinal"/></c:set>
<c:setVariable var="nextOrdinal" select="$nextOrdinal + 1"/>
</c:iterate>
</c:iterate>


flow_template2.jet :


<%-- templates/outputFile.xml.jet --%>
<?xml version="1.0" encoding="utf-8"?>
<tns:flow name="<c:get select="/Flow/@flowName"/>" >
<bin_table><c:get select="/Flow/BinTable/@name"/></bin_table>
<c:iterate select="/Flow/nodes" var="node">
<node name="<c:get select="$node/@nodeName"/>">
<c:if test="$node/@inputLabel">
<input_label><c:get select="$node/@inputLabel"/></input_label>
</c:if>
<c:iterate select="$node/outputLinks" var="link">
<output_label_<c:get select="$link/@ordinal"/>><c:get
select="$link/@inputLabel"/></output_label_<c:get
select="$link/@ordinal"/>>
</c:iterate>
</node>
</c:iterate>
</tns:flow>


floweditor.ecore :

<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="flowdiagram"
nsURI="http://com.atmel.metatest.flowdiagram" nsPrefix="">
<eClassifiers xsi:type="ecore:EClass" name="Node" abstract="true">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="inputLabel"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="nodeName"
lowerBound="1"
eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="outputLinks"
upperBound="-1"
eType="#//Link" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="TestBlock"
eSuperTypes="#//Node">
<eStructuralFeatures xsi:type="ecore:EReference" name="params"
upperBound="-1"
eType="#//Param" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="group"
lowerBound="1" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="subGroup"
lowerBound="1"
eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="binning"
lowerBound="1"
eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="testBlocks"
lowerBound="1"
upperBound="-1" eType="#//ElementaryTestBlock" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="SubFlow"
eSuperTypes="#//Node #//Flow"/>
<eClassifiers xsi:type="ecore:EClass" name="Flow">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="flowName"
lowerBound="1"
eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"
defaultValueLiteral="MyFlow"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="nodes"
upperBound="-1"
eType="#//Node" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="binTables"
eType="#//BinTable"
containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="BinTable">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
lowerBound="1" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="bins"
lowerBound="2" upperBound="-1"
eType="#//Bin" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Link">
<eStructuralFeatures xsi:type="ecore:EReference" name="targetNode"
lowerBound="1"
eType="#//Node"/>
</eClassifiers>
</ecore:EPackage>


Many thanks in advance for your time!

Georges
Re: Getting the name of an element which is itself an attribute value [message #44775 is a reply to message #44744] Tue, 29 April 2008 13:10 Go to previous messageGo to next message
Paul Elder is currently offline Paul ElderFriend
Messages: 849
Registered: July 2009
Senior Member
Georges:

Some answers...

> * What is the purpose of the loop you suggest me to include in the
> main.jet file?

Your sample output had a different element name for each linked node:

<output_label_1>SF1</output_label_1>
<output_label_2>SF2</output_label_2>

The idea of ordinal was to calculate a value for it (and keep that
calculation out of the template)

> Is it here to add an "ordinal" attribute to every "link"? Does this mean
> that I can manipulate an in-memory structure which is an image of the XML
> input file one?

JET can 'annotate' any element in the input model via c:set. c:set will work
even if the underlying model element does not have an attribute of that
name. This is useful in 'completing' the model so that templates have less
calculate.

>
> * I understand from this that we could use the main.jet file to prepare
> things in order to make the transformation easier to code. Is this
> correct?

Exactly!

>
> * The JET transformation produces errors :
> templates/flow_template2.jet(11,22): <c:get select="$link/@ordinal">
> Error: XPath expression returned no result
> templates/flow_template2.jet(11,55): <c:get select="$link/@inputLabel">
>
> Do you see why?
>

I found a few typo's in my code (the Ecore model has helps - thanks). Plus
there was one problem in your main.jet. Lets start with the ECore model. It
defines:

Flow
nodes[0..*]: Node
Node
inputLabel [0..1] : String
nodeName [1..1] : String
outputLinks[0..*] : Link
Link
tagetNode[1..1]: Node

In main.jet, I've put the calculation of @ordinal before the
invocation of the flow_template2.jet.

<%-- templates/main.jet --%>
<c:iterate select="/Flow/nodes" var="node">
<c:setVariable var="nextOrdinal" select="1"/>
<c:iterate select="$node/outputLinks" var="link">
<c:set select="$link" name="ordinal"><c:get
select="$nextOrdinal"/></c:set>
<c:setVariable var="nextOrdinal" select="$nextOrdinal + 1"/>
</c:iterate>
</c:iterate>

<ws:file template="templates/flow_template2.jet"
path="{$org.eclipse.jet.resource.project.name}/flow.xml"/>


As for the flow_template2.jet, the only change is that to go from a Link to
a Node, you need
XPath such as $link/targetNode/@inputLabel, rather than $link/@inputLable.

<%-- templates/flow_template2.jet --%>
<?xml version="1.0" encoding="utf-8"?>
<tns:flow name="<c:get select=/Flow/@flowName/>" >
<bin_table><c:get select="/Flow/BinTable/@name"/></bin_table>
<c:iterate select="/Flow/nodes" var="node">
<c:if test="$node/@inputLabel">
<input_label><c:get select="$node/@inputLabel"/></input_label>
</c:if>
<node name="<c:get select="$node/@nodeName"/>">
<c:iterate select="$node/outputLinks" var="link">
<output_label_<c:get select="$link/@ordinal"/>><c:get
select="$link/targetNode/@inputLabel"/></output_label_<c:get
select="$link/@ordinal"/>>
</c:iterate>
</node>
</c:iterate>
</tns:flow>
Re: Getting the name of an element which is itself an attribute value [message #44832 is a reply to message #44775] Wed, 30 April 2008 06:00 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: georges.bachelier.atmel.com

Hello Paul,

thank you very much for your time and teaching; I have learned a lot about
JET in a short time and our transformation works fine now.
I have one more question though: the transformation works only if it is
performed from a second instance of Eclipse on which my plug-ins are
loaded. The transformation is launched as follows from our GMF-based
editor on diagram saving :

../..
IDiagramDocument diagramDocument = ( IDiagramDocument ) document;
TransactionalEditingDomain domain =
diagramDocument.getEditingDomain( );
XMIResourceImpl resource = ( XMIResourceImpl )
domain.getResourceSet( ).getResources( ).get( 1 );
Map< String, String > variables = new HashMap< String, String >( );
variables.put( "org.eclipse.jet.resource.project.name",
resource.getURI( ).segments( )[ 1 ] );
IStatus status = JET2Platform.runTransformOnObject(
"com.xxx.yyy.testfloweditor.jet", resource, variables, new
NullProgressMonitor( ) );
../..

No problem with this. But, if I run the transformation in Eclipse through
a "JET transformation" run configuration, I get the following error
message:

templates/flow_template.jet(48,52): <c:get
select="$link/targetNode/@inputLabel">
Error: XPath expression returned no result

It seems that the 'path'to the 'inputLabel' attribute cannot be resolved.
Although I am happy with the current JET results, it would save a lot of
time if we could perform a successful transformation from Eclipse.
What do you think about this? Is there anything I can tune to make this
work?

Best regards,

Georges
Re: Getting the name of an element which is itself an attribute value [message #44870 is a reply to message #44832] Wed, 30 April 2008 15:07 Go to previous messageGo to next message
Paul Elder is currently offline Paul ElderFriend
Messages: 849
Registered: July 2009
Senior Member
Georges:

In order to read you model, JET requires information on the ECore package
describing your model. I'm guessing that the plug-in defining Flow Model is
located in your development workspace.

When JET attempts to load a file from disk, it looks for an registered ECore
package for the files extension. But, as your EMF plug-in is in the
workspace the association with the extension has not happen. In this case,
JET falls back to loading the document as XML. This doesn't work in your
case becuase your documents are serialized as XMI. (XML and XMI make this
all very confusing. Bottom line is that the XPath expressions are not the
same if the model is loaded as a pure XML document rather than interpreted
as XMI.)

But, all is not lost! Do the following to let JET know that it should load
your JET transformations input using EMF.
a) Open plugin.xml
b) Swtich to the Extensions tab
c) Expand org.eclipse.jet.transform
d) Click (transform)
e) In the modelLoader field, enter org.eclipse.jet.emf
f) Save and close the plug-in editor.

Works like a charm (in my tests, anyhow)!

Paul

"Georges" <georges.bachelier@atmel.com> wrote in message
news:fe9d169e22cac7f7c37c6ff2a40368b4$1@www.eclipse.org...
> Hello Paul,
>
> thank you very much for your time and teaching; I have learned a lot about
> JET in a short time and our transformation works fine now.
> I have one more question though: the transformation works only if it is
> performed from a second instance of Eclipse on which my plug-ins are
> loaded. The transformation is launched as follows from our GMF-based
> editor on diagram saving :
>
> ./..
> IDiagramDocument diagramDocument = ( IDiagramDocument ) document;
> TransactionalEditingDomain domain =
> diagramDocument.getEditingDomain( );
> XMIResourceImpl resource = ( XMIResourceImpl )
> domain.getResourceSet( ).getResources( ).get( 1 );
> Map< String, String > variables = new HashMap< String, String >( );
> variables.put( "org.eclipse.jet.resource.project.name",
> resource.getURI( ).segments( )[ 1 ] );
> IStatus status = JET2Platform.runTransformOnObject(
> "com.xxx.yyy.testfloweditor.jet", resource, variables, new
> NullProgressMonitor( ) );
> ./..
>
> No problem with this. But, if I run the transformation in Eclipse through
> a "JET transformation" run configuration, I get the following error
> message:
>
> templates/flow_template.jet(48,52): <c:get
> select="$link/targetNode/@inputLabel">
> Error: XPath expression returned no result
>
> It seems that the 'path'to the 'inputLabel' attribute cannot be resolved.
> Although I am happy with the current JET results, it would save a lot of
> time if we could perform a successful transformation from Eclipse.
> What do you think about this? Is there anything I can tune to make this
> work?
>
> Best regards,
>
> Georges
>
>
>
Re: Getting the name of an element which is itself an attribute value [message #44987 is a reply to message #44870] Sat, 03 May 2008 07:20 Go to previous messageGo to next message
Georges Bachelier is currently offline Georges BachelierFriend
Messages: 8
Registered: July 2009
Junior Member
Hello Paul,


thank you very much for this reply! I already had the modelLoader field
set as you proposed, but the transformation still fails when launched from
the 'JET Transformation' configuration. Here is my plugin.xml file :

<plugin>
<extension
id=""
name=""
point="org.eclipse.jet.transform">
<transform
modelLoader="org.eclipse.jet.emf"
startTemplate="templates/main.jet"

templateLoaderClass="org.eclipse.jet.compiled._jet_transformation ">
<description></description>
<tagLibraries>
<importLibrary id="org.eclipse.jet.controlTags" usePrefix="c"
autoImport="true"/>
<importLibrary id="org.eclipse.jet.javaTags" usePrefix="java"
autoImport="true"/>
<importLibrary id="org.eclipse.jet.formatTags" usePrefix="f"
autoImport="true"/>
<importLibrary id="org.eclipse.jet.workspaceTags"
usePrefix="ws" autoImport="false"/>
</tagLibraries>
</transform>
</extension>
</plugin>

Should I try setting a modelExtension ? I have already tested 'xml' with
no success.

Thanks a lot in advance for your time and help!

Georges
Re: Getting the name of an element which is itself an attribute value [message #45003 is a reply to message #44744] Sun, 04 May 2008 01:16 Go to previous messageGo to next message
Paul Elder is currently offline Paul ElderFriend
Messages: 849
Registered: July 2009
Senior Member
Georges:

I did a little more looking at what I think I previously described as EMF
magic.

Here's a snippet of my XMI encoded file I created with the refective ecore
editor. (In case you are not aware, this lets you create instances of
models using only the .ecore file.)

<bob:Root xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:bob="http://bob.com/test"
xsi:schemaLocation="http://bob.com/test ../my.emf.project/model/My.ecore">


The xmlns:bob defines the namespace.

The xsi:schemaLocation attribute tells EMF how to find the ecore file for
that namespace. Just so long as the URL after the space in
xsi:schemaLocation is accurate, JET should be able to load the model.
Depending on how you created the XMI file, that xsi:schemaLocation
attribute may be missing. If so, try adding it.

As for the reflective ECore editor, you start it as follows:

To create an XMI document:
1) open the .ecore file,
2) right click the type that will be the root of the XMI document
3) click Create Dynamic Instance. You'll be prompted for a file name, and
then the new file will appear in the editor as a sibling to the ecore
model. You can then add child elements, and set properties.

To open an XMI file again in the reflective editor:
1) right click the saved XMI file
2) click Open With > Sample Reflective Ecore Model Editor

Paul
Re: Getting the name of an element which is itself an attribute value [message #45090 is a reply to message #45003] Sun, 04 May 2008 07:33 Go to previous messageGo to next message
Georges Bachelier is currently offline Georges BachelierFriend
Messages: 8
Registered: July 2009
Junior Member
Hello Paul,


you were right, the xsi:schemaLocation was missing. Everything works fine
now!
Thank you very much for your help and teaching.

Best regards,

Georges
Re: Getting the name of an element which is itself an attribute value [message #45112 is a reply to message #45090] Sun, 04 May 2008 14:48 Go to previous message
Paul Elder is currently offline Paul ElderFriend
Messages: 849
Registered: July 2009
Senior Member
Georges:

Glad it's working. I learned a lot this time, too. Keep asking the
questions.

Paul
Previous Topic:multivalued attributes
Next Topic:ensure import programatically
Goto Forum:
  


Current Time: Wed Nov 26 04:37:41 GMT 2014

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

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