org.traccar.web.server.model.DataServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.traccar.web.server.model.DataServiceImpl.java

Source

/*
 * Copyright 2013 Anton Tananaev (anton.tananaev@gmail.com)
 *
 * 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.traccar.web.server.model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.traccar.web.client.model.DataService;
import org.traccar.web.shared.model.*;
import org.traccar.web.shared.model.ApplicationSettings;
import org.traccar.web.shared.model.Device;
import org.traccar.web.shared.model.PersonalHistory;
import org.traccar.web.shared.model.Point;
import org.traccar.web.shared.model.Position;
import org.traccar.web.shared.model.QuakeData;
import org.traccar.web.shared.model.User;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class DataServiceImpl extends RemoteServiceServlet implements DataService {

    private static final long serialVersionUID = 1;

    private static final String PERSISTENCE_DATASTORE = "java:/DefaultDS";
    private static final String PERSISTENCE_UNIT_DEBUG = "debug";
    private static final String PERSISTENCE_UNIT_RELEASE = "release";
    private static final String ATTRIBUTE_USER = "traccar.user";
    private static final String ATTRIBUTE_ENTITYMANAGER = "traccar.entitymanager";

    private EntityManagerFactory entityManagerFactory;

    private Timer refreshQuakesTimer = new Timer();
    private static final int REFRESH_QUAKES_INTERVAL = 5 * 60 * 10000;
    private String modisFilesLocation;
    private String modisSearchResultLocation;

    @Override
    public void init() throws ServletException {
        super.init();
        ServletContext servletContext = getServletContext();
        modisFilesLocation = servletContext.getInitParameter("modis_files_location");
        modisSearchResultLocation = servletContext.getInitParameter("modis_search_result_location");

        String persistenceUnit;
        try {
            Context context = new InitialContext();
            context.lookup(PERSISTENCE_DATASTORE);
            persistenceUnit = PERSISTENCE_UNIT_RELEASE;
        } catch (NamingException e) {
            persistenceUnit = PERSISTENCE_UNIT_DEBUG;
        }

        entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit);

        // Create Administrator account
        EntityManager entityManager = getServletEntityManager();
        TypedQuery<User> query = entityManager.createQuery("SELECT x FROM User x WHERE x.login = 'roger'",
                User.class);
        List<User> results = query.getResultList();
        if (results.isEmpty()) {
            User user = new User();
            user.setLogin("roger");
            user.setPassword("roger");
            user.setAdmin(true);
            createUser(entityManager, user);
        }
        refreshQuakesTimer.schedule(new TimerTask() {

            @Override
            public void run() {
                loadEarthquakeData();

            }
        }, REFRESH_QUAKES_INTERVAL);
        // Load earthquake data
        loadEarthquakeData();
    }

    private EntityManager servletEntityManager;

    private EntityManager getServletEntityManager() {
        if (servletEntityManager == null) {
            servletEntityManager = entityManagerFactory.createEntityManager();
        }
        return servletEntityManager;
    }

    private EntityManager getSessionEntityManager() {
        HttpSession session = getThreadLocalRequest().getSession();
        EntityManager entityManager = (EntityManager) session.getAttribute(ATTRIBUTE_ENTITYMANAGER);
        if (entityManager == null) {
            entityManager = entityManagerFactory.createEntityManager();
            session.setAttribute(ATTRIBUTE_ENTITYMANAGER, entityManager);
        }
        return entityManager;
    }

    private void setSessionUser(User user) {
        HttpSession session = getThreadLocalRequest().getSession();
        if (user != null) {
            session.setAttribute(ATTRIBUTE_USER, user);
        } else {
            session.removeAttribute(ATTRIBUTE_USER);
        }
    }

    public User getSessionUser() {
        HttpSession session = getThreadLocalRequest().getSession();
        User user = (User) session.getAttribute(ATTRIBUTE_USER);
        if (user == null) {
            throw new IllegalStateException();
        }
        return user;
    }

    @Override
    public User authenticated() throws IllegalStateException {
        return getSessionUser();
    }

    @Override
    public User login(String login, String password) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            TypedQuery<User> query = entityManager.createQuery("SELECT x FROM User x WHERE x.login = :login",
                    User.class);
            query.setParameter("login", login);
            List<User> results = query.getResultList();

            if (!results.isEmpty() && password.equals(results.get(0).getPassword())) {
                User user = results.get(0);
                setSessionUser(user);
                return user;
            }
            throw new IllegalStateException();
        }
    }

    @Override
    public boolean logout() {
        setSessionUser(null);
        return true;
    }

    @Override
    public User register(String login, String password) {
        if (getApplicationSettings().getRegistrationEnabled()) {
            User user = new User();
            user.setLogin(login);
            user.setPassword(password);
            createUser(getSessionEntityManager(), user);
            setSessionUser(user);
            return user;
        } else {
            throw new SecurityException();
        }
    }

    @Override
    public List<User> getUsers() {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            List<User> users = new LinkedList<User>();
            users.addAll(entityManager.createQuery("SELECT x FROM User x", User.class).getResultList());
            return users;
        }
    }

    @Override
    public User addUser(User user) {
        User currentUser = getSessionUser();
        if (user.getLogin().isEmpty() || user.getPassword().isEmpty()) {
            throw new IllegalArgumentException();
        }
        if (currentUser.getAdmin()) {
            EntityManager entityManager = getSessionEntityManager();
            synchronized (entityManager) {
                entityManager.getTransaction().begin();
                try {
                    entityManager.persist(user);
                    entityManager.getTransaction().commit();
                    return user;
                } catch (RuntimeException e) {
                    entityManager.getTransaction().rollback();
                    throw e;
                }
            }
        } else {
            throw new SecurityException();
        }
    }

    @Override
    public User updateUser(User user) {
        User currentUser = getSessionUser();
        if (user.getLogin().isEmpty() || user.getPassword().isEmpty()) {
            throw new IllegalArgumentException();
        }
        if (currentUser.getAdmin() || (currentUser.getId() == user.getId() && !user.getAdmin())) {
            EntityManager entityManager = getSessionEntityManager();
            synchronized (entityManager) {
                entityManager.getTransaction().begin();
                try {
                    // TODO: better solution?
                    if (currentUser.getId() == user.getId()) {
                        currentUser.setLogin(user.getLogin());
                        currentUser.setPassword(user.getPassword());
                        currentUser.setUserSettings(user.getUserSettings());
                        currentUser.setAdmin(user.getAdmin());
                        entityManager.merge(currentUser);
                        user = currentUser;
                    } else {
                        // TODO: handle other users
                    }

                    entityManager.getTransaction().commit();
                    setSessionUser(user);
                    return user;
                } catch (RuntimeException e) {
                    entityManager.getTransaction().rollback();
                    throw e;
                }
            }
        } else {
            throw new SecurityException();
        }
    }

    @Override
    public User removeUser(User user) {
        User currentUser = getSessionUser();
        if (currentUser.getAdmin()) {
            EntityManager entityManager = getSessionEntityManager();
            synchronized (entityManager) {
                entityManager.getTransaction().begin();
                try {
                    user = entityManager.merge(user);
                    user.getDevices().clear();
                    entityManager.remove(user);
                    entityManager.getTransaction().commit();
                    return user;
                } catch (RuntimeException e) {
                    entityManager.getTransaction().rollback();
                    throw e;
                }
            }
        } else {
            throw new SecurityException();
        }
    }

    private void createUser(EntityManager entityManager, User user) {
        synchronized (entityManager) {
            entityManager.getTransaction().begin();
            try {
                entityManager.persist(user);
                entityManager.getTransaction().commit();
            } catch (RuntimeException e) {
                entityManager.getTransaction().rollback();
                throw e;
            }
        }
    }

    @Override
    public List<Device> getDevices() {
        List<Device> devices = new LinkedList<Device>();
        User user = getSessionUser();
        devices.addAll(user.getDevices());
        return devices;
    }

    @Override
    public Device addDevice(Device device) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            User user = getSessionUser();
            entityManager.getTransaction().begin();
            try {
                entityManager.persist(device);
                user.getDevices().add(device);
                entityManager.getTransaction().commit();
                return device;
            } catch (RuntimeException e) {
                entityManager.getTransaction().rollback();
                throw e;
            }
        }
    }

    @Override
    public Device updateDevice(Device device) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            entityManager.getTransaction().begin();
            try {
                device = entityManager.merge(device);
                entityManager.getTransaction().commit();
                return device;
            } catch (RuntimeException e) {
                entityManager.getTransaction().rollback();
                throw e;
            }
        }
    }

    @Override
    public Device removeDevice(Device device) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            User user = getSessionUser();
            entityManager.getTransaction().begin();
            try {
                device = entityManager.merge(device);
                user.getDevices().remove(device);
                device.setLatestPosition(null);
                entityManager.flush();
                Query query = entityManager.createQuery("DELETE FROM Position x WHERE x.device = :device");
                query.setParameter("device", device);
                query.executeUpdate();
                entityManager.remove(device);
                entityManager.getTransaction().commit();
                return device;
            } catch (RuntimeException e) {
                entityManager.getTransaction().rollback();
                throw e;
            }
        }
    }

    @Override
    public List<Position> getPositions(Device device, Date from, Date to) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            List<Position> positions = new LinkedList<Position>();
            TypedQuery<Position> query = entityManager.createQuery(
                    "SELECT x FROM Position x WHERE x.device = :device AND x.time BETWEEN :from AND :to",
                    Position.class);
            query.setParameter("device", device);
            query.setParameter("from", from);
            query.setParameter("to", to);
            positions.addAll(query.getResultList());
            return positions;
        }
    }

    public List<Position> getPositions(Device device, int hoursAgo) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            List<Position> positions = new LinkedList<Position>();
            TypedQuery<Position> query = null;
            if (hoursAgo > -1) {
                long nowMs = new Date().getTime();
                Date time = new Date();
                time.setTime(nowMs - hoursAgo * 60 * 60 * 1000);
                query = entityManager.createQuery(
                        "SELECT x FROM Position x WHERE x.device = :device AND x.time > :time ORDER BY x.time ASC",
                        Position.class);
                query.setParameter("time", time);
            } else {
                query = entityManager.createQuery(
                        "SELECT x FROM Position x WHERE x.device = :device ORDER BY x.time ASC", Position.class);
            }

            query.setParameter("device", device);
            positions.addAll(query.getResultList());
            return positions;
        }
    }

    @Override
    public List<Position> getLatestPositions() {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            List<Position> positions = new LinkedList<Position>();
            User user = getSessionUser();
            if (user.getDevices() != null && !user.getDevices().isEmpty()) {
                TypedQuery<Position> query = entityManager.createQuery("SELECT x FROM Position x WHERE x.id IN ("
                        + "SELECT y.latestPosition FROM Device y WHERE y IN (:devices))", Position.class);
                query.setParameter("devices", user.getDevices());
                positions.addAll(query.getResultList());
            }
            return positions;
        }
    }

    @Override
    public List<ImagePosition> getImagePositions(int days) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            List<ImagePosition> positions = new LinkedList<ImagePosition>();
            TypedQuery<ImagePosition> query;
            if (days > -1) {
                Date time = new Date();
                long nowMs = time.getTime();
                time.setTime(nowMs - days * 24 * 60 * 60 * 1000);
                query = entityManager.createQuery(
                        "SELECT x FROM ImagePosition x WHERE x.time > :time ORDER BY x.time ASC",
                        ImagePosition.class);
                query.setParameter("time", time);
            } else {
                query = entityManager.createQuery("SELECT x FROM ImagePosition x ORDER BY x.time ASC",
                        ImagePosition.class);
            }
            positions.addAll(query.getResultList());
            return positions;
        }
    }

    private ApplicationSettings applicationSettings;

    private ApplicationSettings getApplicationSettings() {
        if (applicationSettings == null) {
            EntityManager entityManager = getServletEntityManager();
            synchronized (entityManager) {
                TypedQuery<ApplicationSettings> query = entityManager
                        .createQuery("SELECT x FROM ApplicationSettings x", ApplicationSettings.class);
                List<ApplicationSettings> resultList = query.getResultList();
                if (resultList == null || resultList.isEmpty()) {
                    applicationSettings = new ApplicationSettings();
                    entityManager.getTransaction().begin();
                    try {
                        entityManager.persist(applicationSettings);
                        entityManager.getTransaction().commit();
                    } catch (RuntimeException e) {
                        entityManager.getTransaction().rollback();
                        throw e;
                    }
                } else {
                    applicationSettings = resultList.get(0);
                }
            }
        }
        return applicationSettings;
    }

    @Override
    public ApplicationSettings updateApplicationSettings(ApplicationSettings applicationSettings) {
        if (applicationSettings == null) {
            return getApplicationSettings();
        } else {
            EntityManager entityManager = getServletEntityManager();
            synchronized (entityManager) {
                User user = getSessionUser();
                if (user.getAdmin()) {
                    entityManager.getTransaction().begin();
                    try {
                        entityManager.merge(applicationSettings);
                        entityManager.getTransaction().commit();
                        this.applicationSettings = applicationSettings;
                        return applicationSettings;
                    } catch (RuntimeException e) {
                        entityManager.getTransaction().rollback();
                        throw e;
                    }
                } else {
                    throw new SecurityException();
                }
            }
        }
    }

    @Override
    public HashMap<String, String> getCustomLayers() {
        String fileName = "/WEB-INF/custom.properties";
        HashMap<String, String> map = new HashMap<String, String>();
        Properties customLayerFile = new Properties();
        try {
            customLayerFile.load(super.getServletContext().getResourceAsStream(fileName));
            if (!customLayerFile.isEmpty()) {
                Iterator<Entry<Object, Object>> layers = customLayerFile.entrySet().iterator();
                while (layers.hasNext()) {
                    Entry e = layers.next();
                    String layerName = e.getKey().toString();
                    String layerUrl = e.getValue().toString();
                    map.put(layerName, layerUrl);
                }
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return map;
    }

    public String searchModis(String type, String state, String area, String startYearStr, String startMonthStr,
            String endYearStr, String endMonthStr) {
        int startYear = Integer.parseInt(startYearStr);
        int startMonth = Integer.parseInt(startMonthStr);
        int endYear = startYear;
        if (!StringUtils.isEmpty(endYearStr)) {
            endYear = Integer.parseInt(endYearStr);
        }
        int endMonth = startMonth;
        if (!StringUtils.isEmpty(endMonthStr)) {
            endMonth = Integer.parseInt(endMonthStr);
        }
        String searchResultKey = "";
        try {
            if ("Hot Spot".equalsIgnoreCase(type) || "Burnt Area".equalsIgnoreCase(type)) {
                File currentFolder = null;
                if ("Hot Spot".equalsIgnoreCase(type)) {
                    currentFolder = getHotSpotFolder(state, area, startYear);
                } else {
                    currentFolder = getBurntAreaFolder(state, area, startYear);
                }

                JSONObject result;
                // Read first file

                if (currentFolder != null && currentFolder.exists()) {
                    File firstResultFile = getMonthFile(currentFolder, startMonth);
                    if (firstResultFile == null) {
                        return null;
                    }
                    // Result is at least the start month file
                    String resultContent = readFileContent(firstResultFile);
                    result = new JSONObject(resultContent);
                    JSONArray resultFeaturesArray = result.optJSONArray("features");
                    if (startYear == endYear) {
                        for (int m = startMonth + 1; m <= endMonth; m++) {
                            File file = getMonthFile(currentFolder, m);
                            if (file != null && file.exists()) {
                                JSONObject obj = new JSONObject(readFileContent(file));
                                JSONArray newFeaturesArray = obj.optJSONArray("features");

                                if (resultFeaturesArray != null && newFeaturesArray != null
                                        && newFeaturesArray.length() > 0) {
                                    for (int i = 0; i < newFeaturesArray.length(); i++) {
                                        resultFeaturesArray.put(newFeaturesArray.get(i));
                                    }
                                }
                            }
                        }
                    }
                    result.put("features", resultFeaturesArray);
                    if (!StringUtils.isEmpty(result.toString())) {
                        UUID token = UUID.randomUUID();
                        File resultFile = new File(modisSearchResultLocation, token.toString() + ".geojson");
                        FileWriter writer = new FileWriter(resultFile);
                        writer.write(result.toString());
                        writer.close();
                        searchResultKey = token.toString();
                    }
                }

            } else {

            }

        } catch (JSONException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return searchResultKey;
    }

    private File getMonthFile(File baseFolder, int month) {
        File monthFile = null;
        if (baseFolder != null && baseFolder.isDirectory()) {
            File[] files = baseFolder.listFiles();
            if (files != null && files.length > 0) {
                for (File file : files) {
                    String fileMonth = file.getName().split("_")[1];
                    try {
                        if (Integer.parseInt(fileMonth) == month && !file.isHidden()
                                && !file.getName().endsWith("~fglg ,hl,khlg'[4" + "lkn")) {
                            monthFile = file;
                            break;
                        }
                    } catch (NumberFormatException ignored) {

                    }
                }
            }
        }
        return monthFile;
    }

    public String readFileContent(File file) {

        FileReader reader;
        String content = "";
        try {
            reader = new FileReader(file);
            StringWriter writer = new StringWriter();
            IOUtils.copy(reader, writer);
            content = writer.toString();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;

    }

    public File getHotSpotFolder(String state, String area, int startYear) {
        File currentFolder = null;
        File folder = new File(modisFilesLocation,
                "HotSpot" + File.separator + state + File.separator + area + File.separator + startYear);
        if (folder.exists() && folder.isDirectory()) {
            currentFolder = folder;
        }
        return currentFolder;
    }

    public File getBurntAreaFolder(String state, String area, int startYear) {
        File currentFolder = null;
        File folder = new File(modisFilesLocation,
                "JSON" + File.separator + state + File.separator + area + File.separator + startYear);
        if (folder.exists() && folder.isDirectory()) {
            currentFolder = folder;
        }
        return currentFolder;
    }

    @Override
    public List<PersonalHistory> getPersonalHistory(int hoursAgo) {
        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            List<PersonalHistory> personalHistories = new LinkedList<PersonalHistory>();
            User user = getSessionUser();
            if (user.getDevices() != null && !user.getDevices().isEmpty()) {
                personalHistories = createPersonalHistories(user, hoursAgo);
            }
            return personalHistories;
        }
    }

    private List<PersonalHistory> createPersonalHistories(User user, int hoursAgo) {
        List<PersonalHistory> personalHistories = null;
        List<Device> devices = user.getDevices();
        if (devices != null && devices.size() > 0) {
            personalHistories = new ArrayList<PersonalHistory>();
            for (Device device : devices) {
                PersonalHistory personalHistory = new PersonalHistory();

                personalHistory.setName(device.getFirstName() + " " + device.getSecondName());
                personalHistory.setAge(calculateAge(device.getBirthDate()));
                personalHistory.setFireDepartment(device.getFireDepartment());
                personalHistory.setWeight(device.getWeight());
                personalHistory.setHeight(device.getHeight());

                List<Position> positions = getPositions(device, hoursAgo);
                if (positions != null && positions.size() > 0) {
                    Date firstPositionDate = positions.get(0).getTime();
                    personalHistory.setActiveTime(firstPositionDate);
                    double totalInclination = 0, uphillInclination = 0, downhillInclination = 0, totalKilometer = 0;
                    for (int i = 0; i < positions.size(); i++) {

                        totalInclination += positions.get(i).getAltitude();

                        if (i > 0) {
                            Position previousPoint = positions.get(i - 1);
                            Position currentPoint = positions.get(i);
                            totalKilometer += Math
                                    .abs(distance(previousPoint.getLatitude(), currentPoint.getLatitude(),
                                            previousPoint.getLongitude(), currentPoint.getLongitude(),
                                            previousPoint.getAltitude(), currentPoint.getAltitude()));
                            double inclination = positions.get(i).getAltitude()
                                    - positions.get(i - 1).getAltitude();
                            if (inclination < 0) {
                                uphillInclination += Math.abs(inclination);
                            } else {
                                downhillInclination += inclination;
                            }

                        }
                    }
                    personalHistory.setTotalInclination(String.valueOf(round(totalInclination, 2)));
                    personalHistory.setTotalKilometers(String.valueOf(round(totalKilometer, 2)));
                    personalHistory.setUphillInclination(String.valueOf(round(uphillInclination, 2)));
                    personalHistory.setDownhillInclination(String.valueOf(round(downhillInclination, 2)));
                }
                // Future Use
                personalHistory.setActivity("");
                personalHistory.setBloodOxygen("");
                personalHistory.setHeartRate(0);
                personalHistory.setSkin("");
                personalHistories.add(personalHistory);
            }
        }
        return personalHistories;
    }

    public static double round(double value, int places) {
        if (places < 0)
            throw new IllegalArgumentException();

        long factor = (long) Math.pow(10, places);
        value = value * factor;
        long tmp = Math.round(value);
        return (double) tmp / factor;
    }

    public static int calculateAge(Date dateOfBirth) {
        if (dateOfBirth == null)
            return 0;
        Calendar dob = Calendar.getInstance();
        dob.setTime(dateOfBirth);
        Calendar today = Calendar.getInstance();
        int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
        if (today.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR))
            age--;
        return age;
    }

    /*
     * Calculate distance between two points in latitude and longitude taking
     * into account height difference. If you are not interested in height
     * difference pass 0.0. Uses Haversine method as its base.
     * 
     * lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
     * el2 End altitude in meters
     */
    private double distance(double lat1, double lat2, double lon1, double lon2, double el1, double el2) {

        final int R = 6371; // Radius of the earth

        Double latDistance = deg2rad(lat2 - lat1);
        Double lonDistance = deg2rad(lon2 - lon1);
        Double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) + Math.cos(deg2rad(lat1))
                * Math.cos(deg2rad(lat2)) * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = R * c;// In kilometer

        double height = el1 - el2;
        distance = Math.pow(distance, 2) + Math.pow(height, 2);
        return Math.sqrt(distance);
    }

    private double deg2rad(double deg) {
        return (deg * Math.PI / 180.0);
    }

    @Override
    public List<Point> search(String searchType, Date from, Date to) {
        // TODO Auto-generated method stub
        return null;
    }

    List<QuakeData> quakes;

    public List<QuakeData> getEarthquakes() {

        while (quakes == null) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return quakes;

    }

    private void loadEarthquakeData() {
        String URL = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_week_age.kml";
        String content = "";
        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet(URL);
        List<QuakeData> quakes = null;
        try {
            HttpResponse res = httpClient.execute(httpGet);

            quakes = new ArrayList<QuakeData>();
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder;
            dBuilder = dbFactory.newDocumentBuilder();
            Document dom = dBuilder.parse(res.getEntity().getContent());
            Element doc = dom.getDocumentElement();
            NodeList elems = doc.getElementsByTagName("Placemark");
            for (int i = 0; i < elems.getLength(); i++) {
                Element elem = (Element) elems.item(i);
                // Collect the data from the XML text
                String name = getElementTextValue(elem, "name");
                String description = getElementTextValue(elem, "description");
                Element lookAtElement = (Element) elem.getElementsByTagName("LookAt").item(0);
                String latitude = getElementTextValue(lookAtElement, "latitude");
                String longitude = getElementTextValue(lookAtElement, "longitude");
                Element iconStyleElement = (Element) elem.getElementsByTagName("IconStyle").item(0);
                String colorPlusAlpha = getElementTextValue(iconStyleElement, "color");
                String color = colorPlusAlpha.substring(2);

                QuakeData quakeData = new QuakeData();
                quakeData.setName(name);
                quakeData.setSummary(description);
                quakeData.setLat(Double.valueOf(latitude));
                quakeData.setLon(Double.valueOf(longitude));
                quakeData.setColor(color);
                quakeData.setMagnitude(Float.parseFloat(name.substring(2, name.indexOf(" ", 2))));

                quakes.add(quakeData);
            }
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        this.quakes = quakes;
    }

    private String getElementTextValue(Element parent, String tag) {
        return parent.getElementsByTagName(tag).item(0).getFirstChild().getNodeValue();
    }

    @Override
    public Device changeAlarmSettings(Device device) {

        EntityManager entityManager = getSessionEntityManager();
        synchronized (entityManager) {
            entityManager.getTransaction().begin();
            try {
                device.setAlarmEnabled(!device.isAlarmEnabled());
                device = entityManager.merge(device);
                entityManager.getTransaction().commit();
                return device;
            } catch (RuntimeException e) {
                entityManager.getTransaction().rollback();
                throw e;
            }
        }
    }
}