Text not verified for kermeta 2 | |
---|---|
If you have existing code that you want to run in a Kermeta program, you can use one of those two mechanisms : extern call or seamless require.
The extern call is currently the more robust approach as it is used internally by Kermeta to implement some part of its framework. It also helps to clearly specify the border between java and Kermeta.
The seamless java require is more straitghforward to use (no wrapper to write) but is still in prototype (v0.4.2) and still have several limitations.
The extern allows you to call a java static method from Kermeta. But, to do that, you will have firstly to create a Java wrapper, that will be able to manipulate correctly the Java objects, and secondly to add this wrapper in your java global classpath.
Then, from this method you can access all your java libraries. One task of the static method will be to convert the basic types like Integer or String.
You'll need to refer to the Javadoc of the interpreter in order to know how to access the internal RuntimeObject of Kermeta.
Example 1 : sample of Kermeta code using extern (io.kmt):
/** * An implementation of a StdIO class in Kermeta using existing Java: standard * input/output */ class StdIO { /** * write the object to standard output */ operation write(object : Object) : Void is do result ?= extern fr::irisa::triskell::kermeta::runtime::basetypes::StdIO.write(object) end /** * writeln the object to standard output */ operation writeln(object : Object) : Void is do result ?= extern fr::irisa::triskell::kermeta::runtime::basetypes::StdIO.writeln(object) end /** * read an object from standard input */ operation read(prompt : String) : String is do result ?= extern fr::irisa::triskell::kermeta::runtime::basetypes::StdIO.read(prompt) end }
Example 2 : sample of Java code ("wrapper") called by the Kermeta extern:
/** Implementation of input and output methods */ public class StdIO{ // Implementation of method write called as : // extern fr::irisa::triskell::kermeta::runtime::basetypes::Io.write(output) public static RuntimeObject write(RuntimeObject output) { output.getFactory().getKermetaIOStream().print(output.getData().get("StringValue")); return output.getFactory().getMemory().voidINSTANCE; } // Implementation of method writeln called as : // extern fr::irisa::triskell::kermeta::runtime::basetypes::Io.writeln(output) public static RuntimeObject writeln(RuntimeObject output) { write(output); output.getFactory().getKermetaIOStream().print("\n"); return output.getFactory().getMemory().voidINSTANCE; } // Implementation of method writeln called as : // extern fr::irisa::triskell::kermeta::runtime::basetypes::Io.read(output) public static RuntimeObject read(RuntimeObject prompt) { java.lang.String input = null; // We also have our own String wrapper if (String.getValue(prompt).length()>0) prompt.getFactory().getKermetaIOStream().print(String.getValue(prompt)); // FIXME : dirty cast.. read returns a String or could return smthg else? input = (java.lang.String)prompt.getFactory().getKermetaIOStream().read( String.getValue(prompt)); RuntimeObject result = String.create(input, prompt.getFactory()); return result; }
Tip | |
---|---|
This method is used to implement Kermeta framework. You'll find much more code samples of extern call in its sources. |
Warning | |
---|---|
This feature is still a prototype and still have many limitations. The first version is already available but any help is welcome to help us to improve it. |
The basic principle, is to simply require your jar file.
require "yourjar.jar"
Then Kermeta automatically retreive the class definition it contains to be used from Kermeta code. However, as java and Kermeta have different language constraints, some adaptation are automatically made.
If there is several operations with the same name (as this is legal in Java but not in Kermeta) they are renamed. (Please use the outline to find the new name of the operation you want)
Java contructors are generated as "initialize" operation.
When creating a new java object from Kermeta, a call to new is not enough, you also need to call one of the "initialize" operation in order to correctly create it.
In order to get the standard library direclty from your running
java, you can
require java_rt_jar
but as this
library is really big and as you probably don't need all
java from
Kermeta ;-) then
you must use the includeFilter and
excludeFilter.
Sample using java.io from java Standard library
require kermeta require java_rt_jar includeFilter ("java::io") // the filter ensure we don't get all java using java::io using kermeta::kunit class testRequireJava inherits kermeta::kunit::TestCase { operation main() : Void is do var tr : TestRunner init TestRunner.new tr.run(testRequireJava) tr.printTestResult end operation testmain() : Void is do // create and initialize a File with the String var f : File init File.new.initialize_String("c:/temp/test.txt") var f2 : File // create and initialize a FileWriter with the File var fwriter : FileWriter init FileWriter.new.initialize_File(f) if (f.exists) then stdio.writeln(f.toString + " already exists") else stdio.writeln(f.createNewFile.toString) end fwriter.write_String("Hello world") fwriter.close stdio.writeln("file written") stdio.writeln(fwriter.toString) stdio.writeln(f.getPath) stdio.writeln(f.separator) f2 := f stdio.writeln(f2.createNewFile.toString) stdio.writeln((f2.equals(f)).toString) assert( f2.equals(f)) var fwriter2 : FileWriter fwriter2 := fwriter stdio.writeln((fwriter2.equals(fwriter)).toString) assert( fwriter2.equals(fwriter)) stdio.writeln(f.getPath) stdio.writeln(f.toString) stdio.writeln("End") end }
includeFilter
and
excludeFilter
accept a comma separated list of
qualified name.
includeFilter
adds only elements
whose qualified name start with one of the list.
excludeFilter
removes elements whose qualified name
start with one of the list. If
you use a combinaison of
includeFilter
and
excludeFilter
,
then the
includeFilter
is applied before the
excludeFilter
(that'll remove element from the
included one.
Currently known limitations: no support for java5 generics (they are ignored), requiring very big jar like the full java library end up with out of memory error (you need to use the includefilter and excludeFilter), some bugs with some primitives types (double/float)