Adds gpg, sonatype, changes groupId

This commit is contained in:
Guillaume Tâche
2025-01-03 22:08:50 +01:00
parent c3d9e72e42
commit f59863c628
183 changed files with 860 additions and 779 deletions
@@ -0,0 +1,32 @@
package ch.gtache.fxml.compiler;
import java.util.List;
/**
* Info about a controller field
*/
public interface ControllerFieldInfo {
/**
* Returns the field name
*
* @return The name
*/
String name();
/**
* Returns whether the field is generic
*
* @return True if the field is generic, false if not (or raw)
*/
default boolean isGeneric() {
return !genericTypes().isEmpty();
}
/**
* Returns the generic types for the field
*
* @return The generic types as a list, empty if not generic or raw
*/
List<GenericTypes> genericTypes();
}
@@ -0,0 +1,23 @@
package ch.gtache.fxml.compiler;
/**
* Base field {@link InjectionType}s
*/
public enum ControllerFieldInjectionType implements InjectionType {
/**
* Inject using variable assignment
*/
ASSIGN,
/**
* Inject using a factory
*/
FACTORY,
/**
* Inject using reflection
*/
REFLECTION,
/**
* Inject using setters
*/
SETTERS
}
@@ -0,0 +1,57 @@
package ch.gtache.fxml.compiler;
import java.util.Map;
/**
* Info about a controller for code generation
*/
public interface ControllerInfo {
/**
* Returns the controller class name
*
* @return The name
*/
String className();
/**
* Returns a mapping of event handler method name -> boolean
*
* @return A mapping of method name to true if the method has an argument (event handler may not have an argument)
*/
Map<String, Boolean> handlerHasArgument();
/**
* Returns whether the given event handler method has an argument
*
* @param methodName The method name
* @return True if the method has an argument
*/
default boolean handlerHasArgument(final String methodName) {
return handlerHasArgument().getOrDefault(methodName, true);
}
/**
* Returns a mapping of property name -> field info
*
* @return the mapping
*/
Map<String, ControllerFieldInfo> fieldInfo();
/**
* Returns the field information for the given property
*
* @param property The property
* @return The info, or null if not found
*/
default ControllerFieldInfo fieldInfo(final String property) {
return fieldInfo().get(property);
}
/**
* Returns whether the controller has an initialize method
*
* @return True if the controller has an initialize method
*/
boolean hasInitialize();
}
@@ -0,0 +1,15 @@
package ch.gtache.fxml.compiler;
/**
* Base controller {@link InjectionType}s
*/
public enum ControllerInjectionType implements InjectionType {
/**
* Inject the controller instance
*/
INSTANCE,
/**
* Inject a controller factory
*/
FACTORY
}
@@ -0,0 +1,15 @@
package ch.gtache.fxml.compiler;
/**
* Base methods {@link InjectionType}s
*/
public enum ControllerMethodsInjectionType implements InjectionType {
/**
* Inject using visible methods
*/
REFERENCE,
/**
* Inject using reflection
*/
REFLECTION,
}
@@ -0,0 +1,36 @@
package ch.gtache.fxml.compiler;
/**
* Exception thrown when a generation error occurs
*/
@SuppressWarnings("serial")
public class GenerationException extends Exception {
/**
* Instantiates a new exception
*
* @param message The message
*/
public GenerationException(final String message) {
super(message);
}
/**
* Instantiates a new exception
*
* @param message The message
* @param cause The cause
*/
public GenerationException(final String message, final Throwable cause) {
super(message, cause);
}
/**
* Instantiates a new exception
*
* @param cause The cause
*/
public GenerationException(final Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,61 @@
package ch.gtache.fxml.compiler;
import ch.gtache.fxml.compiler.compatibility.GenerationCompatibility;
import java.util.Map;
/**
* Parameters for FXML generation
*/
public interface GenerationParameters {
/**
* Returns the compatibility information
*
* @return The compatibility
*/
GenerationCompatibility compatibility();
/**
* Returns whether to use Image InputStream constructor instead of the String (url) one.
* This allows avoiding opening some packages with JPMS
*
* @return True if the constructor should be used
*/
boolean useImageInputStreamConstructor();
/**
* Returns the mapping of controller class to resource bundle path (in case of GET-BUNDLE injection)
*
* @return The map
*/
Map<String, String> bundleMap();
/**
* Returns the controller injection to use
*
* @return The injection
*/
ControllerInjectionType controllerInjectionType();
/**
* Returns the field injection to use
*
* @return The injection
*/
ControllerFieldInjectionType fieldInjectionType();
/**
* Returns the method injection to use
*
* @return The injection
*/
ControllerMethodsInjectionType methodInjectionType();
/**
* Returns the resource injection to use
*
* @return The injection
*/
ResourceBundleInjectionType resourceInjectionType();
}
@@ -0,0 +1,44 @@
package ch.gtache.fxml.compiler;
import ch.gtache.fxml.compiler.parsing.ParsedObject;
/**
* Represents a request for a code generation
*/
public interface GenerationRequest {
/**
* Returns the info about the main controller for code generation
*
* @return The info
*/
ControllerInfo controllerInfo();
/**
* Returns the generation parameters
*
* @return The parameters
*/
GenerationParameters parameters();
/**
* Returns the info about the main source file
*
* @return The info
*/
SourceInfo sourceInfo();
/**
* Returns the object to generate code for
*
* @return The object
*/
ParsedObject rootObject();
/**
* Returns the output class name
*
* @return The class name
*/
String outputClassName();
}
@@ -0,0 +1,17 @@
package ch.gtache.fxml.compiler;
/**
* Generates compiled FXML code
*/
@FunctionalInterface
public interface Generator {
/**
* Generates the java code
*
* @param request The request
* @return The java code
* @throws GenerationException if an error occurs
*/
String generate(GenerationRequest request) throws GenerationException;
}
@@ -0,0 +1,23 @@
package ch.gtache.fxml.compiler;
import java.util.List;
/**
* Represents generic types for a field
*/
public interface GenericTypes {
/**
* Returns the name of the type
*
* @return The name
*/
String name();
/**
* Returns the possible subtypes of the type
*
* @return The list of subtypes, empty if no subtypes
*/
List<GenericTypes> subTypes();
}
@@ -0,0 +1,15 @@
package ch.gtache.fxml.compiler;
/**
* A type of injection for controllers
*/
@FunctionalInterface
public interface InjectionType {
/**
* Returns the name of the type
*
* @return The name
*/
String name();
}
@@ -0,0 +1,27 @@
package ch.gtache.fxml.compiler;
/**
* Base {@link InjectionType}s for resource bundles
*/
public enum ResourceBundleInjectionType implements InjectionType {
/**
* Resource bundle is injected in the constructor
*/
CONSTRUCTOR,
/**
* Resource bundle is injected as a function in the constructor
*/
CONSTRUCTOR_FUNCTION,
/**
* Resource bundle name is injected in the constructor
*/
CONSTRUCTOR_NAME,
/**
* Resource bundle is loaded using getBundle
*/
GET_BUNDLE,
/**
* Resource bundle is retrieved from controller using getter
*/
GETTER
}
@@ -0,0 +1,54 @@
package ch.gtache.fxml.compiler;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
/**
* Info about a source file
*/
public interface SourceInfo {
/**
* Returns the generated view class name
*
* @return The class name
*/
String generatedClassName();
/**
* Returns the controller class name
*
* @return The class name
*/
String controllerClassName();
/**
* Returns the source file
*
* @return The file
*/
Path sourceFile();
/**
* Returns the included sources.
* Note that there can be multiple times the same source.
*
* @return The sources
*/
List<SourceInfo> includedSources();
/**
* Returns the mapping of source value to source info
*
* @return The mapping
*/
Map<String, SourceInfo> sourceToSourceInfo();
/**
* Returns whether the source or its children requires a resource bundle
*
* @return True if the subtree requires a resource bundle
*/
boolean requiresResourceBundle();
}
@@ -0,0 +1,57 @@
package ch.gtache.fxml.compiler.compatibility;
/**
* Compatibility information for generated code
*/
@FunctionalInterface
public interface GenerationCompatibility {
/**
* Returns the minimum supported Java version
*
* @return The version
*/
int javaVersion();
/**
* Returns whether to use var for object declaration
*
* @return True if var should be used
*/
default boolean useVar() {
return javaVersion() >= 10;
}
/**
* Returns the type of list collector to use
*
* @return The collector
*/
default ListCollector listCollector() {
if (javaVersion() >= 16) {
return ListCollector.TO_LIST;
} else if (javaVersion() >= 10) {
return ListCollector.COLLECT_TO_UNMODIFIABLE_LIST;
} else {
return ListCollector.COLLECT_TO_LIST;
}
}
/**
* Returns whether to use List.of() (or Set.of() etc.) instead of Arrays.asList()
*
* @return True if List.of() should be used
*/
default boolean useCollectionsOf() {
return javaVersion() >= 9;
}
/**
* Returns whether to use getFirst() or get(0)
*
* @return True if getFirst() should be used
*/
default boolean useGetFirst() {
return javaVersion() >= 21;
}
}
@@ -0,0 +1,22 @@
package ch.gtache.fxml.compiler.compatibility;
/**
* Type of list collector to use for generated code
*/
public enum ListCollector {
/**
* Use .toList()
*/
TO_LIST,
/**
* Use .collect(Collectors.toUnmodifiableList())
*/
COLLECT_TO_UNMODIFIABLE_LIST,
/**
* Use .collect(Collectors.toList())
*/
COLLECT_TO_LIST
}
@@ -0,0 +1,37 @@
package ch.gtache.fxml.compiler.parsing;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Parses FXML files to object tree
*/
@FunctionalInterface
public interface FXMLParser {
/**
* Parses the given FXML content
*
* @param content The FXML content
* @return The parsed object
* @throws ParseException if an error occurs
*/
ParsedObject parse(final String content) throws ParseException;
/**
* Parses the FXML file at the given path
*
* @param path The path
* @return The parsed object
* @throws ParseException if an error occurs
*/
default ParsedObject parse(final Path path) throws ParseException {
try {
final var content = Files.readString(path);
return parse(content);
} catch (final IOException e) {
throw new ParseException("Error parsing " + path, e);
}
}
}
@@ -0,0 +1,36 @@
package ch.gtache.fxml.compiler.parsing;
/**
* Exception thrown when a parsing error occurs
*/
@SuppressWarnings("serial")
public class ParseException extends Exception {
/**
* Instantiates a new exception
*
* @param message The message
*/
public ParseException(final String message) {
super(message);
}
/**
* Instantiates a new exception
*
* @param message The message
* @param cause The cause
*/
public ParseException(final String message, final Throwable cause) {
super(message, cause);
}
/**
* Instantiates a new exception
*
* @param cause The cause
*/
public ParseException(final Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,36 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:constant
*/
public interface ParsedConstant extends ParsedObject {
/**
* Returns the constant value from fx:constant
*
* @return The value
*/
default String constant() {
final var attribute = attributes().get("fx:constant");
if (attribute == null) {
throw new IllegalStateException("Missing fx:constant");
} else {
return attribute.value();
}
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
@Override
default SequencedCollection<ParsedObject> children() {
return List.of();
}
}
@@ -0,0 +1,42 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:copy
*/
@FunctionalInterface
public interface ParsedCopy extends ParsedObject {
/**
* Returns the source from fx:copy
*
* @return The source
*/
default String source() {
final var attribute = attributes().get("source");
if (attribute == null) {
throw new IllegalStateException("Missing source");
} else {
return attribute.value();
}
}
@Override
default String className() {
return ParsedCopy.class.getName();
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
@Override
default SequencedCollection<ParsedObject> children() {
return List.of();
}
}
@@ -0,0 +1,28 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:define
*/
@FunctionalInterface
public interface ParsedDefine extends ParsedObject {
@Override
default String className() {
return ParsedDefine.class.getName();
}
@Override
default Map<String, ParsedProperty> attributes() {
return Map.of();
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
}
@@ -0,0 +1,38 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:factory
*/
public interface ParsedFactory extends ParsedObject {
/**
* Returns the factory value from fx:factory
*
* @return The value
*/
default String factory() {
final var attribute = attributes().get("fx:factory");
if (attribute == null) {
throw new IllegalStateException("Missing fx:factory");
} else {
return attribute.value();
}
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
/**
* Returns the arguments for the factory.
* Different from {@link ParsedObject#children()} (in practice, children should only contain fx:define)
*
* @return The arguments
*/
SequencedCollection<ParsedObject> arguments();
}
@@ -0,0 +1,70 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:include
*/
@FunctionalInterface
public interface ParsedInclude extends ParsedObject {
/**
* Returns the subcontroller id (if present)
*
* @return The id
*/
default String controllerId() {
final var property = attributes().get("fx:id");
if (property == null) {
return null;
} else {
return property.value() + "Controller";
}
}
/**
* Returns the subview resources path if present
*
* @return The resources
*/
default String resources() {
final var property = attributes().get("resources");
if (property == null) {
return null;
} else {
return property.value().replace("/", ".");
}
}
/**
* Returns the include source
*
* @return The source
*/
default String source() {
final var property = attributes().get("source");
if (property == null) {
throw new IllegalStateException("Missing source");
} else {
return property.value();
}
}
@Override
default String className() {
return ParsedInclude.class.getName();
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
@Override
default SequencedCollection<ParsedObject> children() {
return List.of();
}
}
@@ -0,0 +1,39 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.Map;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Parsed object from FXML
*/
public interface ParsedObject {
/**
* Returns the type of the object
*
* @return The class name
*/
String className();
/**
* Returns the object's attributes (simple properties)
*
* @return The attributes
*/
Map<String, ParsedProperty> attributes();
/**
* Returns the object's complex properties
*
* @return The properties
*/
SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties();
/**
* Returns the children (fx:define, fx:copy, etc.) contained in this object
*
* @return The children
*/
SequencedCollection<ParsedObject> children();
}
@@ -0,0 +1,28 @@
package ch.gtache.fxml.compiler.parsing;
/**
* Parsed property/attribute from FXML
*/
public interface ParsedProperty {
/**
* Returns the name of the property
*
* @return The name
*/
String name();
/**
* Returns the source type (owner class) of the property (in case of static property)
*
* @return The source type name
*/
String sourceType();
/**
* Returns the value of the property
*
* @return The value
*/
String value();
}
@@ -0,0 +1,42 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:reference
*/
@FunctionalInterface
public interface ParsedReference extends ParsedObject {
/**
* Returns the source from fx:reference
*
* @return The source
*/
default String source() {
final var attribute = attributes().get("source");
if (attribute == null) {
throw new IllegalStateException("Missing source");
} else {
return attribute.value();
}
}
@Override
default String className() {
return ParsedReference.class.getName();
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
@Override
default SequencedCollection<ParsedObject> children() {
return List.of();
}
}
@@ -0,0 +1,41 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for simple text
*/
@FunctionalInterface
public interface ParsedText extends ParsedObject {
/**
* Returns the text value
*
* @return The value
*/
String text();
@Override
default String className() {
return String.class.getName();
}
@Override
default SequencedCollection<ParsedObject> children() {
return List.of();
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
@Override
default Map<String, ParsedProperty> attributes() {
return Map.of();
}
}
@@ -0,0 +1,36 @@
package ch.gtache.fxml.compiler.parsing;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.SequencedCollection;
import java.util.SequencedMap;
/**
* Special {@link ParsedObject} for fx:value
*/
public interface ParsedValue extends ParsedObject {
/**
* Returns the value from fx:value
*
* @return The value
*/
default String value() {
final var attribute = attributes().get("fx:value");
if (attribute == null) {
throw new IllegalStateException("Missing fx:value");
} else {
return attribute.value();
}
}
@Override
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
return new LinkedHashMap<>();
}
@Override
default SequencedCollection<ParsedObject> children() {
return List.of();
}
}