Skip to content

Commit

Permalink
feat: parsing args and generating an executable jar
Browse files Browse the repository at this point in the history
  • Loading branch information
bamthomas committed Nov 4, 2024
1 parent 5778b2d commit da5e07f
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 21 deletions.
23 changes: 23 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,29 @@
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.7.1</version>
<configuration>
<archive>
<manifest>
<mainClass>org.icij.ftm.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
Expand Down
49 changes: 33 additions & 16 deletions src/main/java/org/icij/ftm/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Objects;
import java.util.Properties;

import static java.lang.String.format;
import static java.util.stream.Collectors.toMap;
import static org.icij.ftm.Utils.propertiesFromMap;

Expand All @@ -18,26 +19,42 @@
*/
public class Main {
public static final String SCHEMA_URL = "https://api.github.com/repos/alephdata/followthemoney/contents/followthemoney/schema";
public static final String ATTRIBUTE_MODE_KEY = "attributeMode";
public static final String DEFAULT_ATTRIBUTE_MODE = "FEATURED";
public static final String INTERFACES_KEY = "interfaces";
public static final String DEFAULT_INTERFACES_VALUE = "false";

public static void main(String[] args) throws Exception {
Path destDir = Path.of("target", "generated-sources", "org", "icij", "ftm");
destDir.toFile().mkdirs();
Path yamlFilesDir = Utils.downloadYamlModels(URI.create(SCHEMA_URL));
File[] yamlFiles = Objects.requireNonNull(yamlFilesDir.toFile().listFiles());
Model.Mode attributeMode = Model.Mode.FEATURED;
Properties properties = propertiesFromMap(Map.of(
"parents", Utils.findParents(yamlFiles, attributeMode),
"models", Arrays.stream(yamlFiles).map(File::getName).map(s -> s.substring(0, s.indexOf("."))).toList(),
"attributeMode", attributeMode.name(),
"interfaces", true
));

SourceGenerator sourceGenerator = new SourceGenerator(properties);

for (File yamlFile: yamlFiles) {
String javaSource = sourceGenerator.generate(yamlFile.toPath());
Files.writeString(destDir.resolve(Utils.getJavaFileName(yamlFile)), javaSource);

try {
Map<String, String> argsMap = Utils.parseArgs(args);

Model.Mode attributeMode = Model.Mode.valueOf(argsMap.getOrDefault(ATTRIBUTE_MODE_KEY, DEFAULT_ATTRIBUTE_MODE));
boolean interfaces = Boolean.parseBoolean(argsMap.getOrDefault(INTERFACES_KEY, DEFAULT_INTERFACES_VALUE));

Path yamlFilesDir = Utils.downloadYamlModels(URI.create(SCHEMA_URL));
File[] yamlFiles = Objects.requireNonNull(yamlFilesDir.toFile().listFiles());
Properties properties = propertiesFromMap(Map.of(
"parents", Utils.findParents(yamlFiles, attributeMode),
"models", Arrays.stream(yamlFiles).map(File::getName).map(s -> s.substring(0, s.indexOf("."))).toList(),
"attributeMode", attributeMode.name(),
"interfaces", interfaces
));

System.out.printf("generating classes into %s for FtM with %s%n", destDir, properties);
SourceGenerator sourceGenerator = new SourceGenerator(properties);

for (File yamlFile: yamlFiles) {
String javaSource = sourceGenerator.generate(yamlFile.toPath());
Files.writeString(destDir.resolve(Utils.getJavaFileName(yamlFile)), javaSource);
}
} catch (IllegalArgumentException argex) {
System.out.println(argex.getMessage());
System.out.println("usage: Main <properties>");
System.out.printf("\t--%s: FtM properties mode (REQUIRED, FEATURED, FULL default %s)%n", ATTRIBUTE_MODE_KEY, DEFAULT_ATTRIBUTE_MODE);
System.out.printf("\t--%s: only generate interfaces (default %s)%n", INTERFACES_KEY, DEFAULT_INTERFACES_VALUE);
}
}

}
39 changes: 34 additions & 5 deletions src/main/java/org/icij/ftm/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

Expand All @@ -33,6 +36,7 @@
*/
public class Utils {
private static final Load yaml = new Load(LoadSettings.builder().build());

public static Properties propertiesFromMap(Map<String, Object> map) {
Properties props = new Properties();
props.putAll(map);
Expand All @@ -45,7 +49,8 @@ static Path downloadYamlModels(URI downloadUri) throws IOException, InterruptedE
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(downloadUri).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
List<Map<String, Object>> yamlFileList = new ObjectMapper().readValue(response.body(), new TypeReference<>() {});
List<Map<String, Object>> yamlFileList = new ObjectMapper().readValue(response.body(), new TypeReference<>() {
});

List<HttpRequest> requests = yamlFileList.stream()
.map(yamlFileDesc -> HttpRequest.newBuilder().uri(URI.create((String) yamlFileDesc.get("download_url"))))
Expand All @@ -54,8 +59,8 @@ static Path downloadYamlModels(URI downloadUri) throws IOException, InterruptedE

// parallelize downloads
CompletableFuture.allOf(requests.stream()
.map(r -> client.sendAsync(r, HttpResponse.BodyHandlers.ofFile(tempDirectory.resolve(Path.of(r.uri().getPath()).getFileName()))))
.toArray(CompletableFuture<?>[]::new)).join();
.map(r -> client.sendAsync(r, HttpResponse.BodyHandlers.ofFile(tempDirectory.resolve(Path.of(r.uri().getPath()).getFileName()))))
.toArray(CompletableFuture<?>[]::new)).join();

return tempDirectory;
}
Expand All @@ -67,15 +72,15 @@ static Map<String, Model> findParents(File[] yamlFiles) throws FileNotFoundExcep
static Map<String, Model> findParents(File[] yamlFiles, Model.Mode attributeMode) throws FileNotFoundException {
Set<String> parentNames = new LinkedHashSet<>();
Map<String, Map<String, Object>> modelsMap = new HashMap<>();
for (File file: yamlFiles) {
for (File file : yamlFiles) {
Map<String, Object> yamlContent = getYamlContent(file);
Model model = new Model(yamlContent);
parentNames.addAll(model.getExtends());
modelsMap.put(model.name(), yamlContent);
}
Map<String, Map<String, Object>> mapOfMap = modelsMap.entrySet().stream().filter(e -> parentNames.contains(e.getKey())).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
Map<String, Model> parents = new HashMap<>();
for (Map.Entry<String, Map<String, Object>> entry: mapOfMap.entrySet()) {
for (Map.Entry<String, Map<String, Object>> entry : mapOfMap.entrySet()) {
parents.put(entry.getKey(), new Model(entry.getValue(), parents, attributeMode));
}
return parents;
Expand All @@ -93,4 +98,28 @@ static Map<String, Object> getYamlContent(File yamlFile) throws FileNotFoundExce
static Path pathFromLoader(String name) {
return Paths.get(ClassLoader.getSystemResource(name).getPath());
}

public static Map<String, String> parseArgs(String[] args) {
List<String> argumentList = List.of("attributeMode", "interfaces", "help");
Scanner scanner = new Scanner(String.join(" ", args));
Map<String, String> properties = new HashMap<>();
while (scanner.hasNext()) {
String arg = scanner.next();
String argName = arg.substring(2);
if (arg.startsWith("--") && argumentList.contains(argName)) {
if ("help".equals(argName)) {
throw new IllegalArgumentException("Help:");
}
if (!scanner.hasNext()) {
throw new IllegalArgumentException("arg " + argName + " should have a value ");
}

String value = scanner.next();
properties.put(argName, value);
} else {
throw new IllegalArgumentException("unknown arg " + argName);
}
}
return properties;
}
}
41 changes: 41 additions & 0 deletions src/test/java/org/icij/ftm/UtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.fest.assertions.Assertions.assertThat;
import static org.icij.ftm.Model.Mode.FEATURED;
import static org.icij.ftm.Utils.propertiesFromMap;

public class UtilsTest {
@Test
Expand All @@ -27,6 +30,44 @@ public void test_find_parents() throws Exception {
assertThat(Utils.findParents(modelFiles.toArray(new File[]{})).keySet()).contains("Interval", "Thing");
}

@Test
public void test_parse_args() {
assertThat(Utils.parseArgs(new String[] {"--attributeMode", "FEATURED"})).isEqualTo(propertiesFromMap(Map.of("attributeMode", "FEATURED")));
}

@Test
public void test_parse_two_args() {
assertThat(Utils.parseArgs(new String[] {"--attributeMode", "FEATURED", "--interfaces", "true"}))
.isEqualTo(propertiesFromMap(Map.of(
"attributeMode", "FEATURED",
"interfaces", "true"
)));
}

@Test(expected = IllegalArgumentException.class)
public void test_parse_unknown_args() {
Utils.parseArgs(new String[] {"--foo", "bar"});
}

@Test(expected = IllegalArgumentException.class)
public void test_parse_missing_two_dashes() {
Utils.parseArgs(new String[] {"attributeMode", "bar"});
}

@Test(expected = IllegalArgumentException.class)
public void test_parse_missing_value() {
Utils.parseArgs(new String[] {"--interfaces"});
}

@Test
public void test_parse_help() {
try {
Utils.parseArgs(new String[]{"--help"});
} catch (IllegalArgumentException ex) {
assertThat(ex.getMessage()).isEqualTo("Help:");
}
}

private static List<File> getFiles(List<String> models) {
return models.stream().map(ClassLoader::getSystemResource).map(url -> {
try {
Expand Down

0 comments on commit da5e07f

Please sign in to comment.