Java tutorial
/******************************************************************************* * 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.importer; import static com.gisgraphy.street.HouseNumberUtil.normalizeNumber; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.hibernate.FlushMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import com.gisgraphy.domain.geoloc.entity.HouseNumber; import com.gisgraphy.domain.geoloc.entity.OpenStreetMap; import com.gisgraphy.domain.repository.IOpenStreetMapDao; import com.gisgraphy.domain.repository.ISolRSynchroniser; import com.gisgraphy.domain.repository.IhouseNumberDao; import com.gisgraphy.domain.valueobject.HouseNumberType; import com.gisgraphy.domain.valueobject.NameValueDTO; import com.gisgraphy.domain.valueobject.Output; import com.gisgraphy.domain.valueobject.Output.OutputStyle; import com.gisgraphy.domain.valueobject.Pagination; import com.gisgraphy.fulltext.FullTextSearchEngine; import com.gisgraphy.fulltext.FulltextQuery; import com.gisgraphy.fulltext.FulltextResultsDto; import com.gisgraphy.fulltext.IFullTextSearchEngine; import com.gisgraphy.fulltext.SolrResponseDto; import com.gisgraphy.helper.GeolocHelper; import com.gisgraphy.importer.dto.AddressInclusion; import com.gisgraphy.importer.dto.AssociatedStreetHouseNumber; import com.gisgraphy.importer.dto.AssociatedStreetMember; import com.gisgraphy.importer.dto.InterpolationHouseNumber; import com.gisgraphy.importer.dto.InterpolationMember; import com.gisgraphy.importer.dto.InterpolationType; import com.gisgraphy.importer.dto.NodeHouseNumber; import com.gisgraphy.service.ServiceException; import com.vividsolutions.jts.geom.Point; /** * Import the street from an (pre-processed) openStreet map data file . * * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a> */ public class OpenStreetMapHouseNumberSimpleImporter extends AbstractSimpleImporterProcessor { protected static final Logger logger = LoggerFactory.getLogger(OpenStreetMapHouseNumberSimpleImporter.class); protected IOpenStreetMapDao openStreetMapDao; protected IhouseNumberDao houseNumberDao; protected ISolRSynchroniser solRSynchroniser; protected IFullTextSearchEngine fullTextSearchEngine; private static final String ASSOCIATED_HOUSE_NUMBER_REGEXP = "([0-9]+)___([^_]*)___((?:(?!___).)*)___((?:(?!___).)*)___([NW])___([^_]*)(?:___)?"; private static final String INTERPOLATION_HOUSE_NUMBER_REGEXP = "([0-9]+)___([0-9])___((?:(?!___).)+)*___((?:(?!___).)+)*___((?:(?!___).)+)*(?:___)?"; private static final Pattern ASSOCIATED_HOUSE_NUMBER_PATTERN = Pattern.compile(ASSOCIATED_HOUSE_NUMBER_REGEXP, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); private static final Pattern INTERPOLATION_HOUSE_NUMBER_PATTERN = Pattern .compile(INTERPOLATION_HOUSE_NUMBER_REGEXP, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); protected final static Output MEDIUM_OUTPUT = Output.withDefaultFormat().withStyle(OutputStyle.MEDIUM); protected static final double SEARCH_DISTANCE = 6000; /* * (non-Javadoc) * * @see * com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#flushAndClear * () */ @Override protected void flushAndClear() { openStreetMapDao.flushAndClear(); houseNumberDao.flushAndClear(); } @Override protected void setup() { //temporary disable logging when importing FullTextSearchEngine.disableLogging = true; super.setup(); } /* * (non-Javadoc) * * @see * com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#getFiles() */ @Override protected File[] getFiles() { return ImporterHelper.listCountryFilesToImport(importerConfig.getOpenStreetMapHouseNumberDir()); } /* * (non-Javadoc) * * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor# * getNumberOfColumns() */ @Override protected int getNumberOfColumns() { return 9; } protected AssociatedStreetHouseNumber parseAssociatedStreetHouseNumber(String line) { /* * A 1264114 "{" * "47129758___0101000020E61000005CCBD3C231E76240AA6514FE5BF440C0___Bowral Street___Bowral Street___W___street" * ", ""84623507 * ___0101000020E6100000546690CC36E76240A417D5545AF440C0___71___Bowral * Street___W___house""}" */ if (line == null || "".equals(line.trim())) { return null; } String[] fields = line.split("\t"); if (fields.length != 3) { logger.warn("wrong number of fields for line " + line + " expected 3 but was " + fields.length); return null; } if (!"A".equals(fields[0])) { logger.warn("wrong house Number Type for line " + line + " expected 'A' but was " + fields[0]); return null; } AssociatedStreetHouseNumber houseNumber = new AssociatedStreetHouseNumber(); if (!isEmptyField(fields, 1, false)) { houseNumber.setRelationID(fields[1].trim()); } if (!isEmptyField(fields, 2, false)) { Matcher matcher = ASSOCIATED_HOUSE_NUMBER_PATTERN.matcher(fields[2].trim()); int i = 0; while (matcher.find()) { AssociatedStreetMember member = new AssociatedStreetMember(); if (matcher.groupCount() != 6) { logger.warn("wrong number of fields for AssociatedStreetMember no " + i + "for line " + line); continue; } member.setId(matcher.group(1)); Point point; try { point = (Point) GeolocHelper.convertFromHEXEWKBToGeometry(matcher.group(2)); } catch (Exception e) { logger.warn(e.getMessage()); return null; } if (point == null) { logger.warn("wrong location for AssociatedStreetMember for point n" + i + "for line " + line); continue; } member.setLocation(point); String role = matcher.group(6); member.setRole(role); member.setHouseNumber(matcher.group(3)); member.setStreetName(matcher.group(4)); member.setType(matcher.group(5)); houseNumber.addMember(member); i++; } } else { return null; } return houseNumber; } protected InterpolationHouseNumber parseInterpolationHouseNumber(String line) { /* * I 168365171 1796478450___0___0101000020E61000009A023EE4525350C0959C137B682F38C0______; * 1366275082___1___0101000020E610000068661CD94B5350C0B055270C6F2F38C0______; * 1796453793___2___0101000020E610000038691A144D5350C023ADE75A6A2F38C0___600___; * 1796453794___3___0101000020E6100000F38F6390605350C028A6666A6D2F38C0___698___ even */ if (line == null || "".equals(line.trim())) { return null; } String[] fields = line.split("\t"); if (fields.length < 5 || fields.length > 6) { logger.warn("wrong number of fields for line " + line + " expected 5/6 but was " + fields.length); return null; } if (!"I".equals(fields[0])) { logger.warn("wrong house Number Type for line " + line + " expected 'A' but was " + fields[0]); return null; } InterpolationHouseNumber houseNumber = new InterpolationHouseNumber(); if (!isEmptyField(fields, 1, false)) { houseNumber.setWayId(fields[1].trim()); } if (!isEmptyField(fields, 4, false)) { try { houseNumber.setInterpolationType(InterpolationType.valueOf(fields[4].trim().toLowerCase())); } catch (Exception e) { //ignore } } if (!isEmptyField(fields, 3, false)) { houseNumber.setStreetName(fields[3].trim()); } if (!isEmptyField(fields, 5, false)) { try { houseNumber.setAddressInclusion(AddressInclusion.valueOf(fields[5].trim().toLowerCase())); } catch (Exception e) { //ignore } } if (!isEmptyField(fields, 2, false)) { Matcher matcher = INTERPOLATION_HOUSE_NUMBER_PATTERN.matcher(fields[2].trim()); int i = 0; while (matcher.find()) { InterpolationMember member = new InterpolationMember(); if (matcher.groupCount() != 5) { logger.warn("wrong number of fields for InterpolationMember n" + i + "for line " + line); continue; } member.setId(matcher.group(1)); // seqId String seqIdAsString = matcher.group(2); int seqId = 0; try { seqId = Integer.parseInt(seqIdAsString); } catch (NumberFormatException e) { logger.warn("can not convert sequence id " + seqIdAsString + " to integer"); continue; } member.setSequenceId(seqId); // location Point point; try { point = (Point) GeolocHelper.convertFromHEXEWKBToGeometry(matcher.group(3)); } catch (Exception e) { logger.warn(e.getMessage()); return null; } if (point == null) { logger.warn("wrong location for InterpolationMember point n" + i + "for line " + line); continue; } member.setLocation(point); member.setHouseNumber(matcher.group(4)); member.setStreetname(matcher.group(5)); houseNumber.addMember(member); i++; } Collections.sort(houseNumber.getMembers()); } else { return null; } return houseNumber; } protected NodeHouseNumber parseNodeHouseNumber(String line) { //N 1053493828 0101000020E610000060910486D17250C05D4B6D4ECA753CC0 75 Sandwichs La Estrellita Estanislao Maldones if (line == null || "".equals(line.trim())) { return null; } String[] fields = line.split("\t"); if (fields.length < 4) { logger.warn("wrong number of fields for line " + line + " expected 4 but was " + fields.length); return null; } if (!"N".equals(fields[0]) && !"W".equals(fields[0])) { logger.warn("wrong house Number Type for line " + line + " expected 'N' or 'w' but was " + fields[0]); return null; } NodeHouseNumber node = new NodeHouseNumber(); if (!isEmptyField(fields, 1, false)) { node.setNodeId(fields[1].trim()); } if (!isEmptyField(fields, 2, false)) { Point point; try { point = (Point) GeolocHelper.convertFromHEXEWKBToGeometry(fields[2].trim()); } catch (Exception e) { logger.warn(e.getMessage()); return null; } if (point == null) { logger.warn("wrong location for NodeHouseNumber for point for line " + line); return null; } else { node.setLocation(point); } } if (!isEmptyField(fields, 3, false)) { node.setHouseNumber(fields[3].trim()); } if (!isEmptyField(fields, 4, false)) { node.setName(fields[4].trim()); } if (!isEmptyField(fields, 5, false)) { node.setStreetName(fields[5].trim()); } return node; } /* * (non-Javadoc) * * @see * com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#processData * (java.lang.String) */ @Override protected void processData(String line) throws ImporterException { if (line == null || "".equals(line.trim())) { return; } if (line.startsWith("A")) { AssociatedStreetHouseNumber house = parseAssociatedStreetHouseNumber(line); if (house != null) { processAssociatedStreet(house); } } else if (line.startsWith("N")) { NodeHouseNumber house = parseNodeHouseNumber(line); if (house != null) { processNodeHouseNumber(house); } } else if (line.startsWith("W")) { NodeHouseNumber house = parseNodeHouseNumber(line); if (house != null) { processNodeHouseNumber(house); } } else if (line.startsWith("I")) { InterpolationHouseNumber house = parseInterpolationHouseNumber(line); if (house == null) { return; } List<InterpolationMember> members = house.getMembers(); if (members.size() <= 1) { //we can not interpolate if there is less than 2 points logger.warn("can not interpolate if there is less than two points for " + line); return; } OpenStreetMap osm = null; if (house.getStreetName() != null && !"".equals(house.getStreetName().trim()) && !"\"\"".equals(house.getStreetName().trim())) { osm = findNearestStreet(house.getStreetName(), members.get(0).getLocation()); if (osm == null) { logger.warn("can not find street for name " + house.getStreetName() + ", position :" + members.get(0).getLocation()); return;// we don't know which street to add the numbers } } else { return; } List<HouseNumber> houseNumbers = processInterpolationHouseNumber(house); if (houseNumbers.size() != 0) { osm.addHouseNumbers(houseNumbers); openStreetMapDao.save(osm); } } else { logger.warn("unknow node type for line " + line); } } protected void processAssociatedStreet(AssociatedStreetHouseNumber house) { if (house == null) { return; } List<AssociatedStreetMember> streetMembers = house.getStreetMembers(); List<AssociatedStreetMember> houseMembers = house.getHouseMembers(); if (houseMembers.size() == 0) { //no streets or no house logger.warn("there is no member for associated street " + house); return; } if (streetMembers.size() == 0) { //treet as node, it is often the case when associated with a relation and our script don't manage it so we link it here if (houseMembers != null) { String streetname = null; boolean allHouseHaveTheSameStreetName = true; OpenStreetMap street = null; for (AssociatedStreetMember houseMember : houseMembers) { if (streetname == null && houseMember.getStreetName() != null) { streetname = houseMember.getStreetName(); street = findNearestStreet(houseMember.getStreetName(), houseMember.getLocation()); continue; } else { if (!houseMember.getStreetName().equals(streetname)) { allHouseHaveTheSameStreetName = false; street = null; break; } } } for (AssociatedStreetMember houseMember : houseMembers) { if (houseMember.getStreetName() != null && !"".equals(houseMember.getStreetName().trim()) && houseMember.getLocation() != null) { if (!allHouseHaveTheSameStreetName) {//we have to find for each one street = findNearestStreet(houseMember.getStreetName(), houseMember.getLocation()); } if (street != null) { //Long openstreetmapId = street.getOpenstreetmap_id(); //OpenStreetMap osm = openStreetMapDao.getByOpenStreetMapId(openstreetmapId); HouseNumber houseNumber = buildHouseNumberFromAssociatedHouseNumber(houseMember); if (houseNumber != null) { street.addHouseNumber(houseNumber); openStreetMapDao.save(street); } } else { logger.warn("can not find associated street for name " + houseMember.getStreetName() + ", position :" + houseMember.getLocation()); } } } } } else if (streetMembers.size() == 1) { AssociatedStreetMember associatedStreetMember = streetMembers.get(0); if (associatedStreetMember.getId() == null) { logger.warn("associated street " + associatedStreetMember + " has no id"); return; } Long idAsLong = null; try { idAsLong = Long.valueOf(associatedStreetMember.getId()); } catch (NumberFormatException e) { logger.warn(idAsLong + " is not a valid id for associated street"); return; } OpenStreetMap associatedStreet = openStreetMapDao.getByOpenStreetMapId(idAsLong); if (associatedStreet == null) { logger.warn("no street can be found for associated street for id " + idAsLong); return; } for (AssociatedStreetMember houseMember : houseMembers) { HouseNumber houseNumber = buildHouseNumberFromAssociatedHouseNumber(houseMember); if (houseNumber != null) { associatedStreet.addHouseNumber(houseNumber); } } openStreetMapDao.save(associatedStreet); } else if (streetMembers.size() > 1) { //for each house, search the nearest street //getStreetIds List<Long> streetIds = new ArrayList<Long>(); for (AssociatedStreetMember street : streetMembers) { Long id; try { id = Long.valueOf(street.getId()); streetIds.add(id); } catch (NumberFormatException e) { logger.warn(street + " has no id"); } } for (AssociatedStreetMember houseMember : houseMembers) { if (houseMember != null && houseMember.getLocation() != null) { HouseNumber houseNumber = buildHouseNumberFromAssociatedHouseNumber(houseMember); OpenStreetMap associatedStreet = openStreetMapDao.getNearestByosmIds(houseMember.getLocation(), streetIds); if (associatedStreet != null && houseNumber != null) { associatedStreet.addHouseNumber(houseNumber); openStreetMapDao.save(associatedStreet); } else { logger.warn("associated street " + associatedStreet + ", or house numer " + houseNumber + " is null"); } } } } } protected HouseNumber processNodeHouseNumber(NodeHouseNumber house) { if (house == null || house.getLocation() == null) { return null; } HouseNumber houseNumber = new HouseNumber(); houseNumber.setNumber(normalizeNumber(house.getHouseNumber())); houseNumber.setName(house.getName()); houseNumber.setType(HouseNumberType.NODE); try { Long id = Long.valueOf(house.getNodeId()); houseNumber.setOpenstreetmapId(id); } catch (NumberFormatException e) { //ignore } Point location = house.getLocation(); houseNumber.setLocation(location); OpenStreetMap osm = findNearestStreet(house.getStreetName(), location); if (osm != null) { try { osm.addHouseNumber(houseNumber); openStreetMapDao.save(osm); } catch (Exception e) { logger.error("error processing node housenumber, we ignore it but you should consider it : " + e.getMessage(), e); } return houseNumber; } else { logger.warn("can not find node street for name " + house.getStreetName() + ", position :" + location + " for " + house); } return null; } protected List<HouseNumber> processInterpolationHouseNumber(InterpolationHouseNumber house) { //the results List<HouseNumber> houseNumbers = new ArrayList<HouseNumber>(); boolean multipleInterpolation = false;//boolean to indicate that we //interpolate several segment, so we should not add the N2 point //cause it has already been added by last interpolation //N1--------N2-------N3 List<InterpolationMember> membersForSegmentation = new ArrayList<InterpolationMember>(); List<InterpolationMember> members = house.getMembers(); if (members != null) { for (InterpolationMember member : members) { if (member.getHouseNumber() != null && !"".equals(member.getHouseNumber().trim())) { // got HN in the member membersForSegmentation.add(member); if (membersForSegmentation.size() == 1) { continue;// we only have one point and need at // least one other } else { int nbInnerPoint = 0; int increment = 1; if (house.getInterpolationType() == InterpolationType.alphabetic) { //WE choose to ignore Alphabetic interpolation due to poor interest } else { // odd,even,all=>should be numeric String firstNumberAsString = membersForSegmentation.get(0).getHouseNumber(); String lastNumberAsString = membersForSegmentation .get(membersForSegmentation.size() - 1).getHouseNumber(); int firstNumberAsInt = 0; int lastNumberAsInt = 0; try { firstNumberAsInt = Integer.parseInt(normalizeNumber(firstNumberAsString)); lastNumberAsInt = Integer.parseInt(normalizeNumber(lastNumberAsString)); } catch (NumberFormatException e) { logger.warn("interpolation house number " + firstNumberAsString + " and/or " + lastNumberAsString + "are not numbers"); return houseNumbers; } if (house.getInterpolationType() == InterpolationType.even) {// pair if (firstNumberAsInt % 2 == 1) { firstNumberAsInt++; membersForSegmentation.get(0).setHouseNumber(firstNumberAsInt + ""); } if (lastNumberAsInt % 2 == 1) { lastNumberAsInt++; membersForSegmentation.get(membersForSegmentation.size() - 1) .setHouseNumber(lastNumberAsInt + ""); } // two even number substracts always give an odd one nbInnerPoint = Math.abs((firstNumberAsInt - lastNumberAsInt) / 2) - 1; if (firstNumberAsInt < lastNumberAsInt) { increment = 2; } else { increment = -2; } } else if (house.getInterpolationType() == InterpolationType.odd) {// impair if (firstNumberAsInt % 2 == 0) { firstNumberAsInt++; membersForSegmentation.get(0).setHouseNumber(firstNumberAsInt + ""); } if (lastNumberAsInt % 2 == 0) { lastNumberAsInt++; membersForSegmentation.get(membersForSegmentation.size() - 1) .setHouseNumber(lastNumberAsInt + ""); } nbInnerPoint = Math.abs((firstNumberAsInt - lastNumberAsInt) / 2) - 1; if (firstNumberAsInt < lastNumberAsInt) { increment = 2; } else { increment = -2; } } else if (house.getInterpolationType() == InterpolationType.all) { nbInnerPoint = Math.abs((firstNumberAsInt - lastNumberAsInt)) - 1; if (firstNumberAsInt < lastNumberAsInt) { increment = 1; } else { increment = -1; } } List<Point> points = new ArrayList<Point>(membersForSegmentation.size()); for (InterpolationMember memberForSegmentation : membersForSegmentation) { points.add(memberForSegmentation.getLocation()); } List<Point> segmentizedPoint = segmentize(points, nbInnerPoint); for (int i = 0; i < segmentizedPoint.size(); i++) { if (i == 0 && multipleInterpolation) { continue;//this point has already been added by previous interpolation } HouseNumber houseNumberToAdd = new HouseNumber(); //set the openstretmapid of the first point if ((i == 0 && membersForSegmentation.get(0) != null && membersForSegmentation.get(0).getId() != null)) { try { Long id = Long.valueOf(membersForSegmentation.get(i).getId()); houseNumberToAdd.setOpenstreetmapId(id); } catch (NumberFormatException e) { //ignore } } //set the openstretmapid of the last point if ((i == (segmentizedPoint.size() - 1) && membersForSegmentation.get(1) != null && membersForSegmentation.get(1).getId() != null)) { try { Long id = Long.valueOf(membersForSegmentation.get(1).getId()); houseNumberToAdd.setOpenstreetmapId(id); } catch (NumberFormatException e) { //ignore } } Point p = segmentizedPoint.get(i); houseNumberToAdd.setType(HouseNumberType.INTERPOLATION); houseNumberToAdd.setLocation(p); houseNumberToAdd.setNumber(firstNumberAsInt + (increment * i) + ""); houseNumbers.add(houseNumberToAdd); } //return houseNumbers; } membersForSegmentation = new ArrayList<InterpolationMember>(); multipleInterpolation = true; // restart the process with the last point; membersForSegmentation.add(member); } } else { // no housenumber in the members, it is a point to draw a street if (membersForSegmentation.size() == 0) { // we go to the next point to search for a point with HN continue; } else { // we add the member and continue to search for a point with HN; membersForSegmentation.add(member); } } } } return houseNumbers; } protected OpenStreetMap findNearestStreet(String streetName, Point location) { //Openstreetmap has sometimes, for a same street, several segment, so we do a fulltext search and then search for the nearest based on shape,not nearest point if (location == null) { return null; } if (streetName == null || "".equals(streetName.trim()) || "\"\"".equals(streetName.trim()) || "-".equals(streetName.trim()) || "---".equals(streetName.trim()) || "--".equals(streetName.trim())) { return openStreetMapDao.getNearestFrom(location); } FulltextQuery query; try { query = new FulltextQuery(streetName, Pagination.DEFAULT_PAGINATION, MEDIUM_OUTPUT, com.gisgraphy.fulltext.Constants.STREET_PLACETYPE, null); } catch (IllegalArgumentException e) { logger.error("can not create a fulltext query for " + streetName + ", will return the nearest"); return openStreetMapDao.getNearestFrom(location); } query.withAllWordsRequired(false).withoutSpellChecking(); query.around(location); query.withRadius(SEARCH_DISTANCE); FulltextResultsDto results; try { results = fullTextSearchEngine.executeQuery(query); } catch (RuntimeException e) { logger.error("error during fulltext search : " + e.getMessage(), e); return null; } int resultsSize = results.getResultsSize(); List<SolrResponseDto> resultsList = results.getResults(); if (resultsSize == 1) { SolrResponseDto street = resultsList.get(0); if (street != null) { Long openstreetmapId = street.getOpenstreetmap_id(); if (openstreetmapId != null) { OpenStreetMap osm = openStreetMapDao.getByOpenStreetMapId(openstreetmapId); if (osm == null) { logger.warn("can not find street for id " + openstreetmapId); } return osm; } } } if (resultsSize > 1) { return getNearestByIds(resultsList, location); } else { return null; } } protected OpenStreetMap getNearestByIds(List<SolrResponseDto> results, Point point) { List<Long> ids = new ArrayList<Long>(); OpenStreetMap result = null; if (results != null) { for (SolrResponseDto dto : results) { if (dto != null && dto.getOpenstreetmap_id() != null) { ids.add(dto.getOpenstreetmap_id()); } } result = openStreetMapDao.getNearestByosmIds(point, ids); } return result; /*SolrResponseDto candidate=null; if (results!=null ){ float score =0; Double smallestDistance = 0D; for (SolrResponseDto dto: results){ if (score==0){//initialize with first element score= dto.getScore(); smallestDistance = GeolocHelper.distance(GeolocHelper.createPoint(dto.getLng(), dto.getLat()), point); candidate=dto; continue; } if ((Math.abs(dto.getScore()-score)*100/score) < SCORE_THRESOLD){//the score is very close => < X% if (GeolocHelper.distance(GeolocHelper.createPoint(dto.getLng(), dto.getLat()), point) < smallestDistance){//if the dto is closer, we keep it candidate = dto; } } else {//score is too far, and results are sorted by score, we return the candidate return candidate; } } } return candidate; */ } protected HouseNumber buildHouseNumberFromAssociatedHouseNumber(AssociatedStreetMember houseMember) { HouseNumber houseNumber = new HouseNumber(); if (houseMember.getLocation() != null) {//it is a mandatory field houseNumber.setLocation(houseMember.getLocation()); } else { return null; } houseNumber.setNumber(normalizeNumber(houseMember.getHouseNumber()));//todo normalize 11 d Long osmId = null; try { osmId = Long.valueOf(houseMember.getId()); houseNumber.setOpenstreetmapId(osmId); } catch (NumberFormatException e) { logger.warn(osmId + " is not a valid openstreetmapId"); } houseNumber.setType(HouseNumberType.ASSOCIATED); return houseNumber; } /** * @param points a list of point, typically a list of point that represent a street * @param nbInnerPoint the number of point to add beetween the startpoint and the endpoint * @return the intermediate points that represents segments of same size, if nbInnerPoint=4, * we will get 6 points back */ protected List<Point> segmentize(List<Point> points, int nbInnerPoint) { List<Point> result = new ArrayList<Point>(); if (points == null || nbInnerPoint <= 0 || points.size() == 0) { return result; } if (points.size() >= 1) { result.add(points.get(0)); } if (points.size() == 1) { return result; } List<Double> distances = new ArrayList<Double>();//5/10/15 double totalDistance = 0;//30 for (int i = 0; i < points.size() - 1; i++) { double distance = GeolocHelper.distance(points.get(i), points.get(i + 1)); distances.add(distance); totalDistance += distance; } int nbSegment = nbInnerPoint + 1;//4+1 int nbpoints = nbInnerPoint + 1;//4+1 double segmentLength = totalDistance / nbSegment;//30/5=6 int currentSubSegment = 1; double currentSubLength = 0; for (int i = 1; i <= nbpoints; i++) { while (currentSubLength + distances.get(currentSubSegment - 1) < i * segmentLength) { currentSubLength += distances.get(currentSubSegment - 1); currentSubSegment++; if (currentSubSegment > distances.size()) { return result; } } double distanceLeft = (i * segmentLength) - currentSubLength; double ratio = distanceLeft / (distances.get(currentSubSegment - 1)); if (ratio <= 0) { //it is the last point result.add(points.get(points.size() - 1)); } else { //we put it at the correct ratio Point p1 = points.get(currentSubSegment - 1); Point p2 = points.get(currentSubSegment); Double lng = (p2.getX() - p1.getX()) * ratio + p1.getX(); Double lat = (p2.getY() - p1.getY()) * ratio + p1.getY(); Point p = GeolocHelper.createPoint(lng.floatValue(), lat.floatValue()); result.add(p); } } return result; } /* * (non-Javadoc) * * @see * com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#shouldBeSkiped * () */ @Override public boolean shouldBeSkipped() { return !importerConfig.isOpenstreetmapHouseNumberImporterEnabled(); } /* * (non-Javadoc) * * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor# * setCommitFlushMode() */ @Override protected void setCommitFlushMode() { this.openStreetMapDao.setFlushMode(FlushMode.COMMIT); this.houseNumberDao.setFlushMode(FlushMode.COMMIT); } /* * (non-Javadoc) * * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor# * shouldIgnoreComments() */ @Override protected boolean shouldIgnoreComments() { return false; } /* * (non-Javadoc) * * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor# * shouldIgnoreFirstLine() */ @Override protected boolean shouldIgnoreFirstLine() { return false; } /* * (non-Javadoc) * * @see com.gisgraphy.domain.geoloc.importer.IGeonamesProcessor#rollback() */ public List<NameValueDTO<Integer>> rollback() { List<NameValueDTO<Integer>> deletedObjectInfo = new ArrayList<NameValueDTO<Integer>>(); logger.info("reseting house number importer..."); int deleted = houseNumberDao.deleteAll(); if (deleted != 0) { deletedObjectInfo .add(new NameValueDTO<Integer>(houseNumberDao.getPersistenceClass().getSimpleName(), deleted)); } logger.info(deleted + " house number entities have been deleted"); resetStatus(); return deletedObjectInfo; } @Override // TODO test protected void tearDown() { super.tearDown(); FullTextSearchEngine.disableLogging = false; this.statusMessage = internationalisationService.getString("import.fulltext.optimize"); solRSynchroniser.optimize(); } @Required public void setHouseNumberDao(IhouseNumberDao houseNumberDao) { this.houseNumberDao = houseNumberDao; } @Required public void setOpenStreetMapDao(IOpenStreetMapDao openStreetMapDao) { this.openStreetMapDao = openStreetMapDao; } @Required public void setFullTextSearchEngine(IFullTextSearchEngine fullTextSearchEngine) { this.fullTextSearchEngine = fullTextSearchEngine; } @Required public void setSolRSynchroniser(ISolRSynchroniser solRSynchroniser) { this.solRSynchroniser = solRSynchroniser; } }