com.bing.maps.rest.services.impl.BaseBingMapsApiQuery.java Source code

Java tutorial

Introduction

Here is the source code for com.bing.maps.rest.services.impl.BaseBingMapsApiQuery.java

Source

/*
 * Copyright 2010 Nabeel Mukhtar 
 * 
 * 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 com.bing.maps.rest.services.impl;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.bing.maps.rest.schema.AddressComponentType;
import com.bing.maps.rest.schema.GeoLocation;
import com.bing.maps.rest.schema.LocationType;
import com.bing.maps.rest.schema.TravelMode;
import com.bing.maps.rest.services.AsyncResponseHandler;
import com.bing.maps.rest.services.BingMapsException;
import com.bing.maps.rest.services.BingMapsQuery;
import com.bing.maps.rest.services.InvalidRequestException;
import com.bing.maps.rest.services.NotFoundException;
import com.bing.maps.rest.services.OverQueryLimitsException;
import com.bing.maps.rest.services.RequestDeniedException;
import com.bing.maps.rest.services.constant.BingMapsApiUrls.GoogleMapsApiUrlBuilder;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.googleapis.maps.services.ApplicationConstants;
import com.googleapis.maps.services.GoogleMapsApiGateway;

/**
 * The Class BaseGoogleMapsApiQuery.
 */
public abstract class BaseBingMapsApiQuery<T> extends GoogleMapsApiGateway implements BingMapsQuery<T> {

    /** The Constant UTF_8_CHAR_SET. */
    protected static final Charset UTF_8_CHAR_SET = Charset.forName(ApplicationConstants.CONTENT_ENCODING);

    /** The api url builder. */
    protected GoogleMapsApiUrlBuilder apiUrlBuilder;

    /** The parser. */
    protected final JsonParser parser = new JsonParser();

    /** The handlers. */
    private List<AsyncResponseHandler<List<T>>> handlers = new ArrayList<AsyncResponseHandler<List<T>>>();

    /**
     * Instantiates a new base google maps api query.
     * 
     * @param applicationId the application id
     */
    public BaseBingMapsApiQuery(String applicationId) {
        super.setApplicationKey(applicationId);
        requestHeaders = new HashMap<String, String>();

        // by default we compress contents
        requestHeaders.put("Accept-Encoding", "gzip, deflate");
        this.reset();
    }

    /**
     * Instantiates a new base google maps api query.
     * 
     * @param applicationId the application id
     * @param apiVersion the api version
     */
    public BaseBingMapsApiQuery(String applicationId, String apiVersion) {
        this(applicationId);
        super.setApiVersion(apiVersion);
    }

    /* (non-Javadoc)
     * @see com.google.code.stackexchange.client.query.StackOverflowApiQuery#list()
     */
    @Override
    public List<T> list() {
        InputStream jsonContent = null;
        try {
            jsonContent = callApiGet(apiUrlBuilder.buildUrl());
            JsonElement response = parser.parse(new InputStreamReader(jsonContent, UTF_8_CHAR_SET));
            if (response.isJsonObject()) {
                List<T> responseList = unmarshallList(response.getAsJsonObject());
                notifyObservers(responseList);
                return responseList;
            }
            throw new BingMapsException("Unknown content found in response:" + response.toString());
        } catch (Exception e) {
            throw new BingMapsException(e);
        } finally {
            closeStream(jsonContent);
        }
    }

    /**
     * Unmarshall list.
     * 
     * @param response the response
     * 
     * @return the list< t>
     */
    protected List<T> unmarshallList(JsonObject response) {
        String status = response.get("status").getAsString();
        if (!"OK".equals(status) && !"ZERO_RESULTS".equals(status)) {
            throw createGoogleMapsException(status);
        }
        ArrayList<T> list = new ArrayList<T>();
        JsonArray results = response.get("results").getAsJsonArray();
        for (JsonElement object : results) {
            T element = unmarshall(object);
            list.add(element);
        }
        return list;
    }

    /**
     * Unmarshall.
     * 
     * @param object the object
     * 
     * @return the t
     */
    protected abstract T unmarshall(JsonElement object);

    /* (non-Javadoc)
     * @see com.google.code.stackexchange.client.query.StackOverflowApiQuery#singleResult()
     */
    @Override
    public T singleResult() {
        List<T> list = list();
        return (list == null || list.isEmpty()) ? null : list.get(0);
    }

