Java tutorial
/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package fr.lemet.application.keolis; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.xml.sax.SAXException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import fr.lemet.application.keolis.modele.Answer; import fr.lemet.application.keolis.modele.ParametreUrl; import fr.lemet.application.keolis.modele.bus.Alert; import fr.lemet.application.keolis.modele.bus.Departure; import fr.lemet.application.keolis.modele.bus.ParkRelai; import fr.lemet.application.keolis.modele.bus.PointDeVente; import fr.lemet.application.keolis.modele.bus.ResultDeparture; import fr.lemet.application.keolis.modele.velos.Station; import fr.lemet.application.keolis.xml.sax.GetAlertsHandler; import fr.lemet.application.keolis.xml.sax.GetDeparturesHandler; import fr.lemet.application.keolis.xml.sax.GetParkRelaiHandler; import fr.lemet.application.keolis.xml.sax.GetPointDeVenteHandler; import fr.lemet.application.keolis.xml.sax.GetStationHandler; import fr.lemet.application.keolis.xml.sax.KeolisHandler; import fr.lemet.application.util.HttpUtils; import fr.lemet.transportscommun.donnees.modele.ArretFavori; import fr.lemet.transportscommun.util.ErreurReseau; import fr.lemet.transportscommun.util.LogYbo; /** * Classe d'accs aux API Keolis. Cette classe est une singletton. * * @author ybonnel */ public final class Keolis { private static final LogYbo LOG_YBO = new LogYbo(Keolis.class); /** * Instance du singletton. */ private static Keolis instance; /** * URL d'accs au API Keolis. */ private static final String URL = "http://data.keolis-rennes.com/xml/"; /** * Version. */ private static final String VERSION = "2.0"; /** * Cl de l'application. */ private static final String KEY = "G7JE45LI1RK3W1P"; /** * Commande pour rcuprer les stations. */ private static final String COMMANDE_STATIONS = "getbikestations"; /** * Commande pour rcuprer les alerts. */ private static final String COMMANDE_ALERTS = "getlinesalerts"; /** * Commande pour rcuprer les Park relais. */ private static final String COMMANDE_PARK_RELAI = "getrelayparks"; /** * Commande pour rcuprer les points de vente. */ private static final String COMMANDE_POS = "getpos"; private static final String COMMANDE_DEPARTURE = "getbusnextdepartures"; private static final String VERSION_DEPARTURE = "2.1"; /** * Retourne l'instance du singletton. * * @return l'instance du singletton. */ public static synchronized Keolis getInstance() { if (instance == null) { instance = new Keolis(); } return instance; } /** * Constructeur priv. */ private Keolis() { } /** * @param <ObjetKeolis> type d'objet Keolis. * @param url url. * @param handler handler. * @return liste d'objets Keolis. * @throws fr.lemet.transportscommun.util.ErreurReseau en cas d'erreur rseau. * @throws KeolisException en cas d'erreur lors de l'appel aux API Keolis. */ @SuppressWarnings("unchecked") private <ObjetKeolis> List<ObjetKeolis> appelKeolis(String url, KeolisHandler<ObjetKeolis> handler) throws ErreurReseau { LOG_YBO.debug("Appel d'une API Keolis sur l'url '" + url + '\''); long startTime = System.nanoTime() / 1000; HttpClient httpClient = HttpUtils.getHttpClient(); HttpUriRequest httpPost = new HttpPost(url); Answer<?> answer; try { HttpResponse reponse = httpClient.execute(httpPost); ByteArrayOutputStream ostream = new ByteArrayOutputStream(); reponse.getEntity().writeTo(ostream); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new ByteArrayInputStream(ostream.toByteArray()), handler); answer = handler.getAnswer(); } catch (IOException socketException) { throw new ErreurReseau(socketException); } catch (SAXException saxException) { throw new ErreurReseau(saxException); } catch (ParserConfigurationException exception) { throw new KeolisException("Erreur lors de l'appel l'API keolis", exception); } if (answer == null || answer.getStatus() == null || !"0".equals(answer.getStatus().getCode())) { throw new ErreurReseau(); } long elapsedTime = System.nanoTime() / 1000 - startTime; LOG_YBO.debug("Rponse de Keolis en " + elapsedTime + "s"); return (List<ObjetKeolis>) answer.getData(); } /** * Appel les API Keolis pour rcuprer les alertes. * * @return les alertes. * @throws ErreurReseau pour toutes erreurs rseaux. */ public Iterable<Alert> getAlerts() throws ErreurReseau { return appelKeolis(getUrl(COMMANDE_ALERTS), new GetAlertsHandler()); } /** * Appel aux API Keolis pour rcuprer les stations. * * @param url url appeler. * @return la liste des stations. * @throws ErreurReseau pour toutes erreurs rseaux. */ private List<Station> getStation(String url) throws ErreurReseau { return appelKeolis(url, new GetStationHandler()); } /** * Appel aux API Keolis pour rcuprer une station partir de son number. * * @param number numro de la station. * @return la station. * @throws ErreurReseau pour toutes erreurs rseaux. */ private Station getStationByNumber(String number) throws ErreurReseau { ParametreUrl[] params = { new ParametreUrl("station", "number"), new ParametreUrl("value", number) }; List<Station> stations = getStation(getUrl(COMMANDE_STATIONS, params)); if (stations.isEmpty()) { return null; } return stations.get(0); } /** * Appel aux API Keolis pour rcuprer les stations partir de leurs * numros. * * @param numbers numros des stations. * @return la station. * @throws ErreurReseau pour toutes erreurs rseaux. */ public Collection<Station> getStationByNumbers(Collection<String> numbers) throws ErreurReseau { Collection<Station> stations = new ArrayList<Station>(5); if (numbers.size() <= 2) { for (String number : numbers) { stations.add(getStationByNumber(number)); } } else { for (Station station : getStations()) { if (numbers.contains(station.number)) { stations.add(station); } } } return stations; } /** * Appel aux API Keolis pour rcuprer les stations. * * @return la listes des stations. * @throws ErreurReseau pour toutes erreurs rseaux. */ public List<Station> getStations() throws ErreurReseau { return getStation(getUrl(COMMANDE_STATIONS)); } /** * @return les parks relais. * @throws ErreurReseau pour toutes erreurs rseaux. */ public List<ParkRelai> getParkRelais() throws ErreurReseau { return appelKeolis(getUrl(COMMANDE_PARK_RELAI), new GetParkRelaiHandler()); } /** * @return les points de ventes. * @throws ErreurReseau pour toutes erreurs rseaux. */ public List<PointDeVente> getPointDeVente() throws ErreurReseau { return appelKeolis(getUrl(COMMANDE_POS), new GetPointDeVenteHandler()); } public ResultDeparture getDepartues(ArretFavori favori) throws ErreurReseau { ParametreUrl[] params = { new ParametreUrl("mode", "stopline"), new ParametreUrl("route][", favori.ligneId), new ParametreUrl("direction][", Integer.toString(favori.macroDirection)), new ParametreUrl("stop][", favori.arretId) }; GetDeparturesHandler handler = new GetDeparturesHandler(); List<Departure> departures = appelKeolis(getUrl(COMMANDE_DEPARTURE, params, VERSION_DEPARTURE), handler); return new ResultDeparture(departures, handler.getDateApi()); } /** * Permet de rcuprer l'URL d'accs aux API Keolis en fonction de la * commande excuter. * * @param commande commande excuter. * @return l'url. */ private String getUrl(String commande) { return getUrl(commande, VERSION); } /** * Permet de rcuprer l'URL d'accs aux API Keolis en fonction de la * commande excuter. * * @param commande * commande excuter. * @return l'url. */ private String getUrl(String commande, String version) { StringBuilder stringBuilder = new StringBuilder(URL); stringBuilder.append("?version=").append(version); stringBuilder.append("&key=").append(KEY); stringBuilder.append("&cmd=").append(commande); return stringBuilder.toString(); } /** * Permet de rcuprer l'URL d'accs aux API Keolis en fonction de la * commande excuter et d'un paramtre. * * @param commande commande excuter. * @param params liste de paramtres de l'url. * @return l'url. */ private String getUrl(String commande, ParametreUrl[] params) { return getUrl(commande, params, VERSION); } /** * Permet de rcuprer l'URL d'accs aux API Keolis en fonction de la * commande excuter et d'un paramtre. * * @param commande * commande excuter. * @param params * liste de paramtres de l'url. * @return l'url. */ private String getUrl(String commande, ParametreUrl[] params, String version) { StringBuilder stringBuilder = new StringBuilder(getUrl(commande, version)); for (ParametreUrl param : params) { try { stringBuilder.append("¶m[").append(param.getName()).append("]=") .append(URLEncoder.encode(param.getValue(), "utf-8")); } catch (UnsupportedEncodingException e) { throw new KeolisException("Erreur lors de la construction de l'URL", e); } } return stringBuilder.toString(); } }