Adds HelperProvider, starts testing internal classes

This commit is contained in:
Guillaume Tâche
2024-12-14 22:02:07 +01:00
parent d63188e8ee
commit 38056c43f7
28 changed files with 1057 additions and 482 deletions

View File

@@ -3,10 +3,8 @@ package com.github.gtache.fxml.compiler.impl;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.GenerationRequest; import com.github.gtache.fxml.compiler.GenerationRequest;
import com.github.gtache.fxml.compiler.Generator; import com.github.gtache.fxml.compiler.Generator;
import com.github.gtache.fxml.compiler.impl.internal.ConstructorFormatter;
import com.github.gtache.fxml.compiler.impl.internal.GenerationProgress; import com.github.gtache.fxml.compiler.impl.internal.GenerationProgress;
import com.github.gtache.fxml.compiler.impl.internal.HelperMethodsFormatter; import com.github.gtache.fxml.compiler.impl.internal.HelperProvider;
import com.github.gtache.fxml.compiler.impl.internal.LoadMethodFormatter;
//TODO handle binding (${}) //TODO handle binding (${})
@@ -14,11 +12,11 @@ import com.github.gtache.fxml.compiler.impl.internal.LoadMethodFormatter;
* Implementation of {@link Generator} * Implementation of {@link Generator}
*/ */
public class GeneratorImpl implements Generator { public class GeneratorImpl implements Generator {
@Override @Override
public String generate(final GenerationRequest request) throws GenerationException { public String generate(final GenerationRequest request) throws GenerationException {
final var progress = new GenerationProgress(request); final var progress = new GenerationProgress(request);
final var helperProvider = new HelperProvider(progress);
final var className = request.outputClassName(); final var className = request.outputClassName();
final var pkgName = className.substring(0, className.lastIndexOf('.')); final var pkgName = className.substring(0, className.lastIndexOf('.'));
final var simpleClassName = className.substring(className.lastIndexOf('.') + 1); final var simpleClassName = className.substring(className.lastIndexOf('.') + 1);
@@ -27,15 +25,15 @@ public class GeneratorImpl implements Generator {
sb.append("package ").append(pkgName).append(";\n"); sb.append("package ").append(pkgName).append(";\n");
sb.append("\n"); sb.append("\n");
sb.append("/**\n"); sb.append("/**\n");
sb.append(" * Generated code, not thread-safe\n"); sb.append(" * Generated code\n");
sb.append(" */\n"); sb.append(" */\n");
sb.append("public final class ").append(simpleClassName).append(" {\n"); sb.append("public final class ").append(simpleClassName).append(" {\n");
sb.append("\n"); sb.append("\n");
ConstructorFormatter.formatFieldsAndConstructor(progress); helperProvider.getInitializationFormatter().formatFieldsAndConstructor();
sb.append("\n"); sb.append("\n");
LoadMethodFormatter.formatLoadMethod(progress); helperProvider.getLoadMethodFormatter().formatLoadMethod();
sb.append("\n"); sb.append("\n");
HelperMethodsFormatter.formatHelperMethods(progress); helperProvider.getHelperMethodsFormatter().formatHelperMethods();
sb.append("\n"); sb.append("\n");
formatControllerMethod(progress, controllerInjectionClass); formatControllerMethod(progress, controllerInjectionClass);
sb.append("}\n"); sb.append("}\n");

View File

@@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set; import java.util.Set;
/** /**
@@ -16,7 +17,10 @@ import java.util.Set;
*/ */
final class ConstructorHelper { final class ConstructorHelper {
private ConstructorHelper() { private final HelperProvider helperProvider;
ConstructorHelper(final HelperProvider helperProvider) {
this.helperProvider = Objects.requireNonNull(helperProvider);
} }
/** /**
@@ -27,8 +31,9 @@ final class ConstructorHelper {
* @return The list of constructor arguments * @return The list of constructor arguments
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static List<String> getListConstructorArgs(final ConstructorArgs constructorArgs, final ParsedObject parsedObject) throws GenerationException { List<String> getListConstructorArgs(final ConstructorArgs constructorArgs, final ParsedObject parsedObject) throws GenerationException {
final var args = new ArrayList<String>(constructorArgs.namedArgs().size()); final var args = new ArrayList<String>(constructorArgs.namedArgs().size());
final var valueFormatter = helperProvider.getValueFormatter();
for (final var entry : constructorArgs.namedArgs().entrySet()) { for (final var entry : constructorArgs.namedArgs().entrySet()) {
final var type = entry.getValue().type(); final var type = entry.getValue().type();
final var p = parsedObject.attributes().get(entry.getKey()); final var p = parsedObject.attributes().get(entry.getKey());
@@ -36,12 +41,12 @@ final class ConstructorHelper {
final var c = parsedObject.properties().entrySet().stream().filter(e -> final var c = parsedObject.properties().entrySet().stream().filter(e ->
e.getKey().name().equals(entry.getKey())).findFirst().orElse(null); e.getKey().name().equals(entry.getKey())).findFirst().orElse(null);
if (c == null) { if (c == null) {
args.add(ValueFormatter.toString(entry.getValue().defaultValue(), type)); args.add(valueFormatter.toString(entry.getValue().defaultValue(), type));
} else { } else {
throw new GenerationException("Constructor using complex property not supported yet"); throw new GenerationException("Constructor using complex property not supported yet");
} }
} else { } else {
args.add(ValueFormatter.toString(p.value(), type)); args.add(valueFormatter.toString(p.value(), type));
} }
} }
return args; return args;

View File

@@ -1,5 +1,6 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.ControllerInfo;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.InjectionType; import com.github.gtache.fxml.compiler.InjectionType;
import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes; import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes;
@@ -7,26 +8,39 @@ import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedProperty; import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
import java.util.SequencedCollection;
import static java.util.Objects.requireNonNull;
/** /**
* Various methods to help {@link GeneratorImpl} for injecting controllers * Various methods to help {@link GeneratorImpl} for injecting controllers
*/ */
final class ControllerInjector { final class ControllerInjector {
private ControllerInjector() { private final ControllerInfo controllerInfo;
private final InjectionType fieldInjectionType;
private final InjectionType methodInjectionType;
private final StringBuilder sb;
private final SequencedCollection<String> controllerFactoryPostAction;
ControllerInjector(final ControllerInfo controllerInfo, final InjectionType fieldInjectionType, final InjectionType methodInjectionType,
final StringBuilder sb, final SequencedCollection<String> controllerFactoryPostAction) {
this.controllerInfo = controllerInfo;
this.fieldInjectionType = requireNonNull(fieldInjectionType);
this.methodInjectionType = requireNonNull(methodInjectionType);
this.sb = requireNonNull(sb);
this.controllerFactoryPostAction = requireNonNull(controllerFactoryPostAction);
} }
/** /**
* Injects the given variable into the controller * Injects the given variable into the controller
* *
* @param progress The generation progress
* @param id The object id * @param id The object id
* @param variable The object variable * @param variable The object variable
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void injectControllerField(final GenerationProgress progress, final String id, final String variable) throws GenerationException { void injectControllerField(final String id, final String variable) throws GenerationException {
final var fieldInjectionType = progress.request().parameters().fieldInjectionType();
if (fieldInjectionType instanceof final ControllerFieldInjectionTypes types) { if (fieldInjectionType instanceof final ControllerFieldInjectionTypes types) {
final var sb = progress.stringBuilder();
switch (types) { switch (types) {
case FACTORY -> case FACTORY ->
sb.append(" fieldMap.put(\"").append(id).append("\", ").append(variable).append(");\n"); sb.append(" fieldMap.put(\"").append(id).append("\", ").append(variable).append(");\n");
@@ -46,41 +60,37 @@ final class ControllerInjector {
/** /**
* Injects an event handler controller method * Injects an event handler controller method
* *
* @param progress The generation progress
* @param property The property to inject * @param property The property to inject
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void injectEventHandlerControllerMethod(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { void injectEventHandlerControllerMethod(final ParsedProperty property, final String parentVariable) throws GenerationException {
injectControllerMethod(progress, getEventHandlerMethodInjection(progress, property, parentVariable)); injectControllerMethod(getEventHandlerMethodInjection(property, parentVariable));
} }
/** /**
* Injects a callback controller method * Injects a callback controller method
* *
* @param progress The generation progress
* @param property The property to inject * @param property The property to inject
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @param argumentClazz The argument class * @param argumentClazz The argument class
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void injectCallbackControllerMethod(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String argumentClazz) throws GenerationException { void injectCallbackControllerMethod(final ParsedProperty property, final String parentVariable, final String argumentClazz) throws GenerationException {
injectControllerMethod(progress, getCallbackMethodInjection(progress, property, parentVariable, argumentClazz)); injectControllerMethod(getCallbackMethodInjection(property, parentVariable, argumentClazz));
} }
/** /**
* Injects a controller method * Injects a controller method
* *
* @param progress The generation progress
* @param methodInjection The method injection * @param methodInjection The method injection
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static void injectControllerMethod(final GenerationProgress progress, final String methodInjection) throws GenerationException { private void injectControllerMethod(final String methodInjection) throws GenerationException {
final var fieldInjectionType = progress.request().parameters().fieldInjectionType();
if (fieldInjectionType instanceof final ControllerFieldInjectionTypes fieldTypes) { if (fieldInjectionType instanceof final ControllerFieldInjectionTypes fieldTypes) {
switch (fieldTypes) { switch (fieldTypes) {
case FACTORY -> progress.controllerFactoryPostAction().add(methodInjection); case FACTORY -> controllerFactoryPostAction.add(methodInjection);
case ASSIGN, SETTERS, REFLECTION -> progress.stringBuilder().append(methodInjection); case ASSIGN, SETTERS, REFLECTION -> sb.append(methodInjection);
} }
} else { } else {
throw getUnknownInjectionException(fieldInjectionType); throw getUnknownInjectionException(fieldInjectionType);
@@ -90,20 +100,18 @@ final class ControllerInjector {
/** /**
* Computes the method injection for event handler * Computes the method injection for event handler
* *
* @param progress The generation progress
* @param property The property * @param property The property
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @return The method injection * @return The method injection
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static String getEventHandlerMethodInjection(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { private String getEventHandlerMethodInjection(final ParsedProperty property, final String parentVariable) throws GenerationException {
final var setMethod = GenerationHelper.getSetMethod(property.name()); final var setMethod = GenerationHelper.getSetMethod(property.name());
final var methodInjectionType = progress.request().parameters().methodInjectionType();
final var controllerMethod = property.value().replace("#", ""); final var controllerMethod = property.value().replace("#", "");
if (methodInjectionType instanceof final ControllerMethodsInjectionType methodTypes) { if (methodInjectionType instanceof final ControllerMethodsInjectionType methodTypes) {
return switch (methodTypes) { return switch (methodTypes) {
case REFERENCE -> { case REFERENCE -> {
final var hasArgument = progress.request().controllerInfo().handlerHasArgument(controllerMethod); final var hasArgument = controllerInfo.handlerHasArgument(controllerMethod);
if (hasArgument) { if (hasArgument) {
yield " " + parentVariable + "." + setMethod + "(controller::" + controllerMethod + ");\n"; yield " " + parentVariable + "." + setMethod + "(controller::" + controllerMethod + ");\n";
} else { } else {
@@ -121,16 +129,14 @@ final class ControllerInjector {
/** /**
* Computes the method injection for callback * Computes the method injection for callback
* *
* @param progress The generation progress
* @param property The property * @param property The property
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @param argumentClazz The argument class * @param argumentClazz The argument class
* @return The method injection * @return The method injection
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static String getCallbackMethodInjection(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String argumentClazz) throws GenerationException { private String getCallbackMethodInjection(final ParsedProperty property, final String parentVariable, final String argumentClazz) throws GenerationException {
final var setMethod = GenerationHelper.getSetMethod(property.name()); final var setMethod = GenerationHelper.getSetMethod(property.name());
final var methodInjectionType = progress.request().parameters().methodInjectionType();
final var controllerMethod = property.value().replace("#", ""); final var controllerMethod = property.value().replace("#", "");
if (methodInjectionType instanceof final ControllerMethodsInjectionType methodTypes) { if (methodInjectionType instanceof final ControllerMethodsInjectionType methodTypes) {
return switch (methodTypes) { return switch (methodTypes) {

View File

@@ -1,68 +1,79 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.InjectionType;
import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes; import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedProperty; import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
import java.util.SequencedCollection;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.EXPRESSION_PREFIX; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.EXPRESSION_PREFIX;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to set fields * Helper methods for {@link GeneratorImpl} to set fields
*/ */
final class FieldSetter { final class FieldSetter {
private FieldSetter() { private final HelperProvider helperProvider;
private final InjectionType fieldInjectionType;
private final StringBuilder sb;
private final SequencedCollection<String> controllerFactoryPostAction;
FieldSetter(final HelperProvider helperProvider, final InjectionType fieldInjectionType,
final StringBuilder sb, final SequencedCollection<String> controllerFactoryPostAction) {
this.helperProvider = requireNonNull(helperProvider);
this.fieldInjectionType = requireNonNull(fieldInjectionType);
this.sb = requireNonNull(sb);
this.controllerFactoryPostAction = requireNonNull(controllerFactoryPostAction);
} }
/** /**
* Sets an event handler field * Sets an event handler field
* *
* @param progress The generation progress
* @param property The property to inject * @param property The property to inject
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @throws GenerationException if an error occurs@ * @throws GenerationException if an error occurs@
*/ */
static void setEventHandler(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { void setEventHandler(final ParsedProperty property, final String parentVariable) throws GenerationException {
setField(progress, property, parentVariable, "javafx.event.EventHandler"); setField(property, parentVariable, "javafx.event.EventHandler");
} }
/** /**
* Sets a field * Sets a field
* *
* @param progress The generation progress
* @param property The property to inject * @param property The property to inject
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @param fieldType The field type * @param fieldType The field type
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void setField(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String fieldType) throws GenerationException { void setField(final ParsedProperty property, final String parentVariable, final String fieldType) throws GenerationException {
final var fieldInjectionType = progress.request().parameters().fieldInjectionType();
if (fieldInjectionType instanceof final ControllerFieldInjectionTypes fieldTypes) { if (fieldInjectionType instanceof final ControllerFieldInjectionTypes fieldTypes) {
switch (fieldTypes) { switch (fieldTypes) {
case ASSIGN -> setAssign(progress, property, parentVariable); case ASSIGN -> setAssign(property, parentVariable);
case FACTORY -> setFactory(progress, property, parentVariable); case FACTORY -> setFactory(property, parentVariable);
case SETTERS -> setSetter(progress, property, parentVariable); case SETTERS -> setSetter(property, parentVariable);
case REFLECTION -> setReflection(progress, property, parentVariable, fieldType); case REFLECTION -> setReflection(property, parentVariable, fieldType);
} }
} else { } else {
throw new GenerationException("Unknown injection type : " + fieldInjectionType); throw new GenerationException("Unknown injection type : " + fieldInjectionType);
} }
} }
private static void setAssign(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) { private void setAssign(final ParsedProperty property, final String parentVariable) {
final var methodName = GenerationHelper.getSetMethod(property); final var methodName = GenerationHelper.getSetMethod(property);
final var value = property.value().replace(EXPRESSION_PREFIX, ""); final var value = property.value().replace(EXPRESSION_PREFIX, "");
progress.stringBuilder().append(" ").append(parentVariable).append(".").append(methodName).append("(").append(value).append(");\n"); sb.append(" ").append(parentVariable).append(".").append(methodName).append("(").append(value).append(");\n");
} }
private static void setFactory(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) { private void setFactory(final ParsedProperty property, final String parentVariable) {
progress.controllerFactoryPostAction().add(getSetString(property, parentVariable)); controllerFactoryPostAction.add(getSetString(property, parentVariable));
} }
private static void setSetter(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) { private void setSetter(final ParsedProperty property, final String parentVariable) {
progress.stringBuilder().append(getSetString(property, parentVariable)); sb.append(getSetString(property, parentVariable));
} }
private static String getSetString(final ParsedProperty property, final String parentVariable) { private static String getSetString(final ParsedProperty property, final String parentVariable) {
@@ -73,14 +84,14 @@ final class FieldSetter {
return " " + parentVariable + "." + methodName + "(" + split[0] + "." + getterName + ");\n"; return " " + parentVariable + "." + methodName + "(" + split[0] + "." + getterName + ");\n";
} }
private static void setReflection(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String fieldType) { private void setReflection(final ParsedProperty property, final String parentVariable, final String fieldType) {
final var methodName = GenerationHelper.getSetMethod(property); final var methodName = GenerationHelper.getSetMethod(property);
final var value = property.value().replace(EXPRESSION_PREFIX, ""); final var value = property.value().replace(EXPRESSION_PREFIX, "");
final var split = value.split("\\."); final var split = value.split("\\.");
final var fieldName = split[1]; final var fieldName = split[1];
final var sb = progress.stringBuilder();
sb.append(" try {\n"); sb.append(" try {\n");
sb.append(" ").append(GenerationCompatibilityHelper.getStartVar(progress, "java.lang.reflect.Field", 0)).append("field = controller.getClass().getDeclaredField(\"").append(fieldName).append("\");\n"); sb.append(" ").append(helperProvider.getCompatibilityHelper().getStartVar("java.lang.reflect.Field", 0))
.append("field = controller.getClass().getDeclaredField(\"").append(fieldName).append("\");\n");
sb.append(" field.setAccessible(true);\n"); sb.append(" field.setAccessible(true);\n");
sb.append(" final var value = (").append(fieldType).append(") field.get(controller);\n"); sb.append(" final var value = (").append(fieldType).append(") field.get(controller);\n");
sb.append(" ").append(parentVariable).append(".").append(methodName).append("(value);\n"); sb.append(" ").append(parentVariable).append(".").append(methodName).append("(value);\n");

View File

@@ -11,6 +11,7 @@ import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.Objects;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes;
@@ -20,15 +21,19 @@ import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.get
*/ */
final class FontFormatter { final class FontFormatter {
private FontFormatter() { private final HelperProvider helperProvider;
private final StringBuilder sb;
FontFormatter(final HelperProvider helperProvider, final StringBuilder sb) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.sb = Objects.requireNonNull(sb);
} }
private static String getStartFont(final GenerationProgress progress) { private String getStartFont() {
return GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.text.Font"); return helperProvider.getCompatibilityHelper().getStartVar("javafx.scene.text.Font");
} }
static void formatFont(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void formatFont(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) { if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) {
final var value = parseFontValue(parsedObject); final var value = parseFontValue(parsedObject);
final var url = value.url(); final var url = value.url();
@@ -37,37 +42,36 @@ final class FontFormatter {
final var size = value.size(); final var size = value.size();
final var name = value.name(); final var name = value.name();
if (url != null) { if (url != null) {
formatURL(progress, url, size, variableName); formatURL(url, size, variableName);
} else if (fw == null && fp == null) { } else if (fw == null && fp == null) {
formatNoStyle(progress, name, size, variableName); formatNoStyle(name, size, variableName);
} else { } else {
formatStyle(progress, fw, fp, size, name, variableName); formatStyle(fw, fp, size, name, variableName);
} }
GenerationHelper.handleId(progress, parsedObject, variableName); helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
} else { } else {
throw new GenerationException("Font cannot have children or properties : " + parsedObject); throw new GenerationException("Font cannot have children or properties : " + parsedObject);
} }
} }
private static void formatURL(final GenerationProgress progress, final URL url, final double size, final String variableName) { private void formatURL(final URL url, final double size, final String variableName) {
final var urlVariableName = URLFormatter.formatURL(progress, url.toString()); final var urlVariableName = helperProvider.getURLFormatter().formatURL(url.toString());
final var sb = progress.stringBuilder();
sb.append(" final javafx.scene.text.Font ").append(variableName).append(";\n"); sb.append(" final javafx.scene.text.Font ").append(variableName).append(";\n");
sb.append(" try (").append(GenerationCompatibilityHelper.getStartVar(progress, "java.io.InputStream", 0)).append(" in = ").append(urlVariableName).append(".openStream()) {\n"); sb.append(" try (").append(helperProvider.getCompatibilityHelper().getStartVar("java.io.InputStream", 0)).append(" in = ").append(urlVariableName).append(".openStream()) {\n");
sb.append(" ").append(variableName).append(" = javafx.scene.text.Font.loadFont(in, ").append(size).append(");\n"); sb.append(" ").append(variableName).append(" = javafx.scene.text.Font.loadFont(in, ").append(size).append(");\n");
sb.append(" } catch (final java.io.IOException e) {\n"); sb.append(" } catch (final java.io.IOException e) {\n");
sb.append(" throw new RuntimeException(e);\n"); sb.append(" throw new RuntimeException(e);\n");
sb.append(" }\n"); sb.append(" }\n");
} }
private static void formatNoStyle(final GenerationProgress progress, final String name, final double size, final String variableName) { private void formatNoStyle(final String name, final double size, final String variableName) {
progress.stringBuilder().append(getStartFont(progress)).append(variableName).append(" = new javafx.scene.text.Font(\"").append(name).append("\", ").append(size).append(");\n"); sb.append(getStartFont()).append(variableName).append(" = new javafx.scene.text.Font(\"").append(name).append("\", ").append(size).append(");\n");
} }
private static void formatStyle(final GenerationProgress progress, final FontWeight fw, final FontPosture fp, final double size, final String name, final String variableName) { private void formatStyle(final FontWeight fw, final FontPosture fp, final double size, final String name, final String variableName) {
final var finalFW = fw == null ? FontWeight.NORMAL : fw; final var finalFW = fw == null ? FontWeight.NORMAL : fw;
final var finalFP = fp == null ? FontPosture.REGULAR : fp; final var finalFP = fp == null ? FontPosture.REGULAR : fp;
progress.stringBuilder().append(getStartFont(progress)).append(variableName).append(" = new javafx.scene.text.Font(\"").append(name) sb.append(getStartFont()).append(variableName).append(" = new javafx.scene.text.Font(\"").append(name)
.append("\", javafx.scene.text.FontWeight.").append(finalFW.name()).append(", javafx.scene.text.FontPosture.") .append("\", javafx.scene.text.FontWeight.").append(finalFW.name()).append(", javafx.scene.text.FontPosture.")
.append(finalFP.name()).append(", ").append(size).append(");\n"); .append(finalFP.name()).append(", ").append(size).append(");\n");
} }

View File

@@ -1,52 +1,59 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.compatibility.GenerationCompatibility;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import java.util.Objects;
/** /**
* Various helper methods for {@link GeneratorImpl} to handle compatibility with older java versions * Various helper methods for {@link GeneratorImpl} to handle compatibility with older java versions
*/ */
final class GenerationCompatibilityHelper { final class GenerationCompatibilityHelper {
private GenerationCompatibilityHelper() { private final HelperProvider helperProvider;
private final GenerationCompatibility compatibility;
GenerationCompatibilityHelper(final HelperProvider helperProvider, final GenerationCompatibility compatibility) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.compatibility = Objects.requireNonNull(compatibility);
} }
static String getStartVar(final GenerationProgress progress, final ParsedObject parsedObject) throws GenerationException { String getStartVar(final ParsedObject parsedObject) throws GenerationException {
return getStartVar(progress, parsedObject.className() + ReflectionHelper.getGenericTypes(progress, parsedObject)); return getStartVar(parsedObject.className() + helperProvider.getReflectionHelper().getGenericTypes(parsedObject));
} }
static String getStartVar(final GenerationProgress progress, final String className) { String getStartVar(final String className) {
return getStartVar(progress, className, 8); return getStartVar(className, 8);
} }
static String getStartVar(final GenerationProgress progress, final String className, final int indent) { String getStartVar(final String className, final int indent) {
if (progress.request().parameters().compatibility().useVar()) { if (compatibility.useVar()) {
return " ".repeat(indent) + "final var "; return " ".repeat(indent) + "final var ";
} else { } else {
return " ".repeat(indent) + "final " + className + " "; return " ".repeat(indent) + "final " + className + " ";
} }
} }
static String getToList(final GenerationProgress progress) { String getToList() {
return switch (progress.request().parameters().compatibility().listCollector()) { return switch (compatibility.listCollector()) {
case TO_LIST -> ".toList()"; case TO_LIST -> ".toList()";
case COLLECT_TO_UNMODIFIABLE_LIST -> ".collect(java.util.stream.Collectors.toUnmodifiableList())"; case COLLECT_TO_UNMODIFIABLE_LIST -> ".collect(java.util.stream.Collectors.toUnmodifiableList())";
case COLLECT_TO_LIST -> ".collect(java.util.stream.Collectors.toList())"; case COLLECT_TO_LIST -> ".collect(java.util.stream.Collectors.toList())";
}; };
} }
static String getGetFirst(final GenerationProgress progress) { String getGetFirst() {
if (progress.request().parameters().compatibility().useGetFirst()) { if (compatibility.useGetFirst()) {
return ".getFirst()"; return ".getFirst()";
} else { } else {
return ".get(0)"; return ".get(0)";
} }
} }
static String getListOf(final GenerationProgress progress) { String getListOf() {
if (progress.request().parameters().compatibility().useCollectionsOf()) { if (compatibility.useCollectionsOf()) {
return "java.util.List.of("; return "java.util.List.of(";
} else { } else {
return "java.util.Arrays.asList("; return "java.util.Arrays.asList(";

View File

@@ -1,5 +1,6 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.ControllerInfo;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
@@ -10,6 +11,8 @@ import org.apache.logging.log4j.Logger;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static java.util.Objects.requireNonNull;
/** /**
* Various helper methods for {@link GeneratorImpl} * Various helper methods for {@link GeneratorImpl}
*/ */
@@ -28,35 +31,41 @@ final class GenerationHelper {
static final String BINDING_EXPRESSION_PREFIX = "${"; static final String BINDING_EXPRESSION_PREFIX = "${";
static final String BI_DIRECTIONAL_BINDING_PREFIX = "#{"; static final String BI_DIRECTIONAL_BINDING_PREFIX = "#{";
private final HelperProvider helperProvider;
private final ControllerInfo controllerInfo;
private final Map<String, VariableInfo> idToVariableInfo;
private GenerationHelper() { GenerationHelper(final HelperProvider helperProvider, final ControllerInfo controllerInfo, final Map<String, VariableInfo> idToVariableInfo) {
this.helperProvider = requireNonNull(helperProvider);
this.controllerInfo = requireNonNull(controllerInfo);
this.idToVariableInfo = requireNonNull(idToVariableInfo);
} }
/** /**
* Handles the fx:id attribute of an object * Handles the fx:id attribute of an object
* *
* @param progress The generation progress
* @param parsedObject The parsed object * @param parsedObject The parsed object
* @param variableName The variable name * @param variableName The variable name
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void handleId(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void handleId(final ParsedObject parsedObject, final String variableName) throws GenerationException {
final var id = parsedObject.attributes().get(FX_ID); final var id = parsedObject.attributes().get(FX_ID);
if (id != null) { if (id != null) {
final var idValue = id.value(); final var idValue = id.value();
final String className; final String className;
if (progress.request().controllerInfo().fieldInfo(idValue) == null) { if (controllerInfo.fieldInfo(idValue) == null) {
className = parsedObject.className(); className = parsedObject.className();
logger.debug("Not injecting {} because it is not found in controller", idValue); logger.debug("Not injecting {} because it is not found in controller", idValue);
} else { } else {
final var reflectionHelper = helperProvider.getReflectionHelper();
if (ReflectionHelper.isGeneric(ReflectionHelper.getClass(parsedObject.className()))) { if (ReflectionHelper.isGeneric(ReflectionHelper.getClass(parsedObject.className()))) {
className = parsedObject.className() + ReflectionHelper.getGenericTypes(progress, parsedObject); className = parsedObject.className() + reflectionHelper.getGenericTypes(parsedObject);
} else { } else {
className = parsedObject.className(); className = parsedObject.className();
} }
ControllerInjector.injectControllerField(progress, idValue, variableName); helperProvider.getControllerInjector().injectControllerField(idValue, variableName);
} }
progress.idToVariableInfo().put(idValue, new VariableInfo(idValue, parsedObject, variableName, className)); idToVariableInfo.put(idValue, new VariableInfo(idValue, parsedObject, variableName, className));
} }
} }

View File

@@ -64,7 +64,7 @@ public record GenerationProgress(GenerationRequest request, Map<String, Variable
* @param prefix The variable name prefix * @param prefix The variable name prefix
* @return The next available variable name * @return The next available variable name
*/ */
public String getNextVariableName(final String prefix) { String getNextVariableName(final String prefix) {
final var counter = variableNameCounters.computeIfAbsent(prefix, k -> new AtomicInteger(0)); final var counter = variableNameCounters.computeIfAbsent(prefix, k -> new AtomicInteger(0));
return prefix + counter.getAndIncrement(); return prefix + counter.getAndIncrement();
} }

View File

@@ -1,30 +1,37 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.InjectionType;
import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes; import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes;
import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType; import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType;
import java.util.Objects;
/** /**
* Formats the helper methods for the generated code * Formats the helper methods for the generated code
*/ */
public final class HelperMethodsFormatter { public final class HelperMethodsFormatter {
private final HelperProvider helperProvider;
private final InjectionType fieldInjectionType;
private final InjectionType methodInjectionType;
private final StringBuilder sb;
private HelperMethodsFormatter() { HelperMethodsFormatter(final HelperProvider helperProvider, final InjectionType fieldInjectionType, final InjectionType methodInjectionType, final StringBuilder sb) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.fieldInjectionType = Objects.requireNonNull(fieldInjectionType);
this.methodInjectionType = Objects.requireNonNull(methodInjectionType);
this.sb = Objects.requireNonNull(sb);
} }
/** /**
* Formats the helper methods for the given generation progress * Formats the helper methods
*
* @param progress The generation progress
*/ */
public static void formatHelperMethods(final GenerationProgress progress) { public void formatHelperMethods() {
final var parameters = progress.request().parameters(); final var compatibilityHelper = helperProvider.getCompatibilityHelper();
final var methodInjectionType = parameters.methodInjectionType();
final var sb = progress.stringBuilder();
if (methodInjectionType == ControllerMethodsInjectionType.REFLECTION) { if (methodInjectionType == ControllerMethodsInjectionType.REFLECTION) {
final var toList = GenerationCompatibilityHelper.getToList(progress); final var toList = compatibilityHelper.getToList();
final var getFirst = GenerationCompatibilityHelper.getGetFirst(progress); final var getFirst = compatibilityHelper.getGetFirst();
final var startVariableMethodList = GenerationCompatibilityHelper.getStartVar(progress, "java.util.List<java.lang.reflect.Method>", 0); final var startVariableMethodList = compatibilityHelper.getStartVar("java.util.List<java.lang.reflect.Method>", 0);
sb.append(" private <T extends javafx.event.Event> void callEventHandlerMethod(final String methodName, final T event) {\n"); sb.append(" private <T extends javafx.event.Event> void callEventHandlerMethod(final String methodName, final T event) {\n");
sb.append(" try {\n"); sb.append(" try {\n");
sb.append(" final java.lang.reflect.Method method;\n"); sb.append(" final java.lang.reflect.Method method;\n");
@@ -84,10 +91,10 @@ public final class HelperMethodsFormatter {
sb.append(" }\n"); sb.append(" }\n");
sb.append(" }\n"); sb.append(" }\n");
} }
if (parameters.fieldInjectionType() == ControllerFieldInjectionTypes.REFLECTION) { if (fieldInjectionType == ControllerFieldInjectionTypes.REFLECTION) {
sb.append(" private <T> void injectField(final String fieldName, final T object) {\n"); sb.append(" private <T> void injectField(final String fieldName, final T object) {\n");
sb.append(" try {\n"); sb.append(" try {\n");
sb.append(" ").append(GenerationCompatibilityHelper.getStartVar(progress, "java.lang.reflect.Field", 0)).append("field = controller.getClass().getDeclaredField(fieldName);\n"); sb.append(" ").append(compatibilityHelper.getStartVar("java.lang.reflect.Field", 0)).append("field = controller.getClass().getDeclaredField(fieldName);\n");
sb.append(" field.setAccessible(true);\n"); sb.append(" field.setAccessible(true);\n");
sb.append(" field.set(controller, object);\n"); sb.append(" field.set(controller, object);\n");
sb.append(" } catch (final NoSuchFieldException | IllegalAccessException e) {\n"); sb.append(" } catch (final NoSuchFieldException | IllegalAccessException e) {\n");

View File

@@ -0,0 +1,117 @@
package com.github.gtache.fxml.compiler.impl.internal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Provider of helper classes
*/
public class HelperProvider {
private final Map<Class<?>, Object> helpers;
private final GenerationProgress progress;
/**
* Instantiates a new helper provider
* @param progress The generation progress
*/
public HelperProvider(final GenerationProgress progress) {
this.progress = Objects.requireNonNull(progress);
this.helpers = new HashMap<>();
}
ConstructorHelper getConstructorHelper() {
return (ConstructorHelper) helpers.computeIfAbsent(ConstructorHelper.class, c -> new ConstructorHelper(this));
}
ControllerInjector getControllerInjector() {
final var request = progress.request();
final var controllerInfo = request.controllerInfo();
final var parameters = request.parameters();
final var fieldInjectionType = parameters.fieldInjectionType();
final var methodInjectionType = parameters.methodInjectionType();
final var sb = progress.stringBuilder();
final var controllerFactoryPostAction = progress.controllerFactoryPostAction();
return (ControllerInjector) helpers.computeIfAbsent(ControllerInjector.class, c -> new ControllerInjector(controllerInfo, fieldInjectionType, methodInjectionType, sb, controllerFactoryPostAction));
}
FieldSetter getFieldSetter() {
final var fieldInjectionType = progress.request().parameters().fieldInjectionType();
final var sb = progress.stringBuilder();
final var controllerFactoryPostAction = progress.controllerFactoryPostAction();
return (FieldSetter) helpers.computeIfAbsent(FieldSetter.class, c -> new FieldSetter(this, fieldInjectionType, sb, controllerFactoryPostAction));
}
FontFormatter getFontFormatter() {
final var sb = progress.stringBuilder();
return (FontFormatter) helpers.computeIfAbsent(FontFormatter.class, c -> new FontFormatter(this, sb));
}
GenerationCompatibilityHelper getCompatibilityHelper() {
final var compatibility = progress.request().parameters().compatibility();
return (GenerationCompatibilityHelper) helpers.computeIfAbsent(GenerationCompatibilityHelper.class, c -> new GenerationCompatibilityHelper(this, compatibility));
}
GenerationHelper getGenerationHelper() {
final var controllerInfo = progress.request().controllerInfo();
final var idToVariableInfo = progress.idToVariableInfo();
return (GenerationHelper) helpers.computeIfAbsent(GenerationHelper.class, c -> new GenerationHelper(this, controllerInfo, idToVariableInfo));
}
public HelperMethodsFormatter getHelperMethodsFormatter() {
final var parameters = progress.request().parameters();
final var fieldInjectionType = parameters.fieldInjectionType();
final var methodInjectionType = parameters.methodInjectionType();
final var sb = progress.stringBuilder();
return (HelperMethodsFormatter) helpers.computeIfAbsent(HelperMethodsFormatter.class, c -> new HelperMethodsFormatter(this, fieldInjectionType, methodInjectionType, sb));
}
ImageFormatter getImageFormatter() {
return (ImageFormatter) helpers.computeIfAbsent(ImageFormatter.class, c -> new ImageFormatter(this, progress));
}
public InitializationFormatter getInitializationFormatter() {
return (InitializationFormatter) helpers.computeIfAbsent(InitializationFormatter.class, c -> new InitializationFormatter(this, progress));
}
public LoadMethodFormatter getLoadMethodFormatter() {
return (LoadMethodFormatter) helpers.computeIfAbsent(LoadMethodFormatter.class, c -> new LoadMethodFormatter(this, progress));
}
ObjectFormatter getObjectFormatter() {
return (ObjectFormatter) helpers.computeIfAbsent(ObjectFormatter.class, c -> new ObjectFormatter(this, progress));
}
PropertyFormatter getPropertyFormatter() {
return (PropertyFormatter) helpers.computeIfAbsent(PropertyFormatter.class, c -> new PropertyFormatter(this, progress));
}
ReflectionHelper getReflectionHelper() {
final var controllerInfo = progress.request().controllerInfo();
return (ReflectionHelper) helpers.computeIfAbsent(ReflectionHelper.class, c -> new ReflectionHelper(controllerInfo));
}
SceneFormatter getSceneFormatter() {
return (SceneFormatter) helpers.computeIfAbsent(SceneFormatter.class, c -> new SceneFormatter(this, progress));
}
TriangleMeshFormatter getTriangleMeshFormatter() {
final var sb = progress.stringBuilder();
return (TriangleMeshFormatter) helpers.computeIfAbsent(TriangleMeshFormatter.class, c -> new TriangleMeshFormatter(this, sb));
}
URLFormatter getURLFormatter() {
return (URLFormatter) helpers.computeIfAbsent(URLFormatter.class, c -> new URLFormatter(this, progress));
}
ValueFormatter getValueFormatter() {
final var resourceInjectionType = progress.request().parameters().resourceInjectionType();
final var idToVariableInfo = progress.idToVariableInfo();
return (ValueFormatter) helpers.computeIfAbsent(ValueFormatter.class, c -> new ValueFormatter(resourceInjectionType, idToVariableInfo));
}
WebViewFormatter getWebViewFormatter() {
return (WebViewFormatter) helpers.computeIfAbsent(WebViewFormatter.class, c -> new WebViewFormatter(this, progress));
}
}

View File

@@ -4,6 +4,8 @@ import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import java.util.Objects;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes;
@@ -12,24 +14,28 @@ import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.get
*/ */
final class ImageFormatter { final class ImageFormatter {
private ImageFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
ImageFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.progress = Objects.requireNonNull(progress);
} }
static void formatImage(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void formatImage(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) { if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) {
doFormatImage(progress, parsedObject, variableName); doFormatImage(parsedObject, variableName);
} else { } else {
throw new GenerationException("Image cannot have children or properties : " + parsedObject); throw new GenerationException("Image cannot have children or properties : " + parsedObject);
} }
} }
private static void formatInputStream(final GenerationProgress progress, final String url, final double requestedWidth, private void formatInputStream(final String url, final double requestedWidth,
final double requestedHeight, final boolean preserveRatio, final boolean smooth, final String variableName) { final double requestedHeight, final boolean preserveRatio, final boolean smooth, final String variableName) {
final var inputStream = progress.getNextVariableName("inputStream"); final var inputStream = progress.getNextVariableName("inputStream");
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
sb.append(" final javafx.scene.image.Image ").append(variableName).append(";\n"); sb.append(" final javafx.scene.image.Image ").append(variableName).append(";\n");
sb.append(" try (").append(GenerationCompatibilityHelper.getStartVar(progress, "java.io.InputStream", 0)).append(inputStream).append(" = ").append(url).append(".openStream()) {\n"); sb.append(" try (").append(helperProvider.getCompatibilityHelper().getStartVar("java.io.InputStream", 0)).append(inputStream).append(" = ").append(url).append(".openStream()) {\n");
sb.append(" ").append(variableName).append(" = new javafx.scene.image.Image(").append(inputStream); sb.append(" ").append(variableName).append(" = new javafx.scene.image.Image(").append(inputStream);
sb.append(", ").append(requestedWidth).append(", ").append(requestedHeight).append(", ").append(preserveRatio).append(", ").append(smooth).append(");\n"); sb.append(", ").append(requestedWidth).append(", ").append(requestedHeight).append(", ").append(preserveRatio).append(", ").append(smooth).append(");\n");
sb.append(" } catch (final java.io.IOException e) {\n"); sb.append(" } catch (final java.io.IOException e) {\n");
@@ -37,7 +43,7 @@ final class ImageFormatter {
sb.append(" }\n"); sb.append(" }\n");
} }
private static void doFormatImage(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { private void doFormatImage(final ParsedObject parsedObject, final String variableName) throws GenerationException {
final var sortedAttributes = getSortedAttributes(parsedObject); final var sortedAttributes = getSortedAttributes(parsedObject);
String url = null; String url = null;
var requestedWidth = 0.0; var requestedWidth = 0.0;
@@ -50,7 +56,7 @@ final class ImageFormatter {
case FX_ID -> { case FX_ID -> {
//Do nothing //Do nothing
} }
case "url" -> url = URLFormatter.formatURL(progress, property.value()); case "url" -> url = helperProvider.getURLFormatter().formatURL(property.value());
case "requestedWidth" -> requestedWidth = Double.parseDouble(property.value()); case "requestedWidth" -> requestedWidth = Double.parseDouble(property.value());
case "requestedHeight" -> requestedHeight = Double.parseDouble(property.value()); case "requestedHeight" -> requestedHeight = Double.parseDouble(property.value());
case "preserveRatio" -> preserveRatio = Boolean.parseBoolean(property.value()); case "preserveRatio" -> preserveRatio = Boolean.parseBoolean(property.value());
@@ -61,20 +67,21 @@ final class ImageFormatter {
} }
if (progress.request().parameters().useImageInputStreamConstructor()) { if (progress.request().parameters().useImageInputStreamConstructor()) {
formatInputStream(progress, url, requestedWidth, requestedHeight, preserveRatio, smooth, variableName); formatInputStream(url, requestedWidth, requestedHeight, preserveRatio, smooth, variableName);
} else { } else {
formatURL(progress, url, requestedWidth, requestedHeight, preserveRatio, smooth, backgroundLoading, variableName); formatURL(url, requestedWidth, requestedHeight, preserveRatio, smooth, backgroundLoading, variableName);
} }
GenerationHelper.handleId(progress, parsedObject, variableName); helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
} }
private static void formatURL(final GenerationProgress progress, final String url, final double requestedWidth, private void formatURL(final String url, final double requestedWidth,
final double requestedHeight, final boolean preserveRatio, final boolean smooth, final double requestedHeight, final boolean preserveRatio, final boolean smooth,
final boolean backgroundLoading, final String variableName) { final boolean backgroundLoading, final String variableName) {
final var urlString = progress.getNextVariableName("urlStr"); final var urlString = progress.getNextVariableName("urlStr");
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "String")).append(urlString).append(" = ").append(url).append(".toString();\n"); final var compatibilityHelper = helperProvider.getCompatibilityHelper();
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.image.Image")).append(variableName).append(" = new javafx.scene.image.Image(").append(urlString) sb.append(compatibilityHelper.getStartVar("String")).append(urlString).append(" = ").append(url).append(".toString();\n");
sb.append(compatibilityHelper.getStartVar("javafx.scene.image.Image")).append(variableName).append(" = new javafx.scene.image.Image(").append(urlString)
.append(", ").append(requestedWidth).append(", ").append(requestedHeight).append(", ") .append(", ").append(requestedWidth).append(", ").append(requestedHeight).append(", ")
.append(preserveRatio).append(", ").append(smooth).append(", ").append(backgroundLoading).append(");\n"); .append(preserveRatio).append(", ").append(smooth).append(", ").append(backgroundLoading).append(");\n");
} }

View File

@@ -7,32 +7,38 @@ import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes;
import com.github.gtache.fxml.compiler.parsing.ParsedInclude; import com.github.gtache.fxml.compiler.parsing.ParsedInclude;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Utility class to provide the view's constructor and fields * Utility class to provide the view's constructor and fields
*/ */
public final class ConstructorFormatter { public final class InitializationFormatter {
private ConstructorFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
InitializationFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.progress = Objects.requireNonNull(progress);
} }
public static void formatFieldsAndConstructor(final GenerationProgress progress) throws GenerationException { public void formatFieldsAndConstructor() throws GenerationException {
final var className = progress.request().outputClassName(); final var className = progress.request().outputClassName();
final var simpleClassName = className.substring(className.lastIndexOf('.') + 1); final var simpleClassName = className.substring(className.lastIndexOf('.') + 1);
final var mainControllerClass = progress.request().controllerInfo().className(); final var mainControllerClass = progress.request().controllerInfo().className();
final var isFactory = progress.request().parameters().controllerInjectionType() == ControllerInjectionTypes.FACTORY; final var isFactory = progress.request().parameters().controllerInjectionType() == ControllerInjectionTypes.FACTORY;
if (hasDuplicateControllerClass(progress) && !isFactory) { if (hasDuplicateControllerClass() && !isFactory) {
throw new GenerationException("Some controllers in the view tree have the same class ; Factory field injection is required"); throw new GenerationException("Some controllers in the view tree have the same class ; Factory field injection is required");
} }
fillControllers(progress); fillControllers();
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
final var controllerMap = progress.controllerClassToVariable(); final var controllerMap = progress.controllerClassToVariable();
controllerMap.forEach((c, v) -> sb.append(" private final ").append(c).append(" ").append(v).append(isFactory ? "Factory" : "").append(";\n")); controllerMap.forEach((c, v) -> sb.append(" private final ").append(c).append(" ").append(v).append(isFactory ? "Factory" : "").append(";\n"));
final var controllerArg = getVariableName("controller", isFactory); final var controllerArg = getVariableName("controller", isFactory);
final var controllerArgClass = getType(mainControllerClass, isFactory); final var controllerArgClass = getType(mainControllerClass, isFactory);
final var resourceBundleInfo = getResourceBundleInfo(progress); final var resourceBundleInfo = getResourceBundleInfo();
final var resourceBundleType = resourceBundleInfo.type(); final var resourceBundleType = resourceBundleInfo.type();
final var resourceBundleArg = resourceBundleInfo.variableName(); final var resourceBundleArg = resourceBundleInfo.variableName();
if (isFactory) { if (isFactory) {
@@ -70,7 +76,7 @@ public final class ConstructorFormatter {
sb.append(" }\n"); sb.append(" }\n");
} }
private static ResourceBundleInfo getResourceBundleInfo(final GenerationProgress progress) throws GenerationException { private ResourceBundleInfo getResourceBundleInfo() throws GenerationException {
final var injectionType = progress.request().parameters().resourceInjectionType(); final var injectionType = progress.request().parameters().resourceInjectionType();
if (injectionType instanceof final ResourceBundleInjectionTypes types) { if (injectionType instanceof final ResourceBundleInjectionTypes types) {
return switch (types) { return switch (types) {
@@ -109,7 +115,7 @@ public final class ConstructorFormatter {
return variableName + suffix; return variableName + suffix;
} }
private static boolean hasDuplicateControllerClass(final GenerationProgress progress) { private boolean hasDuplicateControllerClass() {
final var set = new HashSet<String>(); final var set = new HashSet<String>();
return hasDuplicateControllerClass(progress.request().sourceInfo(), set); return hasDuplicateControllerClass(progress.request().sourceInfo(), set);
} }
@@ -122,13 +128,13 @@ public final class ConstructorFormatter {
return info.includedSources().stream().anyMatch(s -> hasDuplicateControllerClass(s, controllers)); return info.includedSources().stream().anyMatch(s -> hasDuplicateControllerClass(s, controllers));
} }
private static void fillControllers(final GenerationProgress progress) { private void fillControllers() {
progress.request().sourceInfo().includedSources().forEach(s -> fillControllers(progress, s)); progress.request().sourceInfo().includedSources().forEach(this::fillControllers);
} }
private static void fillControllers(final GenerationProgress progress, final SourceInfo info) { private void fillControllers(final SourceInfo info) {
progress.controllerClassToVariable().put(info.controllerClassName(), progress.getNextVariableName(GenerationHelper.getVariablePrefix(info.controllerClassName()))); progress.controllerClassToVariable().put(info.controllerClassName(), progress.getNextVariableName(GenerationHelper.getVariablePrefix(info.controllerClassName())));
info.includedSources().forEach(s -> fillControllers(progress, s)); info.includedSources().forEach(this::fillControllers);
} }
private static void fillControllers(final SourceInfo info, final Set<? super String> controllers) { private static void fillControllers(final SourceInfo info, final Set<? super String> controllers) {
@@ -136,7 +142,7 @@ public final class ConstructorFormatter {
info.includedSources().forEach(s -> fillControllers(s, controllers)); info.includedSources().forEach(s -> fillControllers(s, controllers));
} }
static String formatSubViewConstructorCall(final GenerationProgress progress, final ParsedInclude include) throws GenerationException { String formatSubViewConstructorCall(final ParsedInclude include) throws GenerationException {
final var request = progress.request(); final var request = progress.request();
final var info = request.sourceInfo(); final var info = request.sourceInfo();
final var subInfo = info.sourceToSourceInfo().get(include.source()); final var subInfo = info.sourceToSourceInfo().get(include.source());
@@ -149,17 +155,17 @@ public final class ConstructorFormatter {
final var subControllers = new HashSet<String>(); final var subControllers = new HashSet<String>();
subInfo.includedSources().forEach(s -> fillControllers(s, subControllers)); subInfo.includedSources().forEach(s -> fillControllers(s, subControllers));
final var arguments = subControllers.stream().sorted().map(c -> getVariableName(progress.controllerClassToVariable().get(c), isFactory)).collect(Collectors.joining(", ")); final var arguments = subControllers.stream().sorted().map(c -> getVariableName(progress.controllerClassToVariable().get(c), isFactory)).collect(Collectors.joining(", "));
final var bundleVariable = subInfo.requiresResourceBundle() ? getBundleVariable(progress, include) : null; final var bundleVariable = subInfo.requiresResourceBundle() ? getBundleVariable(include) : null;
final var argumentList = subControllerVariable + (arguments.isEmpty() ? "" : ", " + arguments) + (bundleVariable == null ? "" : ", " + bundleVariable); final var argumentList = subControllerVariable + (arguments.isEmpty() ? "" : ", " + arguments) + (bundleVariable == null ? "" : ", " + bundleVariable);
final var subViewName = subInfo.generatedClassName(); final var subViewName = subInfo.generatedClassName();
final var variable = progress.getNextVariableName(GenerationHelper.getVariablePrefix(subViewName)); final var variable = progress.getNextVariableName(GenerationHelper.getVariablePrefix(subViewName));
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, subViewName)).append(variable).append(" = new ").append(subViewName).append("(").append(argumentList).append(");\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(subViewName)).append(variable).append(" = new ").append(subViewName).append("(").append(argumentList).append(");\n");
return variable; return variable;
} }
} }
private static String getBundleVariable(final GenerationProgress progress, final ParsedInclude include) throws GenerationException { private String getBundleVariable(final ParsedInclude include) throws GenerationException {
final var info = getResourceBundleInfo(progress); final var info = getResourceBundleInfo();
if (info.type() == null) { if (info.type() == null) {
return null; return null;
} else if (include.resources() == null) { } else if (include.resources() == null) {
@@ -167,21 +173,22 @@ public final class ConstructorFormatter {
} else { } else {
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
if (progress.request().parameters().resourceInjectionType() instanceof final ResourceBundleInjectionTypes types) { if (progress.request().parameters().resourceInjectionType() instanceof final ResourceBundleInjectionTypes types) {
final var compatibilityHelper = helperProvider.getCompatibilityHelper();
return switch (types) { return switch (types) {
case GETTER, GET_BUNDLE -> null; case GETTER, GET_BUNDLE -> null;
case CONSTRUCTOR_NAME -> { case CONSTRUCTOR_NAME -> {
final var bundleVariable = progress.getNextVariableName("resourceBundleName"); final var bundleVariable = progress.getNextVariableName("resourceBundleName");
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "String")).append(bundleVariable).append(" = \"").append(include.resources()).append("\";\n"); sb.append(compatibilityHelper.getStartVar("String")).append(bundleVariable).append(" = \"").append(include.resources()).append("\";\n");
yield bundleVariable; yield bundleVariable;
} }
case CONSTRUCTOR_FUNCTION -> { case CONSTRUCTOR_FUNCTION -> {
final var bundleVariable = progress.getNextVariableName("resourceBundleFunction"); final var bundleVariable = progress.getNextVariableName("resourceBundleFunction");
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.function.Function<String, String>")).append(bundleVariable).append(" = (java.util.function.Function<String, String>) s -> \"").append(include.resources()).append("\";\n"); sb.append(compatibilityHelper.getStartVar("java.util.function.Function<String, String>")).append(bundleVariable).append(" = (java.util.function.Function<String, String>) s -> \"").append(include.resources()).append("\";\n");
yield bundleVariable; yield bundleVariable;
} }
case CONSTRUCTOR -> { case CONSTRUCTOR -> {
final var bundleVariable = progress.getNextVariableName("resourceBundle"); final var bundleVariable = progress.getNextVariableName("resourceBundle");
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.ResourceBundle")).append(bundleVariable).append(" = java.util.ResourceBundle.getBundle(\"").append(include.resources()).append("\");\n"); sb.append(compatibilityHelper.getStartVar("java.util.ResourceBundle")).append(bundleVariable).append(" = java.util.ResourceBundle.getBundle(\"").append(include.resources()).append("\");\n");
yield bundleVariable; yield bundleVariable;
} }
}; };

View File

@@ -5,21 +5,27 @@ import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes;
import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType; import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType;
import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes; import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes;
import static java.util.Objects.requireNonNull;
/** /**
* Formats the load method for the generated code * Formats the load method for the generated code
*/ */
public final class LoadMethodFormatter { public final class LoadMethodFormatter {
private LoadMethodFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
LoadMethodFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = requireNonNull(helperProvider);
this.progress = requireNonNull(progress);
} }
/** /**
* Formats the load method * Formats the load method
* *
* @param progress The generation progress
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
public static void formatLoadMethod(final GenerationProgress progress) throws GenerationException { public void formatLoadMethod() throws GenerationException {
final var request = progress.request(); final var request = progress.request();
final var rootObject = request.rootObject(); final var rootObject = request.rootObject();
final var parameters = progress.request().parameters(); final var parameters = progress.request().parameters();
@@ -36,23 +42,24 @@ public final class LoadMethodFormatter {
sb.append(" throw new IllegalStateException(\"Already loaded\");\n"); sb.append(" throw new IllegalStateException(\"Already loaded\");\n");
sb.append(" }\n"); sb.append(" }\n");
final var resourceBundleInjection = parameters.resourceInjectionType(); final var resourceBundleInjection = parameters.resourceInjectionType();
final var generationCompatibilityHelper = helperProvider.getCompatibilityHelper();
if (resourceBundleInjection == ResourceBundleInjectionTypes.CONSTRUCTOR_NAME) { if (resourceBundleInjection == ResourceBundleInjectionTypes.CONSTRUCTOR_NAME) {
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.ResourceBundle")).append("resourceBundle = java.util.ResourceBundle.getBundle(\"resourceBundleName\");\n"); sb.append(generationCompatibilityHelper.getStartVar("java.util.ResourceBundle")).append("resourceBundle = java.util.ResourceBundle.getBundle(\"resourceBundleName\");\n");
} else if (resourceBundleInjection == ResourceBundleInjectionTypes.GET_BUNDLE && parameters.bundleMap().containsKey(controllerClass)) { } else if (resourceBundleInjection == ResourceBundleInjectionTypes.GET_BUNDLE && parameters.bundleMap().containsKey(controllerClass)) {
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.ResourceBundle")).append("resourceBundle = java.util.ResourceBundle.getBundle(\"").append(parameters.bundleMap().get(controllerClass)).append("\");\n"); sb.append(generationCompatibilityHelper.getStartVar("java.util.ResourceBundle")).append("resourceBundle = java.util.ResourceBundle.getBundle(\"").append(parameters.bundleMap().get(controllerClass)).append("\");\n");
} }
if (controllerInjectionType == ControllerFieldInjectionTypes.FACTORY) { if (controllerInjectionType == ControllerFieldInjectionTypes.FACTORY) {
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.Map<String, Object>")).append("fieldMap = new java.util.HashMap<String, Object>();\n"); sb.append(generationCompatibilityHelper.getStartVar("java.util.Map<String, Object>")).append("fieldMap = new java.util.HashMap<String, Object>();\n");
} }
final var variableName = progress.getNextVariableName(GenerationHelper.getVariablePrefix(rootObject)); final var variableName = progress.getNextVariableName(GenerationHelper.getVariablePrefix(rootObject));
ObjectFormatter.format(progress, rootObject, variableName); helperProvider.getObjectFormatter().format(rootObject, variableName);
if (controllerInjectionType == ControllerFieldInjectionTypes.FACTORY) { if (controllerInjectionType == ControllerFieldInjectionTypes.FACTORY) {
sb.append(" controller = (").append(controllerClass).append(") controllerFactory.create(fieldMap);\n"); sb.append(" controller = (").append(controllerClass).append(") controllerFactory.create(fieldMap);\n");
progress.controllerFactoryPostAction().forEach(sb::append); progress.controllerFactoryPostAction().forEach(sb::append);
} }
if (parameters.methodInjectionType() == ControllerMethodsInjectionType.REFLECTION) { if (parameters.methodInjectionType() == ControllerMethodsInjectionType.REFLECTION) {
sb.append(" try {\n"); sb.append(" try {\n");
sb.append(" ").append(GenerationCompatibilityHelper.getStartVar(progress, "java.lang.reflect.Method", 0)).append("initialize = controller.getClass().getDeclaredMethod(\"initialize\");\n"); sb.append(" ").append(generationCompatibilityHelper.getStartVar("java.lang.reflect.Method", 0)).append("initialize = controller.getClass().getDeclaredMethod(\"initialize\");\n");
sb.append(" initialize.setAccessible(true);\n"); sb.append(" initialize.setAccessible(true);\n");
sb.append(" initialize.invoke(controller);\n"); sb.append(" initialize.invoke(controller);\n");
sb.append(" } catch (final java.lang.reflect.InvocationTargetException | IllegalAccessException e) {\n"); sb.append(" } catch (final java.lang.reflect.InvocationTargetException | IllegalAccessException e) {\n");

View File

@@ -16,6 +16,7 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to format properties * Helper methods for {@link GeneratorImpl} to format properties
@@ -45,103 +46,106 @@ public final class ObjectFormatter {
"java.lang.Double" "java.lang.Double"
); );
private ObjectFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
ObjectFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = requireNonNull(helperProvider);
this.progress = requireNonNull(progress);
} }
/** /**
* Formats an object * Formats an object
* *
* @param progress The generation progress
* @param parsedObject The parsed object to format * @param parsedObject The parsed object to format
* @param variableName The variable name for the object * @param variableName The variable name for the object
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
public static void format(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { public void format(final ParsedObject parsedObject, final String variableName) throws GenerationException {
switch (parsedObject) { switch (parsedObject) {
case final ParsedConstant constant -> formatConstant(progress, constant, variableName); case final ParsedConstant constant -> formatConstant(constant, variableName);
case final ParsedCopy copy -> formatCopy(progress, copy, variableName); case final ParsedCopy copy -> formatCopy(copy, variableName);
case final ParsedDefine define -> formatDefine(progress, define); case final ParsedDefine define -> formatDefine(define);
case final ParsedFactory factory -> formatFactory(progress, factory, variableName); case final ParsedFactory factory -> formatFactory(factory, variableName);
case final ParsedInclude include -> formatInclude(progress, include, variableName); case final ParsedInclude include -> formatInclude(include, variableName);
case final ParsedReference reference -> formatReference(progress, reference, variableName); case final ParsedReference reference -> formatReference(reference, variableName);
case final ParsedValue value -> formatValue(progress, value, variableName); case final ParsedValue value -> formatValue(value, variableName);
case final ParsedText text -> formatText(progress, text, variableName); case final ParsedText text -> formatText(text, variableName);
default -> formatObject(progress, parsedObject, variableName); default -> formatObject(parsedObject, variableName);
} }
} }
/** /**
* Formats a simple text * Formats a simple text
* *
* @param progress The generation progress
* @param text The parsed text * @param text The parsed text
* @param variableName The variable name * @param variableName The variable name
*/ */
private static void formatText(final GenerationProgress progress, final ParsedText text, final String variableName) { private void formatText(final ParsedText text, final String variableName) {
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, "String")).append(variableName).append(" = \"").append(text.text()).append("\";\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar("String")).append(variableName).append(" = \"").append(text.text()).append("\";\n");
} }
/** /**
* Formats a basic object * Formats a basic object
* *
* @param progress The generation progress
* @param parsedObject The parsed object to format * @param parsedObject The parsed object to format
* @param variableName The variable name for the object * @param variableName The variable name for the object
*/ */
private static void formatObject(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { private void formatObject(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (BUILDER_CLASSES.contains(parsedObject.className())) { if (BUILDER_CLASSES.contains(parsedObject.className())) {
formatBuilderObject(progress, parsedObject, variableName); formatBuilderObject(parsedObject, variableName);
} else { } else {
formatNotBuilder(progress, parsedObject, variableName); formatNotBuilder(parsedObject, variableName);
} }
} }
/** /**
* Formats a builder object * Formats a builder object
* *
* @param progress The generation progress
* @param parsedObject The parsed object * @param parsedObject The parsed object
* @param variableName The variable name * @param variableName The variable name
*/ */
private static void formatBuilderObject(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { private void formatBuilderObject(final ParsedObject parsedObject, final String variableName) throws GenerationException {
final var className = parsedObject.className(); final var className = parsedObject.className();
switch (className) { switch (className) {
case "javafx.scene.Scene" -> SceneFormatter.formatScene(progress, parsedObject, variableName); case "javafx.scene.Scene" -> helperProvider.getSceneFormatter().formatScene(parsedObject, variableName);
case "javafx.scene.text.Font" -> FontFormatter.formatFont(progress, parsedObject, variableName); case "javafx.scene.text.Font" -> helperProvider.getFontFormatter().formatFont(parsedObject, variableName);
case "javafx.scene.image.Image" -> ImageFormatter.formatImage(progress, parsedObject, variableName); case "javafx.scene.image.Image" ->
case "java.net.URL" -> URLFormatter.formatURL(progress, parsedObject, variableName); helperProvider.getImageFormatter().formatImage(parsedObject, variableName);
case "java.net.URL" -> helperProvider.getURLFormatter().formatURL(parsedObject, variableName);
case "javafx.scene.shape.TriangleMesh" -> case "javafx.scene.shape.TriangleMesh" ->
TriangleMeshFormatter.formatTriangleMesh(progress, parsedObject, variableName); helperProvider.getTriangleMeshFormatter().formatTriangleMesh(parsedObject, variableName);
case "javafx.scene.web.WebView" -> WebViewFormatter.formatWebView(progress, parsedObject, variableName); case "javafx.scene.web.WebView" ->
helperProvider.getWebViewFormatter().formatWebView(parsedObject, variableName);
default -> throw new IllegalArgumentException("Unknown builder class : " + className); default -> throw new IllegalArgumentException("Unknown builder class : " + className);
} }
} }
private static void formatNotBuilder(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { private void formatNotBuilder(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (isSimpleClass(parsedObject)) { if (isSimpleClass(parsedObject)) {
formatSimpleClass(progress, parsedObject, variableName); formatSimpleClass(parsedObject, variableName);
} else { } else {
formatComplexClass(progress, parsedObject, variableName); formatComplexClass(parsedObject, variableName);
} }
} }
private static void formatSimpleClass(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { private void formatSimpleClass(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (!parsedObject.properties().isEmpty()) { if (!parsedObject.properties().isEmpty()) {
throw new GenerationException("Simple class cannot have properties : " + parsedObject); throw new GenerationException("Simple class cannot have properties : " + parsedObject);
} }
if (parsedObject.attributes().keySet().stream().anyMatch(k -> !k.equals(FX_ID) && !k.equals(VALUE) && !k.equals(FX_VALUE))) { if (parsedObject.attributes().keySet().stream().anyMatch(k -> !k.equals(FX_ID) && !k.equals(VALUE) && !k.equals(FX_VALUE))) {
throw new GenerationException("Invalid attributes for simple class : " + parsedObject); throw new GenerationException("Invalid attributes for simple class : " + parsedObject);
} }
final var value = getSimpleValue(progress, parsedObject); final var value = getSimpleValue(parsedObject);
final var valueStr = ValueFormatter.toString(value, ReflectionHelper.getClass(parsedObject.className())); final var valueStr = helperProvider.getValueFormatter().toString(value, ReflectionHelper.getClass(parsedObject.className()));
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, parsedObject)).append(variableName).append(" = ").append(valueStr).append(";\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(parsedObject)).append(variableName).append(" = ").append(valueStr).append(";\n");
GenerationHelper.handleId(progress, parsedObject, variableName); helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
} }
private static String getSimpleValue(final GenerationProgress progress, final ParsedObject parsedObject) throws GenerationException { private String getSimpleValue(final ParsedObject parsedObject) throws GenerationException {
final var definedChildren = parsedObject.children().stream().filter(ParsedDefine.class::isInstance).toList(); final var definedChildren = parsedObject.children().stream().filter(ParsedDefine.class::isInstance).toList();
for (final var definedChild : definedChildren) { for (final var definedChild : definedChildren) {
formatObject(progress, definedChild, progress.getNextVariableName("define")); formatObject(definedChild, progress.getNextVariableName("define"));
} }
final var notDefinedChildren = parsedObject.children().stream().filter(c -> !(c instanceof ParsedDefine)).toList(); final var notDefinedChildren = parsedObject.children().stream().filter(c -> !(c instanceof ParsedDefine)).toList();
if (parsedObject.attributes().containsKey(FX_VALUE)) { if (parsedObject.attributes().containsKey(FX_VALUE)) {
@@ -182,7 +186,7 @@ public final class ObjectFormatter {
} }
} }
private static boolean isSimpleClass(final ParsedObject object) throws GenerationException { private boolean isSimpleClass(final ParsedObject object) throws GenerationException {
final var className = object.className(); final var className = object.className();
if (SIMPLE_CLASSES.contains(className)) { if (SIMPLE_CLASSES.contains(className)) {
return true; return true;
@@ -192,7 +196,7 @@ public final class ObjectFormatter {
} }
} }
private static void formatComplexClass(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { private void formatComplexClass(final ParsedObject parsedObject, final String variableName) throws GenerationException {
final var clazz = ReflectionHelper.getClass(parsedObject.className()); final var clazz = ReflectionHelper.getClass(parsedObject.className());
final var children = parsedObject.children(); final var children = parsedObject.children();
final var definedChildren = children.stream().filter(ParsedDefine.class::isInstance).toList(); final var definedChildren = children.stream().filter(ParsedDefine.class::isInstance).toList();
@@ -202,7 +206,7 @@ public final class ObjectFormatter {
allPropertyNames.addAll(parsedObject.properties().keySet().stream().map(ParsedProperty::name).collect(Collectors.toSet())); allPropertyNames.addAll(parsedObject.properties().keySet().stream().map(ParsedProperty::name).collect(Collectors.toSet()));
if (!definedChildren.isEmpty()) { if (!definedChildren.isEmpty()) {
for (final var definedChild : definedChildren) { for (final var definedChild : definedChildren) {
format(progress, definedChild, progress.getNextVariableName("define")); format(definedChild, progress.getNextVariableName("define"));
} }
} }
if (!notDefinedChildren.isEmpty()) { if (!notDefinedChildren.isEmpty()) {
@@ -213,31 +217,32 @@ public final class ObjectFormatter {
} }
final var constructorArgs = ConstructorHelper.getMatchingConstructorArgs(constructors, allPropertyNames); final var constructorArgs = ConstructorHelper.getMatchingConstructorArgs(constructors, allPropertyNames);
if (constructorArgs == null) { if (constructorArgs == null) {
formatNoConstructor(progress, parsedObject, variableName, allPropertyNames); formatNoConstructor(parsedObject, variableName, allPropertyNames);
} else { } else {
formatConstructor(progress, parsedObject, variableName, constructorArgs); formatConstructor(parsedObject, variableName, constructorArgs);
} }
} }
private static void formatNoConstructor(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName, final Collection<String> allPropertyNames) throws GenerationException { private void formatNoConstructor(final ParsedObject parsedObject, final String variableName, final Collection<String> allPropertyNames) throws GenerationException {
final var clazz = ReflectionHelper.getClass(parsedObject.className()); final var clazz = ReflectionHelper.getClass(parsedObject.className());
if (allPropertyNames.size() == 1 && allPropertyNames.iterator().next().equals("fx:constant")) { if (allPropertyNames.size() == 1 && allPropertyNames.iterator().next().equals("fx:constant")) {
final var property = parsedObject.attributes().get("fx:constant"); final var property = parsedObject.attributes().get("fx:constant");
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, parsedObject)).append(variableName).append(" = ").append(clazz.getCanonicalName()).append(".").append(property.value()).append(";\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(parsedObject)).append(variableName).append(" = ").append(clazz.getCanonicalName()).append(".").append(property.value()).append(";\n");
} else { } else {
throw new GenerationException("Cannot find constructor for " + clazz.getCanonicalName()); throw new GenerationException("Cannot find constructor for " + clazz.getCanonicalName());
} }
} }
private static void formatConstructor(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName, final ConstructorArgs constructorArgs) throws GenerationException { private void formatConstructor(final ParsedObject parsedObject, final String variableName, final ConstructorArgs constructorArgs) throws GenerationException {
final var args = ConstructorHelper.getListConstructorArgs(constructorArgs, parsedObject); final var reflectionHelper = helperProvider.getReflectionHelper();
final var genericTypes = ReflectionHelper.getGenericTypes(progress, parsedObject); final var args = helperProvider.getConstructorHelper().getListConstructorArgs(constructorArgs, parsedObject);
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, parsedObject)).append(variableName).append(NEW_ASSIGN).append(parsedObject.className()) final var genericTypes = reflectionHelper.getGenericTypes(parsedObject);
progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(parsedObject)).append(variableName).append(NEW_ASSIGN).append(parsedObject.className())
.append(genericTypes).append("(").append(String.join(", ", args)).append(");\n"); .append(genericTypes).append("(").append(String.join(", ", args)).append(");\n");
final var sortedAttributes = getSortedAttributes(parsedObject); final var sortedAttributes = getSortedAttributes(parsedObject);
for (final var value : sortedAttributes) { for (final var value : sortedAttributes) {
if (!constructorArgs.namedArgs().containsKey(value.name())) { if (!constructorArgs.namedArgs().containsKey(value.name())) {
PropertyFormatter.formatProperty(progress, value, parsedObject, variableName); helperProvider.getPropertyFormatter().formatProperty(value, parsedObject, variableName);
} }
} }
final var sortedProperties = parsedObject.properties().entrySet().stream().sorted(Comparator.comparing(e -> e.getKey().name())).toList(); final var sortedProperties = parsedObject.properties().entrySet().stream().sorted(Comparator.comparing(e -> e.getKey().name())).toList();
@@ -245,7 +250,7 @@ public final class ObjectFormatter {
if (!constructorArgs.namedArgs().containsKey(e.getKey().name())) { if (!constructorArgs.namedArgs().containsKey(e.getKey().name())) {
final var p = e.getKey(); final var p = e.getKey();
final var o = e.getValue(); final var o = e.getValue();
formatChild(progress, parsedObject, p, o, variableName); formatChild(parsedObject, p, o, variableName);
} }
} }
final var notDefinedChildren = parsedObject.children().stream().filter(c -> !(c instanceof ParsedDefine)).toList(); final var notDefinedChildren = parsedObject.children().stream().filter(c -> !(c instanceof ParsedDefine)).toList();
@@ -253,7 +258,7 @@ public final class ObjectFormatter {
final var defaultProperty = ReflectionHelper.getDefaultProperty(parsedObject.className()); final var defaultProperty = ReflectionHelper.getDefaultProperty(parsedObject.className());
if (!constructorArgs.namedArgs().containsKey(defaultProperty)) { if (!constructorArgs.namedArgs().containsKey(defaultProperty)) {
final var property = new ParsedPropertyImpl(defaultProperty, null, null); final var property = new ParsedPropertyImpl(defaultProperty, null, null);
formatChild(progress, parsedObject, property, notDefinedChildren, variableName); formatChild(parsedObject, property, notDefinedChildren, variableName);
} }
} }
} }
@@ -261,28 +266,27 @@ public final class ObjectFormatter {
/** /**
* Formats an include object * Formats an include object
* *
* @param progress The generation progress
* @param include The include object * @param include The include object
* @param subNodeName The sub node name * @param subNodeName The sub node name
*/ */
private static void formatInclude(final GenerationProgress progress, final ParsedInclude include, final String subNodeName) throws GenerationException { private void formatInclude(final ParsedInclude include, final String subNodeName) throws GenerationException {
final var subViewVariable = progress.getNextVariableName("view"); final var subViewVariable = progress.getNextVariableName("view");
final var viewVariable = ConstructorFormatter.formatSubViewConstructorCall(progress, include); final var viewVariable = helperProvider.getInitializationFormatter().formatSubViewConstructorCall(include);
progress.stringBuilder().append(" final javafx.scene.Parent ").append(subNodeName).append(" = ").append(viewVariable).append(".load();\n"); progress.stringBuilder().append(" final javafx.scene.Parent ").append(subNodeName).append(" = ").append(viewVariable).append(".load();\n");
injectSubController(progress, include, subViewVariable); injectSubController(include, subViewVariable);
} }
private static void injectSubController(final GenerationProgress progress, final ParsedInclude include, final String subViewVariable) throws GenerationException { private void injectSubController(final ParsedInclude include, final String subViewVariable) throws GenerationException {
final var id = include.controllerId(); final var id = include.controllerId();
if (id != null) { if (id != null) {
final var subControllerVariable = progress.getNextVariableName("controller"); final var subControllerVariable = progress.getNextVariableName("controller");
final var controllerClass = progress.request().sourceInfo().sourceToSourceInfo().get(include.source()).controllerClassName(); final var controllerClass = progress.request().sourceInfo().sourceToSourceInfo().get(include.source()).controllerClassName();
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, controllerClass)).append(subControllerVariable).append(" = ").append(subViewVariable).append(".controller();\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(controllerClass)).append(subControllerVariable).append(" = ").append(subViewVariable).append(".controller();\n");
progress.idToVariableInfo().put(id, new VariableInfo(id, include, subControllerVariable, controllerClass)); progress.idToVariableInfo().put(id, new VariableInfo(id, include, subControllerVariable, controllerClass));
if (progress.request().controllerInfo().fieldInfo(id) == null) { if (progress.request().controllerInfo().fieldInfo(id) == null) {
logger.debug("Not injecting {} because it is not found in controller", id); logger.debug("Not injecting {} because it is not found in controller", id);
} else { } else {
ControllerInjector.injectControllerField(progress, id, subControllerVariable); helperProvider.getControllerInjector().injectControllerField(id, subControllerVariable);
} }
} }
} }
@@ -290,93 +294,88 @@ public final class ObjectFormatter {
/** /**
* Formats a fx:define * Formats a fx:define
* *
* @param progress The generation progress
* @param define The parsed define * @param define The parsed define
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static void formatDefine(final GenerationProgress progress, final ParsedObject define) throws GenerationException { private void formatDefine(final ParsedObject define) throws GenerationException {
for (final var child : define.children()) { for (final var child : define.children()) {
format(progress, child, progress.getNextVariableName("definedObject")); format(child, progress.getNextVariableName("definedObject"));
} }
} }
/** /**
* Formats a fx:reference * Formats a fx:reference
* *
* @param progress The generation progress
* @param reference The parsed reference * @param reference The parsed reference
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static void formatReference(final GenerationProgress progress, final ParsedReference reference, final String variableName) throws GenerationException { private void formatReference(final ParsedReference reference, final String variableName) throws GenerationException {
final var id = reference.source(); final var id = reference.source();
final var variableInfo = progress.idToVariableInfo().get(id); final var variableInfo = progress.idToVariableInfo().get(id);
if (variableInfo == null) { if (variableInfo == null) {
throw new GenerationException("Unknown id : " + id); throw new GenerationException("Unknown id : " + id);
} }
final var referenceName = variableInfo.variableName(); final var referenceName = variableInfo.variableName();
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, variableInfo.className())).append(variableName).append(" = ").append(referenceName).append(";\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(variableInfo.className())).append(variableName).append(" = ").append(referenceName).append(";\n");
} }
/** /**
* Formats a fx:copy * Formats a fx:copy
* *
* @param progress The generation progress
* @param copy The parsed copy * @param copy The parsed copy
* @param variableName The variable name * @param variableName The variable name
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static void formatCopy(final GenerationProgress progress, final ParsedCopy copy, final String variableName) throws GenerationException { private void formatCopy(final ParsedCopy copy, final String variableName) throws GenerationException {
final var id = copy.source(); final var id = copy.source();
final var variableInfo = progress.idToVariableInfo().get(id); final var variableInfo = progress.idToVariableInfo().get(id);
if (variableInfo == null) { if (variableInfo == null) {
throw new GenerationException("Unknown id : " + id); throw new GenerationException("Unknown id : " + id);
} }
final var copyVariable = variableInfo.variableName(); final var copyVariable = variableInfo.variableName();
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, variableInfo.className())).append(variableName).append(NEW_ASSIGN).append(variableInfo.className()).append("(").append(copyVariable).append(");\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(variableInfo.className())).append(variableName).append(NEW_ASSIGN).append(variableInfo.className()).append("(").append(copyVariable).append(");\n");
} }
/** /**
* Formats a constant object * Formats a constant object
* *
* @param progress The generation progress
* @param constant The constant * @param constant The constant
* @param variableName The variable name * @param variableName The variable name
*/ */
private static void formatConstant(final GenerationProgress progress, final ParsedConstant constant, final String variableName) { private void formatConstant(final ParsedConstant constant, final String variableName) throws GenerationException {
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, constant.className())).append(variableName).append(" = ").append(constant.className()).append(".").append(constant.constant()).append(";\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(constant.className())).append(variableName).append(" = ").append(constant.className()).append(".").append(constant.constant()).append(";\n");
} }
/** /**
* Formats a value object * Formats a value object
* *
* @param progress The generation progress
* @param value The value * @param value The value
* @param variableName The variable name * @param variableName The variable name
*/ */
private static void formatValue(final GenerationProgress progress, final ParsedValue value, final String variableName) { private void formatValue(final ParsedValue value, final String variableName) throws GenerationException {
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, value.className())).append(variableName).append(" = ").append(value.className()).append(".valueOf(\"").append(value.value()).append("\");\n"); progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(value.className())).append(variableName).append(" = ").append(value.className()).append(".valueOf(\"").append(value.value()).append("\");\n");
} }
/** /**
* Formats a factory object * Formats a factory object
* *
* @param progress The generation progress
* @param factory The factory * @param factory The factory
* @param variableName The variable name * @param variableName The variable name
*/ */
private static void formatFactory(final GenerationProgress progress, final ParsedFactory factory, final String variableName) throws GenerationException { private void formatFactory(final ParsedFactory factory, final String variableName) throws GenerationException {
final var variables = new ArrayList<String>(); final var variables = new ArrayList<String>();
for (final var argument : factory.arguments()) { for (final var argument : factory.arguments()) {
final var argumentVariable = progress.getNextVariableName("arg"); final var argumentVariable = progress.getNextVariableName("arg");
variables.add(argumentVariable); variables.add(argumentVariable);
format(progress, argument, argumentVariable); format(argument, argumentVariable);
} }
final var compatibilityHelper = helperProvider.getCompatibilityHelper();
if (progress.request().parameters().compatibility().useVar()) { if (progress.request().parameters().compatibility().useVar()) {
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, factory.className())).append(variableName).append(" = ").append(factory.className()) progress.stringBuilder().append(compatibilityHelper.getStartVar(factory.className())).append(variableName).append(" = ").append(factory.className())
.append(".").append(factory.factory()).append("(").append(String.join(", ", variables)).append(");\n"); .append(".").append(factory.factory()).append("(").append(String.join(", ", variables)).append(");\n");
} else { } else {
final var returnType = ReflectionHelper.getReturnType(factory.className(), factory.factory()); final var returnType = ReflectionHelper.getReturnType(factory.className(), factory.factory());
progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, returnType)).append(variableName).append(" = ").append(factory.className()) progress.stringBuilder().append(compatibilityHelper.getStartVar(returnType)).append(variableName).append(" = ").append(factory.className())
.append(".").append(factory.factory()).append("(").append(String.join(", ", variables)).append(");\n"); .append(".").append(factory.factory()).append("(").append(String.join(", ", variables)).append(");\n");
} }
} }
@@ -384,45 +383,43 @@ public final class ObjectFormatter {
/** /**
* Formats the children objects of a property * Formats the children objects of a property
* *
* @param progress The generation progress
* @param parent The parent object * @param parent The parent object
* @param property The parent property * @param property The parent property
* @param objects The child objects * @param objects The child objects
* @param parentVariable The parent object variable * @param parentVariable The parent object variable
*/ */
private static void formatChild(final GenerationProgress progress, final ParsedObject parent, final ParsedProperty property, private void formatChild(final ParsedObject parent, final ParsedProperty property,
final Iterable<? extends ParsedObject> objects, final String parentVariable) throws GenerationException { final Iterable<? extends ParsedObject> objects, final String parentVariable) throws GenerationException {
final var propertyName = property.name(); final var propertyName = property.name();
final var variables = new ArrayList<String>(); final var variables = new ArrayList<String>();
for (final var object : objects) { for (final var object : objects) {
final var vn = progress.getNextVariableName(GenerationHelper.getVariablePrefix(object)); final var vn = progress.getNextVariableName(getVariablePrefix(object));
format(progress, object, vn); format(object, vn);
if (!(object instanceof ParsedDefine)) { if (!(object instanceof ParsedDefine)) {
variables.add(vn); variables.add(vn);
} }
} }
if (variables.size() > 1) { if (variables.size() > 1) {
formatMultipleChildren(progress, variables, propertyName, parent, parentVariable); formatMultipleChildren(variables, propertyName, parent, parentVariable);
} else if (variables.size() == 1) { } else if (variables.size() == 1) {
final var vn = variables.getFirst(); final var vn = variables.getFirst();
formatSingleChild(progress, vn, property, parent, parentVariable); formatSingleChild(vn, property, parent, parentVariable);
} }
} }
/** /**
* Formats children objects given that they are more than one * Formats children objects given that they are more than one
* *
* @param progress The generation progress
* @param variables The children variables * @param variables The children variables
* @param propertyName The property name * @param propertyName The property name
* @param parent The parent object * @param parent The parent object
* @param parentVariable The parent object variable * @param parentVariable The parent object variable
*/ */
private static void formatMultipleChildren(final GenerationProgress progress, final Iterable<String> variables, final String propertyName, final ParsedObject parent, private void formatMultipleChildren(final Iterable<String> variables, final String propertyName, final ParsedObject parent,
final String parentVariable) throws GenerationException { final String parentVariable) throws GenerationException {
final var getMethod = GenerationHelper.getGetMethod(propertyName); final var getMethod = getGetMethod(propertyName);
if (ReflectionHelper.hasMethod(ReflectionHelper.getClass(parent.className()), getMethod)) { if (ReflectionHelper.hasMethod(ReflectionHelper.getClass(parent.className()), getMethod)) {
progress.stringBuilder().append(" ").append(parentVariable).append(".").append(getMethod).append("().addAll(").append(GenerationCompatibilityHelper.getListOf(progress)).append(String.join(", ", variables)).append("));\n"); progress.stringBuilder().append(" ").append(parentVariable).append(".").append(getMethod).append("().addAll(").append(helperProvider.getCompatibilityHelper().getListOf()).append(String.join(", ", variables)).append("));\n");
} else { } else {
throw getCannotSetException(propertyName, parent.className()); throw getCannotSetException(propertyName, parent.className());
} }
@@ -431,42 +428,40 @@ public final class ObjectFormatter {
/** /**
* Formats a single child object * Formats a single child object
* *
* @param progress The generation progress
* @param variableName The child's variable name * @param variableName The child's variable name
* @param property The parent property * @param property The parent property
* @param parent The parent object * @param parent The parent object
* @param parentVariable The parent object variable * @param parentVariable The parent object variable
*/ */
private static void formatSingleChild(final GenerationProgress progress, final String variableName, final ParsedProperty property, final ParsedObject parent, private void formatSingleChild(final String variableName, final ParsedProperty property, final ParsedObject parent,
final String parentVariable) throws GenerationException { final String parentVariable) throws GenerationException {
if (property.sourceType() == null) { if (property.sourceType() == null) {
formatSingleChildInstance(progress, variableName, property, parent, parentVariable); formatSingleChildInstance(variableName, property, parent, parentVariable);
} else { } else {
formatSingleChildStatic(progress, variableName, property, parentVariable); formatSingleChildStatic(variableName, property, parentVariable);
} }
} }
/** /**
* Formats a single child object using an instance method on the parent object * Formats a single child object using an instance method on the parent object
* *
* @param progress The generation progress
* @param variableName The child's variable name * @param variableName The child's variable name
* @param property The parent property * @param property The parent property
* @param parent The parent object * @param parent The parent object
* @param parentVariable The parent object variable * @param parentVariable The parent object variable
*/ */
private static void formatSingleChildInstance(final GenerationProgress progress, final String variableName, private void formatSingleChildInstance(final String variableName,
final ParsedProperty property, final ParsedObject parent, final ParsedProperty property, final ParsedObject parent,
final String parentVariable) throws GenerationException { final String parentVariable) throws GenerationException {
final var setMethod = GenerationHelper.getSetMethod(property); final var setMethod = getSetMethod(property);
final var getMethod = GenerationHelper.getGetMethod(property); final var getMethod = getGetMethod(property);
final var parentClass = ReflectionHelper.getClass(parent.className()); final var parentClass = ReflectionHelper.getClass(parent.className());
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
if (ReflectionHelper.hasMethod(parentClass, setMethod)) { if (ReflectionHelper.hasMethod(parentClass, setMethod)) {
sb.append(" ").append(parentVariable).append(".").append(setMethod).append("(").append(variableName).append(");\n"); sb.append(" ").append(parentVariable).append(".").append(setMethod).append("(").append(variableName).append(");\n");
} else if (ReflectionHelper.hasMethod(parentClass, getMethod)) { } else if (ReflectionHelper.hasMethod(parentClass, getMethod)) {
//Probably a list method that has only one element //Probably a list method that has only one element
sb.append(" ").append(parentVariable).append(".").append(getMethod).append("().addAll(").append(GenerationCompatibilityHelper.getListOf(progress)).append(variableName).append("));\n"); sb.append(" ").append(parentVariable).append(".").append(getMethod).append("().addAll(").append(helperProvider.getCompatibilityHelper().getListOf()).append(variableName).append("));\n");
} else { } else {
throw getCannotSetException(property.name(), parent.className()); throw getCannotSetException(property.name(), parent.className());
} }
@@ -475,14 +470,13 @@ public final class ObjectFormatter {
/** /**
* Formats a child object using a static method * Formats a child object using a static method
* *
* @param progress The generation progress
* @param variableName The child's variable name * @param variableName The child's variable name
* @param property The parent property * @param property The parent property
* @param parentVariable The parent variable * @param parentVariable The parent variable
*/ */
private static void formatSingleChildStatic(final GenerationProgress progress, final String variableName, private void formatSingleChildStatic(final String variableName,
final ParsedProperty property, final String parentVariable) throws GenerationException { final ParsedProperty property, final String parentVariable) throws GenerationException {
final var setMethod = GenerationHelper.getSetMethod(property); final var setMethod = getSetMethod(property);
if (ReflectionHelper.hasStaticMethod(ReflectionHelper.getClass(property.sourceType()), setMethod)) { if (ReflectionHelper.hasStaticMethod(ReflectionHelper.getClass(property.sourceType()), setMethod)) {
progress.stringBuilder().append(" ").append(property.sourceType()).append(".").append(setMethod) progress.stringBuilder().append(" ").append(property.sourceType()).append(".").append(setMethod)
.append("(").append(parentVariable).append(", ").append(variableName).append(");\n"); .append("(").append(parentVariable).append(", ").append(variableName).append(");\n");

View File

@@ -12,107 +12,112 @@ import java.util.Objects;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.RESOURCE_KEY_PREFIX; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.RESOURCE_KEY_PREFIX;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to format properties * Helper methods for {@link GeneratorImpl} to format properties
*/ */
final class PropertyFormatter { final class PropertyFormatter {
private PropertyFormatter() {
private final HelperProvider helperProvider;
private final GenerationProgress progress;
PropertyFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = requireNonNull(helperProvider);
this.progress = requireNonNull(progress);
} }
/** /**
* Formats a property * Formats a property
* *
* @param progress The generation progress
* @param property The property to format * @param property The property to format
* @param parent The property's parent object * @param parent The property's parent object
* @param parentVariable The parent variable * @param parentVariable The parent variable
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void formatProperty(final GenerationProgress progress, final ParsedProperty property, final ParsedObject parent, final String parentVariable) throws GenerationException { void formatProperty(final ParsedProperty property, final ParsedObject parent, final String parentVariable) throws GenerationException {
final var propertyName = property.name(); final var propertyName = property.name();
if (propertyName.equals(FX_ID)) { if (propertyName.equals(FX_ID)) {
GenerationHelper.handleId(progress, parent, parentVariable); helperProvider.getGenerationHelper().handleId(parent, parentVariable);
} else if (propertyName.equals("fx:controller")) { } else if (propertyName.equals("fx:controller")) {
checkDuplicateController(progress, parent); checkDuplicateController(parent);
} else if (Objects.equals(property.sourceType(), EventHandler.class.getName())) { } else if (Objects.equals(property.sourceType(), EventHandler.class.getName())) {
handleEventHandler(progress, property, parentVariable); handleEventHandler(property, parentVariable);
} else if (property.sourceType() != null) { } else if (property.sourceType() != null) {
handleStaticProperty(progress, property, parentVariable, propertyName); handleStaticProperty(property, parentVariable, propertyName);
} else { } else {
handleProperty(progress, property, parent, parentVariable); handleProperty(property, parent, parentVariable);
} }
} }
private static void checkDuplicateController(final GenerationProgress progress, final ParsedObject parent) throws GenerationException { private void checkDuplicateController(final ParsedObject parent) throws GenerationException {
if (parent != progress.request().rootObject()) { if (parent != progress.request().rootObject()) {
throw new GenerationException("Invalid nested controller"); throw new GenerationException("Invalid nested controller");
} }
} }
private static void handleEventHandler(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { private void handleEventHandler(final ParsedProperty property, final String parentVariable) throws GenerationException {
if (property.value().startsWith("#")) { if (property.value().startsWith("#")) {
ControllerInjector.injectEventHandlerControllerMethod(progress, property, parentVariable); helperProvider.getControllerInjector().injectEventHandlerControllerMethod(property, parentVariable);
} else { } else {
FieldSetter.setEventHandler(progress, property, parentVariable); helperProvider.getFieldSetter().setEventHandler(property, parentVariable);
} }
} }
private static void handleStaticProperty(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String propertyName) throws GenerationException { private void handleStaticProperty(final ParsedProperty property, final String parentVariable, final String propertyName) throws GenerationException {
final var setMethod = GenerationHelper.getSetMethod(propertyName); final var setMethod = GenerationHelper.getSetMethod(propertyName);
final var propertySourceTypeClass = ReflectionHelper.getClass(property.sourceType()); final var propertySourceTypeClass = ReflectionHelper.getClass(property.sourceType());
if (ReflectionHelper.hasStaticMethod(propertySourceTypeClass, setMethod)) { if (ReflectionHelper.hasStaticMethod(propertySourceTypeClass, setMethod)) {
final var method = ReflectionHelper.getStaticMethod(propertySourceTypeClass, setMethod); final var method = ReflectionHelper.getStaticMethod(propertySourceTypeClass, setMethod);
final var parameterType = method.getParameterTypes()[1]; final var parameterType = method.getParameterTypes()[1];
final var arg = ValueFormatter.getArg(progress, property.value(), parameterType); final var arg = helperProvider.getValueFormatter().getArg(property.value(), parameterType);
setLaterIfNeeded(progress, property, parameterType, " " + property.sourceType() + "." + setMethod + "(" + parentVariable + ", " + arg + ");\n"); setLaterIfNeeded(property, parameterType, " " + property.sourceType() + "." + setMethod + "(" + parentVariable + ", " + arg + ");\n");
} else { } else {
throw new GenerationException("Cannot set " + propertyName + " on " + property.sourceType()); throw new GenerationException("Cannot set " + propertyName + " on " + property.sourceType());
} }
} }
private static void handleProperty(final GenerationProgress progress, final ParsedProperty property, final ParsedObject parent, final String parentVariable) throws GenerationException { private void handleProperty(final ParsedProperty property, final ParsedObject parent, final String parentVariable) throws GenerationException {
final var propertyName = property.name(); final var propertyName = property.name();
final var setMethod = GenerationHelper.getSetMethod(propertyName); final var setMethod = GenerationHelper.getSetMethod(propertyName);
final var getMethod = GenerationHelper.getGetMethod(propertyName); final var getMethod = GenerationHelper.getGetMethod(propertyName);
final var parentClass = ReflectionHelper.getClass(parent.className()); final var parentClass = ReflectionHelper.getClass(parent.className());
if (ReflectionHelper.hasMethod(parentClass, setMethod)) { if (ReflectionHelper.hasMethod(parentClass, setMethod)) {
handleSetProperty(progress, property, parentClass, parentVariable); handleSetProperty(property, parentClass, parentVariable);
} else if (ReflectionHelper.hasMethod(parentClass, getMethod)) { } else if (ReflectionHelper.hasMethod(parentClass, getMethod)) {
handleGetProperty(progress, property, parentClass, parentVariable); handleGetProperty(property, parentClass, parentVariable);
} else { } else {
throw new GenerationException("Cannot set " + propertyName + " on " + parent.className()); throw new GenerationException("Cannot set " + propertyName + " on " + parent.className());
} }
} }
private static void handleSetProperty(final GenerationProgress progress, final ParsedProperty property, final Class<?> parentClass, final String parentVariable) throws GenerationException { private void handleSetProperty(final ParsedProperty property, final Class<?> parentClass, final String parentVariable) throws GenerationException {
final var setMethod = GenerationHelper.getSetMethod(property.name()); final var setMethod = GenerationHelper.getSetMethod(property.name());
final var method = ReflectionHelper.getMethod(parentClass, setMethod); final var method = ReflectionHelper.getMethod(parentClass, setMethod);
final var parameterType = method.getParameterTypes()[0]; final var parameterType = method.getParameterTypes()[0];
final var arg = ValueFormatter.getArg(progress, property.value(), parameterType); final var arg = helperProvider.getValueFormatter().getArg(property.value(), parameterType);
setLaterIfNeeded(progress, property, parameterType, " " + parentVariable + "." + setMethod + "(" + arg + ");\n"); setLaterIfNeeded(property, parameterType, " " + parentVariable + "." + setMethod + "(" + arg + ");\n");
} }
private static void handleGetProperty(final GenerationProgress progress, final ParsedProperty property, final Class<?> parentClass, final String parentVariable) throws GenerationException { private void handleGetProperty(final ParsedProperty property, final Class<?> parentClass, final String parentVariable) throws GenerationException {
final var getMethod = GenerationHelper.getGetMethod(property.name()); final var getMethod = GenerationHelper.getGetMethod(property.name());
final var method = ReflectionHelper.getMethod(parentClass, getMethod); final var method = ReflectionHelper.getMethod(parentClass, getMethod);
final var returnType = method.getReturnType(); final var returnType = method.getReturnType();
if (ReflectionHelper.hasMethod(returnType, "addAll")) { if (ReflectionHelper.hasMethod(returnType, "addAll")) {
final var arg = ValueFormatter.getArg(progress, property.value(), String.class); final var arg = helperProvider.getValueFormatter().getArg(property.value(), String.class);
setLaterIfNeeded(progress, property, String.class, " " + parentVariable + "." + getMethod + "().addAll(" + GenerationCompatibilityHelper.getListOf(progress) + arg + "));\n"); setLaterIfNeeded(property, String.class, " " + parentVariable + "." + getMethod + "().addAll(" + helperProvider.getCompatibilityHelper().getListOf() + arg + "));\n");
} }
} }
/** /**
* Saves the text to set after constructor creation if factory injection is used * Saves the text to set after constructor creation if factory injection is used
* *
* @param progress The generation progress
* @param property The property * @param property The property
* @param type The type * @param type The type
* @param arg The argument * @param arg The argument
*/ */
private static void setLaterIfNeeded(final GenerationProgress progress, final ParsedProperty property, final Class<?> type, final String arg) { private void setLaterIfNeeded(final ParsedProperty property, final Class<?> type, final String arg) {
final var parameters = progress.request().parameters(); final var parameters = progress.request().parameters();
if (type == String.class && property.value().startsWith(RESOURCE_KEY_PREFIX) && parameters.resourceInjectionType() == ResourceBundleInjectionTypes.GETTER if (type == String.class && property.value().startsWith(RESOURCE_KEY_PREFIX) && parameters.resourceInjectionType() == ResourceBundleInjectionTypes.GETTER
&& parameters.fieldInjectionType() == ControllerFieldInjectionTypes.FACTORY) { && parameters.fieldInjectionType() == ControllerFieldInjectionTypes.FACTORY) {

View File

@@ -1,5 +1,6 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.ControllerInfo;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.GenericTypes; import com.github.gtache.fxml.compiler.GenericTypes;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
@@ -18,6 +19,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -45,8 +47,10 @@ final class ReflectionHelper {
"float", float.class, "float", float.class,
"double", double.class "double", double.class
); );
private final ControllerInfo controllerInfo;
private ReflectionHelper() { ReflectionHelper(final ControllerInfo controllerInfo) {
this.controllerInfo = Objects.requireNonNull(controllerInfo);
} }
/** /**
@@ -323,12 +327,11 @@ final class ReflectionHelper {
/** /**
* Gets the generic types for the given object * Gets the generic types for the given object
* *
* @param progress The generation progress
* @param parsedObject The parsed object * @param parsedObject The parsed object
* @return The generic types * @return The generic types
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static String getGenericTypes(final GenerationProgress progress, final ParsedObject parsedObject) throws GenerationException { String getGenericTypes(final ParsedObject parsedObject) throws GenerationException {
final var clazz = getClass(parsedObject.className()); final var clazz = getClass(parsedObject.className());
if (isGeneric(clazz)) { if (isGeneric(clazz)) {
final var idProperty = parsedObject.attributes().get(FX_ID); final var idProperty = parsedObject.attributes().get(FX_ID);
@@ -337,7 +340,7 @@ final class ReflectionHelper {
return ""; return "";
} else { } else {
final var id = idProperty.value(); final var id = idProperty.value();
final var fieldInfo = progress.request().controllerInfo().fieldInfo(id); final var fieldInfo = controllerInfo.fieldInfo(id);
if (fieldInfo == null) { //Not found if (fieldInfo == null) { //Not found
logger.warn("No field found for generic class {} (id={}) ; Using raw", clazz.getName(), id); logger.warn("No field found for generic class {} (id={}) ; Using raw", clazz.getName(), id);
return ""; return "";

View File

@@ -10,19 +10,25 @@ import java.util.Collection;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to format Scenes * Helper methods for {@link GeneratorImpl} to format Scenes
*/ */
final class SceneFormatter { final class SceneFormatter {
private SceneFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
SceneFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = requireNonNull(helperProvider);
this.progress = requireNonNull(progress);
} }
static void formatScene(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void formatScene(final ParsedObject parsedObject, final String variableName) throws GenerationException {
final var root = findRoot(parsedObject); final var root = findRoot(parsedObject);
final var rootVariableName = progress.getNextVariableName("root"); final var rootVariableName = progress.getNextVariableName("root");
ObjectFormatter.format(progress, root, rootVariableName); helperProvider.getObjectFormatter().format(root, rootVariableName);
final var sortedAttributes = getSortedAttributes(parsedObject); final var sortedAttributes = getSortedAttributes(parsedObject);
double width = -1; double width = -1;
double height = -1; double height = -1;
@@ -41,10 +47,10 @@ final class SceneFormatter {
} }
} }
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.Scene")).append(variableName).append(" = new javafx.scene.Scene(").append(rootVariableName).append(", ") sb.append(helperProvider.getCompatibilityHelper().getStartVar("javafx.scene.Scene")).append(variableName).append(" = new javafx.scene.Scene(").append(rootVariableName).append(", ")
.append(width).append(", ").append(height).append(", javafx.scene.paint.Color.valueOf(\"").append(paint).append("\"));\n"); .append(width).append(", ").append(height).append(", javafx.scene.paint.Color.valueOf(\"").append(paint).append("\"));\n");
addStylesheets(progress, variableName, stylesheets); addStylesheets(variableName, stylesheets);
GenerationHelper.handleId(progress, parsedObject, variableName); helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
} }
private static ParsedObject findRoot(final ParsedObject parsedObject) throws GenerationException { private static ParsedObject findRoot(final ParsedObject parsedObject) throws GenerationException {
@@ -60,13 +66,14 @@ final class SceneFormatter {
} }
} }
private static void addStylesheets(final GenerationProgress progress, final String variableName, final Collection<String> stylesheets) { private void addStylesheets(final String variableName, final Collection<String> stylesheets) throws GenerationException {
if (!stylesheets.isEmpty()) { if (!stylesheets.isEmpty()) {
final var urlVariables = URLFormatter.formatURL(progress, stylesheets); final var urlVariables = helperProvider.getURLFormatter().formatURL(stylesheets);
final var tmpVariable = progress.getNextVariableName("stylesheets"); final var tmpVariable = progress.getNextVariableName("stylesheets");
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.List<String>")).append(tmpVariable).append(" = ").append(variableName).append(".getStyleSheets();\n"); final var compatibilityHelper = helperProvider.getCompatibilityHelper();
sb.append(" ").append(tmpVariable).append(".addAll(").append(GenerationCompatibilityHelper.getListOf(progress)).append(String.join(", ", urlVariables)).append("));\n"); sb.append(compatibilityHelper.getStartVar("java.util.List<String>")).append(tmpVariable).append(" = ").append(variableName).append(".getStyleSheets();\n");
sb.append(" ").append(tmpVariable).append(".addAll(").append(compatibilityHelper.getListOf()).append(String.join(", ", urlVariables)).append("));\n");
} }
} }
} }

View File

@@ -16,16 +16,22 @@ import java.util.stream.Collectors;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to format TriangleMeshes * Helper methods for {@link GeneratorImpl} to format TriangleMeshes
*/ */
final class TriangleMeshFormatter { final class TriangleMeshFormatter {
private TriangleMeshFormatter() { private final HelperProvider helperProvider;
private final StringBuilder sb;
TriangleMeshFormatter(final HelperProvider helperProvider, final StringBuilder sb) {
this.helperProvider = requireNonNull(helperProvider);
this.sb = requireNonNull(sb);
} }
static void formatTriangleMesh(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void formatTriangleMesh(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) { if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) {
final var sortedAttributes = getSortedAttributes(parsedObject); final var sortedAttributes = getSortedAttributes(parsedObject);
final var points = new ArrayList<Float>(); final var points = new ArrayList<Float>();
@@ -63,15 +69,14 @@ final class TriangleMeshFormatter {
default -> throw new GenerationException("Unknown TriangleMesh attribute : " + property.name()); default -> throw new GenerationException("Unknown TriangleMesh attribute : " + property.name());
} }
} }
final var sb = progress.stringBuilder(); sb.append(helperProvider.getCompatibilityHelper().getStartVar("javafx.scene.shape.TriangleMesh")).append(variableName).append(" = new javafx.scene.shape.TriangleMesh();\n");
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.shape.TriangleMesh")).append(variableName).append(" = new javafx.scene.shape.TriangleMesh();\n"); setPoints(variableName, points);
setPoints(progress, variableName, points); setTexCoords(variableName, texCoords);
setTexCoords(progress, variableName, texCoords); setNormals(variableName, normals);
setNormals(progress, variableName, normals); setFaces(variableName, faces);
setFaces(progress, variableName, faces); setFaceSmoothingGroups(variableName, faceSmoothingGroups);
setFaceSmoothingGroups(progress, variableName, faceSmoothingGroups); setVertexFormat(variableName, vertexFormat);
setVertexFormat(progress, variableName, vertexFormat); helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
GenerationHelper.handleId(progress, parsedObject, variableName);
} else { } else {
throw new GenerationException("Image cannot have children or properties : " + parsedObject); throw new GenerationException("Image cannot have children or properties : " + parsedObject);
} }
@@ -87,39 +92,39 @@ final class TriangleMeshFormatter {
} }
} }
private static void setPoints(final GenerationProgress progress, final String variableName, final Collection<Float> points) { private void setPoints(final String variableName, final Collection<Float> points) {
if (!points.isEmpty()) { if (!points.isEmpty()) {
progress.stringBuilder().append(" ").append(variableName).append(".getPoints().setAll(new float[]{").append(formatList(points)).append("});\n"); sb.append(" ").append(variableName).append(".getPoints().setAll(new float[]{").append(formatList(points)).append("});\n");
} }
} }
private static void setTexCoords(final GenerationProgress progress, final String variableName, final Collection<Float> texCoords) { private void setTexCoords(final String variableName, final Collection<Float> texCoords) {
if (!texCoords.isEmpty()) { if (!texCoords.isEmpty()) {
progress.stringBuilder().append(" ").append(variableName).append(".getTexCoords().setAll(new float[]{").append(formatList(texCoords)).append("});\n"); sb.append(" ").append(variableName).append(".getTexCoords().setAll(new float[]{").append(formatList(texCoords)).append("});\n");
} }
} }
private static void setNormals(final GenerationProgress progress, final String variableName, final Collection<Float> normals) { private void setNormals(final String variableName, final Collection<Float> normals) {
if (!normals.isEmpty()) { if (!normals.isEmpty()) {
progress.stringBuilder().append(" ").append(variableName).append(".getNormals().setAll(new float[]{").append(formatList(normals)).append("});\n"); sb.append(" ").append(variableName).append(".getNormals().setAll(new float[]{").append(formatList(normals)).append("});\n");
} }
} }
private static void setFaces(final GenerationProgress progress, final String variableName, final Collection<Integer> faces) { private void setFaces(final String variableName, final Collection<Integer> faces) {
if (!faces.isEmpty()) { if (!faces.isEmpty()) {
progress.stringBuilder().append(" ").append(variableName).append(".getFaces().setAll(new int[]{").append(formatList(faces)).append("});\n"); sb.append(" ").append(variableName).append(".getFaces().setAll(new int[]{").append(formatList(faces)).append("});\n");
} }
} }
private static void setFaceSmoothingGroups(final GenerationProgress progress, final String variableName, final Collection<Integer> faceSmoothingGroups) { private void setFaceSmoothingGroups(final String variableName, final Collection<Integer> faceSmoothingGroups) {
if (!faceSmoothingGroups.isEmpty()) { if (!faceSmoothingGroups.isEmpty()) {
progress.stringBuilder().append(" ").append(variableName).append(".getFaceSmoothingGroups().setAll(new int[]{").append(formatList(faceSmoothingGroups)).append("});\n"); sb.append(" ").append(variableName).append(".getFaceSmoothingGroups().setAll(new int[]{").append(formatList(faceSmoothingGroups)).append("});\n");
} }
} }
private static void setVertexFormat(final GenerationProgress progress, final String variableName, final VertexFormat vertexFormat) { private void setVertexFormat(final String variableName, final VertexFormat vertexFormat) {
if (vertexFormat != null) { if (vertexFormat != null) {
progress.stringBuilder().append(" ").append(variableName).append(".setVertexFormat(javafx.scene.shape.VertexFormat.").append(vertexFormat).append(");\n"); sb.append(" ").append(variableName).append(".setVertexFormat(javafx.scene.shape.VertexFormat.").append(vertexFormat).append(");\n");
} }
} }
@@ -132,5 +137,4 @@ final class TriangleMeshFormatter {
final var split = splitPattern.split(value); final var split = splitPattern.split(value);
return Arrays.stream(split).map(parser).collect(Collectors.toList()); return Arrays.stream(split).map(parser).collect(Collectors.toList());
} }
} }

View File

@@ -4,10 +4,11 @@ import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import java.util.Collection; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*;
import static java.util.Objects.requireNonNull;
/** /**
@@ -15,18 +16,27 @@ import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*;
*/ */
final class URLFormatter { final class URLFormatter {
private URLFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
URLFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = requireNonNull(helperProvider);
this.progress = requireNonNull(progress);
} }
static List<String> formatURL(final GenerationProgress progress, final Collection<String> stylesheets) { List<String> formatURL(final Iterable<String> stylesheets) {
return stylesheets.stream().map(s -> formatURL(progress, s)).toList(); final var ret = new ArrayList<String>();
for (final var styleSheet : stylesheets) {
ret.add(formatURL(styleSheet));
}
return ret;
} }
static String formatURL(final GenerationProgress progress, final String url) { String formatURL(final String url) {
final var variableName = progress.getNextVariableName("url"); final var variableName = progress.getNextVariableName("url");
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
if (url.startsWith(RELATIVE_PATH_PREFIX)) { if (url.startsWith(RELATIVE_PATH_PREFIX)) {
sb.append(getStartURL(progress)).append(variableName).append(" = getClass().getResource(\"").append(url.substring(1)).append("\");\n"); sb.append(getStartURL()).append(variableName).append(" = getClass().getResource(\"").append(url.substring(1)).append("\");\n");
} else { } else {
sb.append(" final java.net.URL ").append(variableName).append(";\n"); sb.append(" final java.net.URL ").append(variableName).append(";\n");
sb.append(" try {\n"); sb.append(" try {\n");
@@ -38,7 +48,7 @@ final class URLFormatter {
return variableName; return variableName;
} }
static void formatURL(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void formatURL(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) { if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) {
final var sortedAttributes = getSortedAttributes(parsedObject); final var sortedAttributes = getSortedAttributes(parsedObject);
String value = null; String value = null;
@@ -51,14 +61,15 @@ final class URLFormatter {
default -> throw new GenerationException("Unknown URL attribute : " + property.name()); default -> throw new GenerationException("Unknown URL attribute : " + property.name());
} }
} }
progress.stringBuilder().append(getStartURL(progress)).append(variableName).append(" = getClass().getResource(\"").append(value).append("\");\n"); //FIXME only relative path (@) ?
handleId(progress, parsedObject, variableName); progress.stringBuilder().append(getStartURL()).append(variableName).append(" = getClass().getResource(\"").append(value).append("\");\n");
helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
} else { } else {
throw new GenerationException("URL cannot have children or properties : " + parsedObject); throw new GenerationException("URL cannot have children or properties : " + parsedObject);
} }
} }
private static String getStartURL(final GenerationProgress progress) { private String getStartURL() {
return GenerationCompatibilityHelper.getStartVar(progress, "java.net.URL"); return helperProvider.getCompatibilityHelper().getStartVar("java.net.URL");
} }
} }

View File

@@ -1,12 +1,15 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.InjectionType;
import com.github.gtache.fxml.compiler.impl.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.GeneratorImpl;
import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes; import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes;
import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to format values * Helper methods for {@link GeneratorImpl} to format values
@@ -17,28 +20,32 @@ final class ValueFormatter {
private static final Pattern DECIMAL_PATTERN = Pattern.compile("\\d+(?:\\.\\d+)?"); private static final Pattern DECIMAL_PATTERN = Pattern.compile("\\d+(?:\\.\\d+)?");
private static final Pattern START_BACKSLASH_PATTERN = Pattern.compile("^\\\\"); private static final Pattern START_BACKSLASH_PATTERN = Pattern.compile("^\\\\");
private ValueFormatter() { private final InjectionType resourceInjectionType;
private final Map<String, VariableInfo> idToVariableInfo;
ValueFormatter(final InjectionType resourceInjectionType, final Map<String, VariableInfo> idToVariableInfo) {
this.resourceInjectionType = requireNonNull(resourceInjectionType);
this.idToVariableInfo = requireNonNull(idToVariableInfo);
} }
/** /**
* Formats an argument to a method * Formats an argument to a method
* *
* @param progress The generation progress
* @param value The value * @param value The value
* @param parameterType The parameter type * @param parameterType The parameter type
* @return The formatted value * @return The formatted value
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static String getArg(final GenerationProgress progress, final String value, final Class<?> parameterType) throws GenerationException { String getArg(final String value, final Class<?> parameterType) throws GenerationException {
if (parameterType == String.class && value.startsWith(RESOURCE_KEY_PREFIX)) { if (parameterType == String.class && value.startsWith(RESOURCE_KEY_PREFIX)) {
return getBundleValue(progress, value.substring(1)); return getBundleValue(value.substring(1));
} else if (value.startsWith(RELATIVE_PATH_PREFIX)) { } else if (value.startsWith(RELATIVE_PATH_PREFIX)) {
final var subpath = value.substring(1); final var subpath = value.substring(1);
return getResourceValue(subpath); return getResourceValue(subpath);
} else if (value.startsWith(BINDING_EXPRESSION_PREFIX)) { } else if (value.startsWith(BINDING_EXPRESSION_PREFIX)) {
throw new UnsupportedOperationException("Not implemented yet"); throw new GenerationException("Not implemented yet");
} else if (value.startsWith(EXPRESSION_PREFIX)) { } else if (value.startsWith(EXPRESSION_PREFIX)) {
final var variable = progress.idToVariableInfo().get(value.substring(1)); final var variable = idToVariableInfo.get(value.substring(1));
if (variable == null) { if (variable == null) {
throw new GenerationException("Unknown variable : " + value.substring(1)); throw new GenerationException("Unknown variable : " + value.substring(1));
} }
@@ -55,21 +62,19 @@ final class ValueFormatter {
/** /**
* Gets the resource bundle value for the given value * Gets the resource bundle value for the given value
* *
* @param progress The generation progress
* @param value The value * @param value The value
* @return The resource bundle value * @return The resource bundle value
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
private static String getBundleValue(final GenerationProgress progress, final String value) throws GenerationException { private String getBundleValue(final String value) throws GenerationException {
final var resourceBundleInjectionType = progress.request().parameters().resourceInjectionType(); if (resourceInjectionType instanceof final ResourceBundleInjectionTypes types) {
if (resourceBundleInjectionType instanceof final ResourceBundleInjectionTypes types) {
return switch (types) { return switch (types) {
case CONSTRUCTOR, GET_BUNDLE, CONSTRUCTOR_NAME -> "resourceBundle.getString(\"" + value + "\")"; case CONSTRUCTOR, GET_BUNDLE, CONSTRUCTOR_NAME -> "resourceBundle.getString(\"" + value + "\")";
case GETTER -> "controller.resources().getString(\"" + value + "\")"; case GETTER -> "controller.resources().getString(\"" + value + "\")";
case CONSTRUCTOR_FUNCTION -> "resourceBundleFunction.apply(\"" + value + "\")"; case CONSTRUCTOR_FUNCTION -> "resourceBundleFunction.apply(\"" + value + "\")";
}; };
} else { } else {
throw new GenerationException("Unknown resource bundle injection type : " + resourceBundleInjectionType); throw new GenerationException("Unknown resource bundle injection type : " + resourceInjectionType);
} }
} }
@@ -81,9 +86,10 @@ final class ValueFormatter {
* @param clazz The value class * @param clazz The value class
* @return The computed string value * @return The computed string value
*/ */
static String toString(final String value, final Class<?> clazz) { String toString(final String value, final Class<?> clazz) {
if (clazz == String.class) { if (clazz == String.class) {
return "\"" + START_BACKSLASH_PATTERN.matcher(value).replaceAll("").replace("\"", "\\\"") + "\""; return "\"" + START_BACKSLASH_PATTERN.matcher(value).replaceAll("").replace("\\", "\\\\")
.replace("\"", "\\\"") + "\"";
} else if (clazz == char.class || clazz == Character.class) { } else if (clazz == char.class || clazz == Character.class) {
return "'" + value + "'"; return "'" + value + "'";
} else if (clazz == boolean.class || clazz == Boolean.class) { } else if (clazz == boolean.class || clazz == Boolean.class) {

View File

@@ -7,88 +7,94 @@ import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.FX_ID;
import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.getSortedAttributes;
import static java.util.Objects.requireNonNull;
/** /**
* Helper methods for {@link GeneratorImpl} to format WebViews * Helper methods for {@link GeneratorImpl} to format WebViews
*/ */
final class WebViewFormatter { final class WebViewFormatter {
private WebViewFormatter() { private final HelperProvider helperProvider;
private final GenerationProgress progress;
WebViewFormatter(final HelperProvider helperProvider, final GenerationProgress progress) {
this.helperProvider = requireNonNull(helperProvider);
this.progress = requireNonNull(progress);
} }
/** /**
* Formats a WebView object * Formats a WebView object
* *
* @param progress The generation progress
* @param parsedObject The parsed object * @param parsedObject The parsed object
* @param variableName The variable name * @param variableName The variable name
* @throws GenerationException if an error occurs * @throws GenerationException if an error occurs
*/ */
static void formatWebView(final GenerationProgress progress, final ParsedObject parsedObject, final String variableName) throws GenerationException { void formatWebView(final ParsedObject parsedObject, final String variableName) throws GenerationException {
if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) { if (parsedObject.children().isEmpty() && parsedObject.properties().isEmpty()) {
final var sortedAttributes = getSortedAttributes(parsedObject); final var sortedAttributes = getSortedAttributes(parsedObject);
final var sb = progress.stringBuilder(); final var sb = progress.stringBuilder();
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.web.WebView")).append(variableName).append(" = new javafx.scene.web.WebView();\n"); final var compatibilityHelper = helperProvider.getCompatibilityHelper();
sb.append(compatibilityHelper.getStartVar("javafx.scene.web.WebView")).append(variableName).append(" = new javafx.scene.web.WebView();\n");
final var engineVariable = progress.getNextVariableName("engine"); final var engineVariable = progress.getNextVariableName("engine");
sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.web.WebEngine")).append(engineVariable).append(" = ").append(variableName).append(".getEngine();\n"); sb.append(compatibilityHelper.getStartVar("javafx.scene.web.WebEngine")).append(engineVariable).append(" = ").append(variableName).append(".getEngine();\n");
for (final var value : sortedAttributes) { for (final var value : sortedAttributes) {
formatAttribute(progress, value, parsedObject, variableName, engineVariable); formatAttribute(value, parsedObject, variableName, engineVariable);
} }
GenerationHelper.handleId(progress, parsedObject, variableName); helperProvider.getGenerationHelper().handleId(parsedObject, variableName);
} else { } else {
throw new GenerationException("WebView cannot have children or properties : " + parsedObject); throw new GenerationException("WebView cannot have children or properties : " + parsedObject);
} }
} }
private static void formatAttribute(final GenerationProgress progress, final ParsedProperty value, final ParsedObject parsedObject, private void formatAttribute(final ParsedProperty value, final ParsedObject parsedObject,
final String variableName, final String engineVariable) throws GenerationException { final String variableName, final String engineVariable) throws GenerationException {
switch (value.name()) { switch (value.name()) {
case FX_ID -> { case FX_ID -> {
//Do nothing //Do nothing
} }
case "confirmHandler" -> injectConfirmHandler(progress, value, engineVariable); case "confirmHandler" -> injectConfirmHandler(value, engineVariable);
case "createPopupHandler" -> injectCreatePopupHandler(progress, value, engineVariable); case "createPopupHandler" -> injectCreatePopupHandler(value, engineVariable);
case "onAlert", "onResized", "onStatusChanged", "onVisibilityChanged" -> case "onAlert", "onResized", "onStatusChanged", "onVisibilityChanged" ->
injectEventHandler(progress, value, engineVariable); injectEventHandler(value, engineVariable);
case "promptHandler" -> injectPromptHandler(progress, value, engineVariable); case "promptHandler" -> injectPromptHandler(value, engineVariable);
case "location" -> injectLocation(progress, value, engineVariable); case "location" -> injectLocation(value, engineVariable);
default -> PropertyFormatter.formatProperty(progress, value, parsedObject, variableName); default -> helperProvider.getPropertyFormatter().formatProperty(value, parsedObject, variableName);
} }
} }
private static void injectConfirmHandler(final GenerationProgress progress, final ParsedProperty value, final String engineVariable) throws GenerationException { private void injectConfirmHandler(final ParsedProperty value, final String engineVariable) throws GenerationException {
if (value.value().startsWith("#")) { if (value.value().startsWith("#")) {
ControllerInjector.injectCallbackControllerMethod(progress, value, engineVariable, "String.class"); helperProvider.getControllerInjector().injectCallbackControllerMethod(value, engineVariable, "String.class");
} else { } else {
setCallback(progress, value, engineVariable); setCallback(value, engineVariable);
} }
} }
private static void injectCreatePopupHandler(final GenerationProgress progress, final ParsedProperty value, final String engineVariable) throws GenerationException { private void injectCreatePopupHandler(final ParsedProperty value, final String engineVariable) throws GenerationException {
if (value.value().startsWith("#")) { if (value.value().startsWith("#")) {
ControllerInjector.injectCallbackControllerMethod(progress, value, engineVariable, "javafx.scene.web.PopupFeatures.class"); helperProvider.getControllerInjector().injectCallbackControllerMethod(value, engineVariable, "javafx.scene.web.PopupFeatures.class");
} else { } else {
setCallback(progress, value, engineVariable); setCallback(value, engineVariable);
} }
} }
private static void injectEventHandler(final GenerationProgress progress, final ParsedProperty value, final String engineVariable) throws GenerationException { private void injectEventHandler(final ParsedProperty value, final String engineVariable) throws GenerationException {
if (value.value().startsWith("#")) { if (value.value().startsWith("#")) {
ControllerInjector.injectEventHandlerControllerMethod(progress, value, engineVariable); helperProvider.getControllerInjector().injectEventHandlerControllerMethod(value, engineVariable);
} else { } else {
FieldSetter.setEventHandler(progress, value, engineVariable); helperProvider.getFieldSetter().setEventHandler(value, engineVariable);
} }
} }
private static void injectPromptHandler(final GenerationProgress progress, final ParsedProperty value, final String engineVariable) throws GenerationException { private void injectPromptHandler(final ParsedProperty value, final String engineVariable) throws GenerationException {
if (value.value().startsWith("#")) { if (value.value().startsWith("#")) {
ControllerInjector.injectCallbackControllerMethod(progress, value, engineVariable, "javafx.scene.web.PromptData.class"); helperProvider.getControllerInjector().injectCallbackControllerMethod(value, engineVariable, "javafx.scene.web.PromptData.class");
} else { } else {
setCallback(progress, value, engineVariable); setCallback(value, engineVariable);
} }
} }
private static void injectLocation(final GenerationProgress progress, final ParsedProperty value, final String engineVariable) { private void injectLocation(final ParsedProperty value, final String engineVariable) {
progress.stringBuilder().append(" ").append(engineVariable).append(".load(\"").append(value.value()).append("\");\n"); progress.stringBuilder().append(" ").append(engineVariable).append(".load(\"").append(value.value()).append("\");\n");
} }
@@ -96,11 +102,10 @@ final class WebViewFormatter {
/** /**
* Sets a callback field * Sets a callback field
* *
* @param progress The generation progress
* @param property The property to inject * @param property The property to inject
* @param parentVariable The parent variable * @param parentVariable The parent variable
*/ */
private static void setCallback(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { private void setCallback(final ParsedProperty property, final String parentVariable) throws GenerationException {
FieldSetter.setField(progress, property, parentVariable, "javafx.util.Callback"); helperProvider.getFieldSetter().setField(property, parentVariable, "javafx.util.Callback");
} }
} }

View File

@@ -2,8 +2,7 @@ package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.ControllerInfo; import com.github.gtache.fxml.compiler.ControllerInfo;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.GenerationParameters; import com.github.gtache.fxml.compiler.InjectionType;
import com.github.gtache.fxml.compiler.GenerationRequest;
import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes; import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes;
import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType; import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType;
import com.github.gtache.fxml.compiler.parsing.ParsedProperty; import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
@@ -18,14 +17,12 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestControllerInjector { class TestControllerInjector {
private final GenerationProgress progress;
private final GenerationRequest request;
private final GenerationParameters parameters;
private final ControllerInfo controllerInfo; private final ControllerInfo controllerInfo;
private final List<String> controllerFactoryPostAction; private final List<String> controllerFactoryPostAction;
private final String id; private final String id;
@@ -34,12 +31,8 @@ class TestControllerInjector {
private final String propertyValue; private final String propertyValue;
private final StringBuilder sb; private final StringBuilder sb;
TestControllerInjector(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, TestControllerInjector(@Mock final ControllerInfo controllerInfo,
@Mock final GenerationParameters parameters, @Mock final ControllerInfo controllerInfo,
@Mock final ParsedProperty property) { @Mock final ParsedProperty property) {
this.progress = Objects.requireNonNull(progress);
this.request = Objects.requireNonNull(request);
this.parameters = Objects.requireNonNull(parameters);
this.controllerInfo = Objects.requireNonNull(controllerInfo); this.controllerInfo = Objects.requireNonNull(controllerInfo);
this.controllerFactoryPostAction = new ArrayList<>(); this.controllerFactoryPostAction = new ArrayList<>();
this.id = "id"; this.id = "id";
@@ -51,19 +44,14 @@ class TestControllerInjector {
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
when(progress.request()).thenReturn(request);
when(request.parameters()).thenReturn(parameters);
when(request.controllerInfo()).thenReturn(controllerInfo);
when(progress.controllerFactoryPostAction()).thenReturn(controllerFactoryPostAction);
when(progress.stringBuilder()).thenReturn(sb);
when(property.name()).thenReturn("name"); when(property.name()).thenReturn("name");
when(property.value()).thenReturn(propertyValue); when(property.value()).thenReturn(propertyValue);
} }
@Test @Test
void testInjectControllerFieldFactory() throws GenerationException { void testInjectControllerFieldFactory() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
ControllerInjector.injectControllerField(progress, id, variable); injector.injectControllerField(id, variable);
final var expected = " fieldMap.put(\"" + id + "\", " + variable + ");\n"; final var expected = " fieldMap.put(\"" + id + "\", " + variable + ");\n";
assertEquals(expected, sb.toString()); assertEquals(expected, sb.toString());
assertTrue(controllerFactoryPostAction.isEmpty()); assertTrue(controllerFactoryPostAction.isEmpty());
@@ -71,8 +59,8 @@ class TestControllerInjector {
@Test @Test
void testInjectControllerFieldAssign() throws GenerationException { void testInjectControllerFieldAssign() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
ControllerInjector.injectControllerField(progress, id, variable); injector.injectControllerField(id, variable);
final var expected = " controller." + id + " = " + variable + ";\n"; final var expected = " controller." + id + " = " + variable + ";\n";
assertEquals(expected, sb.toString()); assertEquals(expected, sb.toString());
assertTrue(controllerFactoryPostAction.isEmpty()); assertTrue(controllerFactoryPostAction.isEmpty());
@@ -80,8 +68,8 @@ class TestControllerInjector {
@Test @Test
void testInjectControllerFieldSetters() throws GenerationException { void testInjectControllerFieldSetters() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.SETTERS); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.SETTERS, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
ControllerInjector.injectControllerField(progress, id, variable); injector.injectControllerField(id, variable);
final var expected = " controller." + GenerationHelper.getSetMethod(id) + "(" + variable + ");\n"; final var expected = " controller." + GenerationHelper.getSetMethod(id) + "(" + variable + ");\n";
assertEquals(expected, sb.toString()); assertEquals(expected, sb.toString());
assertTrue(controllerFactoryPostAction.isEmpty()); assertTrue(controllerFactoryPostAction.isEmpty());
@@ -89,8 +77,8 @@ class TestControllerInjector {
@Test @Test
void testInjectControllerFieldReflection() throws GenerationException { void testInjectControllerFieldReflection() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.REFLECTION); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.REFLECTION, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
ControllerInjector.injectControllerField(progress, id, variable); injector.injectControllerField(id, variable);
final var expected = " injectField(\"" + id + "\", " + variable + ");\n"; final var expected = " injectField(\"" + id + "\", " + variable + ");\n";
assertEquals(expected, sb.toString()); assertEquals(expected, sb.toString());
assertTrue(controllerFactoryPostAction.isEmpty()); assertTrue(controllerFactoryPostAction.isEmpty());
@@ -98,15 +86,14 @@ class TestControllerInjector {
@Test @Test
void testInjectControllerFieldUnknown() { void testInjectControllerFieldUnknown() {
when(parameters.fieldInjectionType()).thenReturn(null); final var injector = new ControllerInjector(controllerInfo, mock(InjectionType.class), ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
assertThrows(GenerationException.class, () -> ControllerInjector.injectControllerField(progress, id, variable)); assertThrows(GenerationException.class, () -> injector.injectControllerField(id, variable));
} }
@Test @Test
void testInjectEventHandlerReferenceFactoryNoArgument() throws GenerationException { void testInjectEventHandlerReferenceFactoryNoArgument() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFERENCE); injector.injectEventHandlerControllerMethod(property, variable);
ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable);
final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> controller." + property.value().replace("#", "") + "());\n"; final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> controller." + property.value().replace("#", "") + "());\n";
assertEquals(1, controllerFactoryPostAction.size()); assertEquals(1, controllerFactoryPostAction.size());
assertEquals(expected, controllerFactoryPostAction.getFirst()); assertEquals(expected, controllerFactoryPostAction.getFirst());
@@ -115,10 +102,9 @@ class TestControllerInjector {
@Test @Test
void testInjectEventHandlerReferenceFactoryWithArgument() throws GenerationException { void testInjectEventHandlerReferenceFactoryWithArgument() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFERENCE);
when(controllerInfo.handlerHasArgument(propertyValue.replace("#", ""))).thenReturn(true); when(controllerInfo.handlerHasArgument(propertyValue.replace("#", ""))).thenReturn(true);
ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable); injector.injectEventHandlerControllerMethod(property, variable);
final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(controller::" + propertyValue.replace("#", "") + ");\n"; final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(controller::" + propertyValue.replace("#", "") + ");\n";
assertEquals(1, controllerFactoryPostAction.size()); assertEquals(1, controllerFactoryPostAction.size());
assertEquals(expected, controllerFactoryPostAction.getFirst()); assertEquals(expected, controllerFactoryPostAction.getFirst());
@@ -127,9 +113,8 @@ class TestControllerInjector {
@Test @Test
void testInjectEventHandlerReflectionAssign() throws GenerationException { void testInjectEventHandlerReflectionAssign() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, ControllerMethodsInjectionType.REFLECTION, sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFLECTION); injector.injectEventHandlerControllerMethod(property, variable);
ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable);
final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> callEventHandlerMethod(\"" + propertyValue.replace("#", "") + "\", e));\n"; final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> callEventHandlerMethod(\"" + propertyValue.replace("#", "") + "\", e));\n";
assertEquals(expected, sb.toString()); assertEquals(expected, sb.toString());
assertTrue(controllerFactoryPostAction.isEmpty()); assertTrue(controllerFactoryPostAction.isEmpty());
@@ -137,23 +122,20 @@ class TestControllerInjector {
@Test @Test
void testInjectEventHandlerUnknownMethod() { void testInjectEventHandlerUnknownMethod() {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, mock(InjectionType.class), sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(null); assertThrows(GenerationException.class, () -> injector.injectEventHandlerControllerMethod(property, variable));
assertThrows(GenerationException.class, () -> ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable));
} }
@Test @Test
void testInjectEventHandlerUnknownField() { void testInjectEventHandlerUnknownField() {
when(parameters.fieldInjectionType()).thenReturn(null); final var injector = new ControllerInjector(controllerInfo, mock(InjectionType.class), ControllerMethodsInjectionType.REFLECTION, sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFLECTION); assertThrows(GenerationException.class, () -> injector.injectEventHandlerControllerMethod(property, variable));
assertThrows(GenerationException.class, () -> ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable));
} }
@Test @Test
void testInjectCallbackReflectionSetters() throws GenerationException { void testInjectCallbackReflectionSetters() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, ControllerMethodsInjectionType.REFLECTION, sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFLECTION); injector.injectCallbackControllerMethod(property, variable, "clazz");
ControllerInjector.injectCallbackControllerMethod(progress, property, variable, "clazz");
final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> callCallbackMethod(\"" + propertyValue.replace("#", "") + "\", e, clazz));\n"; final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> callCallbackMethod(\"" + propertyValue.replace("#", "") + "\", e, clazz));\n";
assertEquals(expected, sb.toString()); assertEquals(expected, sb.toString());
assertTrue(controllerFactoryPostAction.isEmpty()); assertTrue(controllerFactoryPostAction.isEmpty());
@@ -161,9 +143,8 @@ class TestControllerInjector {
@Test @Test
void testInjectCallbackReferenceFactory() throws GenerationException { void testInjectCallbackReferenceFactory() throws GenerationException {
when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction);
when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFERENCE); injector.injectCallbackControllerMethod(property, variable, "clazz");
ControllerInjector.injectCallbackControllerMethod(progress, property, variable, "clazz");
final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(controller::" + propertyValue.replace("#", "") + ");\n"; final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(controller::" + propertyValue.replace("#", "") + ");\n";
assertEquals(1, controllerFactoryPostAction.size()); assertEquals(1, controllerFactoryPostAction.size());
assertEquals(expected, controllerFactoryPostAction.getFirst()); assertEquals(expected, controllerFactoryPostAction.getFirst());

View File

@@ -1,141 +1,126 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.ControllerFieldInfo;
import com.github.gtache.fxml.compiler.ControllerInfo;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.GenerationParameters;
import com.github.gtache.fxml.compiler.GenerationRequest;
import com.github.gtache.fxml.compiler.compatibility.GenerationCompatibility; import com.github.gtache.fxml.compiler.compatibility.GenerationCompatibility;
import com.github.gtache.fxml.compiler.compatibility.ListCollector; import com.github.gtache.fxml.compiler.compatibility.ListCollector;
import com.github.gtache.fxml.compiler.impl.GenericTypesImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import com.github.gtache.fxml.compiler.parsing.impl.ParsedPropertyImpl;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestGenerationCompatibilityHelper { class TestGenerationCompatibilityHelper {
private final GenerationProgress progress; private final HelperProvider helperProvider;
private final GenerationRequest request; private final ReflectionHelper reflectionHelper;
private final GenerationParameters parameters;
private final GenerationCompatibility compatibility; private final GenerationCompatibility compatibility;
private final ParsedObject parsedObject; private final ParsedObject parsedObject;
private final GenerationCompatibilityHelper compatibilityHelper;
TestGenerationCompatibilityHelper(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, TestGenerationCompatibilityHelper(@Mock final GenerationCompatibility compatibility, @Mock final HelperProvider helperProvider,
@Mock final GenerationParameters parameters, @Mock final GenerationCompatibility compatibility, @Mock final ReflectionHelper reflectionHelper, @Mock final ParsedObject parsedObject) {
@Mock final ParsedObject parsedObject) {
this.progress = Objects.requireNonNull(progress);
this.request = Objects.requireNonNull(request);
this.parameters = Objects.requireNonNull(parameters);
this.compatibility = Objects.requireNonNull(compatibility); this.compatibility = Objects.requireNonNull(compatibility);
this.helperProvider = Objects.requireNonNull(helperProvider);
this.reflectionHelper = Objects.requireNonNull(reflectionHelper);
this.parsedObject = Objects.requireNonNull(parsedObject); this.parsedObject = Objects.requireNonNull(parsedObject);
this.compatibilityHelper = new GenerationCompatibilityHelper(helperProvider, compatibility);
} }
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
when(progress.request()).thenReturn(request); when(helperProvider.getReflectionHelper()).thenReturn(reflectionHelper);
when(request.parameters()).thenReturn(parameters);
when(parameters.compatibility()).thenReturn(compatibility);
when(parsedObject.className()).thenReturn("java.lang.String"); when(parsedObject.className()).thenReturn("java.lang.String");
} }
@Test @Test
void testGetStartVarUseVar() { void testGetStartVarUseVar() {
when(compatibility.useVar()).thenReturn(true); when(compatibility.useVar()).thenReturn(true);
assertEquals(" final var ", GenerationCompatibilityHelper.getStartVar(progress, "class", 2)); assertEquals(" final var ", compatibilityHelper.getStartVar("class", 2));
} }
@Test @Test
void testGetStartVarUseVarDefaultIndent() { void testGetStartVarUseVarDefaultIndent() {
when(compatibility.useVar()).thenReturn(true); when(compatibility.useVar()).thenReturn(true);
assertEquals(" final var ", GenerationCompatibilityHelper.getStartVar(progress, "class")); assertEquals(" final var ", compatibilityHelper.getStartVar("class"));
} }
@Test @Test
void testGetStartVarUseVarObject() throws GenerationException { void testGetStartVarUseVarObject() throws GenerationException {
when(compatibility.useVar()).thenReturn(true); when(compatibility.useVar()).thenReturn(true);
assertEquals(" final var ", GenerationCompatibilityHelper.getStartVar(progress, parsedObject)); assertEquals(" final var ", compatibilityHelper.getStartVar(parsedObject));
} }
@Test @Test
void testGetStartVarDontUseVar() { void testGetStartVarDontUseVar() {
when(compatibility.useVar()).thenReturn(false); when(compatibility.useVar()).thenReturn(false);
assertEquals(" final javafx.scene.control.Label ", GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.control.Label", 2)); assertEquals(" final javafx.scene.control.Label ", compatibilityHelper.getStartVar("javafx.scene.control.Label", 2));
} }
@Test @Test
void testGetStartVarDontUseVarObject() throws GenerationException { void testGetStartVarDontUseVarObject() throws GenerationException {
when(compatibility.useVar()).thenReturn(false); when(compatibility.useVar()).thenReturn(false);
when(parsedObject.className()).thenReturn("javafx.scene.control.Label"); when(parsedObject.className()).thenReturn("javafx.scene.control.Label");
assertEquals(" final javafx.scene.control.Label ", GenerationCompatibilityHelper.getStartVar(progress, parsedObject)); when(reflectionHelper.getGenericTypes(parsedObject)).thenReturn("");
assertEquals(" final javafx.scene.control.Label ", compatibilityHelper.getStartVar(parsedObject));
verify(reflectionHelper).getGenericTypes(parsedObject);
} }
@Test @Test
void testGetStartVarDontUseVarGenericObject() throws GenerationException { void testGetStartVarDontUseVarGenericObject() throws GenerationException {
when(compatibility.useVar()).thenReturn(false); when(compatibility.useVar()).thenReturn(false);
when(parsedObject.className()).thenReturn("javafx.scene.control.TableView"); when(parsedObject.className()).thenReturn("javafx.scene.control.TableView");
final var id = "tableView"; when(reflectionHelper.getGenericTypes(parsedObject)).thenReturn("<java.lang.String, java.lang.Integer>");
when(parsedObject.attributes()).thenReturn(Map.of("fx:id", new ParsedPropertyImpl("fx:id", null, id))); assertEquals(" final javafx.scene.control.TableView<java.lang.String, java.lang.Integer> ", compatibilityHelper.getStartVar(parsedObject));
final var info = mock(ControllerInfo.class); verify(reflectionHelper).getGenericTypes(parsedObject);
final var fieldInfo = mock(ControllerFieldInfo.class);
when(info.fieldInfo(id)).thenReturn(fieldInfo);
when(request.controllerInfo()).thenReturn(info);
when(fieldInfo.isGeneric()).thenReturn(true);
when(fieldInfo.genericTypes()).thenReturn(List.of(new GenericTypesImpl("java.lang.String", List.of()), new GenericTypesImpl("java.lang.Integer", List.of())));
assertEquals(" final javafx.scene.control.TableView<java.lang.String, java.lang.Integer> ", GenerationCompatibilityHelper.getStartVar(progress, parsedObject));
} }
@Test @Test
void testGetToListToList() { void testGetToListToList() {
when(compatibility.listCollector()).thenReturn(ListCollector.TO_LIST); when(compatibility.listCollector()).thenReturn(ListCollector.TO_LIST);
assertEquals(".toList()", GenerationCompatibilityHelper.getToList(progress)); assertEquals(".toList()", compatibilityHelper.getToList());
} }
@Test @Test
void testGetToListCollectToUnmodifiableList() { void testGetToListCollectToUnmodifiableList() {
when(compatibility.listCollector()).thenReturn(ListCollector.COLLECT_TO_UNMODIFIABLE_LIST); when(compatibility.listCollector()).thenReturn(ListCollector.COLLECT_TO_UNMODIFIABLE_LIST);
assertEquals(".collect(java.util.stream.Collectors.toUnmodifiableList())", GenerationCompatibilityHelper.getToList(progress)); assertEquals(".collect(java.util.stream.Collectors.toUnmodifiableList())", compatibilityHelper.getToList());
} }
@Test @Test
void testGetToListCollectToList() { void testGetToListCollectToList() {
when(compatibility.listCollector()).thenReturn(ListCollector.COLLECT_TO_LIST); when(compatibility.listCollector()).thenReturn(ListCollector.COLLECT_TO_LIST);
assertEquals(".collect(java.util.stream.Collectors.toList())", GenerationCompatibilityHelper.getToList(progress)); assertEquals(".collect(java.util.stream.Collectors.toList())", compatibilityHelper.getToList());
} }
@Test @Test
void testGetFirstUse() { void testGetFirstUse() {
when(compatibility.useGetFirst()).thenReturn(true); when(compatibility.useGetFirst()).thenReturn(true);
assertEquals(".getFirst()", GenerationCompatibilityHelper.getGetFirst(progress)); assertEquals(".getFirst()", compatibilityHelper.getGetFirst());
} }
@Test @Test
void testGetFirstDontUse() { void testGetFirstDontUse() {
when(compatibility.useGetFirst()).thenReturn(false); when(compatibility.useGetFirst()).thenReturn(false);
assertEquals(".get(0)", GenerationCompatibilityHelper.getGetFirst(progress)); assertEquals(".get(0)", compatibilityHelper.getGetFirst());
} }
@Test @Test
void testGetListOfUse() { void testGetListOfUse() {
when(compatibility.useCollectionsOf()).thenReturn(true); when(compatibility.useCollectionsOf()).thenReturn(true);
assertEquals("java.util.List.of(", GenerationCompatibilityHelper.getListOf(progress)); assertEquals("java.util.List.of(", compatibilityHelper.getListOf());
} }
@Test @Test
void testGetListOfDontUse() { void testGetListOfDontUse() {
when(compatibility.useCollectionsOf()).thenReturn(false); when(compatibility.useCollectionsOf()).thenReturn(false);
assertEquals("java.util.Arrays.asList(", GenerationCompatibilityHelper.getListOf(progress)); assertEquals("java.util.Arrays.asList(", compatibilityHelper.getListOf());
} }
} }

View File

@@ -19,27 +19,31 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestConstructorFormatter { class TestInitializationFormatter {
private final GenerationProgress progress; private final GenerationProgress progress;
private final GenerationRequest request; private final GenerationRequest request;
private final GenerationParameters parameters; private final GenerationParameters parameters;
private final HelperProvider helperProvider;
private final StringBuilder stringBuilder; private final StringBuilder stringBuilder;
private final SourceInfo sourceInfo; private final SourceInfo sourceInfo;
private final ParsedInclude include; private final ParsedInclude include;
private final Map<String, SourceInfo> sourceToSourceInfo; private final Map<String, SourceInfo> sourceToSourceInfo;
private final InitializationFormatter initializationFormatter;
TestConstructorFormatter(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, TestInitializationFormatter(@Mock final GenerationProgress progress, @Mock final GenerationRequest request,
@Mock final GenerationParameters parameters, @Mock final StringBuilder stringBuilder, @Mock final GenerationParameters parameters, @Mock final HelperProvider helperProvider,
@Mock final SourceInfo sourceInfo, @Mock final ParsedInclude include) { @Mock final SourceInfo sourceInfo, @Mock final ParsedInclude include) {
this.progress = Objects.requireNonNull(progress); this.progress = Objects.requireNonNull(progress);
this.request = Objects.requireNonNull(request); this.request = Objects.requireNonNull(request);
this.parameters = Objects.requireNonNull(parameters); this.parameters = Objects.requireNonNull(parameters);
this.stringBuilder = Objects.requireNonNull(stringBuilder); this.stringBuilder = new StringBuilder();
this.helperProvider = Objects.requireNonNull(helperProvider);
this.sourceInfo = Objects.requireNonNull(sourceInfo); this.sourceInfo = Objects.requireNonNull(sourceInfo);
this.include = Objects.requireNonNull(include); this.include = Objects.requireNonNull(include);
this.sourceToSourceInfo = new HashMap<>(); this.sourceToSourceInfo = new HashMap<>();
this.initializationFormatter = new InitializationFormatter(helperProvider, progress);
} }
@BeforeEach @BeforeEach
@@ -53,6 +57,6 @@ class TestConstructorFormatter {
@Test @Test
void testFormatSubViewConstructorCallNullSubInfo() { void testFormatSubViewConstructorCallNullSubInfo() {
assertThrows(GenerationException.class, () -> ConstructorFormatter.formatSubViewConstructorCall(progress, include)); assertThrows(GenerationException.class, () -> initializationFormatter.formatSubViewConstructorCall(include));
} }
} }

View File

@@ -3,7 +3,6 @@ package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.ControllerFieldInfo; import com.github.gtache.fxml.compiler.ControllerFieldInfo;
import com.github.gtache.fxml.compiler.ControllerInfo; import com.github.gtache.fxml.compiler.ControllerInfo;
import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.GenerationRequest;
import com.github.gtache.fxml.compiler.impl.GenericTypesImpl; import com.github.gtache.fxml.compiler.impl.GenericTypesImpl;
import com.github.gtache.fxml.compiler.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import com.github.gtache.fxml.compiler.parsing.ParsedProperty; import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
@@ -34,28 +33,23 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestReflectionHelper { class TestReflectionHelper {
private final GenerationProgress progress;
private final GenerationRequest request;
private final Map<String, ParsedProperty> attributes; private final Map<String, ParsedProperty> attributes;
private final ControllerInfo controllerInfo; private final ControllerInfo controllerInfo;
private final ControllerFieldInfo fieldInfo; private final ControllerFieldInfo fieldInfo;
private final ParsedObject parsedObject; private final ParsedObject parsedObject;
private final ReflectionHelper reflectionHelper;
TestReflectionHelper(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, TestReflectionHelper(@Mock final ControllerInfo controllerInfo, @Mock final ControllerFieldInfo fieldInfo,
@Mock final ControllerInfo controllerInfo, @Mock final ControllerFieldInfo fieldInfo,
@Mock final ParsedObject parsedObject) { @Mock final ParsedObject parsedObject) {
this.progress = Objects.requireNonNull(progress);
this.request = Objects.requireNonNull(request);
this.controllerInfo = Objects.requireNonNull(controllerInfo); this.controllerInfo = Objects.requireNonNull(controllerInfo);
this.fieldInfo = Objects.requireNonNull(fieldInfo); this.fieldInfo = Objects.requireNonNull(fieldInfo);
this.parsedObject = Objects.requireNonNull(parsedObject); this.parsedObject = Objects.requireNonNull(parsedObject);
this.attributes = new HashMap<>(); this.attributes = new HashMap<>();
this.reflectionHelper = new ReflectionHelper(controllerInfo);
} }
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
when(progress.request()).thenReturn(request);
when(request.controllerInfo()).thenReturn(controllerInfo);
when(controllerInfo.fieldInfo("id")).thenReturn(fieldInfo); when(controllerInfo.fieldInfo("id")).thenReturn(fieldInfo);
when(parsedObject.attributes()).thenReturn(attributes); when(parsedObject.attributes()).thenReturn(attributes);
when(parsedObject.className()).thenReturn("javafx.scene.control.ComboBox"); when(parsedObject.className()).thenReturn("javafx.scene.control.ComboBox");
@@ -191,31 +185,31 @@ class TestReflectionHelper {
@Test @Test
void testGetGenericTypesNotGeneric() throws GenerationException { void testGetGenericTypesNotGeneric() throws GenerationException {
when(parsedObject.className()).thenReturn("java.lang.String"); when(parsedObject.className()).thenReturn("java.lang.String");
assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); assertEquals("", reflectionHelper.getGenericTypes(parsedObject));
} }
@Test @Test
void testGetGenericTypesNullProperty() throws GenerationException { void testGetGenericTypesNullProperty() throws GenerationException {
attributes.clear(); attributes.clear();
assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); assertEquals("", reflectionHelper.getGenericTypes(parsedObject));
} }
@Test @Test
void testGetGenericTypesFieldNotFound() throws GenerationException { void testGetGenericTypesFieldNotFound() throws GenerationException {
when(controllerInfo.fieldInfo("id")).thenReturn(null); when(controllerInfo.fieldInfo("id")).thenReturn(null);
assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); assertEquals("", reflectionHelper.getGenericTypes(parsedObject));
} }
@Test @Test
void testGetGenericTypesFieldNotGeneric() throws GenerationException { void testGetGenericTypesFieldNotGeneric() throws GenerationException {
when(fieldInfo.isGeneric()).thenReturn(false); when(fieldInfo.isGeneric()).thenReturn(false);
when(fieldInfo.genericTypes()).thenReturn(List.of(new GenericTypesImpl("java.lang.String", List.of()), new GenericTypesImpl("java.lang.Integer", List.of()))); when(fieldInfo.genericTypes()).thenReturn(List.of(new GenericTypesImpl("java.lang.String", List.of()), new GenericTypesImpl("java.lang.Integer", List.of())));
assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); assertEquals("", reflectionHelper.getGenericTypes(parsedObject));
} }
@Test @Test
void testGetGenericTypes() throws GenerationException { void testGetGenericTypes() throws GenerationException {
when(fieldInfo.genericTypes()).thenReturn(List.of(new GenericTypesImpl("java.lang.String", List.of()), new GenericTypesImpl("java.lang.Integer", List.of()))); when(fieldInfo.genericTypes()).thenReturn(List.of(new GenericTypesImpl("java.lang.String", List.of()), new GenericTypesImpl("java.lang.Integer", List.of())));
assertEquals("<java.lang.String, java.lang.Integer>", ReflectionHelper.getGenericTypes(progress, parsedObject)); assertEquals("<java.lang.String, java.lang.Integer>", reflectionHelper.getGenericTypes(parsedObject));
} }
} }

View File

@@ -1,9 +1,108 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
import com.github.gtache.fxml.compiler.parsing.impl.ParsedPropertyImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.SequencedCollection;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestURLFormatter { class TestURLFormatter {
private final HelperProvider helperProvider;
private final GenerationHelper generationHelper;
private final GenerationCompatibilityHelper compatibilityHelper;
private final ParsedObject parsedObject;
private final String variableName;
private final StringBuilder sb;
private final GenerationProgress progress;
private final URLFormatter urlFormatter;
TestURLFormatter(@Mock final HelperProvider helperProvider, @Mock final GenerationHelper generationHelper,
@Mock final GenerationCompatibilityHelper compatibilityHelper, @Mock final ParsedObject parsedObject,
@Mock final GenerationProgress progress) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.generationHelper = Objects.requireNonNull(generationHelper);
this.compatibilityHelper = Objects.requireNonNull(compatibilityHelper);
this.parsedObject = Objects.requireNonNull(parsedObject);
this.progress = Objects.requireNonNull(progress);
this.sb = new StringBuilder();
this.variableName = "variable";
this.urlFormatter = new URLFormatter(helperProvider, progress);
}
@BeforeEach
void beforeEach() throws GenerationException {
when(helperProvider.getCompatibilityHelper()).thenReturn(compatibilityHelper);
when(helperProvider.getGenerationHelper()).thenReturn(generationHelper);
when(progress.stringBuilder()).thenReturn(sb);
when(progress.getNextVariableName("url")).thenReturn("url1", "url2");
when(compatibilityHelper.getStartVar(anyString())).then(i -> i.getArgument(0));
when(parsedObject.children()).thenReturn(List.of());
when(parsedObject.properties()).thenReturn(new LinkedHashMap<>());
doAnswer(i -> sb.append("handleId")).when(generationHelper).handleId(any(), anyString());
}
@Test
void testFormatURLSheets() {
final var styleSheets = List.of("style1.css", "@style2.css");
final var expected = " final java.net.URL url1;\n" +
" try {\n" +
" url1 = new java.net.URI(\"style1.css\").toURL();\n" +
" } catch (final java.net.MalformedURLException | java.net.URISyntaxException e) {\n" +
" throw new RuntimeException(\"Couldn't parse url : style1.css\", e);\n" +
" }\njava.net.URLurl2 = getClass().getResource(\"style2.css\");\n";
assertEquals(List.of("url1", "url2"), urlFormatter.formatURL(styleSheets));
assertEquals(expected, sb.toString());
}
@Test
void testFormatURLObjectChildren() {
when(parsedObject.children()).thenReturn(List.of(parsedObject));
assertThrows(GenerationException.class, () -> urlFormatter.formatURL(parsedObject, variableName));
}
@Test
void testFormatURLObjectProperties() {
final var map = new LinkedHashMap<ParsedProperty, SequencedCollection<ParsedObject>>();
map.put(mock(ParsedProperty.class), List.of());
when(parsedObject.properties()).thenReturn(map);
assertThrows(GenerationException.class, () -> urlFormatter.formatURL(parsedObject, variableName));
}
@Test
void testFormatURLObjectUnknownAttribute() {
final var attributes = new HashMap<String, ParsedProperty>();
attributes.put("unknown", new ParsedPropertyImpl("unknown", null, "value"));
when(parsedObject.attributes()).thenReturn(attributes);
assertThrows(GenerationException.class, () -> urlFormatter.formatURL(parsedObject, variableName));
}
@Test
void testFormatURLObject() throws GenerationException {
final var attributes = new HashMap<String, ParsedProperty>();
attributes.put("value", new ParsedPropertyImpl("value", null, "key"));
attributes.put("fx:id", new ParsedPropertyImpl("fx:id", null, "id"));
when(parsedObject.attributes()).thenReturn(attributes);
urlFormatter.formatURL(parsedObject, variableName);
final var expected = "java.net.URL" + variableName + " = getClass().getResource(\"key\");\nhandleId";
assertEquals(expected, sb.toString());
verify(generationHelper).handleId(parsedObject, variableName);
}
} }

View File

@@ -1,8 +1,145 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.InjectionType;
import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes;
import javafx.geometry.Pos;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestValueFormatter { class TestValueFormatter {
private final Map<String, VariableInfo> idToVariableInfo;
private final InjectionType resourceInjectionType;
private final ValueFormatter formatter;
TestValueFormatter(@Mock final InjectionType resourceInjectionType) {
this.resourceInjectionType = requireNonNull(resourceInjectionType);
this.idToVariableInfo = new HashMap<>();
this.formatter = new ValueFormatter(resourceInjectionType, idToVariableInfo);
}
@Test
void testGetArgStringResourceUnknown() {
assertThrows(GenerationException.class, () -> formatter.getArg("%value", String.class));
}
@Test
void testGetArgStringResourceSimpleGet() throws GenerationException {
final var types = List.of(ResourceBundleInjectionTypes.CONSTRUCTOR, ResourceBundleInjectionTypes.CONSTRUCTOR_NAME, ResourceBundleInjectionTypes.GET_BUNDLE);
for (final var type : types) {
final var resourceFormatter = new ValueFormatter(type, idToVariableInfo);
assertEquals("resourceBundle.getString(\"value\")", resourceFormatter.getArg("%value", String.class));
}
}
@Test
void testGetArgStringResourceController() throws GenerationException {
final var resourceFormatter = new ValueFormatter(ResourceBundleInjectionTypes.GETTER, idToVariableInfo);
assertEquals("controller.resources().getString(\"value\")", resourceFormatter.getArg("%value", String.class));
}
@Test
void testGetArgStringResourceFunction() throws GenerationException {
final var resourceFormatter = new ValueFormatter(ResourceBundleInjectionTypes.CONSTRUCTOR_FUNCTION, idToVariableInfo);
assertEquals("resourceBundleFunction.apply(\"value\")", resourceFormatter.getArg("%value", String.class));
}
@Test
void testGetArgRelativePath() throws GenerationException {
assertEquals("getClass().getResource(\"value\").toString()", formatter.getArg("@value", String.class));
assertEquals("getClass().getResource(\"value\").toString()", formatter.getArg("@value", URL.class));
}
@Test
void testGetArgBinding() {
assertThrows(GenerationException.class, () -> formatter.getArg("${value}", String.class));
}
@Test
void testGetArgExpressionNull() {
assertThrows(GenerationException.class, () -> formatter.getArg("$value", String.class));
}
@Test
void testGetArgExpression() throws GenerationException {
final var info = mock(VariableInfo.class);
when(info.variableName()).thenReturn("variable");
idToVariableInfo.put("value", info);
assertEquals("variable", formatter.getArg("$value", String.class));
}
@Test
void testGetArgOther() throws GenerationException {
assertEquals("\"value\"", formatter.getArg("value", String.class));
}
@Test
void testToStringString() {
assertEquals("\"value\"", formatter.toString("value", String.class));
}
@Test
void testToStringEscape() {
assertEquals("\"val\\\\u\\\"e\"", formatter.toString("\\val\\u\"e", String.class));
}
@Test
void testToStringChar() {
assertEquals("'v'", formatter.toString("v", char.class));
assertEquals("'v'", formatter.toString("v", Character.class));
}
@Test
void testToStringBoolean() {
assertEquals("true", formatter.toString("true", boolean.class));
assertEquals("true", formatter.toString("true", Boolean.class));
}
@Test
void testToStringInteger() {
final var types = List.of(byte.class, Byte.class, short.class, Short.class, long.class, Long.class, int.class, Integer.class);
for (final var type : types) {
assertEquals("1", formatter.toString("1", type));
assertEquals(ReflectionHelper.getWrapperClass(type) + ".valueOf(\"value\")", formatter.toString("value", type));
}
}
@Test
void testToStringDecimal() {
final var types = List.of(float.class, Float.class, double.class, Double.class);
for (final var type : types) {
assertEquals("1.0", formatter.toString("1.0", type));
assertEquals(ReflectionHelper.getWrapperClass(type) + ".valueOf(\"value\")", formatter.toString("value", type));
}
}
@Test
void testToStringValueOfEnum() {
assertEquals("javafx.geometry.Pos.value", formatter.toString("value", Pos.class));
}
@Test
void testToStringValueOfColor() {
assertEquals("javafx.scene.paint.Color.valueOf(\"value\")", formatter.toString("value", javafx.scene.paint.Color.class));
}
@Test
void testOther() {
assertEquals("value", formatter.toString("value", Object.class));
}
} }

View File

@@ -1,8 +1,163 @@
package com.github.gtache.fxml.compiler.impl.internal; package com.github.gtache.fxml.compiler.impl.internal;
import com.github.gtache.fxml.compiler.GenerationException;
import com.github.gtache.fxml.compiler.parsing.ParsedObject;
import com.github.gtache.fxml.compiler.parsing.ParsedProperty;
import com.github.gtache.fxml.compiler.parsing.impl.ParsedPropertyImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.SequencedCollection;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TestWebViewFormatter { class TestWebViewFormatter {
private final HelperProvider helperProvider;
private final GenerationCompatibilityHelper compatibilityHelper;
private final ControllerInjector controllerInjector;
private final FieldSetter fieldSetter;
private final PropertyFormatter propertyFormatter;
private final GenerationHelper generationHelper;
private final GenerationProgress progress;
private final ParsedObject parsedObject;
private final String variableName;
private final String engineVariable;
private final ParsedProperty parsedProperty;
private final StringBuilder sb;
private final Map<String, ParsedProperty> attributes;
private final WebViewFormatter webViewFormatter;
TestWebViewFormatter(@Mock final HelperProvider helperProvider, @Mock final GenerationCompatibilityHelper compatibilityHelper,
@Mock final ControllerInjector controllerInjector, @Mock final FieldSetter fieldSetter,
@Mock final PropertyFormatter propertyFormatter, @Mock final GenerationHelper generationHelper,
@Mock final GenerationProgress progress, @Mock final ParsedObject parsedObject,
@Mock final ParsedProperty parsedProperty) {
this.helperProvider = Objects.requireNonNull(helperProvider);
this.compatibilityHelper = Objects.requireNonNull(compatibilityHelper);
this.controllerInjector = Objects.requireNonNull(controllerInjector);
this.fieldSetter = Objects.requireNonNull(fieldSetter);
this.propertyFormatter = Objects.requireNonNull(propertyFormatter);
this.generationHelper = Objects.requireNonNull(generationHelper);
this.progress = Objects.requireNonNull(progress);
this.parsedObject = Objects.requireNonNull(parsedObject);
this.variableName = "variable";
this.engineVariable = "engine";
this.parsedProperty = Objects.requireNonNull(parsedProperty);
this.sb = new StringBuilder();
this.attributes = new HashMap<>();
this.webViewFormatter = new WebViewFormatter(helperProvider, progress);
}
@BeforeEach
void beforeEach() throws GenerationException {
when(parsedObject.children()).thenReturn(List.of());
when(parsedObject.properties()).thenReturn(new LinkedHashMap<>());
when(helperProvider.getCompatibilityHelper()).thenReturn(compatibilityHelper);
when(helperProvider.getControllerInjector()).thenReturn(controllerInjector);
when(helperProvider.getFieldSetter()).thenReturn(fieldSetter);
when(helperProvider.getGenerationHelper()).thenReturn(generationHelper);
when(helperProvider.getPropertyFormatter()).thenReturn(propertyFormatter);
when(compatibilityHelper.getStartVar(anyString())).then(i -> i.getArgument(0));
doAnswer(i -> sb.append(((ParsedProperty) i.getArgument(0)).value()).append((String) i.getArgument(2))).when(controllerInjector).injectCallbackControllerMethod(any(), eq(engineVariable), any());
doAnswer(i -> sb.append(((ParsedProperty) i.getArgument(0)).value())).when(controllerInjector).injectEventHandlerControllerMethod(any(), eq(engineVariable));
doAnswer(i -> sb.append(((ParsedProperty) i.getArgument(0)).value())).when(fieldSetter).setEventHandler(any(), eq(engineVariable));
doAnswer(i -> sb.append(((ParsedProperty) i.getArgument(0)).value()).append((String) i.getArgument(2))).when(fieldSetter).setField(any(), eq(engineVariable), any());
doAnswer(i -> sb.append("handleId")).when(generationHelper).handleId(parsedObject, variableName);
doAnswer(i -> sb.append(((ParsedProperty) i.getArgument(0)).value())).when(propertyFormatter).formatProperty(any(), any(), any());
when(parsedObject.attributes()).thenReturn(attributes);
when(progress.stringBuilder()).thenReturn(sb);
when(progress.getNextVariableName("engine")).thenReturn(engineVariable);
}
@Test
void testFormatHasChildren() {
when(parsedObject.children()).thenReturn(List.of(parsedObject));
assertThrows(GenerationException.class, () -> webViewFormatter.formatWebView(parsedObject, variableName));
}
@Test
void testFormatHasProperty() {
final var properties = new LinkedHashMap<ParsedProperty, SequencedCollection<ParsedObject>>();
properties.put(parsedProperty, List.of(parsedObject));
when(parsedObject.properties()).thenReturn(properties);
assertThrows(GenerationException.class, () -> webViewFormatter.formatWebView(parsedObject, variableName));
}
@Test
void testFormatAllMethods() throws GenerationException {
attributes.put("confirmHandler", new ParsedPropertyImpl("confirmHandler", null, "#confirmHandler"));
attributes.put("createPopupHandler", new ParsedPropertyImpl("createPopupHandler", null, "#createPopupHandler"));
attributes.put("onAlert", new ParsedPropertyImpl("onAlert", null, "#onAlert"));
attributes.put("onResized", new ParsedPropertyImpl("onResized", null, "#onResized"));
attributes.put("onStatusChanged", new ParsedPropertyImpl("onStatusChanged", null, "#onStatusChanged"));
attributes.put("onVisibilityChanged", new ParsedPropertyImpl("onVisibilityChanged", null, "#onVisibilityChanged"));
attributes.put("promptHandler", new ParsedPropertyImpl("promptHandler", null, "#promptHandler"));
attributes.put("location", new ParsedPropertyImpl("location", null, "location"));
attributes.put("property", new ParsedPropertyImpl("property", null, "property"));
attributes.put("fx:id", new ParsedPropertyImpl("fx:id", null, "id"));
webViewFormatter.formatWebView(parsedObject, variableName);
final var expected = "javafx.scene.web.WebViewvariable = new javafx.scene.web.WebView();\n" +
"javafx.scene.web.WebEngineengine = variable.getEngine();\n" +
"#confirmHandlerString.class#createPopupHandlerjavafx.scene.web.PopupFeatures.class" +
" engine.load(\"location\");\n#onAlert#onResized#onStatusChanged#onVisibilityChanged#promptHandlerjavafx.scene.web.PromptData.class" +
"propertyhandleId";
assertEquals(expected, sb.toString());
verify(propertyFormatter).formatProperty(attributes.get("property"), parsedObject, variableName);
verify(controllerInjector).injectCallbackControllerMethod(attributes.get("confirmHandler"), engineVariable, "String.class");
verify(controllerInjector).injectCallbackControllerMethod(attributes.get("createPopupHandler"), engineVariable, "javafx.scene.web.PopupFeatures.class");
verify(controllerInjector).injectEventHandlerControllerMethod(attributes.get("onAlert"), engineVariable);
verify(controllerInjector).injectEventHandlerControllerMethod(attributes.get("onResized"), engineVariable);
verify(controllerInjector).injectEventHandlerControllerMethod(attributes.get("onStatusChanged"), engineVariable);
verify(controllerInjector).injectEventHandlerControllerMethod(attributes.get("onVisibilityChanged"), engineVariable);
verify(controllerInjector).injectCallbackControllerMethod(attributes.get("promptHandler"), engineVariable, "javafx.scene.web.PromptData.class");
verify(generationHelper).handleId(parsedObject, variableName);
}
@Test
void testFormatAllVariables() throws GenerationException {
attributes.put("confirmHandler", new ParsedPropertyImpl("confirmHandler", null, "$controller.confirmHandler"));
attributes.put("createPopupHandler", new ParsedPropertyImpl("createPopupHandler", null, "$controller.createPopupHandler"));
attributes.put("onAlert", new ParsedPropertyImpl("onAlert", null, "$controller.onAlert"));
attributes.put("onResized", new ParsedPropertyImpl("onResized", null, "$controller.onResized"));
attributes.put("onStatusChanged", new ParsedPropertyImpl("onStatusChanged", null, "$controller.onStatusChanged"));
attributes.put("onVisibilityChanged", new ParsedPropertyImpl("onVisibilityChanged", null, "$controller.onVisibilityChanged"));
attributes.put("promptHandler", new ParsedPropertyImpl("promptHandler", null, "$controller.promptHandler"));
attributes.put("location", new ParsedPropertyImpl("location", null, "location"));
attributes.put("property", new ParsedPropertyImpl("property", null, "property"));
attributes.put("fx:id", new ParsedPropertyImpl("fx:id", null, "id"));
webViewFormatter.formatWebView(parsedObject, variableName);
final var expected = "javafx.scene.web.WebViewvariable = new javafx.scene.web.WebView();\n" +
"javafx.scene.web.WebEngineengine = variable.getEngine();\n" +
"$controller.confirmHandlerjavafx.util.Callback$controller.createPopupHandlerjavafx.util.Callback" +
" engine.load(\"location\");\n$controller.onAlert$controller.onResized$controller.onStatusChanged$controller.onVisibilityChanged" +
"$controller.promptHandlerjavafx.util.Callback" +
"propertyhandleId";
assertEquals(expected, sb.toString());
verify(fieldSetter).setEventHandler(attributes.get("onAlert"), engineVariable);
verify(fieldSetter).setEventHandler(attributes.get("onResized"), engineVariable);
verify(fieldSetter).setEventHandler(attributes.get("onStatusChanged"), engineVariable);
verify(fieldSetter).setEventHandler(attributes.get("onVisibilityChanged"), engineVariable);
verify(propertyFormatter).formatProperty(attributes.get("property"), parsedObject, variableName);
verify(fieldSetter).setField(attributes.get("confirmHandler"), engineVariable, "javafx.util.Callback");
verify(fieldSetter).setField(attributes.get("createPopupHandler"), engineVariable, "javafx.util.Callback");
verify(fieldSetter).setField(attributes.get("promptHandler"), engineVariable, "javafx.util.Callback");
verify(generationHelper).handleId(parsedObject, variableName);
}
} }