All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wicketstuff.gmap.geocoder.Geocoder Maven / Gradle / Ivy

There is a newer version: 10.3.0
Show newest version
/*
 *
 * ==============================================================================
 * 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.wicketstuff.gmap.geocoder;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wicketstuff.gmap.GMap;
import org.wicketstuff.gmap.api.GLatLng;
import org.wicketstuff.gmap.api.GLatLngBounds;
import org.wicketstuff.gmap.geocoder.pojos.GeocoderResult;
import org.wicketstuff.gmap.geocoder.pojos.NortheastSoutwestInfo;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.openjson.JSONException;

/**
 * Geocoder. See: https://developers.google.com/maps/documentation/geocoding/
 *
 * @author Thijs Vonk
 * @author Dieter Tremel
 */
public class Geocoder implements Serializable
{

    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = LoggerFactory.getLogger(Geocoder.class);

    // Constants
    public static final String OUTPUT_XML = "xml";
    public static final String OUTPUT_JSON = "json";
    private final String output = OUTPUT_JSON;
    /**
     * Result-Object of a geocoder request
     */
    private GeocoderResult geocoderResult;
    private ObjectMapper objectMapper;
    private String apiKey = null;


    /**
     * Default Constructor.
* Create an {@link ObjectMapper}.
* The {@link ObjectMapper} ignores unknown properties when mapping from JSON * to POJO.
* Use {@link #Geocoder(com.fasterxml.jackson.databind.ObjectMapper, java.lang.String) } to customize * * @param apiKey your Google Maps API-key */ public Geocoder(String apiKey) { objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); this.apiKey = apiKey; } /** * Configuration Constructor.
* If you have to customize the default {@link ObjectMapper} * * @param mapper your customized ObjectMapper * @param apiKey your Google Maps API-key * @see Geocoder#Geocoder(String) */ public Geocoder(ObjectMapper mapper, String apiKey) { this.objectMapper = mapper; this.apiKey = apiKey; } /** * Decode an response of an geocoder request to POJOs.
* Following the successful mapping from JSON to POJO
* all hits are available in {@link #geocoderResult} * * @param response * - JSON response from Google Geocoder Service * @return firstHit - First hit of {@link #geocoderResult} * @throws GeocoderException * - When GeocoderStatus unequal to {@link GeocoderStatus#OK} * @throws JSONException * - The JSONException is thrown by the JSON.org classes when things are amiss. */ public GLatLng decode(String response) throws GeocoderException, JSONException { try { geocoderResult = objectMapper.readValue(response, GeocoderResult.class); } catch (JsonParseException jpe) { LOGGER.error("Geocoder JSON parsing failed", jpe); } catch (JsonMappingException jme) { LOGGER.error( "Something went wrong during json mapping. Check your ObjectMapper when customize.", jme); } catch (IOException ioe) { LOGGER.error("Upps. Panic!", ioe); } GeocoderStatus status = geocoderResult.getStatus(); if (status != GeocoderStatus.OK) { throw new GeocoderException(status); } if (geocoderResult.getResults().length < 1) { throw new IllegalStateException( "GecoderStatus return GeocoderStatus.OK but size of the results was less then 1"); } // Only return the first Element return geocoderResult.getResults()[0].getGeometry().getLocation(); } /** * builds the google geo-coding url * * @param address * @return */ public String encode(final String address) { StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/geocode/"); sb.append(output); sb.append("?"); if (apiKey != null) { sb.append("key=").append(apiKey).append("&"); } sb.append("address=").append(urlEncode(address)); return sb.toString(); } /** * Invoke a geocoder request to the GoogleMaps API.
* Only return the first element of {@link #geocoderResult} to be backward compatible.
* After successful call of {@link #geocode(String)} you can get all results from * {@link #geocoderResult} * * @param address * - Requested address * @return {@link GLatLng} - only first hit of the request * @throws IOException */ public GLatLng geocode(final String address) throws IOException { InputStream is = invokeService(encode(address)); if (is != null) { try { String content = org.apache.wicket.util.io.IOUtils.toString(is); return decode(content); } finally { is.close(); } } return null; } /** * fetches the url content * * @param address * @return * @throws IOException */ protected InputStream invokeService(final String address) throws IOException { URL url = new URL(address); return url.openStream(); } /** * url-encode a value * * @param value * @return */ private String urlEncode(final String value) { try { return URLEncoder.encode(value, "UTF-8"); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex.getMessage()); } } /** * Get the Result of the last geocoder Request * @return the result of the last geocoder request */ public GeocoderResult getGecoderResult() { return geocoderResult; } /** * Convenience method to center and fit the zoom for an address, on the given map. *

* Example: * *

     * GMap myMap = GMap("wicketId");
     * new Geocoder().centerAndFitZoomForAdress(myMap, "Frankfurt am Main");
     * 
* * Result:
* Frankfurt is centered and the zoom is suitable *

* * @param map * - the map where the address should shown * @param address * - address as string for the google geocoder * @throws Exception */ public void centerAndFitZoomForAdress(GMap map, String address) throws Exception { this.geocode(address); NortheastSoutwestInfo port = getGecoderResult().getResults()[0].getGeometry().getViewport(); GLatLng sw = new GLatLng(port.getSouthwest().getLat(), port.getSouthwest().getLng()); GLatLng ne = new GLatLng(port.getNortheast().getLat(), port.getNortheast().getLng()); map.setBounds(new GLatLngBounds(sw, ne)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy