Skip to content

Commit 698f7fa

Browse files
committed
Added a minimal example program that documents hot to use the published jars.
1 parent 7b726e1 commit 698f7fa

5 files changed

Lines changed: 246 additions & 0 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Validate GBFS feeds. Intended as Java native alternative to https://github.com/M
88

99
Uses the official json schema to validate files.
1010

11+
## Example
12+
13+
See the [`example/`](example/) directory for a working Maven project that depends on this library as a published artifact.
14+
1115
## Usage
1216

1317
Create an instance of `GbfsValidator`:

example/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
target/
2+
.idea/
3+
*.iml

example/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# GBFS Validator Java Example
2+
3+
A minimal example project demonstrating how to use the [gbfs-validator-java](https://github.com/MobilityData/gbfs-validator-java) library to validate GBFS feeds programmatically.
4+
5+
## What it does
6+
7+
- Fetches a public GBFS feed (BIXI Montreal by default)
8+
- Validates a single file using `GbfsValidator.validateFile()`
9+
- Validates a full multi-file feed using `GbfsValidator.validate()`
10+
- Prints validation results including errors, version, and schema info
11+
12+
## Prerequisites
13+
14+
- Java 17+
15+
- Maven 3.6+
16+
17+
## Running
18+
19+
```bash
20+
mvn compile exec:java -Dexec.mainClass=org.mobilitydata.gbfs.validator.example.GbfsValidatorExample
21+
```
22+
23+
## Using a different GBFS feed
24+
25+
Edit the `GBFS_FEED_URL` constant in `GbfsValidatorExample.java` to point to any public GBFS feed.
26+
27+
## Using a release version
28+
29+
To use a stable release instead of a snapshot, change `gbfs-validator.version` in `pom.xml` to a published release version, e.g. `3.0.1`, and remove the snapshot repository configuration.
30+
31+
## Key classes
32+
33+
| Class | Description |
34+
|---|---|
35+
| `GbfsValidatorFactory` | Entry point — creates a `GbfsValidator` instance |
36+
| `GbfsValidator` | Validates a single file or a full set of GBFS files |
37+
| `ValidationResult` | Result of validating a full feed (map of file results + summary) |
38+
| `FileValidationResult` | Result for a single file (errors count, version, schema, errors list) |
39+
| `FileValidationError` | A single validation error (message, path in schema, path in file) |

example/pom.xml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>org.mobilitydata</groupId>
8+
<artifactId>gbfs-validator-java-example</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
<packaging>jar</packaging>
11+
12+
<name>GBFS Validator Java Example</name>
13+
<description>
14+
Example project showing how to use the gbfs-validator-java library
15+
to validate GBFS feeds programmatically.
16+
</description>
17+
18+
<properties>
19+
<maven.compiler.source>17</maven.compiler.source>
20+
<maven.compiler.target>17</maven.compiler.target>
21+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
22+
<!-- To use a snapshot, change this to e.g. 3.0.4-SNAPSHOT -->
23+
<gbfs-validator.version>3.0.3</gbfs-validator.version>
24+
</properties>
25+
26+
<repositories>
27+
<!-- Required to resolve SNAPSHOT versions -->
28+
<repository>
29+
<id>central-snapshots</id>
30+
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
31+
<snapshots>
32+
<enabled>true</enabled>
33+
</snapshots>
34+
<releases>
35+
<enabled>false</enabled>
36+
</releases>
37+
</repository>
38+
</repositories>
39+
40+
<dependencies>
41+
<!-- Core validator library -->
42+
<dependency>
43+
<groupId>org.mobilitydata</groupId>
44+
<artifactId>gbfs-validator-java</artifactId>
45+
<version>${gbfs-validator.version}</version>
46+
</dependency>
47+
</dependencies>
48+
49+
50+
</project>
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package org.mobilitydata.gbfs.validator.example;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.net.URI;
7+
import java.net.http.HttpClient;
8+
import java.net.http.HttpRequest;
9+
import java.net.http.HttpResponse;
10+
import java.nio.charset.StandardCharsets;
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
import org.mobilitydata.gbfs.validation.GbfsValidator;
14+
import org.mobilitydata.gbfs.validation.GbfsValidatorFactory;
15+
import org.mobilitydata.gbfs.validation.model.FileValidationError;
16+
import org.mobilitydata.gbfs.validation.model.FileValidationResult;
17+
import org.mobilitydata.gbfs.validation.model.ValidationResult;
18+
19+
/**
20+
* Example showing how to validate a GBFS feed using gbfs-validator-java.
21+
*
22+
* <p>This example:
23+
* <ol>
24+
* <li>Fetches gbfs.json from a public GBFS feed</li>
25+
* <li>Validates the file using GbfsValidatorFactory</li>
26+
* <li>Prints the validation results to stdout</li>
27+
* </ol>
28+
*
29+
* <p>Usage:
30+
* <pre>
31+
* mvn compile exec:java
32+
* # or
33+
* gradle run
34+
* </pre>
35+
*/
36+
public class GbfsValidatorExample {
37+
38+
// A real public GBFS feed (BIXI Montreal)
39+
private static final String GBFS_FEED_URL =
40+
"https://gbfs.velobixi.com/gbfs/gbfs.json";
41+
42+
public static void main(String[] args) throws IOException, InterruptedException {
43+
System.out.println("=== GBFS Validator Java Example ===\n");
44+
45+
// --- Example 1: Validate a single file ---
46+
System.out.println("Example 1: Validate a single file");
47+
System.out.println("Fetching: " + GBFS_FEED_URL);
48+
String fileContents = fetchUrl(GBFS_FEED_URL);
49+
50+
GbfsValidator validator = GbfsValidatorFactory.getGbfsJsonValidator();
51+
InputStream fileStream = new ByteArrayInputStream(
52+
fileContents.getBytes(StandardCharsets.UTF_8)
53+
);
54+
55+
// The API expects file names WITHOUT the .json extension (e.g. "gbfs", not "gbfs.json")
56+
FileValidationResult fileResult = validator.validateFile("gbfs", fileStream);
57+
printFileResult(fileResult);
58+
59+
// --- Example 2: Validate a full feed (multiple files) ---
60+
System.out.println("\nExample 2: Validate a full feed");
61+
Map<String, InputStream> feedFiles = new HashMap<>();
62+
63+
// Keys must be the GBFS file type name (no .json extension)
64+
feedFiles.put("gbfs", new ByteArrayInputStream(
65+
fileContents.getBytes(StandardCharsets.UTF_8)
66+
));
67+
68+
// Fetch additional files — URL uses .json, but map key does not
69+
String[] additionalFileNames = {
70+
"system_information",
71+
"station_information",
72+
"station_status",
73+
"free_bike_status",
74+
};
75+
String baseUrl = GBFS_FEED_URL.substring(0, GBFS_FEED_URL.lastIndexOf('/') + 1);
76+
for (String fileType : additionalFileNames) {
77+
try {
78+
String content = fetchUrl(baseUrl + fileType + ".json");
79+
feedFiles.put(fileType, new ByteArrayInputStream(
80+
content.getBytes(StandardCharsets.UTF_8)
81+
));
82+
System.out.println(" Loaded: " + fileType);
83+
} catch (Exception e) {
84+
System.out.println(" Skipped: " + fileType + " (" + e.getMessage() + ")");
85+
}
86+
}
87+
88+
ValidationResult feedResult = validator.validate(feedFiles);
89+
printFeedResult(feedResult);
90+
}
91+
92+
private static void printFileResult(FileValidationResult result) {
93+
System.out.println(" File : " + result.file());
94+
System.out.println(" Version : " + result.version());
95+
System.out.println(" Schema : " + result.schema());
96+
System.out.println(" Exists : " + result.exists());
97+
System.out.println(" Required: " + result.required());
98+
System.out.println(" Errors : " + result.errorsCount());
99+
100+
if (!result.errors().isEmpty()) {
101+
System.out.println(" Validation errors:");
102+
for (FileValidationError error : result.errors()) {
103+
System.out.println(" - [" + error.keyword() + "] " + error.message());
104+
System.out.println(" instance: " + error.violationPath());
105+
System.out.println(" schema : " + error.schemaPath());
106+
}
107+
}
108+
if (!result.validatorErrors().isEmpty()) {
109+
System.out.println(" System errors:");
110+
result.validatorErrors().forEach(e ->
111+
System.out.println(" - " + e.error() + ": " + e.message())
112+
);
113+
}
114+
}
115+
116+
private static void printFeedResult(ValidationResult result) {
117+
System.out.println(" Summary : " + result.summary());
118+
System.out.println(" Files validated: " + result.files().size());
119+
result.files().forEach((name, fileResult) -> {
120+
System.out.printf(" %-35s errors=%d version=%s%n",
121+
name, fileResult.errorsCount(), fileResult.version());
122+
});
123+
124+
long totalErrors = result.files().values().stream()
125+
.mapToLong(FileValidationResult::errorsCount)
126+
.sum();
127+
System.out.println("\n Total errors across all files: " + totalErrors);
128+
129+
if (totalErrors == 0) {
130+
System.out.println(" ✓ Feed is valid!");
131+
} else {
132+
System.out.println(" ✗ Feed has validation errors.");
133+
}
134+
}
135+
136+
private static String fetchUrl(String url) throws IOException, InterruptedException {
137+
HttpClient client = HttpClient.newHttpClient();
138+
HttpRequest request = HttpRequest.newBuilder()
139+
.uri(URI.create(url))
140+
.GET()
141+
.build();
142+
HttpResponse<String> response = client.send(
143+
request, HttpResponse.BodyHandlers.ofString()
144+
);
145+
if (response.statusCode() != 200) {
146+
throw new IOException("HTTP " + response.statusCode() + " for " + url);
147+
}
148+
return response.body();
149+
}
150+
}

0 commit comments

Comments
 (0)