From 3d0f26deee1021ed19fcc5790c467efddedaa0fb Mon Sep 17 00:00:00 2001 From: Dominic Burger Date: Thu, 31 Oct 2024 16:17:47 +0100 Subject: [PATCH 1/2] Parse command line options --- build.gradle | 5 +- .../ch/geowerkstatt/lk2dxf/LK2DxfOptions.java | 12 ++ .../java/ch/geowerkstatt/lk2dxf/Main.java | 109 +++++++++++++++++- 3 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 src/main/java/ch/geowerkstatt/lk2dxf/LK2DxfOptions.java diff --git a/build.gradle b/build.gradle index ec73cc1..904abdf 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,8 @@ dependencies { implementation 'ch.interlis:iox-ili:1.23.1' implementation 'ch.interlis:ili2c-core:5.5.4' + implementation 'commons-cli:commons-cli:1.9.0' + testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' } @@ -28,7 +30,8 @@ jar { manifest { attributes( 'Main-Class': application.mainClass, - 'Class-Path': configurations.runtimeClasspath.collect { file -> file.getName() }.join(' ') + 'Class-Path': configurations.runtimeClasspath.collect { file -> file.getName() }.join(' '), + 'Implementation-Version': version, ) } } diff --git a/src/main/java/ch/geowerkstatt/lk2dxf/LK2DxfOptions.java b/src/main/java/ch/geowerkstatt/lk2dxf/LK2DxfOptions.java new file mode 100644 index 0000000..646ea9d --- /dev/null +++ b/src/main/java/ch/geowerkstatt/lk2dxf/LK2DxfOptions.java @@ -0,0 +1,12 @@ +package ch.geowerkstatt.lk2dxf; + +import java.util.List; +import java.util.Optional; + +public record LK2DxfOptions( + List xtfFiles, + String dxfFile, + Optional perimeterWkt, + Optional logfile, + boolean trace) { +} diff --git a/src/main/java/ch/geowerkstatt/lk2dxf/Main.java b/src/main/java/ch/geowerkstatt/lk2dxf/Main.java index 5ed1364..788b8c0 100644 --- a/src/main/java/ch/geowerkstatt/lk2dxf/Main.java +++ b/src/main/java/ch/geowerkstatt/lk2dxf/Main.java @@ -1,20 +1,56 @@ package ch.geowerkstatt.lk2dxf; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + import java.io.File; import java.util.List; +import java.util.Optional; public final class Main { + private static final String OPTION_HELP = "help"; + private static final String OPTION_LOGFILE = "logfile"; + private static final String OPTION_PERIMETER = "perimeter"; + private static final String OPTION_TRACE = "trace"; + private static final String OPTION_VERSION = "version"; + + private static final String VERSION; + + static { + String packageVersion = Main.class.getPackage().getImplementationVersion(); + VERSION = packageVersion != null ? packageVersion : "unknown"; + } + private Main() { } /** * Application entry point. */ public static void main(String[] args) { - processFiles(List.of(args)); + Options cliOptions = createCliOptions(); + CommandLine commandLine = parseCommandLine(cliOptions, args); + + if (commandLine.hasOption(OPTION_HELP)) { + printUsage(cliOptions); + } else if (commandLine.hasOption(OPTION_VERSION)) { + System.out.println(VERSION); + } else { + Optional options = parseLK2DxfOptions(commandLine); + if (options.isEmpty()) { + printUsage(cliOptions); + System.exit(1); + } else { + processFiles(options.get()); + } + } } - private static void processFiles(List xtfFiles) { - for (String xtfFile : xtfFiles) { + private static void processFiles(LK2DxfOptions options) { + for (String xtfFile : options.xtfFiles()) { try (LKMapXtfReader reader = new LKMapXtfReader(new File(xtfFile))) { reader.readObjects(iomObject -> { System.out.println(iomObject.getobjectoid()); @@ -26,4 +62,71 @@ private static void processFiles(List xtfFiles) { } } } + + private static CommandLine parseCommandLine(Options options, String[] args) { + try { + DefaultParser parser = new DefaultParser(); + return parser.parse(options, args); + } catch (ParseException e) { + System.err.println("Error parsing command line arguments: " + e.getMessage()); + printUsage(options); + System.exit(1); + return null; + } + } + + private static void printUsage(Options options) { + HelpFormatter formatter = new HelpFormatter(); + formatter.setWidth(100); + formatter.printHelp("java -jar lk2dxf.jar [options] input.xtf [input2.xtf ...] output.dxf", options); + } + + private static Optional parseLK2DxfOptions(CommandLine commandLine) { + List remainingArgs = commandLine.getArgList(); + if (remainingArgs.size() < 2) { + return Optional.empty(); + } + + String dxfFile = remainingArgs.removeLast(); + Optional perimeterWkt = Optional.ofNullable(commandLine.getOptionValue(OPTION_PERIMETER)); + Optional logfile = Optional.ofNullable(commandLine.getOptionValue(OPTION_LOGFILE)); + boolean trace = commandLine.hasOption(OPTION_TRACE); + + return Optional.of(new LK2DxfOptions(remainingArgs, dxfFile, perimeterWkt, logfile, trace)); + } + + private static Options createCliOptions() { + Option help = Option.builder("h") + .longOpt(OPTION_HELP) + .desc("print this help message") + .build(); + Option logfile = Option.builder() + .longOpt(OPTION_LOGFILE) + .desc("path to the log file") + .argName("file") + .hasArg() + .build(); + Option perimeter = Option.builder() + .longOpt(OPTION_PERIMETER) + .desc("exclude all objects whose geometry is fully outside the specified perimeter") + .argName("wkt") + .hasArg() + .build(); + Option trace = Option.builder() + .longOpt(OPTION_TRACE) + .desc("enable trace logging") + .build(); + Option version = Option.builder() + .longOpt(OPTION_VERSION) + .desc("print the version of this application") + .build(); + + Options options = new Options(); + options.addOption(help); + options.addOption(logfile); + options.addOption(perimeter); + options.addOption(trace); + options.addOption(version); + return options; + } } From 0ed0f7240829ed5c239722151beb686e5dd60c0f Mon Sep 17 00:00:00 2001 From: Dominic Burger Date: Mon, 4 Nov 2024 09:06:12 +0100 Subject: [PATCH 2/2] Add description and usage documentation --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 222c417..c167b22 100644 --- a/README.md +++ b/README.md @@ -1 +1,38 @@ -# lk2dxf \ No newline at end of file +[![CI](https://github.com/GeoWerkstatt/lk2dxf/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/GeoWerkstatt/lk2dxf/actions/workflows/ci.yml) +[![Release](https://github.com/GeoWerkstatt/lk2dxf/actions/workflows/release.yml/badge.svg)](https://github.com/GeoWerkstatt/lk2dxf/actions/workflows/release.yml) +[![Latest Release](https://img.shields.io/github/v/release/GeoWerkstatt/lk2dxf)](https://github.com/GeoWerkstatt/lk2dxf/releases/latest) +[![License](https://img.shields.io/github/license/GeoWerkstatt/lk2dxf)](https://github.com/GeoWerkstatt/lk2dxf/blob/main/LICENSE) + +# lk2dxf + +The `lk2dxf` tool can be used to create a DXF file conforming to `SIA 405 SN 532405` from one or more INTERLIS XTF files of the LKMap model `SIA405_LKMap_2015_LV95`. + +## Requirements + +Java 21 (LTS) or later is required to run `lk2dxf`. +Required Jar dependencies are bundled with the distribution of the tool. + +A [docker image](https://github.com/GeoWerkstatt/lk2dxf/pkgs/container/lk2dxf) containing all necessary dependencies is also available for download. + +## Usage + +```shell +java -jar lk2dxf.jar [options] +``` + +### Commandline Options +| Option | Description | +| --- | --- | +| --help | Show help message and exit | +| --version | Show version information and exit | +| --perimeter \ | The WKT of a polygon used to filter the objects | +| --logfile \ | Path to the logfile | +| --trace | Enable trace logging | + +### Perimeter + +The `--perimeter` option can be used to filter the objects written the output DXF file. +Well-known text (WKT) syntax is used to specify the polygon of the perimeter. +Only geometries that intersect the perimeter are included in the DXF file and all objects whose geometry is fully outside the specified perimeter are excluded. + +Existing geometries are not modified, which means that some geometries of the DXF file may extend beyond the bounds of the perimeter.