package com.transformuk.bdt.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.transformuk.bdt.mapit.domain.Entity;
import com.transformuk.bdt.mapit.domain.MapItPartialPostCode;
import com.transformuk.bdt.mapit.domain.MapItPointResponse;
import com.transformuk.bdt.mapit.domain.MapItPostCode;
import com.transformuk.bdt.util.MapItCouncilCodes;
import com.transformuk.bdt.util.StaticReferences;
@Service
@Configuration
@PropertySource(value = "classpath:conf.properties")
public class MapItServiceImpl implements IMapItService {
private static final String COMMA = ",";
@Autowired
CustomObjectMapper mapper;
@Autowired
MapItClientService mapItClient;
@Value("${mapit.postcode.api.url}")
private String mapItApiUrl;
@Value("${mapit.partial.postcode.api.url}")
private String mapItPartialApiUrl;
@Value("${mapit.point.api.url}")
private String mapItPointApiUrl;
private static final Logger logger = Logger.getLogger(MapItServiceImpl.class);
@Override
public ResponseEntity<String> getMapItDataForFullPostCode(String postCode) {
logger.debug("Calling Mapit url full code: "+mapItApiUrl+" with postcode:"+postCode);
return mapItClient.callMapIt(mapItApiUrl, postCode);
}
@Override
public ResponseEntity<String> getMapItDataForPartialPostCode(String postCode) {
logger.debug("Calling Mapit url partial code: "+mapItApiUrl+" with postcode:"+postCode);
return mapItClient.callMapIt(mapItPartialApiUrl, postCode);
}
@Override
public ResponseEntity<String> getMapItPointDataForPartialPostCode(String easting, String northing) {
//custom url
StringBuilder url = new StringBuilder();
url.append(mapItPointApiUrl).append(easting).append(COMMA).append(northing);
return mapItClient.callMapIt(url.toString());
}
/**
* Fetches values for partial post code
* @param json response from mapit post code
* @return MapItPostCode containing the easting and northing values
*/
@Override
public MapItPartialPostCode convertDataFromPartialPostCode(String jsonResponse)
throws JsonParseException, JsonMappingException, IOException {
return mapper.readValue(jsonResponse, MapItPartialPostCode.class);
}
/**
* Fetches point values based on easting and northing of a partial post code
* @param json response from mapit post code
* @return ResponseEntity containing json response with gss list, name etc.
*/
@Override
public ResponseEntity<String> getDataFromPointApi(MapItPartialPostCode mapItResponse)
throws JsonParseException, JsonMappingException, IOException {
String easting = mapItResponse.getEasting().toString();
String northing = mapItResponse.getNorthing().toString();
return getMapItPointDataForPartialPostCode(easting, northing);
}
/**
* Returns a map of: all not null gss, name i.e. location (for EUR) list
* and councilList for a given json input
* @param isPartialPostCode
* @param json response from mapit
* @return Map containing gss list, name i.e. location for eur and council
*/
@Override
public Map<String, List<String>> getGssNamesFromPostCodeResponse(
String jsonResponse, boolean isPartialPostCode)
throws JsonParseException, JsonMappingException, IOException {
List<Entity> entities = null;
if (isPartialPostCode) {
//for point api partial post code there are no areas direct entities
MapItPointResponse mapItPostCodeResponse = mapper.readValue(jsonResponse, MapItPointResponse.class);
entities = mapItPostCodeResponse.getEntityList();
} else {
MapItPostCode mapItPostCodeResponse = mapper.readValue(jsonResponse, MapItPostCode.class);
entities = mapItPostCodeResponse.getAreas().getEntityList();
}
List<Entity> entityList = new ArrayList<Entity>();
for (Entity item : entities) {
//dynamic mapping
entityList.add(mapper.convertValue(item, Entity.class));
}
//holds all not null gss codes returned from mapit
List<String> gssList = new ArrayList<String>();
//holds the 'name' list if the type is EUR
//(special case as the name from EUR will be used as 'location' for search query
List<String> eurNameList = new ArrayList<String>();
//holds the country name if the type is EUR
List<String> eurCountryNameList = new ArrayList<String>();
//holds the code for council
List<String> councilCodeList = new ArrayList<String>();
for (Entity item : entityList) {
if (item.getCodes().getGss() != null) {
//only add gss's which are not null
gssList.add(item.getCodes().getGss());
}
//if the type is eur then save its name
String type = item.getType();
//should only contain one EUR element
if (StringUtils.equalsIgnoreCase(type, StaticReferences.EUR)) {
eurNameList.add(item.getName());
eurCountryNameList.add(item.getCountryName());
}
else if (containsCouncilCode(type)){
councilCodeList.add(item.getName());
}
}
Map<String, List<String>> gssNameMap = new HashMap<String, List<String>>();
gssNameMap.put(StaticReferences.GSS, gssList);
gssNameMap.put(StaticReferences.NAMES, eurNameList);
gssNameMap.put(StaticReferences.COUNTRY_NAME, eurCountryNameList);
gssNameMap.put(StaticReferences.COUNCIL_CODE, councilCodeList);
if (logger.isDebugEnabled()) {
logger.debug("Found "+gssList.size()+" GSS codes"+" and "+eurNameList.size()+" Names for EUR");
}
return gssNameMap;
}
@SuppressWarnings("unused")
private boolean containsCouncilCode(String type) {
MapItCouncilCodes councilCode;
try {
councilCode = MapItCouncilCodes.valueOf(type.toUpperCase());
return true;
} catch (IllegalArgumentException ex) {
return false;
}
// for (MapItCouncilCodes councilCode : MapItCouncilCodes.values()) {
// if (StringUtils.equalsIgnoreCase(councilCode.name(),type)) {
// return true;
// }
// }
//
// return false;
}
}