io.github.autsia.crowly.services.geolocation.impl.GeoLocationServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for io.github.autsia.crowly.services.geolocation.impl.GeoLocationServiceImpl.java

Source

/*
 * Copyright 2014 Dmytro Titov
 *
 * 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 io.github.autsia.crowly.services.geolocation.impl;

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import io.github.autsia.crowly.services.geolocation.GeoLocationService;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.social.twitter.api.GeoCode;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.lang.Math.*;

/**
 * Created by Dmytro on 5/8/2014 at 20:59
 * Project: crowly
 */
@Service
public class GeoLocationServiceImpl implements GeoLocationService {

    public static final String RESULTS = "results";
    public static final String GEOMETRY = "geometry";
    public static final String LOCATION = "location";
    public static final String BOUNDS = "bounds";
    public static final String NORTHEAST = "northeast";
    public static final String SOUTHWEST = "southwest";
    public static final String LATITUDE = "lat";
    public static final String LONGITUDE = "lng";
    public static final double EQUATOR = 6378.137d;
    private static final Logger logger = Logger.getLogger(GeoLocationServiceImpl.class);
    @Value("${geo.api.url}")
    private String geoAPIURL;

    @Value("${geo.api.code}")
    private String geoAPICode;

    @Override
    public Map<String, Triple<Double, Double, Double>> getLocationsAsMap(List<String> regionNames) {
        Map<String, Triple<Double, Double, Double>> result = new HashMap<>();
        try {
            for (String regionName : regionNames) {
                HttpResponse<JsonNode> request = Unirest.get(geoAPIURL).field("sensor", true)
                        .field("key", geoAPICode).field("address", regionName).asJson();
                JSONObject response = request.getBody().getObject().getJSONArray(RESULTS).getJSONObject(0)
                        .getJSONObject(GEOMETRY);
                JSONObject location = response.getJSONObject(LOCATION);
                JSONObject bounds = response.getJSONObject(BOUNDS);
                Point center = getCenter(location);
                Double distance = getDistance(bounds);
                result.put(regionName, new ImmutableTriple<>(center.getX(), center.getY(), distance));
            }
        } catch (UnirestException | JSONException e) {
            logger.error(e.getMessage(), e);
        }
        return result;
    }

    @Override
    public GeoCode convertCoordinatesToGeoCode(Triple<Double, Double, Double> location) {
        return new GeoCode(location.getLeft(), location.getMiddle(), location.getRight().intValue());
    }

    public double calculateDistance(double x1, double y1, double x2, double y2) {
        double lat1 = toRadians(x1);
        double long1 = toRadians(y1);
        double lat2 = toRadians(x2);
        double long2 = toRadians(y2);
        // some tricky formula I found on the Web...
        double e = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(long2 - long1));

        return e * EQUATOR;
    }

    protected Point getCenter(JSONObject location) throws JSONException {
        double latitude = Double.parseDouble(location.getString(LATITUDE));
        double longitude = Double.parseDouble(location.getString(LONGITUDE));
        return new Point(latitude, longitude);
    }

    protected Double getDistance(JSONObject bounds) throws JSONException {
        double northeastLatitude = Double.parseDouble(bounds.getJSONObject(NORTHEAST).getString(LATITUDE));
        double northeastLongitude = Double.parseDouble(bounds.getJSONObject(NORTHEAST).getString(LONGITUDE));
        double southwestLatitude = Double.parseDouble(bounds.getJSONObject(SOUTHWEST).getString(LATITUDE));
        double southwestLongitude = Double.parseDouble(bounds.getJSONObject(SOUTHWEST).getString(LONGITUDE));
        return calculateDistance(northeastLatitude, northeastLongitude, southwestLatitude, southwestLongitude)
                * 0.5f;
    }

}