diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/GeneratorImpl.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/GeneratorImpl.java index c554e98..18275cc 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/GeneratorImpl.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/GeneratorImpl.java @@ -3,10 +3,8 @@ package com.github.gtache.fxml.compiler.impl; import com.github.gtache.fxml.compiler.GenerationException; import com.github.gtache.fxml.compiler.GenerationRequest; 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.HelperMethodsFormatter; -import com.github.gtache.fxml.compiler.impl.internal.LoadMethodFormatter; +import com.github.gtache.fxml.compiler.impl.internal.HelperProvider; //TODO handle binding (${}) @@ -14,11 +12,11 @@ import com.github.gtache.fxml.compiler.impl.internal.LoadMethodFormatter; * Implementation of {@link Generator} */ public class GeneratorImpl implements Generator { - @Override public String generate(final GenerationRequest request) throws GenerationException { final var progress = new GenerationProgress(request); + final var helperProvider = new HelperProvider(progress); final var className = request.outputClassName(); final var pkgName = className.substring(0, className.lastIndexOf('.')); 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("\n"); sb.append("/**\n"); - sb.append(" * Generated code, not thread-safe\n"); + sb.append(" * Generated code\n"); sb.append(" */\n"); sb.append("public final class ").append(simpleClassName).append(" {\n"); sb.append("\n"); - ConstructorFormatter.formatFieldsAndConstructor(progress); + helperProvider.getInitializationFormatter().formatFieldsAndConstructor(); sb.append("\n"); - LoadMethodFormatter.formatLoadMethod(progress); + helperProvider.getLoadMethodFormatter().formatLoadMethod(); sb.append("\n"); - HelperMethodsFormatter.formatHelperMethods(progress); + helperProvider.getHelperMethodsFormatter().formatHelperMethods(); sb.append("\n"); formatControllerMethod(progress, controllerInjectionClass); sb.append("}\n"); diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorHelper.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorHelper.java index cbdf1b3..54db734 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorHelper.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorHelper.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -16,7 +17,10 @@ import java.util.Set; */ 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 * @throws GenerationException if an error occurs */ - static List getListConstructorArgs(final ConstructorArgs constructorArgs, final ParsedObject parsedObject) throws GenerationException { + List getListConstructorArgs(final ConstructorArgs constructorArgs, final ParsedObject parsedObject) throws GenerationException { final var args = new ArrayList(constructorArgs.namedArgs().size()); + final var valueFormatter = helperProvider.getValueFormatter(); for (final var entry : constructorArgs.namedArgs().entrySet()) { final var type = entry.getValue().type(); final var p = parsedObject.attributes().get(entry.getKey()); @@ -36,12 +41,12 @@ final class ConstructorHelper { final var c = parsedObject.properties().entrySet().stream().filter(e -> e.getKey().name().equals(entry.getKey())).findFirst().orElse(null); if (c == null) { - args.add(ValueFormatter.toString(entry.getValue().defaultValue(), type)); + args.add(valueFormatter.toString(entry.getValue().defaultValue(), type)); } else { throw new GenerationException("Constructor using complex property not supported yet"); } } else { - args.add(ValueFormatter.toString(p.value(), type)); + args.add(valueFormatter.toString(p.value(), type)); } } return args; diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ControllerInjector.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ControllerInjector.java index dc2208e..f0589dc 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ControllerInjector.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ControllerInjector.java @@ -1,5 +1,6 @@ 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.InjectionType; 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.parsing.ParsedProperty; +import java.util.SequencedCollection; + +import static java.util.Objects.requireNonNull; + /** * Various methods to help {@link GeneratorImpl} for injecting controllers */ final class ControllerInjector { - private ControllerInjector() { + private final ControllerInfo controllerInfo; + private final InjectionType fieldInjectionType; + private final InjectionType methodInjectionType; + private final StringBuilder sb; + private final SequencedCollection controllerFactoryPostAction; + + ControllerInjector(final ControllerInfo controllerInfo, final InjectionType fieldInjectionType, final InjectionType methodInjectionType, + final StringBuilder sb, final SequencedCollection 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 * - * @param progress The generation progress * @param id The object id * @param variable The object variable * @throws GenerationException if an error occurs */ - static void injectControllerField(final GenerationProgress progress, final String id, final String variable) throws GenerationException { - final var fieldInjectionType = progress.request().parameters().fieldInjectionType(); + void injectControllerField(final String id, final String variable) throws GenerationException { if (fieldInjectionType instanceof final ControllerFieldInjectionTypes types) { - final var sb = progress.stringBuilder(); switch (types) { case FACTORY -> sb.append(" fieldMap.put(\"").append(id).append("\", ").append(variable).append(");\n"); @@ -46,41 +60,37 @@ final class ControllerInjector { /** * Injects an event handler controller method * - * @param progress The generation progress * @param property The property to inject * @param parentVariable The parent variable * @throws GenerationException if an error occurs */ - static void injectEventHandlerControllerMethod(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { - injectControllerMethod(progress, getEventHandlerMethodInjection(progress, property, parentVariable)); + void injectEventHandlerControllerMethod(final ParsedProperty property, final String parentVariable) throws GenerationException { + injectControllerMethod(getEventHandlerMethodInjection(property, parentVariable)); } /** * Injects a callback controller method * - * @param progress The generation progress * @param property The property to inject * @param parentVariable The parent variable * @param argumentClazz The argument class * @throws GenerationException if an error occurs */ - static void injectCallbackControllerMethod(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String argumentClazz) throws GenerationException { - injectControllerMethod(progress, getCallbackMethodInjection(progress, property, parentVariable, argumentClazz)); + void injectCallbackControllerMethod(final ParsedProperty property, final String parentVariable, final String argumentClazz) throws GenerationException { + injectControllerMethod(getCallbackMethodInjection(property, parentVariable, argumentClazz)); } /** * Injects a controller method * - * @param progress The generation progress * @param methodInjection The method injection * @throws GenerationException if an error occurs */ - private static void injectControllerMethod(final GenerationProgress progress, final String methodInjection) throws GenerationException { - final var fieldInjectionType = progress.request().parameters().fieldInjectionType(); + private void injectControllerMethod(final String methodInjection) throws GenerationException { if (fieldInjectionType instanceof final ControllerFieldInjectionTypes fieldTypes) { switch (fieldTypes) { - case FACTORY -> progress.controllerFactoryPostAction().add(methodInjection); - case ASSIGN, SETTERS, REFLECTION -> progress.stringBuilder().append(methodInjection); + case FACTORY -> controllerFactoryPostAction.add(methodInjection); + case ASSIGN, SETTERS, REFLECTION -> sb.append(methodInjection); } } else { throw getUnknownInjectionException(fieldInjectionType); @@ -90,20 +100,18 @@ final class ControllerInjector { /** * Computes the method injection for event handler * - * @param progress The generation progress * @param property The property * @param parentVariable The parent variable * @return The method injection * @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 methodInjectionType = progress.request().parameters().methodInjectionType(); final var controllerMethod = property.value().replace("#", ""); if (methodInjectionType instanceof final ControllerMethodsInjectionType methodTypes) { return switch (methodTypes) { case REFERENCE -> { - final var hasArgument = progress.request().controllerInfo().handlerHasArgument(controllerMethod); + final var hasArgument = controllerInfo.handlerHasArgument(controllerMethod); if (hasArgument) { yield " " + parentVariable + "." + setMethod + "(controller::" + controllerMethod + ");\n"; } else { @@ -121,16 +129,14 @@ final class ControllerInjector { /** * Computes the method injection for callback * - * @param progress The generation progress * @param property The property * @param parentVariable The parent variable * @param argumentClazz The argument class * @return The method injection * @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 methodInjectionType = progress.request().parameters().methodInjectionType(); final var controllerMethod = property.value().replace("#", ""); if (methodInjectionType instanceof final ControllerMethodsInjectionType methodTypes) { return switch (methodTypes) { diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FieldSetter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FieldSetter.java index 79abb60..f91d8a1 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FieldSetter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FieldSetter.java @@ -1,68 +1,79 @@ 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.ControllerFieldInjectionTypes; import com.github.gtache.fxml.compiler.impl.GeneratorImpl; 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 java.util.Objects.requireNonNull; /** * Helper methods for {@link GeneratorImpl} to set fields */ final class FieldSetter { - private FieldSetter() { + private final HelperProvider helperProvider; + private final InjectionType fieldInjectionType; + private final StringBuilder sb; + private final SequencedCollection controllerFactoryPostAction; + + FieldSetter(final HelperProvider helperProvider, final InjectionType fieldInjectionType, + final StringBuilder sb, final SequencedCollection controllerFactoryPostAction) { + this.helperProvider = requireNonNull(helperProvider); + this.fieldInjectionType = requireNonNull(fieldInjectionType); + this.sb = requireNonNull(sb); + this.controllerFactoryPostAction = requireNonNull(controllerFactoryPostAction); } /** * Sets an event handler field * - * @param progress The generation progress * @param property The property to inject * @param parentVariable The parent variable * @throws GenerationException if an error occurs@ */ - static void setEventHandler(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { - setField(progress, property, parentVariable, "javafx.event.EventHandler"); + void setEventHandler(final ParsedProperty property, final String parentVariable) throws GenerationException { + setField(property, parentVariable, "javafx.event.EventHandler"); } /** * Sets a field * - * @param progress The generation progress * @param property The property to inject * @param parentVariable The parent variable * @param fieldType The field type * @throws GenerationException if an error occurs */ - static void setField(final GenerationProgress progress, final ParsedProperty property, final String parentVariable, final String fieldType) throws GenerationException { - final var fieldInjectionType = progress.request().parameters().fieldInjectionType(); + void setField(final ParsedProperty property, final String parentVariable, final String fieldType) throws GenerationException { if (fieldInjectionType instanceof final ControllerFieldInjectionTypes fieldTypes) { switch (fieldTypes) { - case ASSIGN -> setAssign(progress, property, parentVariable); - case FACTORY -> setFactory(progress, property, parentVariable); - case SETTERS -> setSetter(progress, property, parentVariable); - case REFLECTION -> setReflection(progress, property, parentVariable, fieldType); + case ASSIGN -> setAssign(property, parentVariable); + case FACTORY -> setFactory(property, parentVariable); + case SETTERS -> setSetter(property, parentVariable); + case REFLECTION -> setReflection(property, parentVariable, fieldType); } } else { 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 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) { - progress.controllerFactoryPostAction().add(getSetString(property, parentVariable)); + private void setFactory(final ParsedProperty property, final String parentVariable) { + controllerFactoryPostAction.add(getSetString(property, parentVariable)); } - private static void setSetter(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) { - progress.stringBuilder().append(getSetString(property, parentVariable)); + private void setSetter(final ParsedProperty property, final String parentVariable) { + sb.append(getSetString(property, 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"; } - 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 value = property.value().replace(EXPRESSION_PREFIX, ""); final var split = value.split("\\."); final var fieldName = split[1]; - final var sb = progress.stringBuilder(); 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(" final var value = (").append(fieldType).append(") field.get(controller);\n"); sb.append(" ").append(parentVariable).append(".").append(methodName).append("(value);\n"); diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FontFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FontFormatter.java index 8d25ff0..b7da57e 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FontFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/FontFormatter.java @@ -11,6 +11,7 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; 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.getSortedAttributes; @@ -20,15 +21,19 @@ import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.get */ 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) { - return GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.text.Font"); + private String getStartFont() { + 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()) { final var value = parseFontValue(parsedObject); final var url = value.url(); @@ -37,37 +42,36 @@ final class FontFormatter { final var size = value.size(); final var name = value.name(); if (url != null) { - formatURL(progress, url, size, variableName); + formatURL(url, size, variableName); } else if (fw == null && fp == null) { - formatNoStyle(progress, name, size, variableName); + formatNoStyle(name, size, variableName); } 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 { 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) { - final var urlVariableName = URLFormatter.formatURL(progress, url.toString()); - final var sb = progress.stringBuilder(); + private void formatURL(final URL url, final double size, final String variableName) { + final var urlVariableName = helperProvider.getURLFormatter().formatURL(url.toString()); 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(" } catch (final java.io.IOException e) {\n"); sb.append(" throw new RuntimeException(e);\n"); sb.append(" }\n"); } - private static void formatNoStyle(final GenerationProgress progress, 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"); + private void formatNoStyle(final String name, final double size, final String variableName) { + 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 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(finalFP.name()).append(", ").append(size).append(");\n"); } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationCompatibilityHelper.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationCompatibilityHelper.java index f04ad49..d752d5c 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationCompatibilityHelper.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationCompatibilityHelper.java @@ -1,52 +1,59 @@ package com.github.gtache.fxml.compiler.impl.internal; 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.parsing.ParsedObject; +import java.util.Objects; + /** * Various helper methods for {@link GeneratorImpl} to handle compatibility with older java versions */ 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 { - return getStartVar(progress, parsedObject.className() + ReflectionHelper.getGenericTypes(progress, parsedObject)); + String getStartVar(final ParsedObject parsedObject) throws GenerationException { + return getStartVar(parsedObject.className() + helperProvider.getReflectionHelper().getGenericTypes(parsedObject)); } - static String getStartVar(final GenerationProgress progress, final String className) { - return getStartVar(progress, className, 8); + String getStartVar(final String className) { + return getStartVar(className, 8); } - static String getStartVar(final GenerationProgress progress, final String className, final int indent) { - if (progress.request().parameters().compatibility().useVar()) { + String getStartVar(final String className, final int indent) { + if (compatibility.useVar()) { return " ".repeat(indent) + "final var "; } else { return " ".repeat(indent) + "final " + className + " "; } } - static String getToList(final GenerationProgress progress) { - return switch (progress.request().parameters().compatibility().listCollector()) { + String getToList() { + return switch (compatibility.listCollector()) { case TO_LIST -> ".toList()"; case COLLECT_TO_UNMODIFIABLE_LIST -> ".collect(java.util.stream.Collectors.toUnmodifiableList())"; case COLLECT_TO_LIST -> ".collect(java.util.stream.Collectors.toList())"; }; } - static String getGetFirst(final GenerationProgress progress) { - if (progress.request().parameters().compatibility().useGetFirst()) { + String getGetFirst() { + if (compatibility.useGetFirst()) { return ".getFirst()"; } else { return ".get(0)"; } } - static String getListOf(final GenerationProgress progress) { - if (progress.request().parameters().compatibility().useCollectionsOf()) { + String getListOf() { + if (compatibility.useCollectionsOf()) { return "java.util.List.of("; } else { return "java.util.Arrays.asList("; diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationHelper.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationHelper.java index 83466bf..a198550 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationHelper.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationHelper.java @@ -1,5 +1,6 @@ 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.impl.GeneratorImpl; 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.Map; +import static java.util.Objects.requireNonNull; + /** * Various helper methods for {@link GeneratorImpl} */ @@ -28,35 +31,41 @@ final class GenerationHelper { static final String BINDING_EXPRESSION_PREFIX = "${"; static final String BI_DIRECTIONAL_BINDING_PREFIX = "#{"; + private final HelperProvider helperProvider; + private final ControllerInfo controllerInfo; + private final Map idToVariableInfo; - private GenerationHelper() { + GenerationHelper(final HelperProvider helperProvider, final ControllerInfo controllerInfo, final Map idToVariableInfo) { + this.helperProvider = requireNonNull(helperProvider); + this.controllerInfo = requireNonNull(controllerInfo); + this.idToVariableInfo = requireNonNull(idToVariableInfo); } /** * Handles the fx:id attribute of an object * - * @param progress The generation progress * @param parsedObject The parsed object * @param variableName The variable name * @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); if (id != null) { final var idValue = id.value(); final String className; - if (progress.request().controllerInfo().fieldInfo(idValue) == null) { + if (controllerInfo.fieldInfo(idValue) == null) { className = parsedObject.className(); logger.debug("Not injecting {} because it is not found in controller", idValue); } else { + final var reflectionHelper = helperProvider.getReflectionHelper(); if (ReflectionHelper.isGeneric(ReflectionHelper.getClass(parsedObject.className()))) { - className = parsedObject.className() + ReflectionHelper.getGenericTypes(progress, parsedObject); + className = parsedObject.className() + reflectionHelper.getGenericTypes(parsedObject); } else { 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)); } } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationProgress.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationProgress.java index 7d9ad3c..b88794d 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationProgress.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/GenerationProgress.java @@ -64,7 +64,7 @@ public record GenerationProgress(GenerationRequest request, Map new AtomicInteger(0)); return prefix + counter.getAndIncrement(); } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperMethodsFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperMethodsFormatter.java index 9b80366..151d039 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperMethodsFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperMethodsFormatter.java @@ -1,30 +1,37 @@ 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.ControllerMethodsInjectionType; +import java.util.Objects; + /** * Formats the helper methods for the generated code */ 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 - * - * @param progress The generation progress + * Formats the helper methods */ - public static void formatHelperMethods(final GenerationProgress progress) { - final var parameters = progress.request().parameters(); - final var methodInjectionType = parameters.methodInjectionType(); - final var sb = progress.stringBuilder(); + public void formatHelperMethods() { + final var compatibilityHelper = helperProvider.getCompatibilityHelper(); if (methodInjectionType == ControllerMethodsInjectionType.REFLECTION) { - final var toList = GenerationCompatibilityHelper.getToList(progress); - final var getFirst = GenerationCompatibilityHelper.getGetFirst(progress); - final var startVariableMethodList = GenerationCompatibilityHelper.getStartVar(progress, "java.util.List", 0); + final var toList = compatibilityHelper.getToList(); + final var getFirst = compatibilityHelper.getGetFirst(); + final var startVariableMethodList = compatibilityHelper.getStartVar("java.util.List", 0); sb.append(" private void callEventHandlerMethod(final String methodName, final T event) {\n"); sb.append(" try {\n"); sb.append(" final java.lang.reflect.Method method;\n"); @@ -84,10 +91,10 @@ public final class HelperMethodsFormatter { sb.append(" }\n"); sb.append(" }\n"); } - if (parameters.fieldInjectionType() == ControllerFieldInjectionTypes.REFLECTION) { + if (fieldInjectionType == ControllerFieldInjectionTypes.REFLECTION) { sb.append(" private void injectField(final String fieldName, final T object) {\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.set(controller, object);\n"); sb.append(" } catch (final NoSuchFieldException | IllegalAccessException e) {\n"); diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperProvider.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperProvider.java new file mode 100644 index 0000000..ed1a4eb --- /dev/null +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/HelperProvider.java @@ -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, 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)); + } +} diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ImageFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ImageFormatter.java index fa0cd3e..9224cb6 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ImageFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ImageFormatter.java @@ -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.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.getSortedAttributes; @@ -12,24 +14,28 @@ import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.get */ 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()) { - doFormatImage(progress, parsedObject, variableName); + doFormatImage(parsedObject, variableName); } else { throw new GenerationException("Image cannot have children or properties : " + parsedObject); } } - private static void formatInputStream(final GenerationProgress progress, final String url, final double requestedWidth, - final double requestedHeight, final boolean preserveRatio, final boolean smooth, final String variableName) { + private void formatInputStream(final String url, final double requestedWidth, + final double requestedHeight, final boolean preserveRatio, final boolean smooth, final String variableName) { final var inputStream = progress.getNextVariableName("inputStream"); final var sb = progress.stringBuilder(); 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(requestedWidth).append(", ").append(requestedHeight).append(", ").append(preserveRatio).append(", ").append(smooth).append(");\n"); sb.append(" } catch (final java.io.IOException e) {\n"); @@ -37,7 +43,7 @@ final class ImageFormatter { 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); String url = null; var requestedWidth = 0.0; @@ -50,7 +56,7 @@ final class ImageFormatter { case FX_ID -> { //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 "requestedHeight" -> requestedHeight = Double.parseDouble(property.value()); case "preserveRatio" -> preserveRatio = Boolean.parseBoolean(property.value()); @@ -61,20 +67,21 @@ final class ImageFormatter { } if (progress.request().parameters().useImageInputStreamConstructor()) { - formatInputStream(progress, url, requestedWidth, requestedHeight, preserveRatio, smooth, variableName); + formatInputStream(url, requestedWidth, requestedHeight, preserveRatio, smooth, variableName); } 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, - final double requestedHeight, final boolean preserveRatio, final boolean smooth, - final boolean backgroundLoading, final String variableName) { + private void formatURL(final String url, final double requestedWidth, + final double requestedHeight, final boolean preserveRatio, final boolean smooth, + final boolean backgroundLoading, final String variableName) { final var urlString = progress.getNextVariableName("urlStr"); final var sb = progress.stringBuilder(); - sb.append(GenerationCompatibilityHelper.getStartVar(progress, "String")).append(urlString).append(" = ").append(url).append(".toString();\n"); - sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.image.Image")).append(variableName).append(" = new javafx.scene.image.Image(").append(urlString) + final var compatibilityHelper = helperProvider.getCompatibilityHelper(); + 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(preserveRatio).append(", ").append(smooth).append(", ").append(backgroundLoading).append(");\n"); } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/InitializationFormatter.java similarity index 82% rename from core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorFormatter.java rename to core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/InitializationFormatter.java index 54f19a8..33ec821 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ConstructorFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/InitializationFormatter.java @@ -7,32 +7,38 @@ import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes; import com.github.gtache.fxml.compiler.parsing.ParsedInclude; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; /** * 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 simpleClassName = className.substring(className.lastIndexOf('.') + 1); final var mainControllerClass = progress.request().controllerInfo().className(); 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"); } - fillControllers(progress); + fillControllers(); final var sb = progress.stringBuilder(); final var controllerMap = progress.controllerClassToVariable(); 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 controllerArgClass = getType(mainControllerClass, isFactory); - final var resourceBundleInfo = getResourceBundleInfo(progress); + final var resourceBundleInfo = getResourceBundleInfo(); final var resourceBundleType = resourceBundleInfo.type(); final var resourceBundleArg = resourceBundleInfo.variableName(); if (isFactory) { @@ -70,7 +76,7 @@ public final class ConstructorFormatter { sb.append(" }\n"); } - private static ResourceBundleInfo getResourceBundleInfo(final GenerationProgress progress) throws GenerationException { + private ResourceBundleInfo getResourceBundleInfo() throws GenerationException { final var injectionType = progress.request().parameters().resourceInjectionType(); if (injectionType instanceof final ResourceBundleInjectionTypes types) { return switch (types) { @@ -109,7 +115,7 @@ public final class ConstructorFormatter { return variableName + suffix; } - private static boolean hasDuplicateControllerClass(final GenerationProgress progress) { + private boolean hasDuplicateControllerClass() { final var set = new HashSet(); return hasDuplicateControllerClass(progress.request().sourceInfo(), set); } @@ -122,13 +128,13 @@ public final class ConstructorFormatter { return info.includedSources().stream().anyMatch(s -> hasDuplicateControllerClass(s, controllers)); } - private static void fillControllers(final GenerationProgress progress) { - progress.request().sourceInfo().includedSources().forEach(s -> fillControllers(progress, s)); + private void fillControllers() { + 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()))); - info.includedSources().forEach(s -> fillControllers(progress, s)); + info.includedSources().forEach(this::fillControllers); } private static void fillControllers(final SourceInfo info, final Set controllers) { @@ -136,7 +142,7 @@ public final class ConstructorFormatter { 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 info = request.sourceInfo(); final var subInfo = info.sourceToSourceInfo().get(include.source()); @@ -149,17 +155,17 @@ public final class ConstructorFormatter { final var subControllers = new HashSet(); 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 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 subViewName = subInfo.generatedClassName(); 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; } } - private static String getBundleVariable(final GenerationProgress progress, final ParsedInclude include) throws GenerationException { - final var info = getResourceBundleInfo(progress); + private String getBundleVariable(final ParsedInclude include) throws GenerationException { + final var info = getResourceBundleInfo(); if (info.type() == null) { return null; } else if (include.resources() == null) { @@ -167,21 +173,22 @@ public final class ConstructorFormatter { } else { final var sb = progress.stringBuilder(); if (progress.request().parameters().resourceInjectionType() instanceof final ResourceBundleInjectionTypes types) { + final var compatibilityHelper = helperProvider.getCompatibilityHelper(); return switch (types) { case GETTER, GET_BUNDLE -> null; case CONSTRUCTOR_NAME -> { 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; } case CONSTRUCTOR_FUNCTION -> { final var bundleVariable = progress.getNextVariableName("resourceBundleFunction"); - sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.function.Function")).append(bundleVariable).append(" = (java.util.function.Function) s -> \"").append(include.resources()).append("\";\n"); + sb.append(compatibilityHelper.getStartVar("java.util.function.Function")).append(bundleVariable).append(" = (java.util.function.Function) s -> \"").append(include.resources()).append("\";\n"); yield bundleVariable; } case CONSTRUCTOR -> { 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; } }; diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/LoadMethodFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/LoadMethodFormatter.java index 6606903..aca810f 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/LoadMethodFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/LoadMethodFormatter.java @@ -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.ResourceBundleInjectionTypes; +import static java.util.Objects.requireNonNull; + /** * Formats the load method for the generated code */ 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 * - * @param progress The generation progress * @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 rootObject = request.rootObject(); final var parameters = progress.request().parameters(); @@ -36,23 +42,24 @@ public final class LoadMethodFormatter { sb.append(" throw new IllegalStateException(\"Already loaded\");\n"); sb.append(" }\n"); final var resourceBundleInjection = parameters.resourceInjectionType(); + final var generationCompatibilityHelper = helperProvider.getCompatibilityHelper(); 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)) { - 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) { - sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.Map")).append("fieldMap = new java.util.HashMap();\n"); + sb.append(generationCompatibilityHelper.getStartVar("java.util.Map")).append("fieldMap = new java.util.HashMap();\n"); } final var variableName = progress.getNextVariableName(GenerationHelper.getVariablePrefix(rootObject)); - ObjectFormatter.format(progress, rootObject, variableName); + helperProvider.getObjectFormatter().format(rootObject, variableName); if (controllerInjectionType == ControllerFieldInjectionTypes.FACTORY) { sb.append(" controller = (").append(controllerClass).append(") controllerFactory.create(fieldMap);\n"); progress.controllerFactoryPostAction().forEach(sb::append); } if (parameters.methodInjectionType() == ControllerMethodsInjectionType.REFLECTION) { 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.invoke(controller);\n"); sb.append(" } catch (final java.lang.reflect.InvocationTargetException | IllegalAccessException e) {\n"); diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ObjectFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ObjectFormatter.java index cdd0796..8d3189b 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ObjectFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ObjectFormatter.java @@ -16,6 +16,7 @@ import java.util.Set; import java.util.stream.Collectors; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*; +import static java.util.Objects.requireNonNull; /** * Helper methods for {@link GeneratorImpl} to format properties @@ -45,103 +46,106 @@ public final class ObjectFormatter { "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 * - * @param progress The generation progress * @param parsedObject The parsed object to format * @param variableName The variable name for the object * @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) { - case final ParsedConstant constant -> formatConstant(progress, constant, variableName); - case final ParsedCopy copy -> formatCopy(progress, copy, variableName); - case final ParsedDefine define -> formatDefine(progress, define); - case final ParsedFactory factory -> formatFactory(progress, factory, variableName); - case final ParsedInclude include -> formatInclude(progress, include, variableName); - case final ParsedReference reference -> formatReference(progress, reference, variableName); - case final ParsedValue value -> formatValue(progress, value, variableName); - case final ParsedText text -> formatText(progress, text, variableName); - default -> formatObject(progress, parsedObject, variableName); + case final ParsedConstant constant -> formatConstant(constant, variableName); + case final ParsedCopy copy -> formatCopy(copy, variableName); + case final ParsedDefine define -> formatDefine(define); + case final ParsedFactory factory -> formatFactory(factory, variableName); + case final ParsedInclude include -> formatInclude(include, variableName); + case final ParsedReference reference -> formatReference(reference, variableName); + case final ParsedValue value -> formatValue(value, variableName); + case final ParsedText text -> formatText(text, variableName); + default -> formatObject(parsedObject, variableName); } } /** * Formats a simple text * - * @param progress The generation progress * @param text The parsed text * @param variableName The variable name */ - private static void formatText(final GenerationProgress progress, final ParsedText text, final String variableName) { - progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, "String")).append(variableName).append(" = \"").append(text.text()).append("\";\n"); + private void formatText(final ParsedText text, final String variableName) { + progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar("String")).append(variableName).append(" = \"").append(text.text()).append("\";\n"); } /** * Formats a basic object * - * @param progress The generation progress * @param parsedObject The parsed object to format * @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())) { - formatBuilderObject(progress, parsedObject, variableName); + formatBuilderObject(parsedObject, variableName); } else { - formatNotBuilder(progress, parsedObject, variableName); + formatNotBuilder(parsedObject, variableName); } } /** * Formats a builder object * - * @param progress The generation progress * @param parsedObject The parsed object * @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(); switch (className) { - case "javafx.scene.Scene" -> SceneFormatter.formatScene(progress, parsedObject, variableName); - case "javafx.scene.text.Font" -> FontFormatter.formatFont(progress, parsedObject, variableName); - case "javafx.scene.image.Image" -> ImageFormatter.formatImage(progress, parsedObject, variableName); - case "java.net.URL" -> URLFormatter.formatURL(progress, parsedObject, variableName); + case "javafx.scene.Scene" -> helperProvider.getSceneFormatter().formatScene(parsedObject, variableName); + case "javafx.scene.text.Font" -> helperProvider.getFontFormatter().formatFont(parsedObject, variableName); + case "javafx.scene.image.Image" -> + helperProvider.getImageFormatter().formatImage(parsedObject, variableName); + case "java.net.URL" -> helperProvider.getURLFormatter().formatURL(parsedObject, variableName); case "javafx.scene.shape.TriangleMesh" -> - TriangleMeshFormatter.formatTriangleMesh(progress, parsedObject, variableName); - case "javafx.scene.web.WebView" -> WebViewFormatter.formatWebView(progress, parsedObject, variableName); + helperProvider.getTriangleMeshFormatter().formatTriangleMesh(parsedObject, variableName); + case "javafx.scene.web.WebView" -> + helperProvider.getWebViewFormatter().formatWebView(parsedObject, variableName); 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)) { - formatSimpleClass(progress, parsedObject, variableName); + formatSimpleClass(parsedObject, variableName); } 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()) { 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))) { throw new GenerationException("Invalid attributes for simple class : " + parsedObject); } - final var value = getSimpleValue(progress, parsedObject); - final var valueStr = ValueFormatter.toString(value, ReflectionHelper.getClass(parsedObject.className())); - progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, parsedObject)).append(variableName).append(" = ").append(valueStr).append(";\n"); - GenerationHelper.handleId(progress, parsedObject, variableName); + final var value = getSimpleValue(parsedObject); + final var valueStr = helperProvider.getValueFormatter().toString(value, ReflectionHelper.getClass(parsedObject.className())); + progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(parsedObject)).append(variableName).append(" = ").append(valueStr).append(";\n"); + 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(); 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(); 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(); if (SIMPLE_CLASSES.contains(className)) { 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 children = parsedObject.children(); 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())); if (!definedChildren.isEmpty()) { for (final var definedChild : definedChildren) { - format(progress, definedChild, progress.getNextVariableName("define")); + format(definedChild, progress.getNextVariableName("define")); } } if (!notDefinedChildren.isEmpty()) { @@ -213,31 +217,32 @@ public final class ObjectFormatter { } final var constructorArgs = ConstructorHelper.getMatchingConstructorArgs(constructors, allPropertyNames); if (constructorArgs == null) { - formatNoConstructor(progress, parsedObject, variableName, allPropertyNames); + formatNoConstructor(parsedObject, variableName, allPropertyNames); } 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 allPropertyNames) throws GenerationException { + private void formatNoConstructor(final ParsedObject parsedObject, final String variableName, final Collection allPropertyNames) throws GenerationException { final var clazz = ReflectionHelper.getClass(parsedObject.className()); if (allPropertyNames.size() == 1 && allPropertyNames.iterator().next().equals("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 { 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 { - final var args = ConstructorHelper.getListConstructorArgs(constructorArgs, parsedObject); - final var genericTypes = ReflectionHelper.getGenericTypes(progress, parsedObject); - progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, parsedObject)).append(variableName).append(NEW_ASSIGN).append(parsedObject.className()) + private void formatConstructor(final ParsedObject parsedObject, final String variableName, final ConstructorArgs constructorArgs) throws GenerationException { + final var reflectionHelper = helperProvider.getReflectionHelper(); + final var args = helperProvider.getConstructorHelper().getListConstructorArgs(constructorArgs, parsedObject); + 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"); final var sortedAttributes = getSortedAttributes(parsedObject); for (final var value : sortedAttributes) { 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(); @@ -245,7 +250,7 @@ public final class ObjectFormatter { if (!constructorArgs.namedArgs().containsKey(e.getKey().name())) { final var p = e.getKey(); 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(); @@ -253,7 +258,7 @@ public final class ObjectFormatter { final var defaultProperty = ReflectionHelper.getDefaultProperty(parsedObject.className()); if (!constructorArgs.namedArgs().containsKey(defaultProperty)) { 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 * - * @param progress The generation progress * @param include The include object * @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 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"); - 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(); if (id != null) { final var subControllerVariable = progress.getNextVariableName("controller"); 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)); if (progress.request().controllerInfo().fieldInfo(id) == null) { logger.debug("Not injecting {} because it is not found in controller", id); } else { - ControllerInjector.injectControllerField(progress, id, subControllerVariable); + helperProvider.getControllerInjector().injectControllerField(id, subControllerVariable); } } } @@ -290,93 +294,88 @@ public final class ObjectFormatter { /** * Formats a fx:define * - * @param progress The generation progress * @param define The parsed define * @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()) { - format(progress, child, progress.getNextVariableName("definedObject")); + format(child, progress.getNextVariableName("definedObject")); } } /** * Formats a fx:reference * - * @param progress The generation progress * @param reference The parsed reference * @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 variableInfo = progress.idToVariableInfo().get(id); if (variableInfo == null) { throw new GenerationException("Unknown id : " + id); } 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 * - * @param progress The generation progress * @param copy The parsed copy * @param variableName The variable name * @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 variableInfo = progress.idToVariableInfo().get(id); if (variableInfo == null) { throw new GenerationException("Unknown id : " + id); } 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 * - * @param progress The generation progress * @param constant The constant * @param variableName The variable name */ - private static void formatConstant(final GenerationProgress progress, final ParsedConstant constant, final String variableName) { - progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, constant.className())).append(variableName).append(" = ").append(constant.className()).append(".").append(constant.constant()).append(";\n"); + private void formatConstant(final ParsedConstant constant, final String variableName) throws GenerationException { + progress.stringBuilder().append(helperProvider.getCompatibilityHelper().getStartVar(constant.className())).append(variableName).append(" = ").append(constant.className()).append(".").append(constant.constant()).append(";\n"); } /** * Formats a value object * - * @param progress The generation progress * @param value The value * @param variableName The variable name */ - private static void formatValue(final GenerationProgress progress, final ParsedValue value, final String variableName) { - progress.stringBuilder().append(GenerationCompatibilityHelper.getStartVar(progress, value.className())).append(variableName).append(" = ").append(value.className()).append(".valueOf(\"").append(value.value()).append("\");\n"); + private void formatValue(final ParsedValue value, final String variableName) throws GenerationException { + 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 * - * @param progress The generation progress * @param factory The factory * @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(); for (final var argument : factory.arguments()) { final var argumentVariable = progress.getNextVariableName("arg"); variables.add(argumentVariable); - format(progress, argument, argumentVariable); + format(argument, argumentVariable); } + final var compatibilityHelper = helperProvider.getCompatibilityHelper(); 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"); } else { 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"); } } @@ -384,45 +383,43 @@ public final class ObjectFormatter { /** * Formats the children objects of a property * - * @param progress The generation progress * @param parent The parent object * @param property The parent property * @param objects The child objects * @param parentVariable The parent object variable */ - private static void formatChild(final GenerationProgress progress, final ParsedObject parent, final ParsedProperty property, - final Iterable objects, final String parentVariable) throws GenerationException { + private void formatChild(final ParsedObject parent, final ParsedProperty property, + final Iterable objects, final String parentVariable) throws GenerationException { final var propertyName = property.name(); final var variables = new ArrayList(); for (final var object : objects) { - final var vn = progress.getNextVariableName(GenerationHelper.getVariablePrefix(object)); - format(progress, object, vn); + final var vn = progress.getNextVariableName(getVariablePrefix(object)); + format(object, vn); if (!(object instanceof ParsedDefine)) { variables.add(vn); } } if (variables.size() > 1) { - formatMultipleChildren(progress, variables, propertyName, parent, parentVariable); + formatMultipleChildren(variables, propertyName, parent, parentVariable); } else if (variables.size() == 1) { 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 * - * @param progress The generation progress * @param variables The children variables * @param propertyName The property name * @param parent The parent object * @param parentVariable The parent object variable */ - private static void formatMultipleChildren(final GenerationProgress progress, final Iterable variables, final String propertyName, final ParsedObject parent, - final String parentVariable) throws GenerationException { - final var getMethod = GenerationHelper.getGetMethod(propertyName); + private void formatMultipleChildren(final Iterable variables, final String propertyName, final ParsedObject parent, + final String parentVariable) throws GenerationException { + final var getMethod = getGetMethod(propertyName); 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 { throw getCannotSetException(propertyName, parent.className()); } @@ -431,42 +428,40 @@ public final class ObjectFormatter { /** * Formats a single child object * - * @param progress The generation progress * @param variableName The child's variable name * @param property The parent property * @param parent The parent object * @param parentVariable The parent object variable */ - private static void formatSingleChild(final GenerationProgress progress, final String variableName, final ParsedProperty property, final ParsedObject parent, - final String parentVariable) throws GenerationException { + private void formatSingleChild(final String variableName, final ParsedProperty property, final ParsedObject parent, + final String parentVariable) throws GenerationException { if (property.sourceType() == null) { - formatSingleChildInstance(progress, variableName, property, parent, parentVariable); + formatSingleChildInstance(variableName, property, parent, parentVariable); } else { - formatSingleChildStatic(progress, variableName, property, parentVariable); + formatSingleChildStatic(variableName, property, parentVariable); } } /** * 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 property The parent property * @param parent The parent object * @param parentVariable The parent object variable */ - private static void formatSingleChildInstance(final GenerationProgress progress, final String variableName, - final ParsedProperty property, final ParsedObject parent, - final String parentVariable) throws GenerationException { - final var setMethod = GenerationHelper.getSetMethod(property); - final var getMethod = GenerationHelper.getGetMethod(property); + private void formatSingleChildInstance(final String variableName, + final ParsedProperty property, final ParsedObject parent, + final String parentVariable) throws GenerationException { + final var setMethod = getSetMethod(property); + final var getMethod = getGetMethod(property); final var parentClass = ReflectionHelper.getClass(parent.className()); final var sb = progress.stringBuilder(); if (ReflectionHelper.hasMethod(parentClass, setMethod)) { sb.append(" ").append(parentVariable).append(".").append(setMethod).append("(").append(variableName).append(");\n"); } else if (ReflectionHelper.hasMethod(parentClass, getMethod)) { //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 { throw getCannotSetException(property.name(), parent.className()); } @@ -475,14 +470,13 @@ public final class ObjectFormatter { /** * Formats a child object using a static method * - * @param progress The generation progress * @param variableName The child's variable name * @param property The parent property * @param parentVariable The parent variable */ - private static void formatSingleChildStatic(final GenerationProgress progress, final String variableName, - final ParsedProperty property, final String parentVariable) throws GenerationException { - final var setMethod = GenerationHelper.getSetMethod(property); + private void formatSingleChildStatic(final String variableName, + final ParsedProperty property, final String parentVariable) throws GenerationException { + final var setMethod = getSetMethod(property); if (ReflectionHelper.hasStaticMethod(ReflectionHelper.getClass(property.sourceType()), setMethod)) { progress.stringBuilder().append(" ").append(property.sourceType()).append(".").append(setMethod) .append("(").append(parentVariable).append(", ").append(variableName).append(");\n"); diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/PropertyFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/PropertyFormatter.java index 411bacd..c7b2db9 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/PropertyFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/PropertyFormatter.java @@ -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.RESOURCE_KEY_PREFIX; +import static java.util.Objects.requireNonNull; /** * Helper methods for {@link GeneratorImpl} to format properties */ 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 * - * @param progress The generation progress * @param property The property to format * @param parent The property's parent object * @param parentVariable The parent variable * @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(); if (propertyName.equals(FX_ID)) { - GenerationHelper.handleId(progress, parent, parentVariable); + helperProvider.getGenerationHelper().handleId(parent, parentVariable); } else if (propertyName.equals("fx:controller")) { - checkDuplicateController(progress, parent); + checkDuplicateController(parent); } else if (Objects.equals(property.sourceType(), EventHandler.class.getName())) { - handleEventHandler(progress, property, parentVariable); + handleEventHandler(property, parentVariable); } else if (property.sourceType() != null) { - handleStaticProperty(progress, property, parentVariable, propertyName); + handleStaticProperty(property, parentVariable, propertyName); } 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()) { 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("#")) { - ControllerInjector.injectEventHandlerControllerMethod(progress, property, parentVariable); + helperProvider.getControllerInjector().injectEventHandlerControllerMethod(property, parentVariable); } 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 propertySourceTypeClass = ReflectionHelper.getClass(property.sourceType()); if (ReflectionHelper.hasStaticMethod(propertySourceTypeClass, setMethod)) { final var method = ReflectionHelper.getStaticMethod(propertySourceTypeClass, setMethod); final var parameterType = method.getParameterTypes()[1]; - final var arg = ValueFormatter.getArg(progress, property.value(), parameterType); - setLaterIfNeeded(progress, property, parameterType, " " + property.sourceType() + "." + setMethod + "(" + parentVariable + ", " + arg + ");\n"); + final var arg = helperProvider.getValueFormatter().getArg(property.value(), parameterType); + setLaterIfNeeded(property, parameterType, " " + property.sourceType() + "." + setMethod + "(" + parentVariable + ", " + arg + ");\n"); } else { 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 setMethod = GenerationHelper.getSetMethod(propertyName); final var getMethod = GenerationHelper.getGetMethod(propertyName); final var parentClass = ReflectionHelper.getClass(parent.className()); if (ReflectionHelper.hasMethod(parentClass, setMethod)) { - handleSetProperty(progress, property, parentClass, parentVariable); + handleSetProperty(property, parentClass, parentVariable); } else if (ReflectionHelper.hasMethod(parentClass, getMethod)) { - handleGetProperty(progress, property, parentClass, parentVariable); + handleGetProperty(property, parentClass, parentVariable); } else { 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 method = ReflectionHelper.getMethod(parentClass, setMethod); final var parameterType = method.getParameterTypes()[0]; - final var arg = ValueFormatter.getArg(progress, property.value(), parameterType); - setLaterIfNeeded(progress, property, parameterType, " " + parentVariable + "." + setMethod + "(" + arg + ");\n"); + final var arg = helperProvider.getValueFormatter().getArg(property.value(), parameterType); + 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 method = ReflectionHelper.getMethod(parentClass, getMethod); final var returnType = method.getReturnType(); if (ReflectionHelper.hasMethod(returnType, "addAll")) { - final var arg = ValueFormatter.getArg(progress, property.value(), String.class); - setLaterIfNeeded(progress, property, String.class, " " + parentVariable + "." + getMethod + "().addAll(" + GenerationCompatibilityHelper.getListOf(progress) + arg + "));\n"); + final var arg = helperProvider.getValueFormatter().getArg(property.value(), String.class); + 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 * - * @param progress The generation progress * @param property The property * @param type The type * @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(); if (type == String.class && property.value().startsWith(RESOURCE_KEY_PREFIX) && parameters.resourceInjectionType() == ResourceBundleInjectionTypes.GETTER && parameters.fieldInjectionType() == ControllerFieldInjectionTypes.FACTORY) { diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ReflectionHelper.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ReflectionHelper.java index 1ad8f87..d6a1237 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ReflectionHelper.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ReflectionHelper.java @@ -1,5 +1,6 @@ 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.GenericTypes; import com.github.gtache.fxml.compiler.parsing.ParsedObject; @@ -18,6 +19,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -45,8 +47,10 @@ final class ReflectionHelper { "float", float.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 * - * @param progress The generation progress * @param parsedObject The parsed object * @return The generic types * @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()); if (isGeneric(clazz)) { final var idProperty = parsedObject.attributes().get(FX_ID); @@ -337,7 +340,7 @@ final class ReflectionHelper { return ""; } else { final var id = idProperty.value(); - final var fieldInfo = progress.request().controllerInfo().fieldInfo(id); + final var fieldInfo = controllerInfo.fieldInfo(id); if (fieldInfo == null) { //Not found logger.warn("No field found for generic class {} (id={}) ; Using raw", clazz.getName(), id); return ""; diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/SceneFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/SceneFormatter.java index 544d955..0410856 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/SceneFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/SceneFormatter.java @@ -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.getSortedAttributes; +import static java.util.Objects.requireNonNull; /** * Helper methods for {@link GeneratorImpl} to format Scenes */ 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 rootVariableName = progress.getNextVariableName("root"); - ObjectFormatter.format(progress, root, rootVariableName); + helperProvider.getObjectFormatter().format(root, rootVariableName); final var sortedAttributes = getSortedAttributes(parsedObject); double width = -1; double height = -1; @@ -41,10 +47,10 @@ final class SceneFormatter { } } 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"); - addStylesheets(progress, variableName, stylesheets); - GenerationHelper.handleId(progress, parsedObject, variableName); + addStylesheets(variableName, stylesheets); + helperProvider.getGenerationHelper().handleId(parsedObject, variableName); } 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 stylesheets) { + private void addStylesheets(final String variableName, final Collection stylesheets) throws GenerationException { 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 sb = progress.stringBuilder(); - sb.append(GenerationCompatibilityHelper.getStartVar(progress, "java.util.List")).append(tmpVariable).append(" = ").append(variableName).append(".getStyleSheets();\n"); - sb.append(" ").append(tmpVariable).append(".addAll(").append(GenerationCompatibilityHelper.getListOf(progress)).append(String.join(", ", urlVariables)).append("));\n"); + final var compatibilityHelper = helperProvider.getCompatibilityHelper(); + sb.append(compatibilityHelper.getStartVar("java.util.List")).append(tmpVariable).append(" = ").append(variableName).append(".getStyleSheets();\n"); + sb.append(" ").append(tmpVariable).append(".addAll(").append(compatibilityHelper.getListOf()).append(String.join(", ", urlVariables)).append("));\n"); } } } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/TriangleMeshFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/TriangleMeshFormatter.java index d904079..c4875a0 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/TriangleMeshFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/TriangleMeshFormatter.java @@ -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.getSortedAttributes; +import static java.util.Objects.requireNonNull; /** * Helper methods for {@link GeneratorImpl} to format TriangleMeshes */ 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()) { final var sortedAttributes = getSortedAttributes(parsedObject); final var points = new ArrayList(); @@ -63,15 +69,14 @@ final class TriangleMeshFormatter { default -> throw new GenerationException("Unknown TriangleMesh attribute : " + property.name()); } } - final var sb = progress.stringBuilder(); - sb.append(GenerationCompatibilityHelper.getStartVar(progress, "javafx.scene.shape.TriangleMesh")).append(variableName).append(" = new javafx.scene.shape.TriangleMesh();\n"); - setPoints(progress, variableName, points); - setTexCoords(progress, variableName, texCoords); - setNormals(progress, variableName, normals); - setFaces(progress, variableName, faces); - setFaceSmoothingGroups(progress, variableName, faceSmoothingGroups); - setVertexFormat(progress, variableName, vertexFormat); - GenerationHelper.handleId(progress, parsedObject, variableName); + sb.append(helperProvider.getCompatibilityHelper().getStartVar("javafx.scene.shape.TriangleMesh")).append(variableName).append(" = new javafx.scene.shape.TriangleMesh();\n"); + setPoints(variableName, points); + setTexCoords(variableName, texCoords); + setNormals(variableName, normals); + setFaces(variableName, faces); + setFaceSmoothingGroups(variableName, faceSmoothingGroups); + setVertexFormat(variableName, vertexFormat); + helperProvider.getGenerationHelper().handleId(parsedObject, variableName); } else { 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 points) { + private void setPoints(final String variableName, final Collection points) { 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 texCoords) { + private void setTexCoords(final String variableName, final Collection texCoords) { 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 normals) { + private void setNormals(final String variableName, final Collection normals) { 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 faces) { + private void setFaces(final String variableName, final Collection faces) { 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 faceSmoothingGroups) { + private void setFaceSmoothingGroups(final String variableName, final Collection faceSmoothingGroups) { 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) { - 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); return Arrays.stream(split).map(parser).collect(Collectors.toList()); } - } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/URLFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/URLFormatter.java index 342ca63..317b88a 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/URLFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/URLFormatter.java @@ -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.parsing.ParsedObject; -import java.util.Collection; +import java.util.ArrayList; import java.util.List; 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 { - 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 formatURL(final GenerationProgress progress, final Collection stylesheets) { - return stylesheets.stream().map(s -> formatURL(progress, s)).toList(); + List formatURL(final Iterable stylesheets) { + final var ret = new ArrayList(); + 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 sb = progress.stringBuilder(); 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 { sb.append(" final java.net.URL ").append(variableName).append(";\n"); sb.append(" try {\n"); @@ -38,7 +48,7 @@ final class URLFormatter { 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()) { final var sortedAttributes = getSortedAttributes(parsedObject); String value = null; @@ -51,14 +61,15 @@ final class URLFormatter { default -> throw new GenerationException("Unknown URL attribute : " + property.name()); } } - progress.stringBuilder().append(getStartURL(progress)).append(variableName).append(" = getClass().getResource(\"").append(value).append("\");\n"); - handleId(progress, parsedObject, variableName); + //FIXME only relative path (@) ? + progress.stringBuilder().append(getStartURL()).append(variableName).append(" = getClass().getResource(\"").append(value).append("\");\n"); + helperProvider.getGenerationHelper().handleId(parsedObject, variableName); } else { throw new GenerationException("URL cannot have children or properties : " + parsedObject); } } - private static String getStartURL(final GenerationProgress progress) { - return GenerationCompatibilityHelper.getStartVar(progress, "java.net.URL"); + private String getStartURL() { + return helperProvider.getCompatibilityHelper().getStartVar("java.net.URL"); } } diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ValueFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ValueFormatter.java index d8945cf..56f4c11 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ValueFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/ValueFormatter.java @@ -1,12 +1,15 @@ 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.GeneratorImpl; import com.github.gtache.fxml.compiler.impl.ResourceBundleInjectionTypes; +import java.util.Map; import java.util.regex.Pattern; import static com.github.gtache.fxml.compiler.impl.internal.GenerationHelper.*; +import static java.util.Objects.requireNonNull; /** * 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 START_BACKSLASH_PATTERN = Pattern.compile("^\\\\"); - private ValueFormatter() { + private final InjectionType resourceInjectionType; + private final Map idToVariableInfo; + + ValueFormatter(final InjectionType resourceInjectionType, final Map idToVariableInfo) { + this.resourceInjectionType = requireNonNull(resourceInjectionType); + this.idToVariableInfo = requireNonNull(idToVariableInfo); } /** * Formats an argument to a method * - * @param progress The generation progress * @param value The value * @param parameterType The parameter type * @return The formatted value * @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)) { - return getBundleValue(progress, value.substring(1)); + return getBundleValue(value.substring(1)); } else if (value.startsWith(RELATIVE_PATH_PREFIX)) { final var subpath = value.substring(1); return getResourceValue(subpath); } 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)) { - final var variable = progress.idToVariableInfo().get(value.substring(1)); + final var variable = idToVariableInfo.get(value.substring(1)); if (variable == null) { throw new GenerationException("Unknown variable : " + value.substring(1)); } @@ -55,21 +62,19 @@ final class ValueFormatter { /** * Gets the resource bundle value for the given value * - * @param progress The generation progress * @param value The value * @return The resource bundle value * @throws GenerationException if an error occurs */ - private static String getBundleValue(final GenerationProgress progress, final String value) throws GenerationException { - final var resourceBundleInjectionType = progress.request().parameters().resourceInjectionType(); - if (resourceBundleInjectionType instanceof final ResourceBundleInjectionTypes types) { + private String getBundleValue(final String value) throws GenerationException { + if (resourceInjectionType instanceof final ResourceBundleInjectionTypes types) { return switch (types) { case CONSTRUCTOR, GET_BUNDLE, CONSTRUCTOR_NAME -> "resourceBundle.getString(\"" + value + "\")"; case GETTER -> "controller.resources().getString(\"" + value + "\")"; case CONSTRUCTOR_FUNCTION -> "resourceBundleFunction.apply(\"" + value + "\")"; }; } 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 * @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) { - 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) { return "'" + value + "'"; } else if (clazz == boolean.class || clazz == Boolean.class) { diff --git a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/WebViewFormatter.java b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/WebViewFormatter.java index 37aa30c..88956a6 100644 --- a/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/WebViewFormatter.java +++ b/core/src/main/java/com/github/gtache/fxml/compiler/impl/internal/WebViewFormatter.java @@ -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.getSortedAttributes; +import static java.util.Objects.requireNonNull; /** * Helper methods for {@link GeneratorImpl} to format WebViews */ 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 * - * @param progress The generation progress * @param parsedObject The parsed object * @param variableName The variable name * @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()) { final var sortedAttributes = getSortedAttributes(parsedObject); 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"); - 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) { - formatAttribute(progress, value, parsedObject, variableName, engineVariable); + formatAttribute(value, parsedObject, variableName, engineVariable); } - GenerationHelper.handleId(progress, parsedObject, variableName); + helperProvider.getGenerationHelper().handleId(parsedObject, variableName); } else { throw new GenerationException("WebView cannot have children or properties : " + parsedObject); } } - private static void formatAttribute(final GenerationProgress progress, final ParsedProperty value, final ParsedObject parsedObject, - final String variableName, final String engineVariable) throws GenerationException { + private void formatAttribute(final ParsedProperty value, final ParsedObject parsedObject, + final String variableName, final String engineVariable) throws GenerationException { switch (value.name()) { case FX_ID -> { //Do nothing } - case "confirmHandler" -> injectConfirmHandler(progress, value, engineVariable); - case "createPopupHandler" -> injectCreatePopupHandler(progress, value, engineVariable); + case "confirmHandler" -> injectConfirmHandler(value, engineVariable); + case "createPopupHandler" -> injectCreatePopupHandler(value, engineVariable); case "onAlert", "onResized", "onStatusChanged", "onVisibilityChanged" -> - injectEventHandler(progress, value, engineVariable); - case "promptHandler" -> injectPromptHandler(progress, value, engineVariable); - case "location" -> injectLocation(progress, value, engineVariable); - default -> PropertyFormatter.formatProperty(progress, value, parsedObject, variableName); + injectEventHandler(value, engineVariable); + case "promptHandler" -> injectPromptHandler(value, engineVariable); + case "location" -> injectLocation(value, engineVariable); + 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("#")) { - ControllerInjector.injectCallbackControllerMethod(progress, value, engineVariable, "String.class"); + helperProvider.getControllerInjector().injectCallbackControllerMethod(value, engineVariable, "String.class"); } 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("#")) { - ControllerInjector.injectCallbackControllerMethod(progress, value, engineVariable, "javafx.scene.web.PopupFeatures.class"); + helperProvider.getControllerInjector().injectCallbackControllerMethod(value, engineVariable, "javafx.scene.web.PopupFeatures.class"); } 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("#")) { - ControllerInjector.injectEventHandlerControllerMethod(progress, value, engineVariable); + helperProvider.getControllerInjector().injectEventHandlerControllerMethod(value, engineVariable); } 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("#")) { - ControllerInjector.injectCallbackControllerMethod(progress, value, engineVariable, "javafx.scene.web.PromptData.class"); + helperProvider.getControllerInjector().injectCallbackControllerMethod(value, engineVariable, "javafx.scene.web.PromptData.class"); } 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"); } @@ -96,11 +102,10 @@ final class WebViewFormatter { /** * Sets a callback field * - * @param progress The generation progress * @param property The property to inject * @param parentVariable The parent variable */ - private static void setCallback(final GenerationProgress progress, final ParsedProperty property, final String parentVariable) throws GenerationException { - FieldSetter.setField(progress, property, parentVariable, "javafx.util.Callback"); + private void setCallback(final ParsedProperty property, final String parentVariable) throws GenerationException { + helperProvider.getFieldSetter().setField(property, parentVariable, "javafx.util.Callback"); } } diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestControllerInjector.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestControllerInjector.java index f004167..401103c 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestControllerInjector.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestControllerInjector.java @@ -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.GenerationException; -import com.github.gtache.fxml.compiler.GenerationParameters; -import com.github.gtache.fxml.compiler.GenerationRequest; +import com.github.gtache.fxml.compiler.InjectionType; import com.github.gtache.fxml.compiler.impl.ControllerFieldInjectionTypes; import com.github.gtache.fxml.compiler.impl.ControllerMethodsInjectionType; import com.github.gtache.fxml.compiler.parsing.ParsedProperty; @@ -18,14 +17,12 @@ import java.util.List; import java.util.Objects; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class TestControllerInjector { - private final GenerationProgress progress; - private final GenerationRequest request; - private final GenerationParameters parameters; private final ControllerInfo controllerInfo; private final List controllerFactoryPostAction; private final String id; @@ -34,12 +31,8 @@ class TestControllerInjector { private final String propertyValue; private final StringBuilder sb; - TestControllerInjector(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, - @Mock final GenerationParameters parameters, @Mock final ControllerInfo controllerInfo, + TestControllerInjector(@Mock final ControllerInfo controllerInfo, @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.controllerFactoryPostAction = new ArrayList<>(); this.id = "id"; @@ -51,19 +44,14 @@ class TestControllerInjector { @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.value()).thenReturn(propertyValue); } @Test void testInjectControllerFieldFactory() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); - ControllerInjector.injectControllerField(progress, id, variable); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + injector.injectControllerField(id, variable); final var expected = " fieldMap.put(\"" + id + "\", " + variable + ");\n"; assertEquals(expected, sb.toString()); assertTrue(controllerFactoryPostAction.isEmpty()); @@ -71,8 +59,8 @@ class TestControllerInjector { @Test void testInjectControllerFieldAssign() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); - ControllerInjector.injectControllerField(progress, id, variable); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + injector.injectControllerField(id, variable); final var expected = " controller." + id + " = " + variable + ";\n"; assertEquals(expected, sb.toString()); assertTrue(controllerFactoryPostAction.isEmpty()); @@ -80,8 +68,8 @@ class TestControllerInjector { @Test void testInjectControllerFieldSetters() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.SETTERS); - ControllerInjector.injectControllerField(progress, id, variable); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.SETTERS, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + injector.injectControllerField(id, variable); final var expected = " controller." + GenerationHelper.getSetMethod(id) + "(" + variable + ");\n"; assertEquals(expected, sb.toString()); assertTrue(controllerFactoryPostAction.isEmpty()); @@ -89,8 +77,8 @@ class TestControllerInjector { @Test void testInjectControllerFieldReflection() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.REFLECTION); - ControllerInjector.injectControllerField(progress, id, variable); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.REFLECTION, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + injector.injectControllerField(id, variable); final var expected = " injectField(\"" + id + "\", " + variable + ");\n"; assertEquals(expected, sb.toString()); assertTrue(controllerFactoryPostAction.isEmpty()); @@ -98,15 +86,14 @@ class TestControllerInjector { @Test void testInjectControllerFieldUnknown() { - when(parameters.fieldInjectionType()).thenReturn(null); - assertThrows(GenerationException.class, () -> ControllerInjector.injectControllerField(progress, id, variable)); + final var injector = new ControllerInjector(controllerInfo, mock(InjectionType.class), ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + assertThrows(GenerationException.class, () -> injector.injectControllerField(id, variable)); } @Test void testInjectEventHandlerReferenceFactoryNoArgument() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); - when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFERENCE); - ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + injector.injectEventHandlerControllerMethod(property, variable); final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> controller." + property.value().replace("#", "") + "());\n"; assertEquals(1, controllerFactoryPostAction.size()); assertEquals(expected, controllerFactoryPostAction.getFirst()); @@ -115,10 +102,9 @@ class TestControllerInjector { @Test void testInjectEventHandlerReferenceFactoryWithArgument() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); - when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFERENCE); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); 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"; assertEquals(1, controllerFactoryPostAction.size()); assertEquals(expected, controllerFactoryPostAction.getFirst()); @@ -127,9 +113,8 @@ class TestControllerInjector { @Test void testInjectEventHandlerReflectionAssign() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); - when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFLECTION); - ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, ControllerMethodsInjectionType.REFLECTION, sb, controllerFactoryPostAction); + injector.injectEventHandlerControllerMethod(property, variable); final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> callEventHandlerMethod(\"" + propertyValue.replace("#", "") + "\", e));\n"; assertEquals(expected, sb.toString()); assertTrue(controllerFactoryPostAction.isEmpty()); @@ -137,23 +122,20 @@ class TestControllerInjector { @Test void testInjectEventHandlerUnknownMethod() { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); - when(parameters.methodInjectionType()).thenReturn(null); - assertThrows(GenerationException.class, () -> ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable)); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, mock(InjectionType.class), sb, controllerFactoryPostAction); + assertThrows(GenerationException.class, () -> injector.injectEventHandlerControllerMethod(property, variable)); } @Test void testInjectEventHandlerUnknownField() { - when(parameters.fieldInjectionType()).thenReturn(null); - when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFLECTION); - assertThrows(GenerationException.class, () -> ControllerInjector.injectEventHandlerControllerMethod(progress, property, variable)); + final var injector = new ControllerInjector(controllerInfo, mock(InjectionType.class), ControllerMethodsInjectionType.REFLECTION, sb, controllerFactoryPostAction); + assertThrows(GenerationException.class, () -> injector.injectEventHandlerControllerMethod(property, variable)); } @Test void testInjectCallbackReflectionSetters() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.ASSIGN); - when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFLECTION); - ControllerInjector.injectCallbackControllerMethod(progress, property, variable, "clazz"); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.ASSIGN, ControllerMethodsInjectionType.REFLECTION, sb, controllerFactoryPostAction); + injector.injectCallbackControllerMethod(property, variable, "clazz"); final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(e -> callCallbackMethod(\"" + propertyValue.replace("#", "") + "\", e, clazz));\n"; assertEquals(expected, sb.toString()); assertTrue(controllerFactoryPostAction.isEmpty()); @@ -161,9 +143,8 @@ class TestControllerInjector { @Test void testInjectCallbackReferenceFactory() throws GenerationException { - when(parameters.fieldInjectionType()).thenReturn(ControllerFieldInjectionTypes.FACTORY); - when(parameters.methodInjectionType()).thenReturn(ControllerMethodsInjectionType.REFERENCE); - ControllerInjector.injectCallbackControllerMethod(progress, property, variable, "clazz"); + final var injector = new ControllerInjector(controllerInfo, ControllerFieldInjectionTypes.FACTORY, ControllerMethodsInjectionType.REFERENCE, sb, controllerFactoryPostAction); + injector.injectCallbackControllerMethod(property, variable, "clazz"); final var expected = " " + variable + "." + GenerationHelper.getSetMethod(property.name()) + "(controller::" + propertyValue.replace("#", "") + ");\n"; assertEquals(1, controllerFactoryPostAction.size()); assertEquals(expected, controllerFactoryPostAction.getFirst()); diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestGenerationCompatibilityHelper.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestGenerationCompatibilityHelper.java index 4e1254e..911217c 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestGenerationCompatibilityHelper.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestGenerationCompatibilityHelper.java @@ -1,141 +1,126 @@ 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.GenerationParameters; -import com.github.gtache.fxml.compiler.GenerationRequest; import com.github.gtache.fxml.compiler.compatibility.GenerationCompatibility; 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.impl.ParsedPropertyImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; -import java.util.Map; import java.util.Objects; 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; @ExtendWith(MockitoExtension.class) class TestGenerationCompatibilityHelper { - private final GenerationProgress progress; - private final GenerationRequest request; - private final GenerationParameters parameters; + private final HelperProvider helperProvider; + private final ReflectionHelper reflectionHelper; private final GenerationCompatibility compatibility; private final ParsedObject parsedObject; + private final GenerationCompatibilityHelper compatibilityHelper; - TestGenerationCompatibilityHelper(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, - @Mock final GenerationParameters parameters, @Mock final GenerationCompatibility compatibility, - @Mock final ParsedObject parsedObject) { - this.progress = Objects.requireNonNull(progress); - this.request = Objects.requireNonNull(request); - this.parameters = Objects.requireNonNull(parameters); + TestGenerationCompatibilityHelper(@Mock final GenerationCompatibility compatibility, @Mock final HelperProvider helperProvider, + @Mock final ReflectionHelper reflectionHelper, @Mock final ParsedObject parsedObject) { this.compatibility = Objects.requireNonNull(compatibility); + this.helperProvider = Objects.requireNonNull(helperProvider); + this.reflectionHelper = Objects.requireNonNull(reflectionHelper); this.parsedObject = Objects.requireNonNull(parsedObject); + this.compatibilityHelper = new GenerationCompatibilityHelper(helperProvider, compatibility); } @BeforeEach void beforeEach() { - when(progress.request()).thenReturn(request); - when(request.parameters()).thenReturn(parameters); - when(parameters.compatibility()).thenReturn(compatibility); + when(helperProvider.getReflectionHelper()).thenReturn(reflectionHelper); when(parsedObject.className()).thenReturn("java.lang.String"); } @Test void testGetStartVarUseVar() { when(compatibility.useVar()).thenReturn(true); - assertEquals(" final var ", GenerationCompatibilityHelper.getStartVar(progress, "class", 2)); + assertEquals(" final var ", compatibilityHelper.getStartVar("class", 2)); } @Test void testGetStartVarUseVarDefaultIndent() { when(compatibility.useVar()).thenReturn(true); - assertEquals(" final var ", GenerationCompatibilityHelper.getStartVar(progress, "class")); + assertEquals(" final var ", compatibilityHelper.getStartVar("class")); } @Test void testGetStartVarUseVarObject() throws GenerationException { when(compatibility.useVar()).thenReturn(true); - assertEquals(" final var ", GenerationCompatibilityHelper.getStartVar(progress, parsedObject)); + assertEquals(" final var ", compatibilityHelper.getStartVar(parsedObject)); } @Test void testGetStartVarDontUseVar() { 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 void testGetStartVarDontUseVarObject() throws GenerationException { when(compatibility.useVar()).thenReturn(false); 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 void testGetStartVarDontUseVarGenericObject() throws GenerationException { when(compatibility.useVar()).thenReturn(false); when(parsedObject.className()).thenReturn("javafx.scene.control.TableView"); - final var id = "tableView"; - when(parsedObject.attributes()).thenReturn(Map.of("fx:id", new ParsedPropertyImpl("fx:id", null, id))); - final var info = mock(ControllerInfo.class); - 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 ", GenerationCompatibilityHelper.getStartVar(progress, parsedObject)); + when(reflectionHelper.getGenericTypes(parsedObject)).thenReturn(""); + assertEquals(" final javafx.scene.control.TableView ", compatibilityHelper.getStartVar(parsedObject)); + verify(reflectionHelper).getGenericTypes(parsedObject); } @Test void testGetToListToList() { when(compatibility.listCollector()).thenReturn(ListCollector.TO_LIST); - assertEquals(".toList()", GenerationCompatibilityHelper.getToList(progress)); + assertEquals(".toList()", compatibilityHelper.getToList()); } @Test void testGetToListCollectToUnmodifiableList() { 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 void testGetToListCollectToList() { 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 void testGetFirstUse() { when(compatibility.useGetFirst()).thenReturn(true); - assertEquals(".getFirst()", GenerationCompatibilityHelper.getGetFirst(progress)); + assertEquals(".getFirst()", compatibilityHelper.getGetFirst()); } @Test void testGetFirstDontUse() { when(compatibility.useGetFirst()).thenReturn(false); - assertEquals(".get(0)", GenerationCompatibilityHelper.getGetFirst(progress)); + assertEquals(".get(0)", compatibilityHelper.getGetFirst()); } @Test void testGetListOfUse() { when(compatibility.useCollectionsOf()).thenReturn(true); - assertEquals("java.util.List.of(", GenerationCompatibilityHelper.getListOf(progress)); + assertEquals("java.util.List.of(", compatibilityHelper.getListOf()); } @Test void testGetListOfDontUse() { when(compatibility.useCollectionsOf()).thenReturn(false); - assertEquals("java.util.Arrays.asList(", GenerationCompatibilityHelper.getListOf(progress)); + assertEquals("java.util.Arrays.asList(", compatibilityHelper.getListOf()); } } diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestConstructorFormatter.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestInitializationFormatter.java similarity index 69% rename from core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestConstructorFormatter.java rename to core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestInitializationFormatter.java index 3106c94..ad46f4d 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestConstructorFormatter.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestInitializationFormatter.java @@ -19,27 +19,31 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -class TestConstructorFormatter { +class TestInitializationFormatter { private final GenerationProgress progress; private final GenerationRequest request; private final GenerationParameters parameters; + private final HelperProvider helperProvider; private final StringBuilder stringBuilder; private final SourceInfo sourceInfo; private final ParsedInclude include; private final Map sourceToSourceInfo; + private final InitializationFormatter initializationFormatter; - TestConstructorFormatter(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, - @Mock final GenerationParameters parameters, @Mock final StringBuilder stringBuilder, - @Mock final SourceInfo sourceInfo, @Mock final ParsedInclude include) { + TestInitializationFormatter(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, + @Mock final GenerationParameters parameters, @Mock final HelperProvider helperProvider, + @Mock final SourceInfo sourceInfo, @Mock final ParsedInclude include) { this.progress = Objects.requireNonNull(progress); this.request = Objects.requireNonNull(request); 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.include = Objects.requireNonNull(include); this.sourceToSourceInfo = new HashMap<>(); + this.initializationFormatter = new InitializationFormatter(helperProvider, progress); } @BeforeEach @@ -53,6 +57,6 @@ class TestConstructorFormatter { @Test void testFormatSubViewConstructorCallNullSubInfo() { - assertThrows(GenerationException.class, () -> ConstructorFormatter.formatSubViewConstructorCall(progress, include)); + assertThrows(GenerationException.class, () -> initializationFormatter.formatSubViewConstructorCall(include)); } } diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestReflectionHelper.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestReflectionHelper.java index 5a24daa..5a701ef 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestReflectionHelper.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestReflectionHelper.java @@ -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.ControllerInfo; 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.parsing.ParsedObject; import com.github.gtache.fxml.compiler.parsing.ParsedProperty; @@ -34,28 +33,23 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class TestReflectionHelper { - private final GenerationProgress progress; - private final GenerationRequest request; private final Map attributes; private final ControllerInfo controllerInfo; private final ControllerFieldInfo fieldInfo; private final ParsedObject parsedObject; + private final ReflectionHelper reflectionHelper; - TestReflectionHelper(@Mock final GenerationProgress progress, @Mock final GenerationRequest request, - @Mock final ControllerInfo controllerInfo, @Mock final ControllerFieldInfo fieldInfo, + TestReflectionHelper(@Mock final ControllerInfo controllerInfo, @Mock final ControllerFieldInfo fieldInfo, @Mock final ParsedObject parsedObject) { - this.progress = Objects.requireNonNull(progress); - this.request = Objects.requireNonNull(request); this.controllerInfo = Objects.requireNonNull(controllerInfo); this.fieldInfo = Objects.requireNonNull(fieldInfo); this.parsedObject = Objects.requireNonNull(parsedObject); this.attributes = new HashMap<>(); + this.reflectionHelper = new ReflectionHelper(controllerInfo); } @BeforeEach void beforeEach() { - when(progress.request()).thenReturn(request); - when(request.controllerInfo()).thenReturn(controllerInfo); when(controllerInfo.fieldInfo("id")).thenReturn(fieldInfo); when(parsedObject.attributes()).thenReturn(attributes); when(parsedObject.className()).thenReturn("javafx.scene.control.ComboBox"); @@ -191,31 +185,31 @@ class TestReflectionHelper { @Test void testGetGenericTypesNotGeneric() throws GenerationException { when(parsedObject.className()).thenReturn("java.lang.String"); - assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); + assertEquals("", reflectionHelper.getGenericTypes(parsedObject)); } @Test void testGetGenericTypesNullProperty() throws GenerationException { attributes.clear(); - assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); + assertEquals("", reflectionHelper.getGenericTypes(parsedObject)); } @Test void testGetGenericTypesFieldNotFound() throws GenerationException { when(controllerInfo.fieldInfo("id")).thenReturn(null); - assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); + assertEquals("", reflectionHelper.getGenericTypes(parsedObject)); } @Test void testGetGenericTypesFieldNotGeneric() throws GenerationException { 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()))); - assertEquals("", ReflectionHelper.getGenericTypes(progress, parsedObject)); + assertEquals("", reflectionHelper.getGenericTypes(parsedObject)); } @Test void testGetGenericTypes() throws GenerationException { 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)); } } diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestURLFormatter.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestURLFormatter.java index d85a27e..8b778e9 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestURLFormatter.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestURLFormatter.java @@ -1,9 +1,108 @@ 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.mockito.Mock; 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) 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>(); + 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(); + 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(); + 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); + } } diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestValueFormatter.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestValueFormatter.java index f81e0d5..ea6c016 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestValueFormatter.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestValueFormatter.java @@ -1,8 +1,145 @@ 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.mockito.Mock; 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) class TestValueFormatter { + + private final Map 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)); + } } diff --git a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestWebViewFormatter.java b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestWebViewFormatter.java index ce85da0..4be2cbc 100644 --- a/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestWebViewFormatter.java +++ b/core/src/test/java/com/github/gtache/fxml/compiler/impl/internal/TestWebViewFormatter.java @@ -1,8 +1,163 @@ 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.mockito.Mock; 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) 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 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>(); + 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); + } }