Skip to content

Commit 41eaf60

Browse files
Merge pull request #12 from Contargo/addres-query
Add API for searching addresses via query
2 parents 52dfb39 + 44e6045 commit 41eaf60

File tree

14 files changed

+283
-29
lines changed

14 files changed

+283
-29
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
1+
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip

src/main/java/net/contargo/iris/address/api/AddressApiController.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939

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

42+
import static org.springframework.web.bind.annotation.RequestMethod.GET;
43+
4244
import static java.util.Collections.singletonList;
4345

4446

@@ -49,12 +51,14 @@
4951
* @author Aljona Murygina - murygina@synyx.de
5052
* @author Arnold Franke - franke@synyx.de
5153
* @author Tobias Schneider - schneider@synyx.de
54+
* @author Sandra Thieme - thieme@synyx.de
55+
* @author Ben Antony - antony@synyx.de
5256
*/
5357
@Controller
5458
@Api(description = "API for querying addresses.", value = "")
5559
public class AddressApiController {
5660

57-
public static final String METHOD_ADDRESS_BY_GEOLOCATION = "addressByGeolocation";
61+
private static final String METHOD_ADDRESS_BY_GEOLOCATION = "addressByGeolocation";
5862
private static final Logger LOG = getLogger(MethodHandles.lookup().lookupClass());
5963

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

189193
return addressDtoService.getAddressesWherePlaceIsIn(placeId);
190194
}
195+
196+
197+
@ApiOperation(
198+
value = "Returns a list of matching addresses.",
199+
notes = "Can be static addresses or nominatim resolved addresses."
200+
)
201+
@ModelAttribute("addresses")
202+
@RequestMapping(value = "/addresses", method = GET, params = { "query" })
203+
public List<AddressDto> getAddresses(@RequestParam("query") String query) {
204+
205+
return addressDtoService.getAddressesByQuery(query);
206+
}
191207
}

src/main/java/net/contargo/iris/address/dto/AddressDtoService.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ public interface AddressDtoService {
4646

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

5959
/**
6060
* Resolves an address (described by the given parameters) to a {@link java.util.List} of
61-
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses multiple
62-
* fallback strategies to find addresses if not all parameters are provided
61+
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses
62+
* multiple fallback strategies to find addresses if not all parameters are provided
6363
*
6464
* @param addressDetails The parameters describing the addresses we are looking for
6565
*
@@ -86,4 +86,14 @@ public interface AddressDtoService {
8686
* @return the {@link AddressDto} with the given hashKey
8787
*/
8888
AddressDto getAddressesByHashKey(String hashKey);
89+
90+
91+
/**
92+
* Returns a list of addresses matching the query.
93+
*
94+
* @param query the address query
95+
*
96+
* @return a list of matching addresses
97+
*/
98+
List<AddressDto> getAddressesByQuery(String query);
8999
}

src/main/java/net/contargo/iris/address/dto/AddressDtoServiceImpl.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import java.util.ArrayList;
99
import java.util.List;
1010
import java.util.Map;
11-
import java.util.stream.Collectors;
1211

1312
import static java.util.Collections.singletonList;
13+
import static java.util.stream.Collectors.toList;
1414

1515

