org.onebusaway.gtfs_realtime.nextbus.services.NextBusApiService.java Source code

Java tutorial

Introduction

Here is the source code for org.onebusaway.gtfs_realtime.nextbus.services.NextBusApiService.java

Source

/**
 * Copyright (C) 2012 Google, Inc.
 *
 * 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 org.onebusaway.gtfs_realtime.nextbus.services;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.digester.Digester;
import org.onebusaway.gtfs_realtime.nextbus.model.RouteStopCoverage;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBDirection;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBPrediction;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBPredictions;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBRoute;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBStop;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBStopTime;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBTrip;
import org.onebusaway.gtfs_realtime.nextbus.model.api.NBVehicle;
import org.xml.sax.SAXException;

@Singleton
public class NextBusApiService {

    private DownloaderService _downloader;

    private String _agencyId;

    private Digester _digester = getDigester();

    private File _cacheDirectory;

    @Inject
    public void setDownloader(DownloaderService downloader) {
        _downloader = downloader;
    }

    public void setAgencyId(String agencyId) {
        _agencyId = agencyId;
    }

    public void setCacheDirectory(File cacheDirectory) {
        _cacheDirectory = cacheDirectory;
    }

    @SuppressWarnings("unchecked")
    public List<NBRoute> downloadRouteList() throws IOException, SAXException {
        String url = "http://webservices.nextbus.com/service/publicXMLFeed?command=routeList&a=" + _agencyId;
        return (List<NBRoute>) digestUrl(url, true);
    }

    @SuppressWarnings("unchecked")
    public List<NBRoute> downloadRouteConfigList(String routeTag) throws IOException, SAXException {
        String url = "http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=" + _agencyId
                + "&r=" + routeTag;
        return (List<NBRoute>) digestUrl(url, true);
    }

    @SuppressWarnings("unchecked")
    public List<NBRoute> downloadRouteScheduleList(String routeTag) throws IOException, SAXException {
        String url = "http://webservices.nextbus.com/service/publicXMLFeed?command=schedule&a=" + _agencyId + "&r="
                + routeTag;
        return (List<NBRoute>) digestUrl(url, true);
    }

    @SuppressWarnings("unchecked")
    public List<NBPredictions> downloadPredictions(RouteStopCoverage coverage) throws IOException, SAXException {
        String url = "http://webservices.nextbus.com/service/publicXMLFeed?command=predictionsForMultiStops&a="
                + _agencyId;
        for (String stopTag : coverage.getStopTags()) {
            url += "&stops=" + coverage.getRouteTag() + "%7c" + stopTag;
        }
        return (List<NBPredictions>) digestUrl(url, false);
    }

    @SuppressWarnings("unchecked")
    public List<NBVehicle> downloadVehicleLocations(String routeTag, long prevRequestTime)
            throws IOException, SAXException {
        String url = "http://webservices.nextbus.com/service/publicXMLFeed?command=vehicleLocations&a=" + _agencyId
                + "&r=" + routeTag;
        if (prevRequestTime != 0) {
            url += "&t=" + prevRequestTime;
        }
        return (List<NBVehicle>) digestUrl(url, false);
    }

    private Object digestUrl(String url, boolean cache) throws IOException, SAXException {
        File cacheFile = getCacheFileForUrl(url);
        if (cache && cacheFile != null && cacheFile.exists()) {
            ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(cacheFile)));
            try {
                Object object = ois.readObject();
                ois.close();
                return object;
            } catch (ClassNotFoundException ex) {
                try {
                    ois.close();
                } catch (IOException ex2) {

                }
                throw new IllegalStateException(ex);
            }
        }
        InputStream in = _downloader.openUrl(url);
        Object result = _digester.parse(in);
        if (cache && cacheFile != null) {
            ObjectOutputStream oos = new ObjectOutputStream(
                    new BufferedOutputStream(new FileOutputStream(cacheFile)));
            oos.writeObject(result);
            oos.close();
        }
        return result;
    }

    private File getCacheFileForUrl(String url) throws UnsupportedEncodingException {
        if (_cacheDirectory == null) {
            return null;
        }
        try {
            MessageDigest cript = MessageDigest.getInstance("SHA-1");
            cript.reset();
            cript.update(url.getBytes("utf8"));
            String name = new String(Hex.encodeHex(cript.digest()));
            return new File(_cacheDirectory, name);
        } catch (NoSuchAlgorithmException ex) {
            throw new IllegalStateException(ex);
        }
    }

    private Digester getDigester() {
        Digester digester = new Digester();
        digester.addObjectCreate("body", ArrayList.class);

        digester.addObjectCreate("body/route", NBRoute.class);
        digester.addSetProperties("body/route");
        digester.addSetNext("body/route", "add");

        digester.addObjectCreate("body/route/stop", NBStop.class);
        digester.addSetProperties("body/route/stop");
        digester.addSetNext("body/route/stop", "addStop");

        digester.addObjectCreate("body/route/direction", NBDirection.class);
        digester.addSetProperties("body/route/direction");
        digester.addSetNext("body/route/direction", "addDirection");

        digester.addObjectCreate("body/route/direction/stop", NBStop.class);
        digester.addSetProperties("body/route/direction/stop");
        digester.addSetNext("body/route/direction/stop", "addStop");

        digester.addObjectCreate("body/route/tr", NBTrip.class);
        digester.addSetProperties("body/route/tr");
        digester.addSetNext("body/route/tr", "addTrip");

        digester.addObjectCreate("body/route/tr/stop", NBStopTime.class);
        digester.addSetProperties("body/route/tr/stop");
        digester.addSetNext("body/route/tr/stop", "addStopTime");

        digester.addObjectCreate("body/predictions", NBPredictions.class);
        digester.addSetProperties("body/predictions");
        digester.addSetNext("body/predictions", "add");

        digester.addObjectCreate("body/predictions/direction", NBDirection.class);
        digester.addSetProperties("body/predictions/direction");
        digester.addSetNext("body/predictions/direction", "addDirection");

        digester.addObjectCreate("body/predictions/direction/prediction", NBPrediction.class);
        digester.addSetProperties("body/predictions/direction/prediction");
        digester.addSetNext("body/predictions/direction/prediction", "addPrediction");

        digester.addObjectCreate("body/vehicle", NBVehicle.class);
        digester.addSetProperties("body/vehicle");
        digester.addSetNext("body/vehicle", "add");

        return digester;
    }
}