| [Neon][SDK] access Scout Model [message #1720512] |
Tue, 19 January 2016 01:45  |
Eclipse User |
|
|
|
As the SDK is also available as standard Maven dependencies, I tried to access the Scout Model of a form class. I've downloaded the SDKs sources and tried to find a hint how to access it, but I didn't find a solution.
So far I found and tested:
File f = new File("xxxx/src/main/java");
Classpath cp = WorkspaceFileSystem.createClasspath(f, true, null);
ClasspathEntry classpathEntry = new ClasspathEntry(cp, StandardCharsets.UTF_8.name());
Collection<ClasspathEntry> all = new ArrayList<>();
all.add(classpathEntry);
JavaEnvironmentSpi javaEnvironment = new JavaEnvironmentWithJdt(all.toArray(new ClasspathEntry[all.size()]));
IJavaEnvironment wrap = javaEnvironment.wrap();
IType type = wrap.findType("xxxx.MyForm");
for (IMethod m : type.methods().list()) {
System.out.println(m.source().toString());
}
But how can I get access to the Scout Model of this class. i.e. I would like to add a form field, or generate a form class from scratch.
|
|
|
|
|
|
|
| Re: [Neon][SDK] access Scout Model [message #1724278 is a reply to message #1723047] |
Mon, 22 February 2016 12:38   |
Eclipse User |
|
|
|
Hi René
If you want to stay IDE independent you can only use the API provided by org.eclipse.scout.sdk.core and org.eclipse.scout.sdk.core.s (both available on Maven Central).
Basically this API consists of two components:
- A parser that is capable to read java or class files into a structural memory representation including validation.
- Source Builders that are capable to create new java source
With this API you can apply a lot of modifications to java files (new or existing ones) but it is more low level than the example you provided.
You can use the following sample test case as starting point. It adds a new string field to an existing form including the form field getter method:
import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import org.eclipse.scout.sdk.core.model.api.Flags;
import org.eclipse.scout.sdk.core.model.api.IJavaEnvironment;
import org.eclipse.scout.sdk.core.model.api.IType;
import org.eclipse.scout.sdk.core.model.spi.internal.ClasspathEntry;
import org.eclipse.scout.sdk.core.model.spi.internal.JavaEnvironmentWithJdt;
import org.eclipse.scout.sdk.core.s.IScoutRuntimeTypes;
import org.eclipse.scout.sdk.core.s.model.ScoutMethodSourceBuilderFactory;
import org.eclipse.scout.sdk.core.signature.Signature;
import org.eclipse.scout.sdk.core.sourcebuilder.compilationunit.CompilationUnitSourceBuilder;
import org.eclipse.scout.sdk.core.sourcebuilder.type.ITypeSourceBuilder;
import org.eclipse.scout.sdk.core.sourcebuilder.type.TypeSourceBuilder;
import org.eclipse.scout.sdk.core.testing.CoreTestingUtils;
import org.eclipse.scout.sdk.core.util.CoreUtils;
import org.junit.Test;
public class StringFieldAddTest {
@Test
public void testAddStringField() {
IJavaEnvironment env = new JavaEnvironmentWithJdt(null, createClasspath()).wrap();
// get existing form
IType form = env.findType("formdata.client.ui.forms.ListBoxForm");
// convert from parsed class to source builder (for modifications)
CompilationUnitSourceBuilder cuBuilder = new CompilationUnitSourceBuilder(form.compilationUnit());
// get existing mainbox builder
ITypeSourceBuilder mainBoxBuilder = getTypeSourceBuilder(cuBuilder.getMainType(), "MainBox");
// add string field
ITypeSourceBuilder newStringField = new TypeSourceBuilder("MyNewStringField");
newStringField.setFlags(Flags.AccPublic);
newStringField.setSuperTypeSignature(Signature.createTypeSignature(IScoutRuntimeTypes.AbstractStringField));
mainBoxBuilder.addType(newStringField);
// add getter
cuBuilder.getMainType().addMethod(ScoutMethodSourceBuilderFactory.createFieldGetter(Signature.createTypeSignature(newStringField.getFullyQualifiedName())));
// create new source
String source = CoreUtils.createJavaCode(cuBuilder, env, "\n", null);
System.out.println(source);
// validate result
CoreTestingUtils.assertNoCompileErrors(env, cuBuilder.getPackageName(), cuBuilder.getMainType().getElementName(), source);
}
private static ClasspathEntry[] createClasspath() {
String encoding = StandardCharsets.UTF_8.name(); // TODO specify the encoding of the files
File[] classpathEntries = new File[]{}; //TODO fill classpath entries
ClasspathEntry[] entries = new ClasspathEntry[classpathEntries.length];
for (int i = 0; i < entries.length; i++) {
boolean isSource = true; // TODO: specifies if classpathEntries[i] references a source jar/folder containing .java files OR a binary jar/folder containing .class files.
Classpath cp = FileSystem.getClasspath(classpathEntries[i].getAbsolutePath(), encoding, isSource, null, null);
entries[i] = new ClasspathEntry(cp, encoding);
}
return entries;
}
private static ITypeSourceBuilder getTypeSourceBuilder(ITypeSourceBuilder declaringType, String name) {
for (ITypeSourceBuilder tsb : declaringType.getTypes()) {
if (name.equals(tsb.getElementName())) {
return tsb;
}
}
return null;
}
}
There are some TODOs in the code where you have to build the classpath of the environment you are working in.
As you can see the API is quite low level but at the same time very flexible.
Therefore for some components there are dedicated builders: There is e.g. a FormSourceBuilder that can create new forms, specific builders for DTOs like a FormData or builders for services, codetypes, pages, etc. Those components can then be stitched together to build complex components.
Hope this helps
Matthias
|
|
|
|
Powered by
FUDForum. Page generated in 0.26110 seconds