1616
/**
@@ -64,7 +64,7 @@ public List<AddressListDto> getAddressesByDetails(Map<String, String> addressDet
6464
return addressServiceWrapper.getAddressesByDetails(addressDetails)
6565
.stream()
6666
.map(AddressListDto::new)
67-
.collect(Collectors.toList());
67+
.collect(toList());
6868
}
6969

7070

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

88-
return addressService.getAddressesWherePlaceIsIn(placeId)
89-
.stream()
90-
.map(AddressDto::new)
91-
.collect(Collectors.toList());
88+
return addressService.getAddressesWherePlaceIsIn(placeId).stream().map(AddressDto::new).collect(toList());
9289
}
9390

9491

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

9895
return new AddressDto(addressServiceWrapper.getByHashKey(hashKey));
9996
}
97+
98+
99+
@Override
100+
public List<AddressDto> getAddressesByQuery(String query) {
101+
102+
return addressServiceWrapper.getAddressesByQuery(query).stream().map(AddressDto::new).collect(toList());
103+
}
100104
}

src/main/java/net/contargo/iris/address/nominatim/service/AddressService.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
* @author Sven Mueller - mueller@synyx.de
1515
* @author Aljona Murygina - murygina@synyx.de
1616
* @author Arnold Franke - franke@synyx.de
17+
* @author Sandra Thieme - thieme@synyx.de
18+
* @author Ben Antony - antony@synyx.de
1719
*/
1820
public interface AddressService {
1921

2022
/**
2123
* Resolves an address (described by the given parameters) to a {@link java.util.List} of
22-
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses multiple
23-
* fallback strategies to find addresses if not all parameters are provided
24+
* {@link net.contargo.iris.address.Address} objects with the attributes name, latitude and longitude. Uses
25+
* multiple fallback strategies to find addresses if not all parameters are provided
2426
*
2527
* @param addressDetails @return
2628
*/
@@ -51,4 +53,14 @@ public interface AddressService {
5153
* @return The address for the given geolocation.
5254
*/
5355
Address getAddressByGeolocation(GeoLocation location);
56+
57+
58+
/**
59+
* Returns a list of addresses matching the query.
60+
*
61+
* @param query the address query
62+
*
63+
* @return a list of matching addresses
64+
*/
65+
List<Address> getAddressesByQuery(String query);
5466
}

src/main/java/net/contargo/iris/address/nominatim/service/NominatimAddressService.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ public Address getAddressByGeolocation(GeoLocation geoLocation) {
120120
}
121121

122122

123+
@Override
124+
public List<Address> getAddressesByQuery(String query) {
125+
126+
String url = nominatimUrlBuilder.buildSearchUrl(query);
127+
128+
return nominatimResponder.getAddresses(url);
129+
}
130+
131+
123132
private List<Address> searchSuburbsViaNominatimsDetailPage(Long osmPlaceId, SuburbType suburbType,
124133
Set<String> suburbGlobalDisplayNames) {
125134

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

192201

193-
private String[][] createResolvingStrategies(String postalCode, String city, String country, String name,
202+
private static String[][] createResolvingStrategies(String postalCode, String city, String country, String name,
194203
String internStreet) {
195204

196205
return new String[][] {

src/main/java/net/contargo/iris/address/nominatim/service/NominatimUrlBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,10 @@ String buildUrl(GeoLocation geoLocation) {
174174

175175
return url;
176176
}
177+
178+
179+
public String buildSearchUrl(String query) {
180+
181+
return baseUrl + "search/" + query + "?format=json&addressdetails=1";
182+
}
177183
}

src/main/java/net/contargo/iris/address/service/AddressServiceWrapper.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.contargo.iris.address.AddressList;
66
import net.contargo.iris.address.nominatim.service.AddressService;
77
import net.contargo.iris.address.staticsearch.StaticAddress;
8+
import net.contargo.iris.address.staticsearch.service.StaticAddressNotFoundException;
89
import net.contargo.iris.address.staticsearch.service.StaticAddressService;
910
import net.contargo.iris.normalizer.NormalizerService;
1011

@@ -14,16 +15,19 @@
1415
import org.slf4j.LoggerFactory;
1516

1617
import java.util.ArrayList;
18+
import java.util.Collection;
1719
import java.util.Collections;
1820
import java.util.List;
1921
import java.util.Map;
22+
import java.util.regex.Pattern;
2023

2124
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.CITY;
2225
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.COUNTRY;
2326
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.POSTAL_CODE;
2427
import static net.contargo.iris.address.nominatim.service.AddressDetailKey.STREET;
2528

2629
import static java.util.Collections.singletonList;
30+
import static java.util.stream.Collectors.toList;
2731

2832

2933
/**
@@ -36,6 +40,7 @@
3640
public class AddressServiceWrapper {
3741

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

4045
private final AddressService addressService;
4146
private final StaticAddressService staticAddressService;
@@ -175,7 +180,7 @@ private List<AddressList> resolveByNominatim(Map<String, String> addressDetails)
175180
}
176181

177182

178-
private List<AddressList> getSimpleAddressList(List<Address> addresses) {
183+
private static List<AddressList> getSimpleAddressList(List<Address> addresses) {
179184

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

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

190195
return addressListList;
191196
}
197+
198+
199+
@SuppressWarnings("squid:S1166")
200+
public List<Address> getAddressesByQuery(String query) {
201+
202+
List<Address> addresses = new ArrayList<>();
203+
204+
if (HASHKEY_MATCHER.matcher(query).matches()) {
205+
try {
206+
addresses.add(getByHashKey(query));
207+
} catch (StaticAddressNotFoundException e) {
208+
// ignoring the exception as the query could be resolved by nominatim
209+
}
210+
}
211+
212+
if (addresses.isEmpty()) {
213+
addresses.addAll(addressService.getAddressesByQuery(query));
214+
215+
List<Address> matchingStaticAddresses = addresses.stream()
216+
.map(a ->
217+
staticAddressService.findAddresses(a.getPostcode(), a.getCity(), a.getCountryCode())
218+
.getAddresses())
219+
.flatMap(Collection::stream)
220+
.distinct()
221+
.collect(toList());
222+
223+
addresses.addAll(matchingStaticAddresses);
224+
}
225+
226+
return addresses;
227+
}
192228
}

src/test/java/net/contargo/iris/address/api/AddressApiControllerMvcUnitTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
* MVC Unit test of {@link AddressApiController}.
5959
*
6060
* @author Arnold Franke - franke@synyx.de
61+
* @author Sandra Thieme - thieme@synyx.de
62+
* @author Ben Antony - antony@synyx.de
6163
*/
6264
@RunWith(SpringJUnit4ClassRunner.class)
6365
@ContextConfiguration(locations = { "classpath:public-api-context.xml" })
@@ -209,4 +211,20 @@ public void testAddressByPlaceId() throws Exception {
209211
.andExpect(content().contentType("application/json"))
210212
.andExpect(jsonPath("$.addresses[0].displayName", is("76137 Karlsruhe")));
211213
}
214+
215+
216+
@Test
217+
public void getAddresses() throws Exception {
218+
219+
Address address = new Address();
220+
address.setDisplayName("Gartenstr. 67, Karlsruhe (Südweststadt)");
221+
222+
when(addressDtoServiceMock.getAddressesByQuery("Gartenstraße 67, Karlsruhe")).thenReturn(singletonList(
223+
new AddressDto(address)));
224+
225+
mockMvc.perform(get("/addresses").param("query", "Gartenstraße 67, Karlsruhe"))
226+
.andExpect(status().isOk())
227+
.andExpect(jsonPath("$.addresses", hasSize(1)))
228+
.andExpect(jsonPath("$.addresses[0].displayName", is("Gartenstr. 67, Karlsruhe (Südweststadt)")));
229+
}
212230
}

src/test/java/net/contargo/iris/address/dto/AddressDtoServiceImplUnitTest.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import static org.hamcrest.MatcherAssert.assertThat;
2525

26+
import static org.hamcrest.Matchers.hasSize;
2627
import static org.hamcrest.Matchers.is;
2728
import static org.hamcrest.Matchers.nullValue;
2829

@@ -45,16 +46,17 @@ public class AddressDtoServiceImplUnitTest {
4546
private static final int OSM_ID = 1;
4647
private static final GeoLocation GEOLOCATION = new GeoLocation(BigDecimal.ONE, BigDecimal.ONE);
4748
private static final Long PLACE_ID = 1L;
49+
4850
private final AddressService addressServiceMock = mock(AddressService.class);
4951
private final AddressServiceWrapper addressServiceWrapperMock = mock(AddressServiceWrapper.class);
5052
private final AddressDtoServiceImpl sut = new AddressDtoServiceImpl(addressServiceMock, addressServiceWrapperMock);
51-
Address address = new Address(BigDecimal.ONE, BigDecimal.ONE);
52-
private Map<String, String> addressDetails;
53+
54+
private final Address address = new Address(BigDecimal.ONE, BigDecimal.ONE);
55+
private final Map<String, String> addressDetails = new HashMap<>();
5356

5457
@Before
55-
public void setUp() throws Exception {
58+
public void setUp() {
5659

57-
addressDetails = new HashMap<>();
5860
addressDetails.put(CITY.getKey(), "city");
5961
addressDetails.put(STREET.getKey(), "street");
6062
addressDetails.put(POSTAL_CODE.getKey(), "postalcode");
@@ -175,4 +177,19 @@ public void getAddressesByHashKey() {
175177
AddressDto addressDto = sut.getAddressesByHashKey(hashKey);
176178
assertThat(addressDto.getDisplayName(), is(displayName));
177179
}
180+
181+
182+
@Test
183+
public void getAddressesByQuery() {
184+
185+
address.setDisplayName("Gartenstr. 67, Karlsruhe (Südweststadt)");
186+
187+
when(addressServiceWrapperMock.getAddressesByQuery("Gartenstraße 67, Karlsruhe")).thenReturn(singletonList(
188+
address));
189+
190+
List<AddressDto> addresses = sut.getAddressesByQuery("Gartenstraße 67, Karlsruhe");
191+
192+
assertThat(addresses, hasSize(1));
193+
assertThat(addresses.get(0).getDisplayName(), is("Gartenstr. 67, Karlsruhe (Südweststadt)"));
194+
}
178195
}

0 commit comments

Comments
 (0)