Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
d571675a31 | |||
f0205d1cc7 | |||
9ff4555ce8 | |||
bd94a98a30 | |||
1698622fc9 | |||
b9656b386a | |||
ee91f05898 | |||
83e6e446ba | |||
e8ca106037 | |||
5808365777 | |||
9e7a2a92ee | |||
4de8f3f073 | |||
8631a43ed8 | |||
c9444bbc97 | |||
0d0859bd3a | |||
d5e09392ef | |||
d12c585083 | |||
ffa8af2d5d | |||
eb400b52ca | |||
0e21c0d64c | |||
7e3af36e22 | |||
93acfad184 | |||
daa84f61c5 | |||
0304f6e0f4 | |||
56d482b723 | |||
afffaa4a6f | |||
e12775b6ae | |||
6b0481a5e1 | |||
ca9578a4d3 | |||
9ecb3763af | |||
a8fc93fb41 | |||
1f4bd9f411 | |||
ee1d8bd2c8 | |||
4b3a255e18 | |||
6fab3ab6fe | |||
35728fa9b1 | |||
5a93a54c64 | |||
d7f6c34fc0 | |||
746696405c | |||
b208a732c7 | |||
03e6fc0338 |
35
.drone.yml
Normal file
35
.drone.yml
Normal file
@ -0,0 +1,35 @@
|
||||
kind: pipeline
|
||||
name: java8
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps:
|
||||
- name: clone
|
||||
image: plugins/git
|
||||
settings:
|
||||
depth: 10
|
||||
skip_verify: true
|
||||
- name: test
|
||||
image: maven:3.5-jdk-8-alpine
|
||||
commands:
|
||||
- mvn clean test
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: java11
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps:
|
||||
- name: clone
|
||||
image: plugins/git
|
||||
settings:
|
||||
depth: 10
|
||||
skip_verify: true
|
||||
- name: test
|
||||
image: maven:3.5-jdk-11-slim
|
||||
commands:
|
||||
- mvn clean test
|
||||
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
target/
|
||||
.idea/
|
||||
*.iml
|
15
.travis.yml
15
.travis.yml
@ -1,3 +1,16 @@
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- oraclejdk8
|
||||
- oraclejdk11
|
||||
install: true
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "stklcode-github"
|
||||
token:
|
||||
secure: "FkEe/+MKpF4pSX3ZYOgu7oeIKf0460Q3XVLUhIX9bk2dyY8hoab74oCo4FtD7jim0+ZC13JVHGDX7iOQMUtS5EZ+x+pA0qpppzCK5zV8afN/l46HJ07kJldvr+EH0klbDVMFZQ5dT7r/w6CoDzjtENHzKQAJLcheUVDNpkcuBdaplTqIAVf3lQpKtOuVjQJ5qZDwwS5wsHNqPcYbcEGrPmcKDVnp3mD3bfI6dT1bbRt845QcD73rPYkQKxen8eIwJxFf5MZStgvbj7yphPxPGwoLAsoLP6LpThTDYcrg+vgUnSs+l9GckL3IbhPAmecixLbKVnphBZzRTvpdMTt5KeOoAJ2nM6RLs5cRCqiEgLEioWkVaSH5WxoBj38Z1h4fTsDV3dTcCuQWX8GFxdeeTelu+XbatdRWMnUgiF7oax+uNvR62fasTbAc7dWPJbARiD7ZbkWH4nHEY07xKKx87xzUz36ZeEHGoBXgqnLmv/FCwqMrEpOoIT41fc0WYtdIA4wjRoAyG0u+wNBMbVlf4PK72seM4b/bmU+TtmaaVla/SvNOiz+A3DHxtJEUScPcL3QGjviddglMf+wyD6VXVViq9VuYRKZFyjpuoNpb5lwEbwmRnmLabBx8jBgyPinjpmqHYlIntcPAwuyLRaqTHFcmCrbeeZEf7KaPRYKx+Cs="
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- '$HOME/.sonar/cache'
|
||||
script:
|
||||
- mvn -P jacoco clean package sonar:sonar
|
||||
|
42
CHANGELOG.md
Normal file
42
CHANGELOG.md
Normal file
@ -0,0 +1,42 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 1.1.4 - 2018-11-19
|
||||
### Fixed
|
||||
* Fixed issue with direction ID as `String` instead if `Integer` (#2)
|
||||
* Fixed issue with vehicle ID being `null` (#3)
|
||||
* Fixed issue with spaces in search parametes (#4)
|
||||
|
||||
|
||||
## 1.1.3 - 2018-11-13
|
||||
### Security
|
||||
* Updates Jackson dependency 2.9.4 to 2.9.7 (CVE-2018-7489)
|
||||
|
||||
### Changed
|
||||
* Client and model classes implement `Serializable`
|
||||
* Dependency updates
|
||||
|
||||
|
||||
## 1.1.2 - 2018-03-24
|
||||
### Changed
|
||||
* Added automatic module name for JPMS compatibility
|
||||
|
||||
|
||||
## 1.1.1 - 2018-02-20
|
||||
### Changed
|
||||
* On connection or parsing errors, the `IOException` is no longer ignored, but encapsulated in `RuntimeException` (no StackTraces printed)
|
||||
* Code cleanup and minor improvements
|
||||
* Minor dependency updates
|
||||
|
||||
|
||||
## 1.1.0 - 2017-01-07
|
||||
### Added
|
||||
* Filter stops by coordinates and radius
|
||||
* Filter trips by destination and and towards fields
|
||||
|
||||
### Misc
|
||||
* Test coverage 100% (line); tested against ASEAG and TFL APIs
|
||||
|
||||
|
||||
## 1.0.0 - 2017-01-02
|
||||
* Initial release
|
118
CONTRIBUTING.md
Normal file
118
CONTRIBUTING.md
Normal file
@ -0,0 +1,118 @@
|
||||
# How to contribute
|
||||
|
||||
As for all great Open Source projects, contributions in form of bug reports and code are welcome and important to keep the project alive.
|
||||
|
||||
In general, this project follows the [GitHub Flow](https://guides.github.com/introduction/flow/).
|
||||
Fork the project, commit your changes to your branch, open a pull request and it will probably be merged.
|
||||
However, to ensure maintainability and quality of the code, there are some guidelines you might be more or less familiar with.
|
||||
For that purpose, this document describes the important points.
|
||||
|
||||
|
||||
## Opening an Issue
|
||||
|
||||
If you experience any issues with the plugin or the code, don't hesitate to file an issue.
|
||||
|
||||
### Bug Reports
|
||||
|
||||
Think you found a bug?
|
||||
Please clearly state what happens and describe your environment to help tracking down the issue.
|
||||
|
||||
* Which version of the project are you running?
|
||||
* Which version of Java?
|
||||
* Which API do you try to query?
|
||||
|
||||
### Feature Requests
|
||||
|
||||
Missing a feature or like to have certain functionality enhanced?
|
||||
No problem, please open an issue and describe what and why you think this change is required.
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
If you want to contribute your code to solve an issue or implement a desired feature yourself, you might open a pull request.
|
||||
If the changes introduce new functionality or affect major parts of existing code, please consider opening an issue for discussion first.
|
||||
|
||||
For adding new functionality a new test case the corresponding JUnit test would be nice (no hard criterion though).
|
||||
|
||||
### Branches
|
||||
|
||||
The `master` branch represents the current state of development.
|
||||
Please ensure your initial code is up to date with it at the time you start development.
|
||||
The `master` should also be target for most pull requests.
|
||||
|
||||
In addition, this project features a `develop` branch, which holds bleeding edge developments, not necessarily considered stable or even compatible.
|
||||
Do not expect this code to run smoothly, but you might have a look into the history to see if some work on an issue has already been started there.
|
||||
|
||||
For fixes and features, there might be additional branches, likely prefixed by `feature/` `fix/` followed by an issue number (if applicable) and/or a title.
|
||||
Feel free to adapt these naming scheme to your forks.
|
||||
|
||||
### Merge Requirements
|
||||
|
||||
To be merged into the master branch, your code has to pass the automated continuous integration tests, to ensure compatibility.
|
||||
In Addition your code has to be approved by a project member.
|
||||
|
||||
#### What if my code fails the tests?
|
||||
|
||||
Don't worry, you can submit your PR anyway.
|
||||
The reviewing process might help you to solve remaining issues.
|
||||
|
||||
### Commit messages
|
||||
|
||||
Please use speaking titles and messages for your commits, to ensure a transparent history.
|
||||
If your patch fixes an issue, reference the ID in the first line.
|
||||
If you feel like you have to _briefly_ explain your changes, do it (for long explanations and discussion, consider opening an issue or describe in the PR).
|
||||
|
||||
**Example commit:**
|
||||
```text
|
||||
Fix nasty bug from #1337
|
||||
|
||||
This example commit fixes the issue that some people write non-speaking commit messages like 'done magic'.
|
||||
A short description is helpful sometimes.
|
||||
```
|
||||
|
||||
You might sign your work, although that's no must.
|
||||
|
||||
|
||||
### When will it be merged?
|
||||
|
||||
Short answer: When it makes sense.
|
||||
|
||||
Bugfixes should be merged in time - assuming they pass the above criteria.
|
||||
New features might be assigned to a certain milestone and as a result of this be scheduled according to the planned release cycle.
|
||||
|
||||
|
||||
## Versioning
|
||||
|
||||
This projects tries to adapt the [Semantic Versioning](https://semver.org).
|
||||
In short, bug fixes without do not affect any compatibility will raise the third number only, new features will be reflected in the second number and any change breaking compatibility with the public API require raising the first number.
|
||||
|
||||
If you have to make a decision for which version to go please keep this in mind.
|
||||
However for most non-member commits this is mostly informative, as the decision will be made by the project team later.
|
||||
|
||||
|
||||
## Build Environment
|
||||
|
||||
All you need to start off - besides your favorite IDE of course - is Java and Maven.
|
||||
The project requires Java 8 or higher, both OpenJDK and Oracle JDK are supported.
|
||||
All build steps are executed by calling e.g. `mvn clean package` in the project's root directory,
|
||||
|
||||
|
||||
## Unit Tests
|
||||
|
||||
The Java code is tested by a set of JUnit tests.
|
||||
All test files are located in the `src/test` directory.
|
||||
Files ending with `Test.java` will be automatically included into the test suite.
|
||||
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
Automated tests are run using [Travis CI](https://travis-ci.org/stklcode/juraclient) for every commit including pull requests.
|
||||
|
||||
There is also a code quality analysis pushing results to [SonarCloud](https://sonarcloud.io/dashboard?id=de.stklcode.pubtrans%3Ajuraclient).
|
||||
Keep in mind that the ruleset is not yet perfect, so not every minor issue has to be fixed immediately.
|
||||
|
||||
|
||||
## Still Open Questions?
|
||||
|
||||
If anything is still left unanswered and you're unsure if you got it right, don't hesitate to contact a team member.
|
||||
In any case you might submit your request/issue anyway, we won't refuse good code only for formal reasons.
|
65
README.md
65
README.md
@ -1,46 +1,69 @@
|
||||
jURAclient [](https://travis-ci.org/stklcode/juraclient)
|
||||
==========
|
||||
|
||||
# jURAclient
|
||||
[](https://travis-ci.org/stklcode/juraclient)
|
||||
[](https://sonarcloud.io/dashboard?id=de.stklcode.pubtrans%3Ajuraclient)
|
||||
[](https://www.javadoc.io/doc/de.stklcode.pubtrans/juraclient)
|
||||
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.pubtrans%22%20AND%20a%3A%22juraclient%22)
|
||||
[](https://github.com/stklcode/juraclient/blob/master/LICENSE.txt)
|
||||
|
||||
Java client for URA based public transport APIs.
|
||||
|
||||
This client allows to simply connect any Java application to the public transport API to implement a monitor for the
|
||||
local bus station or any other custom queries.
|
||||
local bus station or any other custom queries. API versions 1.x and 2.x are supported.
|
||||
|
||||
**Usage Example**
|
||||
## Usage Examples
|
||||
|
||||
### Initialization
|
||||
```java
|
||||
// Instantiate the client (e.g. using the ASEAG API)
|
||||
UraClient ura = new UraClient("http://ivu.aseag.de");
|
||||
// Instantiate the client (e.g. using the TFL API)
|
||||
UraClient ura = new UraClient("http://countdown.api.tfl.gov.uk");
|
||||
|
||||
// Initiailize with non-standard endpoints
|
||||
// Initiailize the API with non-standard endpoints (e.g. ASEAG with API V2)
|
||||
UraClient ura = new UraClient("http://ivu.aseag.de",
|
||||
"interfaces/ura/instant_V2",
|
||||
"interfaces/ura/stream_V2");
|
||||
|
||||
// List available stops
|
||||
List<Stop> stops = ura.listStops();
|
||||
|
||||
// Get next 10 trips for given stops and lines (all filters optional)
|
||||
List<Trip> trips = ura.forStop("100000")
|
||||
.forLines("25", "35")
|
||||
.getTrips(10);
|
||||
```
|
||||
|
||||
**Maven Artifact**
|
||||
### List Stops
|
||||
|
||||
```java
|
||||
// List ALL available stops
|
||||
List<Stop> stops = ura.getStops();
|
||||
|
||||
// List available stops in a 200m radius around given coordinates
|
||||
List<Stop> stops = ura.forPosition(51.51009, -0.1345734, 200)
|
||||
.getStops();
|
||||
|
||||
```
|
||||
|
||||
### Get Trips
|
||||
|
||||
```java
|
||||
// Get next 10 trips for given stops and lines in a single direction (all filters optional)
|
||||
List<Trip> trips = ura.forStop("100000")
|
||||
.forLines("25", "35")
|
||||
.forDirection(1)
|
||||
.getTrips(10);
|
||||
|
||||
// Get trips from given stop towards your destination
|
||||
List<Trip> trips = ura.forStopByName("Piccadilly Circus")
|
||||
.towards("Marble Arch")
|
||||
.getTrips();
|
||||
```
|
||||
|
||||
## Maven Artifact
|
||||
```
|
||||
<dependency>
|
||||
<groupId>de.stklcode.pubtrans</groupId>
|
||||
<artifactId>juraclient</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.1.4</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Planned features:**
|
||||
## Planned Features
|
||||
|
||||
* More refined query parameters
|
||||
* Stream API with asynchronous consumer
|
||||
|
||||
**License**
|
||||
## License
|
||||
|
||||
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
The project is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
187
pom.xml
187
pom.xml
@ -5,28 +5,62 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.stklcode.pubtrans</groupId>
|
||||
<artifactId>juraclien</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<artifactId>juraclient</artifactId>
|
||||
<version>1.1.4</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jURAclient</name>
|
||||
<description>Java client for URA based public transport API</description>
|
||||
<url>https://github.com/stklcode/juraclient</url>
|
||||
<inceptionYear>2016</inceptionYear>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Stefan Kalscheuer</name>
|
||||
<email>stefan@stklcode.de</email>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/stklcode/juraclient.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:stklcode/juraclient.git</developerConnection>
|
||||
<url>https://github.com/stklcode/juraclient</url>
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
<system>github</system>
|
||||
<url>https://github.com/stklcode/juraclient/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<version>2.9.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<version>2.9.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -36,15 +70,15 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy-agent</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@ -54,12 +88,137 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Automatic-Module-Name>de.stklcode.pubtrans.juraclient</Automatic-Module-Name>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jacoco</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>org.jacoco.agent</artifactId>
|
||||
<version>0.8.2</version>
|
||||
<classifier>runtime</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-instrument</id>
|
||||
<goals>
|
||||
<goal>instrument</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>default-restore-instrumented-classes</id>
|
||||
<goals>
|
||||
<goal>restore-instrumented-classes</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<dataFile>${project.build.directory}/coverage.exec</dataFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<jacoco-agent.destfile>${project.build.directory}/jacoco.exec</jacoco-agent.destfile>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>sources</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>javadoc</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<configuration>
|
||||
<overview>${basedir}/src/main/javadoc/overview.html</overview>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
</project>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,22 +20,24 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.stklcode.pubtrans.ura.model.Stop;
|
||||
import de.stklcode.pubtrans.ura.model.Trip;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Client for URA based public transport API.
|
||||
* <p>
|
||||
* This client features builder pattern style query functionality to obtain {@link Trip} and {@link Stop} information.
|
||||
*
|
||||
* @author Stefan Kalscheuer <stefan@stklcode.de>
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
public class UraClient {
|
||||
private static final String DEFAULT_INSTANT_URL = "/interfaces/ura/instant_V2";
|
||||
private static final String DEFAULT_STREAM_URL = "/interfaces/ura/stream_V2";
|
||||
public class UraClient implements Serializable {
|
||||
private static final String DEFAULT_INSTANT_URL = "/interfaces/ura/instant_V1";
|
||||
private static final String DEFAULT_STREAM_URL = "/interfaces/ura/stream_V1";
|
||||
|
||||
private static final String PAR_STOP_ID = "StopID";
|
||||
private static final String PAR_STOP_NAME = "StopPointName";
|
||||
@ -51,10 +53,12 @@ public class UraClient {
|
||||
private static final String PAR_VEHICLE_ID = "VehicleID";
|
||||
private static final String PAR_TRIP_ID = "TripID";
|
||||
private static final String PAR_ESTTIME = "EstimatedTime";
|
||||
private static final String PAR_TOWARDS = "Towards";
|
||||
private static final String PAR_CIRCLE = "Circle";
|
||||
|
||||
private static final Integer RES_TYPE_STOP = 0;
|
||||
private static final Integer RES_TYPE_PREDICTION = 1;
|
||||
|
||||
private static final Integer RES_TYPE_URA_VERSION = 4;
|
||||
|
||||
private static final String[] REQUEST_STOP = {PAR_STOP_NAME, PAR_STOP_ID, PAR_STOP_INDICATOR, PAR_STOP_STATE, PAR_GEOLOCATION};
|
||||
private static final String[] REQUEST_TRIP = {PAR_STOP_NAME, PAR_STOP_ID, PAR_STOP_INDICATOR, PAR_STOP_STATE, PAR_GEOLOCATION,
|
||||
@ -68,20 +72,20 @@ public class UraClient {
|
||||
/**
|
||||
* Constructor with base URL and default API paths.
|
||||
*
|
||||
* @param baseURL the base URL (with protocol, without trailing slash)
|
||||
* @param baseURL The base URL (with protocol, without trailing slash).
|
||||
*/
|
||||
public UraClient(String baseURL) {
|
||||
public UraClient(final String baseURL) {
|
||||
this(baseURL, DEFAULT_INSTANT_URL, DEFAULT_STREAM_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with base URL and custom API paths
|
||||
* Constructor with base URL and custom API paths.
|
||||
*
|
||||
* @param baseURL the base URL (including protocol)
|
||||
* @param instantURL the path for instant requests
|
||||
* @param streamURL the path for stream requests
|
||||
* @param baseURL The base URL (including protocol).
|
||||
* @param instantURL The path for instant requests.
|
||||
* @param streamURL The path for stream requests.
|
||||
*/
|
||||
public UraClient(String baseURL, String instantURL, String streamURL) {
|
||||
public UraClient(final String baseURL, final String instantURL, final String streamURL) {
|
||||
this.baseURL = baseURL;
|
||||
this.instantURL = instantURL;
|
||||
this.streamURL = streamURL;
|
||||
@ -94,7 +98,7 @@ public class UraClient {
|
||||
* @param stops Stop IDs
|
||||
* @return the request
|
||||
*/
|
||||
public Query forStops(final String...stops) {
|
||||
public final Query forStops(final String... stops) {
|
||||
return new Query().forStops(stops);
|
||||
}
|
||||
|
||||
@ -104,45 +108,80 @@ public class UraClient {
|
||||
* @param stopNames Stop Point Names
|
||||
* @return the request
|
||||
*/
|
||||
public Query forStopsByName(final String...stopNames) {
|
||||
public final Query forStopsByName(final String... stopNames) {
|
||||
return new Query().forStopsByName(stopNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given line IDs.
|
||||
*
|
||||
* @param lines line IDs
|
||||
* @return the request
|
||||
* @param lines Line IDs.
|
||||
* @return The request.
|
||||
*/
|
||||
public Query forLines(final String...lines) {
|
||||
public final Query forLines(final String... lines) {
|
||||
return new Query().forLines(lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given line names.
|
||||
*
|
||||
* @param lineNames line names
|
||||
* @return the request
|
||||
* @param lineNames Line names.
|
||||
* @return The request.
|
||||
*/
|
||||
public Query forLinesByName(final String...lineNames) {
|
||||
public final Query forLinesByName(final String... lineNames) {
|
||||
return new Query().forLinesByName(lineNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given direction.
|
||||
*
|
||||
* @param direction the direction ID
|
||||
* @return the request
|
||||
* @param direction The direction ID.
|
||||
* @return The request.
|
||||
*/
|
||||
public Query forDirection(final Integer direction) {
|
||||
public final Query forDirection(final Integer direction) {
|
||||
return new Query().forDirection(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given destination names.
|
||||
*
|
||||
* @param destinationNames Destination names.
|
||||
* @return The request.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public final Query forDestinationNames(final String... destinationNames) {
|
||||
return new Query().forDestinationNames(destinationNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given direction defined by stop point name.
|
||||
*
|
||||
* @param towards Towards stop point names.
|
||||
* @return The request.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public final Query towards(final String... towards) {
|
||||
return new Query().towards(towards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given destination names.
|
||||
*
|
||||
* @param latitude Latitude (WGS84).
|
||||
* @param longitude Longitude (WGS84).
|
||||
* @param radius Search radius (meters).
|
||||
* @return The request.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public final Query forPosition(final Double latitude, final Double longitude, final Integer radius) {
|
||||
return new Query().forPosition(latitude, longitude, radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of trips.
|
||||
* If forStops() and/or forLines() has been called, those will be used as filter.
|
||||
*
|
||||
* @return list of trips
|
||||
* @return List of trips.
|
||||
*/
|
||||
public List<Trip> getTrips() {
|
||||
return getTrips(new Query(), null);
|
||||
@ -152,7 +191,8 @@ public class UraClient {
|
||||
* Get list of trips with limit.
|
||||
* If forStops() and/or forLines() has been called, those will be used as filter.
|
||||
*
|
||||
* @return list of trips
|
||||
* @param limit Maximum number of results.
|
||||
* @return List of trips.
|
||||
*/
|
||||
public List<Trip> getTrips(final Integer limit) {
|
||||
return getTrips(new Query(), limit);
|
||||
@ -162,32 +202,40 @@ public class UraClient {
|
||||
* Get list of trips.
|
||||
* If forStops() and/or forLines() has been called, those will be used as filter.
|
||||
*
|
||||
* @return list of trips
|
||||
* @param query The query.
|
||||
* @return List of trips.
|
||||
*/
|
||||
public List<Trip> getTrips(Query query) {
|
||||
public List<Trip> getTrips(final Query query) {
|
||||
return getTrips(query, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of trips for given stopIDs and lineIDs with result limit.
|
||||
*
|
||||
* @param query the request
|
||||
* @param limit maximum number of results
|
||||
* @return list of trips
|
||||
* @param query The query.
|
||||
* @param limit Maximum number of results.
|
||||
* @return List of trips.
|
||||
*/
|
||||
public List<Trip> getTrips(final Query query, final Integer limit) {
|
||||
List<Trip> trips = new ArrayList<>();
|
||||
try (InputStream is = requestInstant(REQUEST_TRIP, query.stopIDs, query.stopNames, query.lineIDs, query.lineNames, query.direction);
|
||||
try (InputStream is = requestInstant(REQUEST_TRIP, query);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null && (limit == null || trips.size() < limit)) {
|
||||
String version = null;
|
||||
String line = br.readLine();
|
||||
while (line != null && (limit == null || trips.size() < limit)) {
|
||||
List l = mapper.readValue(line, List.class);
|
||||
/* Check if result exists and has correct response type */
|
||||
if (l != null && l.size() > 0 && l.get(0).equals(RES_TYPE_PREDICTION))
|
||||
trips.add(new Trip(l));
|
||||
if (l != null && !l.isEmpty()) {
|
||||
if (l.get(0).equals(RES_TYPE_URA_VERSION)) {
|
||||
version = l.get(1).toString();
|
||||
} else if (l.get(0).equals(RES_TYPE_PREDICTION)) {
|
||||
trips.add(new Trip(l, version));
|
||||
}
|
||||
}
|
||||
line = br.readLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException("Failed to read from API", e);
|
||||
}
|
||||
return trips;
|
||||
}
|
||||
@ -195,7 +243,7 @@ public class UraClient {
|
||||
/**
|
||||
* Get list of stops without filters.
|
||||
*
|
||||
* @return the list
|
||||
* @return Lhe list.
|
||||
*/
|
||||
public List<Stop> getStops() {
|
||||
return getStops(new Query());
|
||||
@ -205,21 +253,23 @@ public class UraClient {
|
||||
* List available stopIDs.
|
||||
* If forStops() and/or forLines() has been called, those will be used as filter.
|
||||
*
|
||||
* @return the list
|
||||
* @param query The query.
|
||||
* @return The list.
|
||||
*/
|
||||
public List<Stop> getStops(Query query) {
|
||||
public List<Stop> getStops(final Query query) {
|
||||
List<Stop> stops = new ArrayList<>();
|
||||
try (InputStream is = requestInstant(REQUEST_STOP, query.stopIDs, query.stopNames, query.lineIDs, query.lineNames, query.direction);
|
||||
try (InputStream is = requestInstant(REQUEST_STOP, query);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
List l = mapper.readValue(line, List.class);
|
||||
/* Check if result exists and has correct response type */
|
||||
if (l != null && l.size() > 0 && l.get(0).equals(RES_TYPE_STOP))
|
||||
if (l != null && !l.isEmpty() && l.get(0).equals(RES_TYPE_STOP)) {
|
||||
stops.add(new Stop(l));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException("Failed to read from API", e);
|
||||
}
|
||||
return stops;
|
||||
}
|
||||
@ -227,43 +277,73 @@ public class UraClient {
|
||||
/**
|
||||
* Issue request to instant endpoint and return input stream.
|
||||
*
|
||||
* @param returnList fields to fetch
|
||||
* @param returnList Fields to fetch.
|
||||
* @param query The query.
|
||||
* @return Input stream of the URL
|
||||
* @throws IOException on errors
|
||||
*/
|
||||
private InputStream requestInstant(String[] returnList, String[] stopIDs, String[] stopNames, String[] lineIDs, String[] lineNames, Integer direction) throws IOException {
|
||||
private InputStream requestInstant(final String[] returnList, final Query query) throws IOException {
|
||||
String urlStr = baseURL + instantURL + "?ReturnList=" + String.join(",", returnList);
|
||||
if (stopIDs != null && stopIDs.length > 0)
|
||||
urlStr += "&" + PAR_STOP_ID + "=" + String.join(",", stopIDs);
|
||||
if (stopNames != null && stopNames.length > 0)
|
||||
urlStr += "&" + PAR_STOP_NAME + "=" + String.join(",", stopNames);
|
||||
if (lineIDs != null && lineIDs.length > 0)
|
||||
urlStr += "&" + PAR_LINE_ID + "=" + String.join(",", lineIDs);
|
||||
if (lineNames != null && lineNames.length > 0)
|
||||
urlStr += "&" + PAR_LINE_NAME + "=" + String.join(",", lineNames);
|
||||
if (direction != null)
|
||||
urlStr += "&" + PAR_DIR_ID + "=" + direction;
|
||||
URL url = new URL(urlStr);
|
||||
return url.openStream();
|
||||
|
||||
if (query.stopIDs != null && query.stopIDs.length > 0) {
|
||||
urlStr += "&" + PAR_STOP_ID + "=" + URLEncoder.encode(String.join(",", query.stopIDs), UTF_8.name());
|
||||
}
|
||||
if (query.stopNames != null && query.stopNames.length > 0) {
|
||||
urlStr += "&" + PAR_STOP_NAME + "=" + URLEncoder.encode(String.join(",", query.stopNames), UTF_8.name());
|
||||
}
|
||||
if (query.lineIDs != null && query.lineIDs.length > 0) {
|
||||
urlStr += "&" + PAR_LINE_ID + "=" + URLEncoder.encode(String.join(",", query.lineIDs), UTF_8.name());
|
||||
}
|
||||
if (query.lineNames != null && query.lineNames.length > 0) {
|
||||
urlStr += "&" + PAR_LINE_NAME + "=" + URLEncoder.encode(String.join(",", query.lineNames), UTF_8.name());
|
||||
}
|
||||
if (query.direction != null) {
|
||||
urlStr += "&" + PAR_DIR_ID + "=" + query.direction;
|
||||
}
|
||||
if (query.destinationNames != null) {
|
||||
urlStr += "&" + PAR_DEST_NAME + "=" + URLEncoder.encode(String.join(",", query.destinationNames), UTF_8.name());
|
||||
}
|
||||
if (query.towards != null) {
|
||||
urlStr += "&" + PAR_TOWARDS + "=" + URLEncoder.encode(String.join(",", query.towards), UTF_8.name());
|
||||
}
|
||||
if (query.circle != null) {
|
||||
urlStr += "&" + PAR_CIRCLE + "=" + URLEncoder.encode(query.circle, UTF_8.name());
|
||||
}
|
||||
|
||||
return request(urlStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open given URL as InputStream.
|
||||
*
|
||||
* @param url The URL.
|
||||
* @return Input Stream of results.
|
||||
* @throws IOException Error opening conneciton or reading data.
|
||||
*/
|
||||
private InputStream request(String url) throws IOException {
|
||||
return new URL(url).openStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request meta object.
|
||||
*/
|
||||
public class Query {
|
||||
public final class Query {
|
||||
private String[] stopIDs;
|
||||
private String[] stopNames;
|
||||
private String[] lineIDs;
|
||||
private String[] lineNames;
|
||||
private Integer direction;
|
||||
private String[] destinationNames;
|
||||
private String[] towards;
|
||||
private String circle;
|
||||
|
||||
/**
|
||||
* Builder pattern to request given line IDs.
|
||||
*
|
||||
* @param lineIDs line IDs
|
||||
* @return the query
|
||||
* @param lineIDs Line IDs.
|
||||
* @return The query.
|
||||
*/
|
||||
public Query forLines(final String...lineIDs) {
|
||||
public Query forLines(final String... lineIDs) {
|
||||
this.lineIDs = lineIDs;
|
||||
return this;
|
||||
}
|
||||
@ -271,10 +351,10 @@ public class UraClient {
|
||||
/**
|
||||
* Builder pattern to request given line names.
|
||||
*
|
||||
* @param lineNames line names
|
||||
* @return the query
|
||||
* @param lineNames Line names.
|
||||
* @return The query.
|
||||
*/
|
||||
public Query forLinesByName(final String...lineNames) {
|
||||
public Query forLinesByName(final String... lineNames) {
|
||||
this.lineNames = lineNames;
|
||||
return this;
|
||||
}
|
||||
@ -282,10 +362,10 @@ public class UraClient {
|
||||
/**
|
||||
* Builder pattern to request given stop IDs.
|
||||
*
|
||||
* @param stopIDs stop IDs
|
||||
* @return the query
|
||||
* @param stopIDs Stop IDs.
|
||||
* @return The query.
|
||||
*/
|
||||
public Query forStops(final String...stopIDs) {
|
||||
public Query forStops(final String... stopIDs) {
|
||||
this.stopIDs = stopIDs;
|
||||
return this;
|
||||
}
|
||||
@ -293,10 +373,10 @@ public class UraClient {
|
||||
/**
|
||||
* Builder pattern to request given stop names.
|
||||
*
|
||||
* @param stopNames line names
|
||||
* @return the query
|
||||
* @param stopNames Line names.
|
||||
* @return The query.
|
||||
*/
|
||||
public Query forStopsByName(final String...stopNames) {
|
||||
public Query forStopsByName(final String... stopNames) {
|
||||
this.stopNames = stopNames;
|
||||
return this;
|
||||
}
|
||||
@ -304,18 +384,56 @@ public class UraClient {
|
||||
/**
|
||||
* Builder pattern to request given direction.
|
||||
*
|
||||
* @param direction the direction
|
||||
* @return the query
|
||||
* @param direction The direction.
|
||||
* @return The query.
|
||||
*/
|
||||
public Query forDirection(final Integer direction) {
|
||||
this.direction = direction;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given destination names.
|
||||
*
|
||||
* @param destinationNames Names of destinations.
|
||||
* @return The query.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public Query forDestinationNames(final String... destinationNames) {
|
||||
this.destinationNames = destinationNames;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given direction defined by stop point name.
|
||||
*
|
||||
* @param towards Towards stop point names.
|
||||
* @return The request.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public Query towards(final String... towards) {
|
||||
this.towards = towards;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder pattern to request given position and radius.
|
||||
*
|
||||
* @param latitude Latitude (WGS84).
|
||||
* @param longitude Longitude (WGS84).
|
||||
* @param radius Search radius (meters).
|
||||
* @return The query.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public Query forPosition(final Double latitude, final Double longitude, final Integer radius) {
|
||||
this.circle = latitude.toString() + "," + longitude.toString() + "," + radius.toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stops for set filters.
|
||||
*
|
||||
* @return List of matching trips
|
||||
* @return List of matching trips.
|
||||
*/
|
||||
public List<Stop> getStops() {
|
||||
return UraClient.this.getStops(this);
|
||||
@ -324,7 +442,7 @@ public class UraClient {
|
||||
/**
|
||||
* Get trips for set filters.
|
||||
*
|
||||
* @return List of matching trips
|
||||
* @return List of matching trips.
|
||||
*/
|
||||
public List<Trip> getTrips() {
|
||||
return UraClient.this.getTrips(this);
|
||||
|
52
src/main/java/de/stklcode/pubtrans/ura/model/Model.java
Normal file
52
src/main/java/de/stklcode/pubtrans/ura/model/Model.java
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.pubtrans.ura.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Interface for model classes to bundle common methods.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 1.1.1
|
||||
*/
|
||||
interface Model extends Serializable {
|
||||
/**
|
||||
* Generate exception for unmatched type when String is expected.
|
||||
*
|
||||
* @param field Field number.
|
||||
* @param actual Actual class.
|
||||
* @return The Exception.
|
||||
*/
|
||||
static IOException typeErrorString(int field, Class actual) {
|
||||
return typeError(field, actual, "String");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate exception for unmatched type.
|
||||
*
|
||||
* @param field Field number.
|
||||
* @param actual Actual class.
|
||||
* @param expected Expected type.
|
||||
* @return The Exception.
|
||||
*/
|
||||
static IOException typeError(int field, Class actual, String expected) {
|
||||
return new IOException(String.format("Field %d not of expected type %s, found %s",
|
||||
field, expected, actual.getSimpleName()));
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,9 +22,17 @@ import java.util.List;
|
||||
/**
|
||||
* Entity for a single stop.
|
||||
*
|
||||
* @author Stefan Kalscheuer <stefan@stklcode.de>
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
public class Stop {
|
||||
public final class Stop implements Model {
|
||||
private static final int F_STOP_NAME = 1;
|
||||
private static final int F_STOP_ID = 2;
|
||||
private static final int F_INDICATOR = 3;
|
||||
private static final int F_STATE = 4;
|
||||
private static final int F_LATITUDE = 5;
|
||||
private static final int F_LONGITUDE = 6;
|
||||
private static final int F_NUM_OF_FIELDS = 7;
|
||||
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final String indicator;
|
||||
@ -32,7 +40,22 @@ public class Stop {
|
||||
private final Double latitude;
|
||||
private final Double longitude;
|
||||
|
||||
public Stop(String id, String name, String indicator, Integer state, Double latitude, Double longitude) {
|
||||
/**
|
||||
* Construct Stop object.
|
||||
*
|
||||
* @param id Stop ID.
|
||||
* @param name Stop name.
|
||||
* @param indicator Stop indicator.
|
||||
* @param state Stop state.
|
||||
* @param latitude Stop geolocation latitude.
|
||||
* @param longitude Stop geolocation longitude.
|
||||
*/
|
||||
public Stop(final String id,
|
||||
final String name,
|
||||
final String indicator,
|
||||
final Integer state,
|
||||
final Double latitude,
|
||||
final Double longitude) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.indicator = indicator;
|
||||
@ -41,56 +64,94 @@ public class Stop {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public Stop(List raw) throws IOException {
|
||||
if (raw == null || raw.size() < 7)
|
||||
/**
|
||||
* Construct Stop object from raw list of attributes parsed from JSON.
|
||||
*
|
||||
* @param raw List of attributes from JSON line
|
||||
* @throws IOException Thrown on invalid line format.
|
||||
*/
|
||||
public Stop(final List raw) throws IOException {
|
||||
if (raw == null || raw.size() < F_NUM_OF_FIELDS) {
|
||||
throw new IOException("Invalid number of fields");
|
||||
}
|
||||
|
||||
if (raw.get(1) instanceof String)
|
||||
name = (String)raw.get(1);
|
||||
else
|
||||
throw new IOException("Field 1 not of expected type String, found " + raw.get(1).getClass().getSimpleName());
|
||||
if (raw.get(2) instanceof String)
|
||||
id = (String)raw.get(2);
|
||||
else
|
||||
throw new IOException("Field 2 not of expected type String, found " + raw.get(2).getClass().getSimpleName());
|
||||
if (raw.get(3) instanceof String)
|
||||
indicator = (String)raw.get(3);
|
||||
else
|
||||
throw new IOException("Field 3 not of expected type String, found " + raw.get(3).getClass().getSimpleName());
|
||||
if (raw.get(4) instanceof Integer)
|
||||
state = (Integer)raw.get(4);
|
||||
else
|
||||
throw new IOException("Field 4 not of expected type Integer, found " + raw.get(4).getClass().getSimpleName());
|
||||
if (raw.get(5) instanceof Double)
|
||||
latitude = (Double)raw.get(5);
|
||||
else
|
||||
throw new IOException("Field 5 not of expected type Double, found " + raw.get(5).getClass().getSimpleName());
|
||||
if (raw.get(6) instanceof Double)
|
||||
longitude = (Double)raw.get(6);
|
||||
else
|
||||
throw new IOException("Field 6 not of expected type Double, found " + raw.get(6).getClass().getSimpleName());
|
||||
if (raw.get(1) instanceof String) {
|
||||
name = (String) raw.get(F_STOP_NAME);
|
||||
} else {
|
||||
throw Model.typeErrorString(F_STOP_NAME, raw.get(F_STOP_NAME).getClass());
|
||||
}
|
||||
|
||||
if (raw.get(F_STOP_ID) instanceof String) {
|
||||
id = (String) raw.get(F_STOP_ID);
|
||||
} else {
|
||||
throw Model.typeErrorString(F_STOP_ID, raw.get(F_STOP_ID).getClass());
|
||||
}
|
||||
|
||||
if (raw.get(F_INDICATOR) instanceof String) {
|
||||
indicator = (String) raw.get(F_INDICATOR);
|
||||
} else if (raw.get(F_INDICATOR) == null) {
|
||||
indicator = null;
|
||||
} else {
|
||||
throw Model.typeErrorString(F_INDICATOR, raw.get(F_INDICATOR).getClass());
|
||||
}
|
||||
|
||||
if (raw.get(F_STATE) instanceof Integer) {
|
||||
state = (Integer) raw.get(F_STATE);
|
||||
} else {
|
||||
throw Model.typeError(F_STATE, raw.get(F_STATE).getClass(), "Integer");
|
||||
}
|
||||
|
||||
if (raw.get(F_LATITUDE) instanceof Double) {
|
||||
latitude = (Double) raw.get(F_LATITUDE);
|
||||
} else {
|
||||
throw Model.typeError(F_LATITUDE, raw.get(F_LATITUDE).getClass(), "Double");
|
||||
}
|
||||
|
||||
if (raw.get(F_LONGITUDE) instanceof Double) {
|
||||
longitude = (Double) raw.get(F_LONGITUDE);
|
||||
} else {
|
||||
throw Model.typeError(F_LONGITUDE, raw.get(F_LONGITUDE).getClass(), "Double");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The stop ID.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The stop name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The stop indicator.
|
||||
*/
|
||||
public String getIndicator() {
|
||||
return indicator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The stop indicator.
|
||||
*/
|
||||
public Integer getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The stop geoloaction latitude.
|
||||
*/
|
||||
public Double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The stop geolocation longitude.
|
||||
*/
|
||||
public Double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,9 +22,20 @@ import java.util.List;
|
||||
/**
|
||||
* Entity for a single trip.
|
||||
*
|
||||
* @author Stefan Kalscheuer <stefan@stklcode.de>
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
public class Trip {
|
||||
public final class Trip implements Model {
|
||||
private static final int VISIT_ID = 7;
|
||||
private static final int LINE_ID = 8;
|
||||
private static final int LINE_NAME = 9;
|
||||
private static final int DIRECTION_ID = 10;
|
||||
private static final int DESTINATION_NAME = 11;
|
||||
private static final int DESTINATION_TEXT = 12;
|
||||
private static final int VEHICLE_ID = 13;
|
||||
private static final int TRIP_ID = 14;
|
||||
private static final int ESTIMATED_TIME = 15;
|
||||
private static final int NUM_OF_FIELDS = 16;
|
||||
|
||||
private final Stop stop;
|
||||
private final String id;
|
||||
private final Integer visitID;
|
||||
@ -36,13 +47,81 @@ public class Trip {
|
||||
private final Long estimatedTime;
|
||||
private final String vehicleID;
|
||||
|
||||
public Trip(String stopID, String stopName, String stopIndicator, Integer stopState, Double stopLatitude, Double stopLongitude,
|
||||
Integer visitID, String lineID, String lineName, Integer directionID, String destinationName, String destinationText, String vehicleID, String tripID, Long estimatedTime) {
|
||||
this(new Stop(stopID, stopName, stopIndicator, stopState, stopLatitude, stopLongitude),
|
||||
visitID, lineID, lineName, directionID, destinationName, destinationText, vehicleID, tripID, estimatedTime);
|
||||
/**
|
||||
* Construct Trip object from complete set of data.
|
||||
*
|
||||
* @param stopID Stop ID.
|
||||
* @param stopName Stop name.
|
||||
* @param stopIndicator Stop Indicator.
|
||||
* @param stopState Stop state.
|
||||
* @param stopLatitude Stop geolocation latitude.
|
||||
* @param stopLongitude Stop geolocation latitude.
|
||||
* @param visitID Visit ID.
|
||||
* @param lineID Line ID.
|
||||
* @param lineName Line name.
|
||||
* @param directionID Direction ID.
|
||||
* @param destinationName Destination name.
|
||||
* @param destinationText Destination text.
|
||||
* @param vehicleID Vehicle ID.
|
||||
* @param tripID Trip ID.
|
||||
* @param estimatedTime Estimated time.
|
||||
*/
|
||||
public Trip(final String stopID,
|
||||
final String stopName,
|
||||
final String stopIndicator,
|
||||
final Integer stopState,
|
||||
final Double stopLatitude,
|
||||
final Double stopLongitude,
|
||||
final Integer visitID,
|
||||
final String lineID,
|
||||
final String lineName,
|
||||
final Integer directionID,
|
||||
final String destinationName,
|
||||
final String destinationText,
|
||||
final String vehicleID,
|
||||
final String tripID,
|
||||
final Long estimatedTime) {
|
||||
this(new Stop(stopID,
|
||||
stopName,
|
||||
stopIndicator,
|
||||
stopState,
|
||||
stopLatitude,
|
||||
stopLongitude),
|
||||
visitID,
|
||||
lineID,
|
||||
lineName,
|
||||
directionID,
|
||||
destinationName,
|
||||
destinationText,
|
||||
vehicleID,
|
||||
tripID,
|
||||
estimatedTime);
|
||||
}
|
||||
|
||||
public Trip(Stop stop, Integer visitID, String lineID, String lineName, Integer directionID, String destinationName, String destinationText, String vehicleID, String tripID, Long estimatedTime) {
|
||||
/**
|
||||
* Construct Trip object from Stop model and set of additional data.
|
||||
*
|
||||
* @param stop Stop model
|
||||
* @param visitID Visit ID
|
||||
* @param lineID Line ID
|
||||
* @param lineName Line name
|
||||
* @param directionID Direction ID
|
||||
* @param destinationName Destination name
|
||||
* @param destinationText Destination text
|
||||
* @param vehicleID Vehicle ID
|
||||
* @param tripID Trip ID
|
||||
* @param estimatedTime Estimated time
|
||||
*/
|
||||
public Trip(final Stop stop,
|
||||
final Integer visitID,
|
||||
final String lineID,
|
||||
final String lineName,
|
||||
final Integer directionID,
|
||||
final String destinationName,
|
||||
final String destinationText,
|
||||
final String vehicleID,
|
||||
final String tripID,
|
||||
final Long estimatedTime) {
|
||||
this.stop = stop;
|
||||
this.visitID = visitID;
|
||||
this.lineID = lineID;
|
||||
@ -55,86 +134,163 @@ public class Trip {
|
||||
this.estimatedTime = estimatedTime;
|
||||
}
|
||||
|
||||
public Trip(List raw) throws IOException {
|
||||
if (raw == null || raw.size() < 16)
|
||||
/**
|
||||
* Construct Trip object from raw list of attributes parsed from JSON.
|
||||
*
|
||||
* @param raw List of attributes from JSON line
|
||||
* @throws IOException Thrown on invalid line format.
|
||||
*/
|
||||
public Trip(final List raw) throws IOException {
|
||||
this(raw, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct Stop object from raw list of attributes parsed from JSON with explicitly specified version.
|
||||
*
|
||||
* @param raw List of attributes from JSON line
|
||||
* @param version API version
|
||||
* @throws IOException Thrown on invalid line format.
|
||||
*/
|
||||
public Trip(final List raw, final String version) throws IOException {
|
||||
if (raw == null || raw.size() < NUM_OF_FIELDS) {
|
||||
throw new IOException("Invalid number of fields");
|
||||
}
|
||||
|
||||
stop = new Stop(raw);
|
||||
|
||||
if (raw.get(7) instanceof Integer)
|
||||
visitID = (Integer) raw.get(7);
|
||||
else
|
||||
throw new IOException("Field 7 not of expected type Integer, found " + raw.get(7).getClass().getSimpleName());
|
||||
if (raw.get(8) instanceof String)
|
||||
lineID = (String)raw.get(8);
|
||||
else
|
||||
throw new IOException("Field 8 not of expected type String, found " + raw.get(8).getClass().getSimpleName());
|
||||
if (raw.get(9) instanceof String)
|
||||
lineName = (String)raw.get(9);
|
||||
else
|
||||
throw new IOException("Field 9 not of expected type String, found " + raw.get(9).getClass().getSimpleName());
|
||||
if (raw.get(10) instanceof Integer)
|
||||
directionID = (Integer)raw.get(10);
|
||||
else
|
||||
throw new IOException("Field 10 not of expected type Integer, found " + raw.get(10).getClass().getSimpleName());
|
||||
if (raw.get(11) instanceof String)
|
||||
destinationName = (String)raw.get(11);
|
||||
else
|
||||
throw new IOException("Field 11 not of expected type String, found " + raw.get(11).getClass().getSimpleName());
|
||||
if (raw.get(12) instanceof String)
|
||||
destinationText = (String)raw.get(12);
|
||||
else
|
||||
throw new IOException("Field 12 not of expected type String, found " + raw.get(12).getClass().getSimpleName());
|
||||
if (raw.get(13) instanceof String)
|
||||
vehicleID = (String)raw.get(13);
|
||||
else
|
||||
throw new IOException("Field 13 not of expected type String, found " + raw.get(13).getClass().getSimpleName());
|
||||
if (raw.get(14) instanceof String)
|
||||
id = (String)raw.get(14);
|
||||
else
|
||||
throw new IOException("Field 14 not of expected type String, found " + raw.get(14).getClass().getSimpleName());
|
||||
if (raw.get(15) instanceof Long)
|
||||
estimatedTime = (Long)raw.get(15);
|
||||
else
|
||||
throw new IOException("Field 15 not of expected type Long, found " + raw.get(15).getClass().getSimpleName());
|
||||
if (raw.get(VISIT_ID) instanceof Integer) {
|
||||
visitID = (Integer) raw.get(VISIT_ID);
|
||||
} else {
|
||||
throw Model.typeError(VISIT_ID, raw.get(VISIT_ID).getClass(), "Integer");
|
||||
}
|
||||
|
||||
if (raw.get(LINE_ID) instanceof String) {
|
||||
lineID = (String) raw.get(LINE_ID);
|
||||
} else {
|
||||
throw Model.typeErrorString(LINE_ID, raw.get(LINE_ID).getClass());
|
||||
}
|
||||
|
||||
if (raw.get(LINE_NAME) instanceof String) {
|
||||
lineName = (String) raw.get(LINE_NAME);
|
||||
} else {
|
||||
throw Model.typeErrorString(LINE_NAME, raw.get(LINE_NAME).getClass());
|
||||
}
|
||||
|
||||
if (raw.get(DIRECTION_ID) instanceof String // Also accept Strings (#2)
|
||||
|| raw.get(DIRECTION_ID) instanceof Integer
|
||||
|| raw.get(DIRECTION_ID) instanceof Long) {
|
||||
directionID = Integer.valueOf(raw.get(DIRECTION_ID).toString());
|
||||
if (directionID < 0 || directionID > 2) {
|
||||
throw new IOException("Direction out of range. Expected 1 or 2, found " + directionID);
|
||||
}
|
||||
} else {
|
||||
throw Model.typeError(DIRECTION_ID, raw.get(DIRECTION_ID).getClass(), "String/Long/Integer");
|
||||
}
|
||||
|
||||
if (raw.get(DESTINATION_NAME) instanceof String) {
|
||||
destinationName = (String) raw.get(DESTINATION_NAME);
|
||||
} else {
|
||||
throw Model.typeErrorString(DESTINATION_NAME, raw.get(DESTINATION_NAME).getClass());
|
||||
}
|
||||
|
||||
if (raw.get(DESTINATION_TEXT) instanceof String) {
|
||||
destinationText = (String) raw.get(DESTINATION_TEXT);
|
||||
} else {
|
||||
throw Model.typeErrorString(DESTINATION_TEXT, raw.get(DESTINATION_TEXT).getClass());
|
||||
}
|
||||
|
||||
/* TFL and ASEAG deliver different types with the same API version, so this field is a little more tolerant */
|
||||
if (raw.get(VEHICLE_ID) instanceof String
|
||||
|| raw.get(VEHICLE_ID) instanceof Integer
|
||||
|| raw.get(VEHICLE_ID) instanceof Long) {
|
||||
vehicleID = raw.get(VEHICLE_ID).toString();
|
||||
} else if (raw.get(VEHICLE_ID) == null) { // Only fail of field is not NULL (#3).
|
||||
vehicleID = null;
|
||||
} else {
|
||||
throw Model.typeError(VEHICLE_ID, raw.get(VEHICLE_ID).getClass(), "String/Integer/Long");
|
||||
}
|
||||
|
||||
if (raw.get(TRIP_ID) instanceof String
|
||||
|| raw.get(TRIP_ID) instanceof Integer
|
||||
|| raw.get(TRIP_ID) instanceof Long) {
|
||||
id = raw.get(TRIP_ID).toString();
|
||||
} else {
|
||||
throw Model.typeError(TRIP_ID, raw.get(TRIP_ID).getClass(), "String/Integer/Long");
|
||||
}
|
||||
|
||||
if (raw.get(ESTIMATED_TIME) instanceof Long) {
|
||||
estimatedTime = (Long) raw.get(ESTIMATED_TIME);
|
||||
} else {
|
||||
throw Model.typeError(ESTIMATED_TIME, raw.get(ESTIMATED_TIME).getClass(), "Long");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The (starting) stop.
|
||||
*/
|
||||
public Stop getStop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The trip ID.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The visit ID.
|
||||
*/
|
||||
public Integer getVisitID() {
|
||||
return visitID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The line ID.
|
||||
*/
|
||||
public String getLineID() {
|
||||
return lineID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The line name.
|
||||
*/
|
||||
public String getLineName() {
|
||||
return lineName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The direction ID.
|
||||
*/
|
||||
public Integer getDirectionID() {
|
||||
return directionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The destination name.
|
||||
*/
|
||||
public String getDestinationName() {
|
||||
return destinationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The destination text.
|
||||
*/
|
||||
public String getDestinationText() {
|
||||
return destinationText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The estimated departure time.
|
||||
*/
|
||||
public Long getEstimatedTime() {
|
||||
return estimatedTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The vehicle ID or {@code null} if not present.
|
||||
*/
|
||||
public String getVehicleID() {
|
||||
return vehicleID;
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* jURAclient model classes that represent responses returned by the URA interface.
|
||||
*/
|
||||
package de.stklcode.pubtrans.ura.model;
|
20
src/main/java/de/stklcode/pubtrans/ura/package-info.java
Normal file
20
src/main/java/de/stklcode/pubtrans/ura/package-info.java
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* jURAclient base package - see {@link de.stklcode.pubtrans.ura.UraClient} for usage.
|
||||
*/
|
||||
package de.stklcode.pubtrans.ura;
|
14
src/main/javadoc/overview.html
Normal file
14
src/main/javadoc/overview.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>API Overview</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Java client for URA based public transport APIs.</p>
|
||||
<p>
|
||||
This client allows to simply connect any Java application to the public transport API to implement a monitor for the
|
||||
local bus station or any other custom queries. API versions 1.x and 2.x are supported.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Stefan Kalscheuer
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -18,89 +18,178 @@ package de.stklcode.pubtrans.ura;
|
||||
|
||||
import de.stklcode.pubtrans.ura.model.Stop;
|
||||
import de.stklcode.pubtrans.ura.model.Trip;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static net.bytebuddy.implementation.MethodDelegation.to;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
|
||||
/**
|
||||
* Unit test for the URA Client.
|
||||
* Tests run against mocked data collected from hte ASEAG API (http://ivu.aseag.de/)
|
||||
* Tests run against mocked data collected from ASEAG API (http://ivu.aseag.de) and
|
||||
* TFL API (http://http://countdown.api.tfl.gov.uk)
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({ UraClient.class, URL.class })
|
||||
public class UraClientTest {
|
||||
@Test
|
||||
public void getStopsTest() throws Exception {
|
||||
/* Mock the HTTP call */
|
||||
URL mockURL = PowerMockito.mock(URL.class);
|
||||
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_stops.txt"));
|
||||
// Mocked resource URL and exception message.
|
||||
private static String mockResource = null;
|
||||
private static String mockException = null;
|
||||
|
||||
/* List stops and verify some values */
|
||||
@BeforeAll
|
||||
public static void initByteBuddy() {
|
||||
// Install ByteBuddy Agent.
|
||||
ByteBuddyAgent.install();
|
||||
|
||||
new ByteBuddy().redefine(UraClient.class)
|
||||
.method(named("request"))
|
||||
.intercept(to(UraClientTest.class))
|
||||
.make()
|
||||
.load(UraClient.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getStopsTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V2_stops.txt");
|
||||
|
||||
// List stops and verify some values.
|
||||
List<Stop> stops = new UraClient("mocked").getStops();
|
||||
assertThat(stops, hasSize(10));
|
||||
assertThat(stops.get(0).getId(), is("100210"));
|
||||
assertThat(stops.get(1).getName(), is("Brockenberg"));
|
||||
assertThat(stops.get(2).getState(), is(0));;
|
||||
assertThat(stops.get(2).getState(), is(0));
|
||||
assertThat(stops.get(3).getLatitude(), is(50.7578775));
|
||||
assertThat(stops.get(4).getLongitude(), is(6.0708663));
|
||||
|
||||
/* Test exception handling */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
throw new IOException("Provoked exception 1.");
|
||||
}
|
||||
});
|
||||
assertThat(new UraClient("mocked").getStops(), hasSize(0));
|
||||
PowerMockito.when(mockURL.openStream()).thenThrow(new IOException("Provoked exception 2."));
|
||||
assertThat(new UraClient("mocked").getStops(), hasSize(0));
|
||||
// Test Exception handling.
|
||||
mockHttpToException("Provoked Exception 1");
|
||||
|
||||
try {
|
||||
new UraClient("mocked").getStops();
|
||||
} catch (RuntimeException e) {
|
||||
assertThat(e, is(instanceOf(IllegalStateException.class)));
|
||||
assertThat(e.getCause(), is(instanceOf(IOException.class)));
|
||||
assertThat(e.getCause().getMessage(), is("Provoked Exception 1"));
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream request(String originalURL) throws IOException {
|
||||
if (mockResource == null && mockException != null) {
|
||||
IOException e = new IOException(mockException);
|
||||
mockException = null;
|
||||
throw e;
|
||||
}
|
||||
|
||||
InputStream res = UraClientTest.class.getResourceAsStream(mockResource);
|
||||
mockResource = null;
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getStopsForLineTest() throws Exception {
|
||||
/* Mock the HTTP call */
|
||||
URL mockURL = PowerMockito.mock(URL.class);
|
||||
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_stops_line.txt"));
|
||||
public void getStopsForLineTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V2_stops_line.txt");
|
||||
|
||||
/* List stops and verify some values */
|
||||
// List stops and verify some values.
|
||||
List<Stop> stops = new UraClient("mocked").forLines("33").getStops();
|
||||
assertThat(stops, hasSize(47));
|
||||
assertThat(stops.get(0).getId(), is("100000"));
|
||||
assertThat(stops.get(1).getName(), is("Kuckelkorn"));
|
||||
assertThat(stops.get(2).getState(), is(0));;
|
||||
assertThat(stops.get(2).getState(), is(0));
|
||||
assertThat(stops.get(3).getLatitude(), is(50.7690688));
|
||||
assertThat(stops.get(4).getIndicator(), is("H.1"));
|
||||
assertThat(stops.get(5).getLongitude(), is(6.2314072));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsTest() throws Exception {
|
||||
/* Mock the HTTP call */
|
||||
URL mockURL = PowerMockito.mock(URL.class);
|
||||
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_all.txt"));
|
||||
public void getStopsForPositionTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_stops_circle.txt");
|
||||
|
||||
/* Get trips without filters and verify some values */
|
||||
// List stops and verify some values.
|
||||
List<Stop> stops = new UraClient("mocked")
|
||||
.forPosition(51.51009, -0.1345734, 200)
|
||||
.getStops();
|
||||
assertThat(stops, hasSize(13));
|
||||
assertThat(stops.get(0).getId(), is("156"));
|
||||
assertThat(stops.get(1).getName(), is("Piccadilly Circus"));
|
||||
assertThat(stops.get(2).getState(), is(0));
|
||||
assertThat(stops.get(3).getLatitude(), is(51.509154));
|
||||
assertThat(stops.get(4).getLongitude(), is(-0.134172));
|
||||
assertThat(stops.get(5).getIndicator(), is(nullValue()));
|
||||
|
||||
mockHttpToFile("instant_V1_stops_circle_name.txt");
|
||||
stops = new UraClient("mocked")
|
||||
.forStopsByName("Piccadilly Circus")
|
||||
.forPosition(51.51009, -0.1345734, 200)
|
||||
.getStops();
|
||||
assertThat(stops, hasSize(7));
|
||||
assertThat(stops.stream().filter(t -> !t.getName().equals("Piccadilly Circus")).findAny(), is(Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsForDestinationNamesTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_trips_destination.txt");
|
||||
|
||||
// List stops and verify some values.
|
||||
List<Trip> trips = new UraClient("mocked").forDestinationNames("Piccadilly Circus").getTrips();
|
||||
assertThat(trips, hasSize(9));
|
||||
assertThat(trips.stream().filter(t -> !t.getDestinationName().equals("Piccadilly Cir")).findAny(),
|
||||
is(Optional.empty()));
|
||||
|
||||
mockHttpToFile("instant_V1_trips_stop_destination.txt");
|
||||
trips = new UraClient("mocked")
|
||||
.forStops("156")
|
||||
.forDestinationNames("Marble Arch")
|
||||
.getTrips();
|
||||
assertThat(trips, hasSize(5));
|
||||
assertThat(trips.stream().filter(t -> !t.getStop().getId().equals("156")).findAny(),
|
||||
is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getDestinationName().equals("Marble Arch")).findAny(),
|
||||
is(Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsTowardsTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_trips_towards.txt");
|
||||
|
||||
/* List stops and verify some values */
|
||||
List<Trip> trips = new UraClient("mocked").towards("Marble Arch").getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
|
||||
mockHttpToFile("instant_V1_trips_stop_towards.txt");
|
||||
trips = new UraClient("mocked").forStops("156").towards("Marble Arch").getTrips();
|
||||
assertThat(trips, hasSize(17));
|
||||
assertThat(trips.stream().filter(t -> !t.getStop().getId().equals("156")).findAny(), is(Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_trips_all.txt");
|
||||
|
||||
// Get trips without filters and verify some values.
|
||||
List<Trip> trips = new UraClient("mocked").getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
assertThat(trips.get(0).getId(), is("27000165015001"));
|
||||
assertThat(trips.get(1).getLineID(), is("55"));
|
||||
assertThat(trips.get(2).getLineName(), is("28"));;
|
||||
assertThat(trips.get(2).getLineName(), is("28"));
|
||||
assertThat(trips.get(3).getDirectionID(), is(1));
|
||||
assertThat(trips.get(4).getDestinationName(), is("Verlautenheide Endstr."));
|
||||
assertThat(trips.get(5).getDestinationText(), is("Aachen Bushof"));
|
||||
@ -109,31 +198,45 @@ public class UraClientTest {
|
||||
assertThat(trips.get(8).getVisitID(), is(30));
|
||||
assertThat(trips.get(9).getStop().getId(), is("100002"));
|
||||
|
||||
/* Get limited number of trips */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_all.txt"));
|
||||
// Repeat test for API V2.
|
||||
mockHttpToFile("instant_V2_trips_all.txt");
|
||||
|
||||
// Get trips without filters and verify some values.
|
||||
trips = new UraClient("mocked").getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
assertThat(trips.get(0).getId(), is("27000165015001"));
|
||||
assertThat(trips.get(1).getLineID(), is("55"));
|
||||
assertThat(trips.get(2).getLineName(), is("28"));
|
||||
assertThat(trips.get(3).getDirectionID(), is(1));
|
||||
assertThat(trips.get(4).getDestinationName(), is("Verlautenheide Endstr."));
|
||||
assertThat(trips.get(5).getDestinationText(), is("Aachen Bushof"));
|
||||
assertThat(trips.get(6).getVehicleID(), is("247"));
|
||||
assertThat(trips.get(7).getEstimatedTime(), is(1482854580000L));
|
||||
assertThat(trips.get(8).getVisitID(), is(30));
|
||||
assertThat(trips.get(9).getStop().getId(), is("100002"));
|
||||
|
||||
// Get limited number of trips.
|
||||
mockHttpToFile("instant_V1_trips_all.txt");
|
||||
trips = new UraClient("mocked").getTrips(5);
|
||||
assertThat(trips, hasSize(5));
|
||||
|
||||
/* Test exception handling */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
throw new IOException("Provoked exception 1.");
|
||||
}
|
||||
});
|
||||
assertThat(new UraClient("mocked").getTrips(), hasSize(0));
|
||||
PowerMockito.when(mockURL.openStream()).thenThrow(new IOException("Provoked exception 2."));
|
||||
assertThat(new UraClient("mocked").getTrips(), hasSize(0));
|
||||
// Test mockException handling.
|
||||
mockHttpToException("Provoked mockException 2");
|
||||
try {
|
||||
new UraClient("mocked").getTrips();
|
||||
} catch (RuntimeException e) {
|
||||
assertThat(e, is(instanceOf(IllegalStateException.class)));
|
||||
assertThat(e.getCause(), is(instanceOf(IOException.class)));
|
||||
assertThat(e.getCause().getMessage(), is("Provoked mockException 2"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsForStopTest() throws Exception {
|
||||
/* Mock the HTTP call */
|
||||
URL mockURL = PowerMockito.mock(URL.class);
|
||||
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_stop.txt"));
|
||||
public void getTripsForStopTest() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_trips_stop.txt");
|
||||
|
||||
/* Get trips for stop ID 100000 (Aachen Bushof) and verify some values */
|
||||
// Get trips for stop ID 100000 (Aachen Bushof) and verify some values.
|
||||
List<Trip> trips = new UraClient("mocked")
|
||||
.forStops("100000")
|
||||
.getTrips();
|
||||
@ -141,30 +244,29 @@ public class UraClientTest {
|
||||
assertThat(trips.stream().filter(t -> !t.getStop().getId().equals("100000")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.get(0).getId(), is("27000158010001"));
|
||||
assertThat(trips.get(1).getLineID(), is("7"));
|
||||
assertThat(trips.get(2).getLineName(), is("25"));;
|
||||
assertThat(trips.get(2).getLineName(), is("25"));
|
||||
assertThat(trips.get(3).getStop().getIndicator(), is("H.15"));
|
||||
|
||||
/* Get trips for stop name "Uniklinik" and verify some values */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_stop_name.txt"));
|
||||
// Get trips for stop name "Uniklinik" and verify some values.
|
||||
mockHttpToFile("instant_V1_trips_stop_name.txt");
|
||||
trips = new UraClient("mocked")
|
||||
.forStopsByName("Uniklinik")
|
||||
.getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
assertThat(trips.stream().filter(t -> !t.getStop().getName().equals("Uniklinik")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getStop().getName().equals("Uniklinik")).findAny(),
|
||||
is(Optional.empty()));
|
||||
assertThat(trips.get(0).getId(), is("92000043013001"));
|
||||
assertThat(trips.get(1).getLineID(), is("5"));
|
||||
assertThat(trips.get(2).getVehicleID(), is("317"));;
|
||||
assertThat(trips.get(2).getVehicleID(), is("317"));
|
||||
assertThat(trips.get(3).getDirectionID(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsForLine() throws Exception {
|
||||
/* Mock the HTTP call */
|
||||
URL mockURL = PowerMockito.mock(URL.class);
|
||||
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_line.txt"));
|
||||
public void getTripsForLine() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_trips_line.txt");
|
||||
|
||||
/* Get trips for line ID 3 and verify some values */
|
||||
// Get trips for line ID 3 and verify some values.
|
||||
List<Trip> trips = new UraClient("mocked")
|
||||
.forLines("3")
|
||||
.getTrips();
|
||||
@ -172,11 +274,11 @@ public class UraClientTest {
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("3")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.get(0).getId(), is("27000154004001"));
|
||||
assertThat(trips.get(1).getLineID(), is("3"));
|
||||
assertThat(trips.get(2).getLineName(), is("3.A"));;
|
||||
assertThat(trips.get(2).getLineName(), is("3.A"));
|
||||
assertThat(trips.get(3).getStop().getIndicator(), is("H.4 (Pontwall)"));
|
||||
|
||||
/* Get trips for line name "3.A" and verify some values */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_line_name.txt"));
|
||||
// Get trips for line name "3.A" and verify some values.
|
||||
mockHttpToFile("instant_V1_trips_line_name.txt");
|
||||
trips = new UraClient("mocked")
|
||||
.forLinesByName("3.A")
|
||||
.getTrips();
|
||||
@ -184,48 +286,56 @@ public class UraClientTest {
|
||||
assertThat(trips.stream().filter(t -> !t.getLineName().equals("3.A")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.get(0).getId(), is("92000288014001"));
|
||||
assertThat(trips.get(1).getLineID(), is("3"));
|
||||
assertThat(trips.get(2).getLineName(), is("3.A"));;
|
||||
assertThat(trips.get(2).getLineName(), is("3.A"));
|
||||
assertThat(trips.get(3).getStop().getName(), is("Aachen Gartenstraße"));
|
||||
|
||||
/* Get trips for line 3 with direction 1 and verify some values */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_line_direction.txt"));
|
||||
// Get trips for line 3 with direction 1 and verify some values.
|
||||
mockHttpToFile("instant_V1_trips_line_direction.txt");
|
||||
trips = new UraClient("mocked")
|
||||
.forLines("3")
|
||||
.forDirection(1)
|
||||
.forLines("412")
|
||||
.forDirection(2)
|
||||
.getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("3")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getDirectionID().equals(1)).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("412")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getDirectionID().equals(2)).findAny(), is(Optional.empty()));
|
||||
|
||||
/* Test lineID and direction in different order */
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_line_direction.txt"));
|
||||
// Test lineID and direction in different order.
|
||||
mockHttpToFile("instant_V1_trips_line_direction.txt");
|
||||
trips = new UraClient("mocked")
|
||||
.forDirection(1)
|
||||
.forLines("3")
|
||||
.forDirection(2)
|
||||
.forLines("412")
|
||||
.getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("3")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getDirectionID().equals(1)).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("412")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getDirectionID().equals(2)).findAny(), is(Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTripsForStopAndLine() throws Exception {
|
||||
/* Mock the HTTP call */
|
||||
URL mockURL = PowerMockito.mock(URL.class);
|
||||
PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL);
|
||||
PowerMockito.when(mockURL.openStream()).thenReturn(getClass().getResourceAsStream("instant_trips_stop_line.txt"));
|
||||
public void getTripsForStopAndLine() {
|
||||
// Mock the HTTP call.
|
||||
mockHttpToFile("instant_V1_trips_stop_line.txt");
|
||||
|
||||
/* Get trips for line ID 25 and 25 at stop 100000 and verify some values */
|
||||
// Get trips for line ID 25 and 25 at stop 100000 and verify some values.
|
||||
List<Trip> trips = new UraClient("mocked")
|
||||
.forLines("25", "35")
|
||||
.forStops("100000")
|
||||
.getTrips();
|
||||
assertThat(trips, hasSize(10));
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("25") && !t.getLineID().equals("35")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getLineID().equals("25") && !t.getLineID().equals("35")).findAny(),
|
||||
is(Optional.empty()));
|
||||
assertThat(trips.stream().filter(t -> !t.getStop().getId().equals("100000")).findAny(), is(Optional.empty()));
|
||||
assertThat(trips.get(0).getId(), is("27000078014001"));
|
||||
assertThat(trips.get(1).getLineID(), is("25"));
|
||||
assertThat(trips.get(3).getLineName(), is("35"));;
|
||||
assertThat(trips.get(3).getLineName(), is("35"));
|
||||
assertThat(trips.get(5).getStop().getIndicator(), is("H.12"));
|
||||
}
|
||||
|
||||
|
||||
private static void mockHttpToFile(String newResourceFile) {
|
||||
mockResource = newResourceFile;
|
||||
}
|
||||
|
||||
private static void mockHttpToException(String newException) {
|
||||
mockException = newException;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,22 @@
|
||||
/*
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.pubtrans.ura.model;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -10,12 +26,12 @@ import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Unit test for the Stop metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer <stefan@stklcode.de>
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
public class StopTest {
|
||||
@Test
|
||||
|
@ -1,6 +1,22 @@
|
||||
/*
|
||||
* Copyright 2016-2018 Stefan Kalscheuer
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.stklcode.pubtrans.ura.model;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -10,18 +26,31 @@ import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Unit test for the Trip metamodel.
|
||||
*
|
||||
* @author Stefan Kalscheuer <stefan@stklcode.de>
|
||||
* @author Stefan Kalscheuer
|
||||
*/
|
||||
public class TripTest {
|
||||
@Test
|
||||
public void basicConstructorTest() {
|
||||
Trip trip = new Trip("sid", "name", "indicator", 1, 2.345, 6.789,
|
||||
123, "lineid", "linename", 0, "destination name", "destination text", "vehicle", "id", 123456789123456789L);
|
||||
Trip trip = new Trip("sid",
|
||||
"name",
|
||||
"indicator",
|
||||
1,
|
||||
2.345,
|
||||
6.789,
|
||||
123,
|
||||
"lineid",
|
||||
"linename",
|
||||
0,
|
||||
"destination name",
|
||||
"destination text",
|
||||
"vehicle",
|
||||
"id",
|
||||
123456789123456789L);
|
||||
assertThat(trip.getStop().getId(), is("sid"));
|
||||
assertThat(trip.getStop().getName(), is("name"));
|
||||
assertThat(trip.getStop().getIndicator(), is("indicator"));
|
||||
@ -57,7 +86,7 @@ public class TripTest {
|
||||
raw.add("destination name");
|
||||
raw.add("destination text");
|
||||
raw.add("vehicle");
|
||||
raw.add("id");
|
||||
raw.add(9876543210L);
|
||||
raw.add(123456789123456789L);
|
||||
|
||||
try {
|
||||
@ -75,12 +104,22 @@ public class TripTest {
|
||||
assertThat(trip.getDestinationName(), is("destination name"));
|
||||
assertThat(trip.getDestinationText(), is("destination text"));
|
||||
assertThat(trip.getVehicleID(), is("vehicle"));
|
||||
assertThat(trip.getId(), is("id"));
|
||||
assertThat(trip.getId(), is("9876543210"));
|
||||
assertThat(trip.getEstimatedTime(), is(123456789123456789L));
|
||||
} catch (IOException e) {
|
||||
fail("Creation of Trip from valid list failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
/* Test with V2 style list */
|
||||
raw.set(14, "id");
|
||||
try {
|
||||
Trip trip = new Trip(raw, "2.0");
|
||||
assertThat(trip.getId(), is("id"));
|
||||
} catch (IOException e) {
|
||||
fail("Creation of Trip from valid list failed: " + e.getMessage());
|
||||
}
|
||||
raw.set(14, 9876543210L);
|
||||
|
||||
/* Excess elements should be ignored */
|
||||
raw.add("foo");
|
||||
try {
|
||||
@ -91,6 +130,26 @@ public class TripTest {
|
||||
fail("Creation of Trip from valid list failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
raw.remove(10);
|
||||
raw.add(10, 0L); // Long values are OK.
|
||||
try {
|
||||
Trip trip = new Trip(raw);
|
||||
assertThat(trip, is(notNullValue()));
|
||||
assertThat(trip.getDirectionID(), is(0));
|
||||
} catch (IOException e) {
|
||||
fail("Creation of Trip from valid list failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
raw.remove(10);
|
||||
raw.add(10, "0"); // String values are OK.
|
||||
try {
|
||||
Trip trip = new Trip(raw);
|
||||
assertThat(trip, is(notNullValue()));
|
||||
assertThat(trip.getDirectionID(), is(0));
|
||||
} catch (IOException e) {
|
||||
fail("Creation of Trip from valid list failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
/* Test exceptions on invalid data */
|
||||
List<Object> invalid = new ArrayList<>(raw);
|
||||
invalid.remove(7);
|
||||
@ -124,7 +183,7 @@ public class TripTest {
|
||||
|
||||
invalid = new ArrayList<>(raw);
|
||||
invalid.remove(10);
|
||||
invalid.add(10, "1");
|
||||
invalid.add(10, "7"); // Strings are generally OK, but 7 is out of range (#2).
|
||||
try {
|
||||
new Trip(invalid);
|
||||
fail("Creation of Trip with invalid directionID field successfull");
|
||||
@ -164,7 +223,7 @@ public class TripTest {
|
||||
|
||||
invalid = new ArrayList<>(raw);
|
||||
invalid.remove(14);
|
||||
invalid.add(14, 123);
|
||||
invalid.add(14, 1.2);
|
||||
try {
|
||||
new Trip(invalid);
|
||||
fail("Creation of Trip with invalid id field successfull");
|
||||
@ -190,5 +249,14 @@ public class TripTest {
|
||||
} catch (Exception e) {
|
||||
assertThat(e, is(instanceOf(IOException.class)));
|
||||
}
|
||||
|
||||
invalid = new ArrayList<>(raw);
|
||||
invalid.set(10, 3);
|
||||
try {
|
||||
new Trip(invalid);
|
||||
fail("Creation of Trip with direction ID 3 successfull");
|
||||
} catch (Exception e) {
|
||||
assertThat(e, is(instanceOf(IOException.class)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
[4,"1.0",1483808583971]
|
||||
[0,"Piccadilly Circus","156","D",0,51.509822,-0.136967]
|
||||
[0,"Piccadilly Circus","149","G",0,51.51006,-0.135545]
|
||||
[0,"Piccadilly Circus","155","C",0,51.50986,-0.135971]
|
||||
[0,"Piccadilly Circus","34716","S",0,51.509154,-0.136245]
|
||||
[0,"Trocadero / Haymarket","161","H",0,51.510515,-0.134172]
|
||||
[0,"Piccadilly Circus, Haymarket","PCIRHM S",null,0,51.509709,-0.13272]
|
||||
[0,"Regent Street / St James's","17683","Z",0,51.508732,-0.134043]
|
||||
[0,"Regent Street / St James's","154","Y",0,51.508942,-0.134207]
|
||||
[0,"Piccadilly Circus","BP5840","E",0,51.509882,-0.137325]
|
||||
[0,"Piccadilly Circus","150","F",0,51.509894,-0.136402]
|
||||
[0,"Trocadero / Haymarket","37229","K",0,51.511194,-0.133366]
|
||||
[0,"Piccadilly Circus","37122","B",0,51.509306,-0.13621]
|
||||
[0,"Haymarket / Jermyn Street","29867","R",0,51.509691,-0.132706]
|
@ -0,0 +1,8 @@
|
||||
[4,"1.0",1483808692732]
|
||||
[0,"Piccadilly Circus","156","D",0,51.509822,-0.136967]
|
||||
[0,"Piccadilly Circus","149","G",0,51.51006,-0.135545]
|
||||
[0,"Piccadilly Circus","155","C",0,51.50986,-0.135971]
|
||||
[0,"Piccadilly Circus","34716","S",0,51.509154,-0.136245]
|
||||
[0,"Piccadilly Circus","BP5840","E",0,51.509882,-0.137325]
|
||||
[0,"Piccadilly Circus","150","F",0,51.509894,-0.136402]
|
||||
[0,"Piccadilly Circus","37122","B",0,51.509306,-0.13621]
|
@ -0,0 +1,10 @@
|
||||
[4,"1.0",1483809193233]
|
||||
[1,"New Bond Street","829","OE",0,51.514814,-0.146117,1,"94","94",1,"Piccadilly Cir","Piccadilly Circus",15925,443778,1483810113000]
|
||||
[1,"New Bond Street","829","OE",0,51.514814,-0.146117,1,"94","94",1,"Piccadilly Cir","Piccadilly Circus",15209,443756,1483810614000]
|
||||
[1,"Hobury Street / Worlds End","11296","QH",0,51.482463,-0.179129,1,"22","22",1,"Piccadilly Cir","Piccadilly Circus",8923,390782,1483810037000]
|
||||
[1,"Abinger Road","11333",null,0,51.496971,-0.24965,1,"94","94",1,"Piccadilly Cir","Piccadilly Circus",15554,444015,1483809664000]
|
||||
[1,"Knightsbridge Station","210","KJ",0,51.500899,-0.160183,1,"22","22",1,"Piccadilly Cir","Piccadilly Circus",7988,392720,1483810456000]
|
||||
[1,"Piccadilly Circus","37122","B",0,51.509306,-0.13621,1,"22","22",1,"Piccadilly Cir","Piccadilly Circus",8027,502319,1483809941000]
|
||||
[1,"Edith Grove / Worlds End","37444",null,0,51.481603,-0.182217,1,"22","22",1,"Piccadilly Cir","Piccadilly Circus",8015,392809,1483810291000]
|
||||
[1,"Selfridges","153","BB",0,51.514067,-0.152921,1,"94","94",1,"Piccadilly Cir","Piccadilly Circus",15105,444021,1483809200000]
|
||||
[1,"Edith Grove / Worlds End","37444",null,0,51.481603,-0.182217,1,"22","22",1,"Piccadilly Cir","Piccadilly Circus",7988,392720,1483809409000]
|
@ -1,11 +1,11 @@
|
||||
[4,"2.0",1482854839773]
|
||||
[1,"Seffenter Weg","100643","",0,50.7820069,6.0644119,19,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","317","27000154004001",1482855824000]
|
||||
[1,"Normaluhr","100009","H.5 (Wilhelmstr.)",0,50.7680616,6.094883,9,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","226","27000134003001",1482855960000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,5,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","226","27000134002001",1482854820000]
|
||||
[1,"Ponttor","100005","H.4 (Pontwall)",0,50.7808611,6.0779722,15,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","226","27000134003001",1482856500000]
|
||||
[1,"Stiewistraße","100630","",0,50.78029,6.05058,25,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","226","27000134004001",1482859800000]
|
||||
[1,"Misereor","100010","",0,50.7685583,6.0833027,7,"3","3.A",1,"Hbf.-Ponttor-Uniklinik","Hbf.-Ponttor-Uniklinik","0","27000134005001",1482861060000]
|
||||
[1,"Wendlingweg","100646","",0,50.7773216,6.0504405,26,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","338","27000128004001",1482858060000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","27000141015001",1482861420000]
|
||||
[1,"Forckenbeckstraße","100628","",0,50.78534,6.05054,23,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","338","27000128003001",1482855127000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","338","27000128003001",1482855067000]
|
||||
[1,"Seffenter Weg","100643","",0,50.7820069,6.0644119,19,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","317",27000154004001,1482855824000]
|
||||
[1,"Normaluhr","100009","H.5 (Wilhelmstr.)",0,50.7680616,6.094883,9,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","226",27000134003001,1482855960000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,5,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","226",27000134002001,1482854820000]
|
||||
[1,"Ponttor","100005","H.4 (Pontwall)",0,50.7808611,6.0779722,15,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","226",27000134003001,1482856500000]
|
||||
[1,"Stiewistraße","100630","",0,50.78029,6.05058,25,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","226",27000134004001,1482859800000]
|
||||
[1,"Misereor","100010","",0,50.7685583,6.0833027,7,"3","3.A",1,"Hbf.-Ponttor-Uniklinik","Hbf.-Ponttor-Uniklinik","0",27000134005001,1482861060000]
|
||||
[1,"Wendlingweg","100646","",0,50.7773216,6.0504405,26,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","338",27000128004001,1482858060000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0",27000141015001,1482861420000]
|
||||
[1,"Forckenbeckstraße","100628","",0,50.78534,6.05054,23,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","338",27000128003001,1482855127000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","338",27000128003001,1482855067000]
|
@ -0,0 +1,11 @@
|
||||
[4,"1.0",1483806258560]
|
||||
[1,"Lower Barn Road","16637",null,0,51.330106,-0.093099,1,"412","412",2,"Purley","Purley",3469,653171,1483807114000]
|
||||
[1,"Sanderstead Plantation","23493",null,0,51.339851,-0.069809,1,"412","412",2,"Purley","Purley",2161,653155,1483807649000]
|
||||
[1,"Christchurch Road / Purley Hospital","10825","E",0,51.340668,-0.113337,1,"412","412",2,"Purley","Purley",3146,653175,1483806540000]
|
||||
[1,"Ridge Langley","20396",null,0,51.346848,-0.072013,1,"412","412",2,"Purley","Purley",2161,653155,1483807260000]
|
||||
[1,"Purley / Downlands Precinct","4396","D",0,51.339165,-0.116083,1,"412","412",2,"Purley","Purley",3469,653171,1483807453000]
|
||||
[1,"Coombe Road","10829","W",0,51.368209,-0.099175,1,"412","412",2,"Purley","Purley",2161,653155,1483806733000]
|
||||
[1,"Ruskin Parade / South Croydon Station","4415","F",0,51.363068,-0.097132,1,"412","412",2,"Purley","Purley",1554,653151,1483807590000]
|
||||
[1,"Sussex Road","18810","GP",0,51.359344,-0.093811,1,"412","412",2,"Purley","Purley",1554,653151,1483807686000]
|
||||
[1,"Farley Road","26185","Z",0,51.342569,-0.063937,1,"412","412",2,"Purley","Purley",1554,653151,1483808161000]
|
||||
[1,"Sanderstead Plantation","23493",null,0,51.339851,-0.069809,1,"412","412",2,"Purley","Purley",3469,653171,1483806820000]
|
@ -0,0 +1,11 @@
|
||||
[4,"2.0",1483362794677]
|
||||
[1,"Westbahnhof","100641","H.2",0,50.7805372,6.0719672,17,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0",92000288014001,1483367880000]
|
||||
[1,"Aachen Gartenstraße","100601","",0,50.7704169,6.0695841,4,"3","3.A",1,"Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor","0",92000058014001,1483368360000]
|
||||
[1,"Schanz","100012","H.2 (Boxgraben)",0,50.76891,6.074498,5,"3","3.A",1,"Hbf.-Ponttor-Uniklinik","Hbf.-Ponttor-Uniklinik","0",92000288015001,1483369380000]
|
||||
[1,"Aachen Gartenstraße","100601","",0,50.7704169,6.0695841,4,"3","3.A",1,"Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor","327",92000289012001,1483363045000]
|
||||
[1,"Kastanienweg","100631","",0,50.7854908,6.0547602,21,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0",92000058014001,1483369860000]
|
||||
[1,"Eurogress","100007","",0,50.7807852,6.0900738,13,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","327",92000289012001,1483363994000]
|
||||
[1,"Augustastraße","100008","",0,50.7731333,6.0959027,10,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","0",92000288014001,1483367280000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0",92000279013001,1483369020000]
|
||||
[1,"Audimax","100029","",0,50.7802655,6.0752138,16,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0",92000058014001,1483369560000]
|
||||
[1,"Aachen Hauptbahnhof","100004","H.1",0,50.7687027,6.0906277,8,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","0",92000288014001,1483367040000]
|
@ -0,0 +1,11 @@
|
||||
[4,"2.0",1482854457011]
|
||||
[1,"Aachen Bushof","100000","H.13",0,50.7775936,6.0908191,20,"1","1",1,"Schevenhütte","Schevenhütte","565",27000158010001,1482854446000]
|
||||
[1,"Aachen Bushof","100000","H.2",0,50.7775936,6.0908191,8,"7","7",1,"Aachen Bushof","Aachen Bushof","514",27000210017001,1482854400000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","0",27000171010001,1482854460000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,17,"47","47",1,"Aachen Bushof","Aachen Bushof","258",27000139003001,1482854460000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,1,"7","7",1,"Aachen Diepenbenden","Aachen Diepenbenden","257",27000089026001,1482854454000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,17,"2","2",1,"Eilendorf Schubertstr.","Eilendorf Schubertstr.","221",27000039021001,1482854445000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,28,"12","12",1,"Campus Melaten","Campus Melaten","298",27000062010001,1482854451000]
|
||||
[1,"Aachen Bushof","100000","H.1",0,50.7775936,6.0908191,27,"51","51",1,"Aachen Bushof","Aachen Bushof","603",27000230015001,1482854801000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,1,"43","43",1,"Hüls Schulz+Elleter F.","Hüls Schulz+Elleter F.","258",27000139004001,1482854520000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,25,"33","33",1,"Aachen Fuchserde","Aachen Fuchserde","286",27000033017001,1482854459000]
|
@ -0,0 +1,6 @@
|
||||
[4,"1.0",1483809267076]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16588,309783,1483809502000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16589,239190,1483809796000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16211,310616,1483810325000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16549,238574,1483810733000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16213,216852,1483810840000]
|
@ -1,11 +1,11 @@
|
||||
[4,"2.0",1482855134910]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,32,"35","35",1,"Vaals Grenze","Vaals Grenze","346","27000078014001",1482855350000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,15,"25","25",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","334","27000268014001",1482856194000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","242","27000270010001",1482856248000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,14,"35","35",1,"Breinig Entengasse","Breinig Entengasse","248","27000074012001",1482856740000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,32,"35","35",1,"Vaals Grenze","Vaals Grenze","294","27000076010001",1482857507000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,15,"25","25",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","0","27000171011001",1482857640000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","191","27000032012001",1482858057000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,14,"35","35",1,"Breinig Entengasse","Breinig Entengasse","346","27000078015001",1482858540000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,15,"25","25",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","242","27000270011001",1482859440000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","187","27000060013001",1482859860000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,32,"35","35",1,"Vaals Grenze","Vaals Grenze","346",27000078014001,1482855350000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,15,"25","25",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","334",27000268014001,1482856194000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","242",27000270010001,1482856248000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,14,"35","35",1,"Breinig Entengasse","Breinig Entengasse","248",27000074012001,1482856740000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,32,"35","35",1,"Vaals Grenze","Vaals Grenze","294",27000076010001,1482857507000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,15,"25","25",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","0",27000171011001,1482857640000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","191",27000032012001,1482858057000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,14,"35","35",1,"Breinig Entengasse","Breinig Entengasse","346",27000078015001,1482858540000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,15,"25","25",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","242",27000270011001,1482859440000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","187",27000060013001,1482859860000]
|
@ -0,0 +1,11 @@
|
||||
[4,"2.0",1483362959788]
|
||||
[1,"Uniklinik","100600","H.2",0,50.7756388,6.04425,11,"33","33","1","Aachen Fuchserde","Aachen Fuchserde","318",92000043013001,1483362935000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,1,"5","5","1","Driescher Hof-Brand","Driescher Hof-Brand","312",92000282009001,1483362936000]
|
||||
[1,"Uniklinik","100600","H.4",0,50.7756388,6.04425,33,"45","45","1","Uniklinik","Uniklinik","317",92000285009001,1483363294000]
|
||||
[1,"Uniklinik","100600","H.3",0,50.7756388,6.04425,28,"10","3.B","1","Uniklinik-Ponttor-Hbf.","Uniklinik-Ponttor-Hbf.","347",92000053015001,1483363039000]
|
||||
[1,"Uniklinik","100600","H.3",0,50.7756388,6.04425,29,"33","33","1","Uniklinik","Uniklinik","529",92000209014001,1483363288000]
|
||||
[1,"Uniklinik","100600","H.2",0,50.7756388,6.04425,1,"73","73","1","Aachen Bf.Rothe Erde","Aachen Bf.Rothe Erde","315",92000291016001,1483363080000]
|
||||
[1,"Uniklinik","100600","H.3",0,50.7756388,6.04425,29,"10","3.B","1","Uniklinik-Ponttor-Hbf.","Uniklinik-Ponttor-Hbf.","347",92000053015001,1483363099000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,28,"3","3.A","1","Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","325",92000288012001,1483363080000]
|
||||
[1,"Uniklinik","100600","H.2",0,50.7756388,6.04425,6,"70","70","1","Aachen Adenauerallee","Aachen Adenauerallee","588",92000225009001,1483363346000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,1,"3","3.A","1","Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor",null,92000288013001,1483363380000]
|
@ -0,0 +1,18 @@
|
||||
[4,"1.0",1483809773487]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"94","94",2,"Acton Green","Acton Green",15294,445809,1483809898000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16589,239190,1483809806000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"6","6",2,"Willesden Gar","Willesden, Bus Garage",10600,216033,1483810030000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"23","23",2,"Westbourne Park","Westbourne Park",20276,685207,1483810231000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"94","94",2,"Acton Green","Acton Green",15296,445944,1483810322000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"6","6",2,"Willesden Gar","Willesden, Bus Garage",10603,216027,1483810421000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16211,310616,1483810135000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"94","94",2,"Acton Green","Acton Green",15105,445989,1483810449000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"23","23",2,"Westbourne Park","Westbourne Park",20322,690792,1483810642000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"94","94",2,"Acton Green","Acton Green",15575,445855,1483810750000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16213,216852,1483810840000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"6","6",2,"Willesden Gar","Willesden, Bus Garage",10602,216822,1483810854000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"23","23",2,"Westbourne Park","Westbourne Park",20337,689508,1483811038000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16549,238574,1483810791000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"94","94",2,"Acton Green","Acton Green",15925,445840,1483811317000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"6","6",2,"Willesden Gar","Willesden, Bus Garage",10596,216025,1483811331000]
|
||||
[1,"Piccadilly Circus","156","D",0,51.509822,-0.136967,1,"159","159",1,"Marble Arch","Marble Arch",16713,310640,1483811409000]
|
@ -0,0 +1,11 @@
|
||||
[4,"1.0",1483810124081]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"36","36",1,"New Cross Gate","New Cross Gate",8864,595212,1483810191000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"7","7",1,"Oxford Circus","Oxford Circus",9932,109224,1483810173000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"36","36",1,"New Cross Gate","New Cross Gate",8862,597163,1483810551000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"23","23",1,"Liverpool St","Liverpool Street",20333,690728,1483810367000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"7","7",1,"Oxford Circus","Oxford Circus",9861,106419,1483810702000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"36","36",1,"New Cross Gate","New Cross Gate",9407,599527,1483810830000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"23","23",1,"Liverpool St","Liverpool Street",20335,683419,1483810677000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"36","36",1,"New Cross Gate","New Cross Gate",9379,599540,1483811196000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"7","7",1,"Oxford Circus","Oxford Circus",10262,109245,1483811093000]
|
||||
[1,"Porchester Terrace North","16972","L",0,51.516451,-0.186379,1,"23","23",1,"Liverpool St","Liverpool Street",20099,684947,1483811250000]
|
@ -0,0 +1,11 @@
|
||||
[4,"2.0",1482850556146]
|
||||
[1,"Fischbachstraße","215812","",0,50.73893,6.2666311,6,"8","8",1,"Eschweiler Bushof","Eschweiler Bushof","0",27000165015001,1482856620000]
|
||||
[1,"Wolferskaul","100322","",0,50.7439086,6.1594241,19,"55","55",1,"Aachen Elisenbrunnen","Aachen Elisenbrunnen","619",27000229015001,1482852180000]
|
||||
[1,"Lindenallee","213227","",0,50.8271524,6.3194636,8,"28","28",1,"Alsdorf Annapark","Alsdorf Annapark","519",27000190012001,1482853140000]
|
||||
[1,"Karlsgraben","100024","",0,50.7728605,6.0766513,6,"5","5",1,"Driescher Hof-Brand","Driescher Hof-Brand","0",27000283012001,1482855960000]
|
||||
[1,"Eilendorf Bahnhof","100246","",0,50.7855477,6.1521783,61,"57","57",1,"Verlautenheide Endstr.","Verlautenheide Endstr.","528",27000200015001,1482855908000]
|
||||
[1,"Elisenbrunnen","100001","H.1",0,50.7747372,6.0879925,24,"34","34",1,"Aachen Bushof","Aachen Bushof","670",27000237013001,1482854520000]
|
||||
[1,"Schneidmühle","215602","",0,50.7847038,6.2190627,42,"22","22",1,"Stolberg Mühlener Bf.","Stolberg Mühlener Bf.","247",27000118005001,1482855180000]
|
||||
[1,"Dechant-Brock-Str.","215824","",0,50.7592927,6.2735355,22,"1","1",1,"Lintert Friedhof","Lintert Friedhof","268",27000102007001,1482854580000]
|
||||
[1,"Am Tiergarten","100382","",0,50.755833,6.1689597,30,"34","34",1,"Brand","Brand","0",27000224012001,1482854040000]
|
||||
[1,"Hansemannplatz","100002","H.1",0,50.7784794,6.0959816,26,"51","51",1,"Aachen Bushof","Aachen Bushof","603",27000230015001,1482854400000]
|
@ -1,11 +0,0 @@
|
||||
[4,"2.0",1483363349461]
|
||||
[1,"Westbahnhof","100641","H.2",0,50.7805372,6.0719672,17,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","325","92000288014001",1483367880000]
|
||||
[1,"Aachen Gartenstraße","100601","",0,50.7704169,6.0695841,4,"3","3.A",1,"Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor","229","92000058014001",1483368360000]
|
||||
[1,"Schanz","100012","H.2 (Boxgraben)",0,50.76891,6.074498,5,"3","3.A",1,"Hbf.-Ponttor-Uniklinik","Hbf.-Ponttor-Uniklinik","0","92000288015001",1483369380000]
|
||||
[1,"Kastanienweg","100631","",0,50.7854908,6.0547602,21,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","229","92000058014001",1483369860000]
|
||||
[1,"Eurogress","100007","",0,50.7807852,6.0900738,13,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","327","92000289012001",1483363996000]
|
||||
[1,"Augustastraße","100008","",0,50.7731333,6.0959027,10,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","325","92000288014001",1483367280000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","92000279013001",1483369020000]
|
||||
[1,"Audimax","100029","",0,50.7802655,6.0752138,16,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","92000288015001",1483370460000]
|
||||
[1,"Misereor","100010","",0,50.7685583,6.0833027,7,"3","3.A",1,"Hbf.-Ponttor-Uniklinik","Hbf.-Ponttor-Uniklinik","0","92000154003001",1483370460000]
|
||||
[1,"Audimax","100029","",0,50.7802655,6.0752138,16,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","229","92000058014001",1483369560000]
|
@ -1,11 +0,0 @@
|
||||
[4,"2.0",1483362794677]
|
||||
[1,"Westbahnhof","100641","H.2",0,50.7805372,6.0719672,17,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","92000288014001",1483367880000]
|
||||
[1,"Aachen Gartenstraße","100601","",0,50.7704169,6.0695841,4,"3","3.A",1,"Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor","0","92000058014001",1483368360000]
|
||||
[1,"Schanz","100012","H.2 (Boxgraben)",0,50.76891,6.074498,5,"3","3.A",1,"Hbf.-Ponttor-Uniklinik","Hbf.-Ponttor-Uniklinik","0","92000288015001",1483369380000]
|
||||
[1,"Aachen Gartenstraße","100601","",0,50.7704169,6.0695841,4,"3","3.A",1,"Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor","327","92000289012001",1483363045000]
|
||||
[1,"Kastanienweg","100631","",0,50.7854908,6.0547602,21,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","92000058014001",1483369860000]
|
||||
[1,"Eurogress","100007","",0,50.7807852,6.0900738,13,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","327","92000289012001",1483363994000]
|
||||
[1,"Augustastraße","100008","",0,50.7731333,6.0959027,10,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","0","92000288014001",1483367280000]
|
||||
[1,"Hörn Brücke","100627","",0,50.7871194,6.051875,22,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","92000279013001",1483369020000]
|
||||
[1,"Audimax","100029","",0,50.7802655,6.0752138,16,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","0","92000058014001",1483369560000]
|
||||
[1,"Aachen Hauptbahnhof","100004","H.1",0,50.7687027,6.0906277,8,"3","3.A",1,"Ponttor-Unikl.-Schanz","Ponttor-Unikl.-Schanz","0","92000288014001",1483367040000]
|
@ -1,11 +0,0 @@
|
||||
[4,"2.0",1482854457011]
|
||||
[1,"Aachen Bushof","100000","H.13",0,50.7775936,6.0908191,20,"1","1",1,"Schevenhütte","Schevenhütte","565","27000158010001",1482854446000]
|
||||
[1,"Aachen Bushof","100000","H.2",0,50.7775936,6.0908191,8,"7","7",1,"Aachen Bushof","Aachen Bushof","514","27000210017001",1482854400000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,30,"25","25",1,"Vaals Busstation","Vaals Busstation","0","27000171010001",1482854460000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,17,"47","47",1,"Aachen Bushof","Aachen Bushof","258","27000139003001",1482854460000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,1,"7","7",1,"Aachen Diepenbenden","Aachen Diepenbenden","257","27000089026001",1482854454000]
|
||||
[1,"Aachen Bushof","100000","H.12",0,50.7775936,6.0908191,17,"2","2",1,"Eilendorf Schubertstr.","Eilendorf Schubertstr.","221","27000039021001",1482854445000]
|
||||
[1,"Aachen Bushof","100000","H.11",0,50.7775936,6.0908191,28,"12","12",1,"Campus Melaten","Campus Melaten","298","27000062010001",1482854451000]
|
||||
[1,"Aachen Bushof","100000","H.1",0,50.7775936,6.0908191,27,"51","51",1,"Aachen Bushof","Aachen Bushof","603","27000230015001",1482854801000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,1,"43","43",1,"Hüls Schulz+Elleter F.","Hüls Schulz+Elleter F.","258","27000139004001",1482854520000]
|
||||
[1,"Aachen Bushof","100000","H.15",0,50.7775936,6.0908191,25,"33","33",1,"Aachen Fuchserde","Aachen Fuchserde","286","27000033017001",1482854459000]
|
@ -1,11 +0,0 @@
|
||||
[4,"2.0",1483362959788]
|
||||
[1,"Uniklinik","100600","H.2",0,50.7756388,6.04425,11,"33","33",1,"Aachen Fuchserde","Aachen Fuchserde","318","92000043013001",1483362935000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,1,"5","5",1,"Driescher Hof-Brand","Driescher Hof-Brand","312","92000282009001",1483362936000]
|
||||
[1,"Uniklinik","100600","H.4",0,50.7756388,6.04425,33,"45","45",1,"Uniklinik","Uniklinik","317","92000285009001",1483363294000]
|
||||
[1,"Uniklinik","100600","H.3",0,50.7756388,6.04425,28,"10","3.B",1,"Uniklinik-Ponttor-Hbf.","Uniklinik-Ponttor-Hbf.","347","92000053015001",1483363039000]
|
||||
[1,"Uniklinik","100600","H.3",0,50.7756388,6.04425,29,"33","33",1,"Uniklinik","Uniklinik","529","92000209014001",1483363288000]
|
||||
[1,"Uniklinik","100600","H.2",0,50.7756388,6.04425,1,"73","73",1,"Aachen Bf.Rothe Erde","Aachen Bf.Rothe Erde","315","92000291016001",1483363080000]
|
||||
[1,"Uniklinik","100600","H.3",0,50.7756388,6.04425,29,"10","3.B",1,"Uniklinik-Ponttor-Hbf.","Uniklinik-Ponttor-Hbf.","347","92000053015001",1483363099000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,28,"3","3.A",1,"Uniklinik-Schanz-Hbf.","Uniklinik-Schanz-Hbf.","325","92000288012001",1483363080000]
|
||||
[1,"Uniklinik","100600","H.2",0,50.7756388,6.04425,6,"70","70",1,"Aachen Adenauerallee","Aachen Adenauerallee","588","92000225009001",1483363346000]
|
||||
[1,"Uniklinik","100600","H.1",0,50.7756388,6.04425,1,"3","3.A",1,"Schanz-Hbf.-Ponttor","Schanz-Hbf.-Ponttor","325","92000288013001",1483363380000]
|
Reference in New Issue
Block a user