Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Epsilon » Accessing OSGi component instance(Possibility of using pre-existing Native instances in ETL)
Accessing OSGi component instance [message #1787545] Mon, 28 May 2018 15:06 Go to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
Hello,

My source model may contain expressions that I want to resolve/calculate during the model transformation, using information available on runtime. For instance, the source model may have mayDrink="currentUser.age > 18" and the equivalent value on the target model may be mayDrink=true.

This calculation is done by a class named ExpressionCalculator, and it is an OSGI component instantiated by the Equinox framework. If I do new Native("my.package.ExpressionCalculator") in the ETL script itself, I would not get the pre-existing component instance that I need to use.

After creating a standalone EtlModule module instance, how can I pass an object to it to be used as a Native variable? Ultimately, I'd like to do something like this inside the transformation rule:

target.mayDrink = calculator.asBoolean(source.mayDrink);


Thanks,

Flavio

[Updated on: Mon, 28 May 2018 15:12]

Report message to a moderator

Re: Accessing OSGi component instance [message #1787572 is a reply to message #1787545] Tue, 29 May 2018 09:28 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2162
Registered: July 2009
Location: York, UK
Senior Member

Hi Flavio,

The following should do the trick:

module.getContext().getFrameStack().putGlobal(Variable.createReadOnlyVariable("calculator", calculator));


Cheers,
Dimitris
Re: Accessing OSGi component instance [message #1790093 is a reply to message #1787572] Mon, 04 June 2018 17:31 Go to previous messageGo to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
Hi Dimitris,

I tested that and it was working fine, thanks!

Unfortunately, once I finished implementing the designed solution, the transformation stopped working, with a "Type 'Origin!MySource' not found" error. I see this happens because the EPackage.Registry is empty... I am still not sure if this is an Epsilon issue or an EMF issue, but I will investigate further and possibly create a new topic as this seems to be a separate issue anyway.

Best regards,

Flavio
Re: Accessing OSGi component instance [message #1791091 is a reply to message #1790093] Fri, 22 June 2018 17:21 Go to previous messageGo to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
Hi Dimitris,

Regarding the issue mentioned above, of EPackage.Registry being empty, I found out that when the system finishes loading, the packages are gone... not sure where/why this happens, but I am able to retrieve a reference to the EPackage while the system is still loading, so this is fine for now.

I continued working on this approach of making usage of Java service objects in the transformation script and I have two other requirements you can probably help with:

1) Injecting an import statement at runtime

The ETL module is currently loaded as follows:
URL etlScript = this.getClass().getResource("myfile.etl");
IEtlModule etlModule = new EtlModule();
module.parse(etlScript.toURI());


Now for the "myfile.etl" that is provided by the end-user, I'd like to make all rules defined in another file such as "library.etl" to be made available transparently. In order words, I want the Java code to make the user-provided ETL module import this "library.etl" without the user having to put an explicit import statement on their script.

I guess that something such as
etlModule.getImports().add(...);
could allow that, or maybe there is a way to parse both files and somehow combine them. Can you help me understand how something like this can be achieved?

2) Using org.eclipse.epsilon.eol.dom to generate and calculate expressions at runtime

The aforementioned ExpressionCalculator class essentially takes an expression represented in EMF/Xtext and produces a result (String, Integer, etc.) for this expression. However, I realize that this design may force me to introduce EMF dependencies to parts of the system where such dependencies are not welcome.

To prevent that, instead of performing the calculation directly with the Xtext input, I am trying to convert the Xtext expression tree into org.eclipse.epsilon.eol.dom.Expression, and then run
eolExpression.execute(context)
, thus delegating the actual calculation logic to Epsilon. I am more comfortable with having Epsilon as a dependency instead of EMF, since Epsilon abstracts the source model technology so it can be eventually changed without impacting the rest of the system.

I did a quick test with boolean and arithmetic expressions, it works as expected. However, in certain expressions I also need to call a Java method to do some processing and I am not sure which Expression subclass to use for that. Is it PropertyCallExpression? Would it work if the method to be called is not named as a getter? What should I pass on the constructor?

Thanks,

Flavio

[Updated on: Fri, 22 June 2018 17:25]

Report message to a moderator

Re: Accessing OSGi component instance [message #1791093 is a reply to message #1791091] Fri, 22 June 2018 17:40 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2162
Registered: July 2009
Location: York, UK
Senior Member

Hi Flavio,

Regarding your first question, what you're proposing should work. See EolModule.getImportsByExtension for code that shows how to initialise imports.

I'm not sure I understand your second question. Could you please elaborate a bit more or provide some code I can run?

Thanks,
Dimitris
Re: Accessing OSGi component instance [message #1791094 is a reply to message #1791093] Fri, 22 June 2018 18:06 Go to previous messageGo to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
I found the code for getImportsByExtension(), I will have a closer look on it, thanks!

For the second question, I hope the code below makes it clearer:

package org.eclipse.epsilon.mwe;

import org.eclipse.epsilon.eol.dom.AndOperatorExpression;
import org.eclipse.epsilon.eol.dom.BooleanLiteral;
import org.eclipse.epsilon.eol.dom.Expression;
import org.eclipse.epsilon.eol.dom.NameExpression;
import org.eclipse.epsilon.eol.dom.PropertyCallExpression;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.context.Variable;
import org.eclipse.epsilon.etl.EtlModule;

/**
 * Minimum example for Expressions.
 *
 * @author Flavio Costa
 */
public class ExpressionsTest {

    public static class MyService {
        public int addOne(int input) {
            return input + 1;
        }
    }

    public static void main(String[] args) {

        EtlModule etlModule = new EtlModule();
        IEolContext context = etlModule.getContext();
        try {
            // boolean expression works great!
            Expression expression = new AndOperatorExpression(new BooleanLiteral(true), new BooleanLiteral(false));
            System.out.println("and(true, false) = " + expression.execute(context));

            MyService myservice = new MyService();
            context.getFrameStack().putGlobal(Variable.createReadOnlyVariable("myservice", myservice));
            // the line immediately below is wrong, I want to do myservice.addOne(1) which should return 2
            expression = new PropertyCallExpression(new NameExpression("myservice"), new NameExpression("addOne"));
            System.out.println("addOne(1) = " + expression.execute(context));

        } catch (EolRuntimeException e) {
            e.printStackTrace();
        }
    }
}
Re: Accessing OSGi component instance [message #1791095 is a reply to message #1791094] Fri, 22 June 2018 18:12 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2162
Registered: July 2009
Location: York, UK
Senior Member

Hi Flavio,

Since addOne is a method, an OperationCallExpression should be used instead of a PropertyCallExpression.

Cheers,
Dimitris
Re: Accessing OSGi component instance [message #1791097 is a reply to message #1791095] Fri, 22 June 2018 19:26 Go to previous messageGo to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
Hi Dimitris,

Yes, this works as expected:
expression = new OperationCallExpression(new NameExpression("myservice"), new NameExpression("addOne"),
      new IntegerLiteral(1));


This is the console output:
and(true, false) = false
addOne(1) = 2


Thanks for your continued support!

Flavio
Re: Accessing OSGi component instance [message #1791104 is a reply to message #1791097] Fri, 22 June 2018 21:29 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2162
Registered: July 2009
Location: York, UK
Senior Member

Great - you're welcome!

Cheers,
Dimitris
Re: Accessing OSGi component instance [message #1792105 is a reply to message #1791104] Wed, 11 July 2018 14:07 Go to previous messageGo to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
Hi Dimitris,

It's me again :)

This is how I did the programmatic import of another ETL module, I will leave the code here in case it's useful for anyone in the future:

    private void addImplicitImport(IEtlModule etlModule, String importName) {
        Import implicitImport = new Import();
        implicitImport.setParent(etlModule);
        implicitImport.setPathLiteral(new StringLiteral(importName));
        implicitImport.setImportedModule(new EtlModule());
        try {
            implicitImport.load(this.getClass().getResource(importName).toURI());
            etlModule.getImports().add(implicitImport);
        } catch (URISyntaxException e) {
            logger.error("Could not import the {} module: {}", importName, e.getMessage());
        }
    }


Other than this, while I move forward with my implementation I realize the best way of getting certain functionality may be by writing my own Expression subclasses, to add some custom logic to certain expressions. Can you please give me an overview of what the methods build(...) and compile(...) are expected to do and when they are used, so I can give them a proper implementations?

Thanks,

Flavio
Re: Accessing OSGi component instance [message #1792113 is a reply to message #1792105] Wed, 11 July 2018 19:21 Go to previous messageGo to next message
Flavio Costa is currently offline Flavio CostaFriend
Messages: 23
Registered: February 2018
Junior Member
Also, I notice that when you use the constructor AbstractModuleElement(ModuleElement parent), the new AbstractModuleElement is added as a child of the parent, but when you use setParent(ModuleElement parent) this doesn't happen. Is there any reason why this code is not in setParent(), rather than in the constructor?
parent.getChildren().add(this);
Re: Accessing OSGi component instance [message #1792154 is a reply to message #1792113] Thu, 12 July 2018 08:26 Go to previous message
Dimitris Kolovos is currently offline Dimitris KolovosFriend
Messages: 2162
Registered: July 2009
Location: York, UK
Senior Member

Hi Flavio,

build() builds ModuleElements from ASTs effectively decoupling execution code from the parser implementation. compile() performs static analysis and records warnings/errors but only a few classes implement it at the moment and analysis is very basic.

Regarding your AbstractModuleElement constructor question, I've tried moving the contents of the constructor to setParent and then calling the method from the constructor but a few of our tests fail after doing this. Could you please raise an enhancement request [1] so that we can investigate?

Cheers,
Dimitris

[1] https://bugs.eclipse.org/bugs/enter_bug.cgi?product=epsilon
Previous Topic:Reading text file in EOL/EGL
Next Topic:Links to source code broken
Goto Forum:
  


Current Time: Tue Apr 16 07:59:32 GMT 2024

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

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

Back to the top