Skip to content

Commit

Permalink
Merge pull request #12 from Contargo/addres-query
Browse files Browse the repository at this point in the history
Add API for searching addresses via query
  • Loading branch information
sandra-thieme authored Jan 16, 2018
2 parents 52dfb39 + 44e6045 commit 41eaf60
Show file tree
Hide file tree
Showing 14 changed files with 283 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;

import static org.springframework.web.bind.annotation.RequestMethod.GET;

import static java.util.Collections.singletonList;


Expand All @@ -49,12 +51,14 @@
* @author Aljona Murygina - murygina@synyx.de
* @author Arnold Franke - franke@synyx.de
* @author Tobias Schneider - schneider@synyx.de
* @author Sandra Thieme - thieme@synyx.de
* @author Ben Antony - antony@synyx.de
*/
@Controller
@Api(description = "API for querying addresses.", value = "")
public class AddressApiController {

public static final String METHOD_ADDRESS_BY_GEOLOCATION = "addressByGeolocation";
private static final String METHOD_ADDRESS_BY_GEOLOCATION = "addressByGeolocation";
private static final Logger LOG = getLogger(MethodHandles.lookup().lookupClass());

private final AddressDtoService addressDtoService;
Expand Down Expand Up @@ -188,4 +192,16 @@ public List<AddressDto> addressesWherePlaceIsIn(

return addressDtoService.getAddressesWherePlaceIsIn(placeId);
}


@ApiOperation(
value = "Returns a list of matching addresses.",
notes = "Can be static addresses or nominatim resolved addresses."
)
@ModelAttribute("addresses")
@RequestMapping(value = "/addresses", method = GET, params = { "query" })
public List<AddressDto> getAddresses(@RequestParam("query") String query) {

return addressDtoService.getAddressesByQuery(query);
}
}
18 changes: 14 additions & 4 deletions src/main/java/net/contargo/iris/address/dto/AddressDtoService.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public interface AddressDtoService {

/**
* Resolves an address (described by the given parameters) to a {@link java.util.List} of
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses multiple
* fallback strategies to find addresses if not all parameters are provided
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses
* multiple fallback strategies to find addresses if not all parameters are provided
*
* @param addressDetails The parameters describing the addresses we are looking for
*
Expand All @@ -58,8 +58,8 @@ public interface AddressDtoService {

/**
* Resolves an address (described by the given parameters) to a {@link java.util.List} of
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses multiple
* fallback strategies to find addresses if not all parameters are provided
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses
* multiple fallback strategies to find addresses if not all parameters are provided
*
* @param addressDetails The parameters describing the addresses we are looking for
*
Expand All @@ -86,4 +86,14 @@ public interface AddressDtoService {
* @return the {@link AddressDto} with the given hashKey
*/
AddressDto getAddressesByHashKey(String hashKey);


/**
* Returns a list of addresses matching the query.
*
* @param query the address query
*
* @return a list of matching addresses
*/
List<AddressDto> getAddressesByQuery(String query);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;


/**
Expand Down Expand Up @@ -64,7 +64,7 @@ public List<AddressListDto> getAddressesByDetails(Map<String, String> addressDet
return addressServiceWrapper.getAddressesByDetails(addressDetails)
.stream()
.map(AddressListDto::new)
.collect(Collectors.toList());
.collect(toList());
}


Expand All @@ -85,10 +85,7 @@ public List<AddressDto> getAddressesByDetailsPlain(Map<String, String> addressDe
@Override
public List<AddressDto> getAddressesWherePlaceIsIn(Long placeId) {

return addressService.getAddressesWherePlaceIsIn(placeId)
.stream()
.map(AddressDto::new)
.collect(Collectors.toList());
return addressService.getAddressesWherePlaceIsIn(placeId).stream().map(AddressDto::new).collect(toList());
}


Expand All @@ -97,4 +94,11 @@ public AddressDto getAddressesByHashKey(String hashKey) {

return new AddressDto(addressServiceWrapper.getByHashKey(hashKey));
}


@Override
public List<AddressDto> getAddressesByQuery(String query) {

return addressServiceWrapper.getAddressesByQuery(query).stream().map(AddressDto::new).collect(toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
* @author Sven Mueller - mueller@synyx.de
* @author Aljona Murygina - murygina@synyx.de
* @author Arnold Franke - franke@synyx.de
* @author Sandra Thieme - thieme@synyx.de
* @author Ben Antony - antony@synyx.de
*/
public interface AddressService {

/**
* Resolves an address (described by the given parameters) to a {@link java.util.List} of
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses multiple
* fallback strategies to find addresses if not all parameters are provided
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses
* multiple fallback strategies to find addresses if not all parameters are provided
*
* @param addressDetails @return
*/
Expand Down Expand Up @@ -51,4 +53,14 @@ public interface AddressService {
* @return The address for the given geolocation.
*/
Address getAddressByGeolocation(GeoLocation location);


/**
* Returns a list of addresses matching the query.
*
* @param query the address query
*
* @return a list of matching addresses
*/
List<Address> getAddressesByQuery(String query);
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ public Address getAddressByGeolocation(GeoLocation geoLocation) {
}


@Override
public List<Address> getAddressesByQuery(String query) {

String url = nominatimUrlBuilder.buildSearchUrl(query);

return nominatimResponder.getAddresses(url);
}


private List<Address> searchSuburbsViaNominatimsDetailPage(Long osmPlaceId, SuburbType suburbType,
Set<String> suburbGlobalDisplayNames) {

Expand Down Expand Up @@ -190,7 +199,7 @@ public List<Address> getAddressesByDetails(Map<String, String> addressDetails) {
}


private String[][] createResolvingStrategies(String postalCode, String city, String country, String name,
private static String[][] createResolvingStrategies(String postalCode, String city, String country, String name,
String internStreet) {

return new String[][] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,10 @@ String buildUrl(GeoLocation geoLocation) {

return url;
}


public String buildSearchUrl(String query) {

return baseUrl + "search/" + query + "?format=json&addressdetails=1";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.contargo.iris.address.AddressList;
import net.contargo.iris.address.nominatim.service.AddressService;
import net.contargo.iris.address.staticsearch.StaticAddress;
import net.contargo.iris.address.staticsearch.service.StaticAddressNotFoundException;
import net.contargo.iris.address.staticsearch.service.StaticAddressService;
import net.contargo.iris.normalizer.NormalizerService;

Expand All @@ -14,16 +15,19 @@
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import static net.contargo.iris.address.nominatim.service.AddressDetailKey.CITY;
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.COUNTRY;
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.POSTAL_CODE;
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.STREET;

import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;


/**
Expand All @@ -36,6 +40,7 @@
public class AddressServiceWrapper {

private static final Logger LOG = LoggerFactory.getLogger(AddressServiceWrapper.class);
private static final Pattern HASHKEY_MATCHER = Pattern.compile("^[A-Z0-9]{5}$");

private final AddressService addressService;
private final StaticAddressService staticAddressService;
Expand Down Expand Up @@ -175,7 +180,7 @@ private List<AddressList> resolveByNominatim(Map<String, String> addressDetails)
}


private List<AddressList> getSimpleAddressList(List<Address> addresses) {
private static List<AddressList> getSimpleAddressList(List<Address> addresses) {

List<AddressList> addressListList = new ArrayList<>();

Expand All @@ -189,4 +194,35 @@ private List<AddressList> getSimpleAddressList(List<Address> addresses) {

return addressListList;
}


@SuppressWarnings("squid:S1166")
public List<Address> getAddressesByQuery(String query) {

List<Address> addresses = new ArrayList<>();

if (HASHKEY_MATCHER.matcher(query).matches()) {
try {
addresses.add(getByHashKey(query));
} catch (StaticAddressNotFoundException e) {
// ignoring the exception as the query could be resolved by nominatim
}
}

if (addresses.isEmpty()) {
addresses.addAll(addressService.getAddressesByQuery(query));

List<Address> matchingStaticAddresses = addresses.stream()
.map(a ->
staticAddressService.findAddresses(a.getPostcode(), a.getCity(), a.getCountryCode())
.getAddresses())
.flatMap(Collection::stream)
.distinct()
.collect(toList());

addresses.addAll(matchingStaticAddresses);
}

return addresses;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
* MVC Unit test of {@link AddressApiController}.
*
* @author Arnold Franke - franke@synyx.de
* @author Sandra Thieme - thieme@synyx.de
* @author Ben Antony - antony@synyx.de
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:public-api-context.xml" })
Expand Down Expand Up @@ -209,4 +211,20 @@ public void testAddressByPlaceId() throws Exception {
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.addresses[0].displayName", is("76137 Karlsruhe")));
}


@Test
public void getAddresses() throws Exception {

Address address = new Address();
address.setDisplayName("Gartenstr. 67, Karlsruhe (Südweststadt)");

when(addressDtoServiceMock.getAddressesByQuery("Gartenstraße 67, Karlsruhe")).thenReturn(singletonList(
new AddressDto(address)));

mockMvc.perform(get("/addresses").param("query", "Gartenstraße 67, Karlsruhe"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.addresses", hasSize(1)))
.andExpect(jsonPath("$.addresses[0].displayName", is("Gartenstr. 67, Karlsruhe (Südweststadt)")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import static org.hamcrest.MatcherAssert.assertThat;

import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;

Expand All @@ -45,16 +46,17 @@ public class AddressDtoServiceImplUnitTest {
private static final int OSM_ID = 1;
private static final GeoLocation GEOLOCATION = new GeoLocation(BigDecimal.ONE, BigDecimal.ONE);
private static final Long PLACE_ID = 1L;

private final AddressService addressServiceMock = mock(AddressService.class);
private final AddressServiceWrapper addressServiceWrapperMock = mock(AddressServiceWrapper.class);
private final AddressDtoServiceImpl sut = new AddressDtoServiceImpl(addressServiceMock, addressServiceWrapperMock);
Address address = new Address(BigDecimal.ONE, BigDecimal.ONE);
private Map<String, String> addressDetails;

private final Address address = new Address(BigDecimal.ONE, BigDecimal.ONE);
private final Map<String, String> addressDetails = new HashMap<>();

@Before
public void setUp() throws Exception {
public void setUp() {

addressDetails = new HashMap<>();
addressDetails.put(CITY.getKey(), "city");
addressDetails.put(STREET.getKey(), "street");
addressDetails.put(POSTAL_CODE.getKey(), "postalcode");
Expand Down Expand Up @@ -175,4 +177,19 @@ public void getAddressesByHashKey() {
AddressDto addressDto = sut.getAddressesByHashKey(hashKey);
assertThat(addressDto.getDisplayName(), is(displayName));
}


@Test
public void getAddressesByQuery() {

address.setDisplayName("Gartenstr. 67, Karlsruhe (Südweststadt)");

when(addressServiceWrapperMock.getAddressesByQuery("Gartenstraße 67, Karlsruhe")).thenReturn(singletonList(
address));

List<AddressDto> addresses = sut.getAddressesByQuery("Gartenstraße 67, Karlsruhe");

assertThat(addresses, hasSize(1));
assertThat(addresses.get(0).getDisplayName(), is("Gartenstr. 67, Karlsruhe (Südweststadt)"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ public void getAddressByOsmIdWithOsmTypeNODE() {

when(nominatimUrlBuilderMock.buildOsmUrl(OSM_ID, OsmType.WAY)).thenReturn(null);
when(nominatimUrlBuilderMock.buildOsmUrl(OSM_ID, OsmType.NODE)).thenReturn(DUMMY_URL);
when(nominatimResponderMock.getAddressesFromOSMId(null)).thenReturn(singletonList(addressWithoutExpectedOsmId));
when(nominatimResponderMock.getAddressesFromOSMId(null)).thenReturn(singletonList(
addressWithoutExpectedOsmId));
when(nominatimResponderMock.getAddressesFromOSMId(DUMMY_URL)).thenReturn(singletonList(expectedAddress));

assertThat(sut.getAddressByOsmId(OSM_ID), is(expectedAddress));
Expand Down Expand Up @@ -288,4 +289,20 @@ public void getAddressByGeolocationIllegalArgument() {
when(nominatimUrlBuilderMock.buildUrl(a1)).thenThrow(new IllegalArgumentException());
sut.getAddressByGeolocation(a1);
}


@Test
public void getAddressesByQuery() {

List<Address> addresses = singletonList(new Address());

when(nominatimResponderMock.getAddresses("http://nominatim/search/Streetname 43, cityName")).thenReturn(
addresses);
when(nominatimUrlBuilderMock.buildSearchUrl("Streetname 43, cityName")).thenReturn(
"http://nominatim/search/Streetname 43, cityName");

List<Address> result = sut.getAddressesByQuery("Streetname 43, cityName");

assertThat(result, is(addresses));
}
}
Loading

0 comments on commit 41eaf60

Please sign in to comment.