    /**
     * Notify observers.
     * 
     * @param response the response
     */
    protected void notifyObservers(List<T> response) {
        for (AsyncResponseHandler<List<T>> handler : handlers) {
            handler.handleResponse(response);
        }
    }

    /* (non-Javadoc)
     * @see com.google.code.stackexchange.client.query.StackExchangeApiQuery#addResonseHandler(com.google.code.stackexchange.client.AsyncResponseHandler)
     */
    public void addResonseHandler(AsyncResponseHandler<List<T>> handler) {
        handlers.add(handler);
    }

    /* (non-Javadoc)
     * @see com.google.code.stackexchange.client.impl.StackOverflowApiGateway#marshallObject(java.lang.Object)
     */
    protected String marshallObject(Object element) {
        return null;
    }

    /**
     * Gets the gson builder.
     * 
     * @return the gson builder
     */
    protected GsonBuilder getGsonBuilder() {
        GsonBuilder builder = new GsonBuilder();
        builder.setDateFormat(ApplicationConstants.RFC822DATEFORMAT);
        builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
        builder.registerTypeAdapter(LocationType.class, new JsonDeserializer<LocationType>() {
            @Override
            public LocationType deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2)
                    throws JsonParseException {
                return LocationType.fromValue(arg0.getAsString());
            }
        });
        builder.registerTypeAdapter(AddressComponentType.class, new JsonDeserializer<AddressComponentType>() {
            @Override
            public AddressComponentType deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2)
                    throws JsonParseException {
                return AddressComponentType.fromValue(arg0.getAsString());
            }
        });
        builder.registerTypeAdapter(TravelMode.class, new JsonDeserializer<TravelMode>() {
            @Override
            public TravelMode deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2)
                    throws JsonParseException {
                return TravelMode.fromValue(arg0.getAsString());
            }
        });

        return builder;
    }

    /* (non-Javadoc)
     * @see com.google.code.googlesearch.client.impl.GoogleSearchApiGateway#unmarshallObject(java.lang.Class, java.io.InputStream)
     */
    @Override
    protected <V> V unmarshallObject(Class<V> clazz, InputStream xmlContent) {
        return null;
    }

    /**
     * Creates the google search api url builder.
     * 
     * @param urlFormat the url format
     * 
     * @return the google maps api url builder
     */
    protected GoogleMapsApiUrlBuilder createGoogleSearchApiUrlBuilder(String urlFormat) {
        return new GoogleMapsApiUrlBuilder(urlFormat);
    }

    /**
     * To parameter string.
     * 
     * @param locations the locations
     * 
     * @return the string
     */
    protected String toParameterString(GeoLocation... locations) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < locations.length; i++) {
            builder.append(locations[i].getLat());
            builder.append(",");
            builder.append(locations[i].getLng());
            if (i < locations.length - 1) {
                builder.append("|");
            }
        }
        return builder.toString();
    }

    /**
     * Creates the google maps exception.
     * 
     * @param statusCode the status code
     * 
     * @return the google maps exception
     */
    protected BingMapsException createGoogleMapsException(String statusCode) {
        if ("OVER_QUERY_LIMIT".equals(statusCode)) {
            return new OverQueryLimitsException("indicates that you are over your quota.");
        } else if ("REQUEST_DENIED".equals(statusCode)) {
            return new RequestDeniedException(
                    "indicates that your request was denied, generally because of lack of a sensor parameter.");
        } else if ("INVALID_REQUEST".equals(statusCode)) {
            return new InvalidRequestException(
                    "generally indicates that the query (address or latlng) is missing.");
        } else if ("NOT_FOUND".equals(statusCode)) {
            return new NotFoundException(
                    "indicates at least one of the locations specified in the requests's origin, destination, or waypoints could not be geocoded.");
        } else if ("MAX_WAYPOINTS_EXCEEDED".equals(statusCode)) {
            return new NotFoundException(
                    "indicates that too many waypointss were provided in the request The maximum allowed waypoints is 8, plus the origin, and destination.");
        } else if ("UNKNOWN_ERROR".equals(statusCode)) {
            return new NotFoundException(
                    "indicates a directions request could not be processed due to a server error. The request may succeed if you try again.");
        } else {
            return null;
        }
    }
}