/*******************************************************************************
* Gisgraphy Project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
* Copyright 2008 Gisgraphy project
* David Masclet <davidmasclet@gisgraphy.com>
*
*
*******************************************************************************/
package com.gisgraphy.reversegeocoding;
import java.util.SortedSet;
import org.springframework.stereotype.Service;
import com.gisgraphy.addressparser.Address;
import com.gisgraphy.addressparser.commons.GeocodingLevels;
import com.gisgraphy.addressparser.format.BasicAddressFormater;
import com.gisgraphy.addressparser.format.DisplayMode;
import com.gisgraphy.domain.geoloc.entity.City;
import com.gisgraphy.domain.geoloc.entity.HouseNumber;
import com.gisgraphy.domain.geoloc.entity.OpenStreetMap;
import com.gisgraphy.helper.GeolocHelper;
import com.gisgraphy.helper.countryInfo;
import com.gisgraphy.importer.LabelGenerator;
import com.vividsolutions.jts.geom.Point;
/**
* Some useful method for housenumber
*
* @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
*/
@Service
public class AddressHelper {
BasicAddressFormater formater = BasicAddressFormater.getInstance();
LabelGenerator labelGenerator = LabelGenerator.getInstance();
public HouseNumberDistance getNearestHouse(SortedSet<HouseNumber> houses, Point location){
if (location==null || houses==null || houses.size()==0){
return null;
}
if (houses.size()==1){
HouseNumber housenumber = houses.first();
if (housenumber!=null){
if (housenumber.getLocation()!=null){
return new HouseNumberDistance(housenumber, GeolocHelper.distance(housenumber.getLocation(), location));
} else {
return new HouseNumberDistance(housenumber, null);
}
} else {
return null;
}
} else {
Double smallestDistance = null;
HouseNumber nearestHouse = null;
for (HouseNumber house:houses){
if (house!=null && house.getLocation()!=null){
Double distance = GeolocHelper.distance(house.getLocation(), location) ;
if (nearestHouse==null){
smallestDistance=distance;
nearestHouse= house;
continue;
} else if (distance <= smallestDistance){
nearestHouse = house;
smallestDistance=distance;
} //house number are sorted by name, we can may be consider that if distance is greater is increase the last smallest distance is the nearest, but it is not,
//the street can have circle or strange shape
}
}
return new HouseNumberDistance(nearestHouse, smallestDistance);
}
}
public Address buildAddressFromOpenstreetMap(OpenStreetMap openStreetMap) {
return buildAddressFromOpenstreetMap(openStreetMap, new Address());
}
public Address buildAddressFromOpenstreetMap(OpenStreetMap openStreetMap,Address address) {
if (openStreetMap==null){
return null;
}
if (openStreetMap.getName()!=null){
address.setStreetName(openStreetMap.getName());
}
if (openStreetMap.getIsIn()!=null){
address.setCity(openStreetMap.getIsIn());
}
if (openStreetMap.getIsInPlace()!=null){
address.setCitySubdivision(openStreetMap.getIsInPlace());
}
if (openStreetMap.getIsInAdm()!=null){
address.setState(openStreetMap.getIsInAdm());
}
if (openStreetMap.getAdm1Name()!=null){
address.setAdm1Name(openStreetMap.getAdm1Name());
}
if (openStreetMap.getAdm2Name()!=null){
address.setAdm2Name(openStreetMap.getAdm2Name());
}
if (openStreetMap.getAdm3Name()!=null){
address.setAdm3Name(openStreetMap.getAdm3Name());
}
if (openStreetMap.getAdm4Name()!=null){
address.setAdm4Name(openStreetMap.getAdm4Name());
}
if (openStreetMap.getAdm5Name()!=null){
address.setAdm5Name(openStreetMap.getAdm5Name());
}
if (openStreetMap.isToll()!=null){
address.setToll(openStreetMap.isToll());
}
if (openStreetMap.getLanes()!=null){
address.setLanes(openStreetMap.getLanes());
}
if (openStreetMap.getSurface()!=null){
address.setSurface(openStreetMap.getSurface());
}
if (openStreetMap.getMaxSpeed()!=null){
address.setMaxSpeed(openStreetMap.getMaxSpeed());
}
if (openStreetMap.getMaxSpeedBackward()!=null){
address.setMaxSpeedBackward(openStreetMap.getMaxSpeedBackward());
}
if (openStreetMap.getSpeedMode()!=null){
address.setSpeedMode(openStreetMap.getSpeedMode().toString());
}
if (openStreetMap.getAzimuthStart()!=null){
address.setAzimuthStart(openStreetMap.getAzimuthStart());
}
if (openStreetMap.getAzimuthEnd()!=null){
address.setAzimuthEnd(openStreetMap.getAzimuthEnd());
}
if (openStreetMap.getStreetType()!=null){
address.setStreetType(openStreetMap.getStreetType().toString());
}
if (openStreetMap.getLength()!=null){
address.setLength(openStreetMap.getLength());
}
if (openStreetMap.isOneWay()){
address.setOneWay(openStreetMap.isOneWay());
}
if (openStreetMap.getZipCode()!=null) {
address.setZipCode(openStreetMap.getZipCode());
} else if (openStreetMap.getIsInZip()!=null && openStreetMap.getIsInZip().size() >=1){
address.setZipCode(labelGenerator.getBestZipString(openStreetMap.getIsInZip()));
}
if (openStreetMap.getLocation()!=null){
address.setLng(openStreetMap.getLongitude());
address.setLat(openStreetMap.getLatitude());
}
if (openStreetMap.getCountryCode()!=null){
address.setCountryCode(openStreetMap.getCountryCode());
}
address.setGeocodingLevel(GeocodingLevels.STREET);//We set it and don't calculate it cause if streetname is null
address.setFormatedFull(labelGenerator.getFullyQualifiedName(address));
address.setFormatedPostal(formater.getEnvelopeAddress(address, DisplayMode.COMMA));
return address;
}
public Address buildAddressFromOpenstreetMapAndPoint(OpenStreetMap openStreetMap, Point point) {
if (openStreetMap==null || point == null){
return null;
}
Address address = new Address();
if (openStreetMap.getLocation()!=null){
address.setDistance(GeolocHelper.distance(point, openStreetMap.getLocation()));
}
//we do the build address at the end because the formatedurl should take the housenumber into account
// and we have to set it first
address = buildAddressFromOpenstreetMap(openStreetMap,address);
return address;
}
public Address buildAddressFromHouseNumberDistance(HouseNumberDistance houseNumberDistance) {
if (houseNumberDistance==null || houseNumberDistance.getHouseNumber()==null){
return null;
}
Address address = new Address();
//we do the build address at the end because the formatedurl should take the housenumber into account
// and we have to set it first
if (houseNumberDistance.getHouseNumber().getNumber()!=null){
address.setHouseNumber(houseNumberDistance.getHouseNumber().getNumber());
}
if (houseNumberDistance.getHouseNumber().getName()!=null){
address.setName(houseNumberDistance.getHouseNumber().getName());
}
address.setDistance(houseNumberDistance.getDistance());
//then enrich the address
address = buildAddressFromOpenstreetMap(houseNumberDistance.getHouseNumber().getStreet(),address);
//and overide lat / long
if (houseNumberDistance.getHouseNumber().getLatitude()!=null){
address.setLat(houseNumberDistance.getHouseNumber().getLatitude());
}
if (houseNumberDistance.getHouseNumber().getLongitude()!=null){
address.setLng(houseNumberDistance.getHouseNumber().getLongitude());
}
address.setGeocodingLevel(GeocodingLevels.HOUSE_NUMBER);
return address;
}
public Address buildAddressFromCityAndPoint(City city,Point point) {
if (city==null || point == null){
return null;
}
Address address = buildAddressFromcity(city);
if (city.getLocation()!=null){
address.setDistance(GeolocHelper.distance(point, city.getLocation()));
}
return address;
}
public Address buildAddressFromcity(City city) {
if (city == null){
return null;
}
Address address = new Address();
if (city.getName()!=null){
address.setCity(city.getName());
}
if (city.getIsInAdm()!=null){
address.setState(city.getIsInAdm());
}
if (city.getAdm1Name()!=null){
address.setAdm1Name(city.getAdm1Name());
}
if (city.getAdm2Name()!=null){
address.setAdm2Name(city.getAdm2Name());
}
if (city.getAdm3Name()!=null){
address.setAdm3Name(city.getAdm3Name());
}
if (city.getAdm4Name()!=null){
address.setAdm4Name(city.getAdm4Name());
}
if (city.getAdm5Name()!=null){
address.setAdm5Name(city.getAdm5Name());
}
if (city.getZipCodes()!=null && city.getZipCodes().size() >=1){
address.setZipCode(city.getZipCodes().iterator().next().toString());
}
if (city.getLocation()!=null){
address.setLng(city.getLongitude());
address.setLat(city.getLatitude());
}
if (city.getCountryCode()!=null){
address.setCountryCode(city.getCountryCode());
}
address.setGeocodingLevel(GeocodingLevels.CITY);//We set it and don't calculate it cause if streetname is null
//geocoding level will be street
address.setFormatedFull(labelGenerator.getFullyQualifiedName(address));
address.setFormatedPostal(formater.getEnvelopeAddress(address, DisplayMode.COMMA));
return address;
}
}