Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce custom exception class instead of RuntimeExceptions #10

Merged
merged 1 commit into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
### Changes
* Using native Java 11 HTTP client
* Client configuration with separate `UraClientConfiguration` class and builder
* Client throws custom checked exception `UraClientException` instead of runtime exceptions on errors (#10)


## 1.3.0 - 2019-12-04
Expand Down
129 changes: 85 additions & 44 deletions src/main/java/de/stklcode/pubtrans/ura/UraClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
package de.stklcode.pubtrans.ura;

import com.fasterxml.jackson.databind.ObjectMapper;
import de.stklcode.pubtrans.ura.exception.UraClientConfigurationException;
import de.stklcode.pubtrans.ura.exception.UraClientException;
import de.stklcode.pubtrans.ura.model.Message;
import de.stklcode.pubtrans.ura.model.Stop;
import de.stklcode.pubtrans.ura.model.Trip;
import de.stklcode.pubtrans.ura.reader.AsyncUraTripReader;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
Expand Down Expand Up @@ -207,8 +210,11 @@ public final Query forPosition(final Double latitude, final Double longitude, fi
* If forStops() and/or forLines() has been called, those will be used as filter.
*
* @return List of trips.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Trip> getTrips() {
public List<Trip> getTrips() throws UraClientException {
return getTrips(new Query(), null);
}

Expand All @@ -218,8 +224,11 @@ public List<Trip> getTrips() {
*
* @param limit Maximum number of results.
* @return List of trips.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Trip> getTrips(final Integer limit) {
public List<Trip> getTrips(final Integer limit) throws UraClientException {
return getTrips(new Query(), limit);
}

Expand All @@ -229,8 +238,12 @@ public List<Trip> getTrips(final Integer limit) {
*
* @param query The query.
* @return List of trips.
* @throws UraClientException Error with API communication.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Trip> getTrips(final Query query) {
public List<Trip> getTrips(final Query query) throws UraClientException {
return getTrips(query, null);
}

Expand All @@ -240,8 +253,11 @@ public List<Trip> getTrips(final Query query) {
* @param query The query.
* @param limit Maximum number of results.
* @return List of trips.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Trip> getTrips(final Query query, final Integer limit) {
public List<Trip> getTrips(final Query query, final Integer limit) throws UraClientException {
List<Trip> trips = new ArrayList<>();
try (InputStream is = requestInstant(REQUEST_TRIP, query);
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
Expand All @@ -260,7 +276,7 @@ public List<Trip> getTrips(final Query query, final Integer limit) {
line = br.readLine();
}
} catch (IOException e) {
throw new IllegalStateException("Failed to read trips from API", e);
throw new UraClientException("Failed to read trips from API", e);
}
return trips;
}
Expand All @@ -271,11 +287,11 @@ public List<Trip> getTrips(final Query query, final Integer limit) {
* @param query The query.
* @param consumer Consumer(s) for single trips.
* @return Trip reader.
* @throws IOException Error reading response.
* @throws UraClientConfigurationException Error reading response.
* @see #getTripsStream(Query, List)
* @since 1.2.0
* @since 1.2
*/
public AsyncUraTripReader getTripsStream(final Query query, final Consumer<Trip> consumer) throws IOException {
public AsyncUraTripReader getTripsStream(final Query query, final Consumer<Trip> consumer) throws UraClientConfigurationException {
return getTripsStream(query, Collections.singletonList(consumer));
}

Expand All @@ -285,28 +301,36 @@ public AsyncUraTripReader getTripsStream(final Query query, final Consumer<Trip>
* @param query The query.
* @param consumers Consumer(s) for single trips.
* @return Trip reader.
* @throws IOException Error retrieving stream response.
* @since 1.2.0
* @throws UraClientConfigurationException Error retrieving stream response.
* @since 1.2
* @since 2.0 Throws {@link UraClientConfigurationException}.
*/
public AsyncUraTripReader getTripsStream(final Query query, final List<Consumer<Trip>> consumers) throws IOException {
public AsyncUraTripReader getTripsStream(final Query query, final List<Consumer<Trip>> consumers) throws UraClientConfigurationException {
// Create the reader.
AsyncUraTripReader reader = new AsyncUraTripReader(
new URL(requestURL(config.getBaseURL() + config.getStreeamPath(), REQUEST_TRIP, query)),
consumers
);
try {
AsyncUraTripReader reader = new AsyncUraTripReader(
new URL(requestURL(config.getBaseURL() + config.getStreeamPath(), REQUEST_TRIP, query)),
consumers
);

// Open the reader, i.e. start reading from API.
reader.open();
// Open the reader, i.e. start reading from API.
reader.open();

return reader;
return reader;
} catch (MalformedURLException e) {
throw new UraClientConfigurationException("Invalid API URL, check client configuration.", e);
}
}

/**
* Get list of stops without filters.
*
* @return The list of stops.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Stop> getStops() {
public List<Stop> getStops() throws UraClientException {
return getStops(new Query());
}

Expand All @@ -316,8 +340,11 @@ public List<Stop> getStops() {
*
* @param query The query.
* @return The list.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Stop> getStops(final Query query) {
public List<Stop> getStops(final Query query) throws UraClientException {
List<Stop> stops = new ArrayList<>();
try (InputStream is = requestInstant(REQUEST_STOP, query);
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
Expand All @@ -330,7 +357,7 @@ public List<Stop> getStops(final Query query) {
}
}
} catch (IOException e) {
throw new IllegalStateException("Failed to read stops from API", e);
throw new UraClientException("Failed to read stops from API", e);
}
return stops;
}
Expand All @@ -339,9 +366,11 @@ public List<Stop> getStops(final Query query) {
* Get list of messages.
*
* @return List of messages.
* @throws UraClientException Error with API communication.
* @since 1.3
* @since 2.0 Throw {@link UraClientException}.
*/
public List<Message> getMessages() {
public List<Message> getMessages() throws UraClientException {
return getMessages(new Query(), null);
}

Expand All @@ -352,9 +381,11 @@ public List<Message> getMessages() {
*
* @param query The query.
* @return List of trips.
* @throws UraClientException Error with API communication.
* @since 1.3
* @since 2.0 Throw {@link UraClientException}.
*/
public List<Message> getMessages(final Query query) {
public List<Message> getMessages(final Query query) throws UraClientException {
return getMessages(query, null);
}

Expand All @@ -364,9 +395,11 @@ public List<Message> getMessages(final Query query) {
* @param query The query.
* @param limit Maximum number of results.
* @return List of trips.
* @throws UraClientException Error with API communication.
* @since 1.3
* @since 2.0 Throw {@link UraClientException}.
*/
public List<Message> getMessages(final Query query, final Integer limit) {
public List<Message> getMessages(final Query query, final Integer limit) throws UraClientException {
List<Message> messages = new ArrayList<>();
try (InputStream is = requestInstant(REQUEST_MESSAGE, query);
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
Expand All @@ -385,7 +418,7 @@ public List<Message> getMessages(final Query query, final Integer limit) {
line = br.readLine();
}
} catch (IOException e) {
throw new IllegalStateException("Failed to read messages from API", e);
throw new UraClientException("Failed to read messages from API", e);
}
return messages;
}
Expand All @@ -409,35 +442,35 @@ private InputStream requestInstant(final String[] returnList, final Query query)
* @param returnList Fields to fetch.
* @param query The query.
* @return The URL
* @throws IOException on errors
* @since 1.2.0
* @since 1.2
* @since 2.0 Does not throw exception anymore.
*/
private String requestURL(final String endpointURL, final String[] returnList, final Query query) throws IOException {
private String requestURL(final String endpointURL, final String[] returnList, final Query query) {
String urlStr = endpointURL + "?ReturnList=" + String.join(",", returnList);

if (query.stopIDs != null && query.stopIDs.length > 0) {
urlStr += "&" + PAR_STOP_ID + "=" + URLEncoder.encode(String.join(",", query.stopIDs), UTF_8.name());
urlStr += "&" + PAR_STOP_ID + "=" + URLEncoder.encode(String.join(",", query.stopIDs), UTF_8);
}
if (query.stopNames != null && query.stopNames.length > 0) {
urlStr += "&" + PAR_STOP_NAME + "=" + URLEncoder.encode(String.join(",", query.stopNames), UTF_8.name());
urlStr += "&" + PAR_STOP_NAME + "=" + URLEncoder.encode(String.join(",", query.stopNames), UTF_8);
}
if (query.lineIDs != null && query.lineIDs.length > 0) {
urlStr += "&" + PAR_LINE_ID + "=" + URLEncoder.encode(String.join(",", query.lineIDs), UTF_8.name());
urlStr += "&" + PAR_LINE_ID + "=" + URLEncoder.encode(String.join(",", query.lineIDs), UTF_8);
}
if (query.lineNames != null && query.lineNames.length > 0) {
urlStr += "&" + PAR_LINE_NAME + "=" + URLEncoder.encode(String.join(",", query.lineNames), UTF_8.name());
urlStr += "&" + PAR_LINE_NAME + "=" + URLEncoder.encode(String.join(",", query.lineNames), UTF_8);
}
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());
urlStr += "&" + PAR_DEST_NAME + "=" + URLEncoder.encode(String.join(",", query.destinationNames), UTF_8);
}
if (query.towards != null) {
urlStr += "&" + PAR_TOWARDS + "=" + URLEncoder.encode(String.join(",", query.towards), UTF_8.name());
urlStr += "&" + PAR_TOWARDS + "=" + URLEncoder.encode(String.join(",", query.towards), UTF_8);
}
if (query.circle != null) {
urlStr += "&" + PAR_CIRCLE + "=" + URLEncoder.encode(query.circle, UTF_8.name());
urlStr += "&" + PAR_CIRCLE + "=" + URLEncoder.encode(query.circle, UTF_8);
}

return urlStr;
Expand Down Expand Up @@ -572,17 +605,23 @@ public Query forPosition(final Double latitude, final Double longitude, final In
* Get stops for set filters.
*
* @return List of matching trips.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Stop> getStops() {
public List<Stop> getStops() throws UraClientException {
return UraClient.this.getStops(this);
}

/**
* Get trips for set filters.
*
* @return List of matching trips.
* @throws UraClientException Error with API communication.
* @since 1.0
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Trip> getTrips() {
public List<Trip> getTrips() throws UraClientException {
return UraClient.this.getTrips(this);
}

Expand All @@ -591,11 +630,11 @@ public List<Trip> getTrips() {
*
* @param consumer Consumer for single trips.
* @return Trip reader.
* @throws IOException Errors retrieving stream response.
* @throws UraClientConfigurationException Error reading response.
* @see #getTripsStream(List)
* @since 1.2.0
* @since 1.2
*/
public AsyncUraTripReader getTripsStream(Consumer<Trip> consumer) throws IOException {
public AsyncUraTripReader getTripsStream(Consumer<Trip> consumer) throws UraClientConfigurationException {
return UraClient.this.getTripsStream(this, consumer);
}

Expand All @@ -604,20 +643,22 @@ public AsyncUraTripReader getTripsStream(Consumer<Trip> consumer) throws IOExcep
*
* @param consumers Consumers for single trips.
* @return Trip reader.
* @throws IOException Errors retrieving stream response.
* @since 1.2.0
* @throws UraClientConfigurationException Errors retrieving stream response.
* @since 1.2
*/
public AsyncUraTripReader getTripsStream(List<Consumer<Trip>> consumers) throws IOException {
public AsyncUraTripReader getTripsStream(List<Consumer<Trip>> consumers) throws UraClientConfigurationException {
return UraClient.this.getTripsStream(this, consumers);
}

/**
* Get trips for set filters.
*
* @return List of matching messages.
* @throws UraClientException Error with API communication.
* @since 1.3
* @since 2.0 Throws {@link UraClientException}.
*/
public List<Message> getMessages() {
public List<Message> getMessages() throws UraClientException {
return UraClient.this.getMessages(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2016-2020 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.exception;

/**
* Custom exception class indicating an error with the URA client configuration.
*
* @author Stefan Kalscheuer
* @since 2.0
*/
public class UraClientConfigurationException extends UraClientException {
private static final long serialVersionUID = -8035752391477338659L;

/**
* Default constructor.
*
* @param message The detail message (which is saved for later retrieval by the {@link #getMessage()} method)
* @param cause The cause (which is saved for later retrieval by the {@link #getCause()} method).
*/
public UraClientConfigurationException(String message, Throwable cause) {
super(message, cause);
}
}
Loading