Initial commit
This commit is contained in:
14
api/pom.xml
Normal file
14
api/pom.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.github.gtache</groupId>
|
||||
<artifactId>fxml-compiler</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>fxml-compiler-api</artifactId>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Factory for creating controllers
|
||||
*
|
||||
* @param <T> The type of the controller
|
||||
*/
|
||||
public interface ControllerFactory<T> {
|
||||
|
||||
/**
|
||||
* Creates a controller
|
||||
*
|
||||
* @param fieldMap The assignment of field name to value
|
||||
* @return The created controller
|
||||
*/
|
||||
T create(final Map<String, Object> fieldMap);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Info about a controller for code generation
|
||||
*/
|
||||
public interface ControllerInfo {
|
||||
|
||||
/**
|
||||
* @return A mapping of method name to true if the method has an argument
|
||||
*/
|
||||
Map<String, Boolean> handlerHasArgument();
|
||||
|
||||
/**
|
||||
* Returns whether the given event handler method has an argument
|
||||
*
|
||||
* @param methodName The method name
|
||||
* @return A mapping of method name to true if the method has an event
|
||||
*/
|
||||
default boolean handlerHasArgument(final String methodName) {
|
||||
return handlerHasArgument().getOrDefault(methodName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A mapping of property name to generic types
|
||||
*/
|
||||
Map<String, List<String>> propertyGenericTypes();
|
||||
|
||||
/**
|
||||
* Returns the generic types for the given property (null if not generic)
|
||||
*
|
||||
* @param property The property
|
||||
* @return The generic types
|
||||
*/
|
||||
default List<String> propertyGenericTypes(final String property) {
|
||||
return propertyGenericTypes().get(property);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
/**
|
||||
* Represents a controller injection to use for generated code
|
||||
*/
|
||||
public interface ControllerInjection {
|
||||
|
||||
/**
|
||||
* @return The injection type for fields
|
||||
*/
|
||||
InjectionType fieldInjectionType();
|
||||
|
||||
/**
|
||||
* @return The injection type for event handlers
|
||||
*/
|
||||
InjectionType methodInjectionType();
|
||||
|
||||
/**
|
||||
* @return The injection class
|
||||
*/
|
||||
String injectionClass();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Parameters for FXML generation
|
||||
*/
|
||||
public interface GenerationParameters {
|
||||
|
||||
/**
|
||||
* @return The mapping of controller class name to controller injection
|
||||
*/
|
||||
Map<String, ControllerInjection> controllerInjections();
|
||||
|
||||
/**
|
||||
* @return The mapping of fx:include source to generated class name
|
||||
*/
|
||||
Map<String, String> sourceToGeneratedClassName();
|
||||
|
||||
/**
|
||||
* @return The mapping of fx:include source to controller class name
|
||||
*/
|
||||
Map<String, String> sourceToControllerName();
|
||||
|
||||
/**
|
||||
* @return The resource bundle injection to use
|
||||
*/
|
||||
ResourceBundleInjection resourceBundleInjection();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import com.github.gtache.fxml.compiler.parsing.ParsedObject;
|
||||
|
||||
/**
|
||||
* Represents a request for a code generation
|
||||
*/
|
||||
public interface GenerationRequest {
|
||||
|
||||
/**
|
||||
* @return The main controller info
|
||||
*/
|
||||
ControllerInfo controllerInfo();
|
||||
|
||||
/**
|
||||
* @return The request parameters
|
||||
*/
|
||||
GenerationParameters parameters();
|
||||
|
||||
/**
|
||||
* @return The object to generate code for
|
||||
*/
|
||||
ParsedObject rootObject();
|
||||
|
||||
/**
|
||||
* @return The output class name
|
||||
*/
|
||||
String outputClassName();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
/**
|
||||
* Generates compiled FXML code
|
||||
*/
|
||||
public interface Generator {
|
||||
|
||||
/**
|
||||
* Generates the java code
|
||||
*
|
||||
* @param request The request
|
||||
* @return The java code
|
||||
*/
|
||||
String generate(GenerationRequest request);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
/**
|
||||
* A type of injection for controllers
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface InjectionType {
|
||||
|
||||
/**
|
||||
* @return The name of the type
|
||||
*/
|
||||
String name();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
/**
|
||||
* Represents a controller injection to use for generated code
|
||||
*/
|
||||
public interface ResourceBundleInjection {
|
||||
|
||||
/**
|
||||
* @return The injection type
|
||||
*/
|
||||
InjectionType injectionType();
|
||||
|
||||
/**
|
||||
* @return The resource bundle path
|
||||
*/
|
||||
String bundleName();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.github.gtache.fxml.compiler.parsing;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.SequencedCollection;
|
||||
import java.util.SequencedMap;
|
||||
|
||||
/**
|
||||
* Special {@link ParsedObject} for fx:include
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ParsedInclude extends ParsedObject {
|
||||
|
||||
/**
|
||||
* @return The controller id if present
|
||||
*/
|
||||
default String controllerId() {
|
||||
final var property = properties().get("fx:id");
|
||||
if (property == null) {
|
||||
return null;
|
||||
} else {
|
||||
return property.value() + "Controller";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The resources if present
|
||||
*/
|
||||
default String resources() {
|
||||
final var property = properties().get("resources");
|
||||
if (property == null) {
|
||||
return null;
|
||||
} else {
|
||||
return property.value().replace("/", ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The source
|
||||
*/
|
||||
default String source() {
|
||||
final var property = properties().get("source");
|
||||
if (property == null) {
|
||||
throw new IllegalStateException("Missing source");
|
||||
} else {
|
||||
return property.value();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default Class<?> clazz() {
|
||||
return ParsedInclude.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> children() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.github.gtache.fxml.compiler.parsing;
|
||||
|
||||
import java.util.SequencedCollection;
|
||||
import java.util.SequencedMap;
|
||||
|
||||
/**
|
||||
* Parsed object from FXML
|
||||
*/
|
||||
public interface ParsedObject {
|
||||
|
||||
/**
|
||||
* @return The object class
|
||||
*/
|
||||
Class<?> clazz();
|
||||
|
||||
/**
|
||||
* @return The object properties
|
||||
*/
|
||||
SequencedMap<String, ParsedProperty> properties();
|
||||
|
||||
/**
|
||||
* @return The object children (complex properties)
|
||||
*/
|
||||
SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> children();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.github.gtache.fxml.compiler.parsing;
|
||||
|
||||
/**
|
||||
* Parsed property/attribute from FXML
|
||||
*/
|
||||
public interface ParsedProperty {
|
||||
|
||||
/**
|
||||
* @return The property name
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* @return The property source type (in case of static property)
|
||||
*/
|
||||
Class<?> sourceType();
|
||||
|
||||
/**
|
||||
* @return The property value
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
7
api/src/main/java/module-info.java
Normal file
7
api/src/main/java/module-info.java
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* API module for FXML compiler
|
||||
*/
|
||||
module com.github.gtache.fxml.compiler.api {
|
||||
exports com.github.gtache.fxml.compiler;
|
||||
exports com.github.gtache.fxml.compiler.parsing;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class TestControllerInfo {
|
||||
|
||||
private final String string;
|
||||
private final Map<String, Boolean> handlerHasArgument;
|
||||
private final Map<String, List<String>> propertyGenericTypes;
|
||||
private final List<String> genericTypes;
|
||||
private final ControllerInfo controllerInfo;
|
||||
|
||||
TestControllerInfo() {
|
||||
this.string = "string";
|
||||
this.handlerHasArgument = new HashMap<>();
|
||||
this.propertyGenericTypes = new HashMap<>();
|
||||
this.genericTypes = List.of("a", "b");
|
||||
this.controllerInfo = spy(ControllerInfo.class);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
when(controllerInfo.handlerHasArgument()).thenReturn(handlerHasArgument);
|
||||
when(controllerInfo.propertyGenericTypes()).thenReturn(propertyGenericTypes);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandlerHasArgumentNull() {
|
||||
assertTrue(controllerInfo.handlerHasArgument(string));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandlerHasArgumentFalse() {
|
||||
handlerHasArgument.put(string, false);
|
||||
assertFalse(controllerInfo.handlerHasArgument(string));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandlerHasArgumentTrue() {
|
||||
handlerHasArgument.put(string, true);
|
||||
assertTrue(controllerInfo.handlerHasArgument(string));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPropertyGenericTypesNull() {
|
||||
assertNull(controllerInfo.propertyGenericTypes(string));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPropertyGenericTypes() {
|
||||
propertyGenericTypes.put(string, genericTypes);
|
||||
assertEquals(genericTypes, controllerInfo.propertyGenericTypes(string));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.github.gtache.fxml.compiler.parsing;
|
||||
|
||||
|
||||
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.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.SequencedMap;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestParsedInclude {
|
||||
|
||||
private final SequencedMap<String, ParsedProperty> properties;
|
||||
private final ParsedProperty property;
|
||||
private final String string;
|
||||
private final ParsedInclude include;
|
||||
|
||||
TestParsedInclude(@Mock final ParsedProperty property) {
|
||||
this.properties = new LinkedHashMap<>();
|
||||
this.property = Objects.requireNonNull(property);
|
||||
this.string = "str/ing";
|
||||
this.include = spy(ParsedInclude.class);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
when(include.properties()).thenReturn(properties);
|
||||
when(property.value()).thenReturn(string);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testControllerIdNull() {
|
||||
assertNull(include.controllerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testControllerId() {
|
||||
properties.put("fx:id", property);
|
||||
assertEquals(string + "Controller", include.controllerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResourcesNull() {
|
||||
assertNull(include.resources());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResources() {
|
||||
properties.put("resources", property);
|
||||
assertEquals(string.replace("/", "."), include.resources());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSourceNull() {
|
||||
assertThrows(IllegalStateException.class, include::source);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSource() {
|
||||
properties.put("source", property);
|
||||
assertEquals(string, include.source());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClazz() {
|
||||
assertEquals(ParsedInclude.class, include.clazz());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChildren() {
|
||||
assertEquals(new LinkedHashMap<>(), include.children());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user