//Dstl (c) Crown Copyright 2017 package uk.gov.dstl.baleen.resources; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.apache.uima.resource.ResourceInitializationException; import org.apache.uima.resource.ResourceSpecifier; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Strings; import uk.gov.dstl.baleen.uima.BaleenResource; /** * A shared resource that provides access to JSON and GeoJSON files pertaining to country information. * Presently only supports some basic functions, but can be extended in the future to allow for retrieval of more information from the JSON files. * * */ public class SharedCountryResource extends BaleenResource { private Map<String, String> demonyms = null; private Map<String, String> geoJson = null; private Map<String, String> countryNames = null; private static final String PROPERTIES = "properties"; @Override protected boolean doInitialize(ResourceSpecifier specifier, Map<String, Object> additionalParams) throws ResourceInitializationException{ ObjectMapper mapper = new ObjectMapper(); loadCountriesJson(mapper); loadCountriesGeoJson(mapper); return true; } private void loadCountriesJson(ObjectMapper mapper) throws ResourceInitializationException{ try( InputStream is = getClass().getResourceAsStream("countries/countries.json"); ){ JsonNode rootNode = mapper.readTree(is); Iterator<JsonNode> iter = rootNode.elements(); demonyms = new HashMap<>(); countryNames = new HashMap<>(); while(iter.hasNext()){ JsonNode node = iter.next(); String demonym = getProperty(node, "demonym").toLowerCase(); String cca3 = getProperty(node, "cca3").toUpperCase(); if(demonym.isEmpty() || cca3.isEmpty()){ getMonitor().warn("Empty demonym or country code found - entry will be skipped"); continue; } demonyms.put(demonym, cca3); for(String name : getNames(node.path("name"))){ countryNames.put(name, cca3); } } getMonitor().info("{} nationalities read", demonyms.size()); }catch(IOException ioe){ getMonitor().error("Unable to read nationalities from countries.json", ioe); throw new ResourceInitializationException(ioe); } } private void loadCountriesGeoJson(ObjectMapper mapper) throws ResourceInitializationException{ try( InputStream is = getClass().getResourceAsStream("countries/countries.geojson"); ){ JsonNode rootNode = mapper.readTree(is); Iterator<JsonNode> iter = rootNode.path("features").elements(); geoJson = new HashMap<>(); while(iter.hasNext()){ JsonNode node = iter.next(); if(!node.has(PROPERTIES)){ getMonitor().warn("No properties found for entry - entry will be skipped"); continue; } String cca3 = getProperty(node.path(PROPERTIES), "ISO_A3").toUpperCase(); String geojson = getProperty(node, "geometry"); if(geojson.isEmpty() || cca3.isEmpty()){ getMonitor().warn("Empty country code or GeoJSON found - entry will not have GeoJSON information"); }else if("-99".equals(cca3)){ getMonitor().warn("Generic country code -99 found - entry {} will not have GeoJSON information", getProperty(node.path(PROPERTIES), "ADMIN")); } else { geoJson.put(cca3, geojson); } } getMonitor().info("{} countries read", geoJson.size()); }catch(IOException ioe){ getMonitor().error("Unable to read countries from countries.geojson", ioe); throw new ResourceInitializationException(ioe); } } private String getProperty(JsonNode node, String propertyName){ if(node != null && node.has(propertyName)){ JsonNode property = node.get(propertyName); if(property == null){ return ""; }else if(property.isValueNode()){ return node.get(propertyName).asText().trim(); }else{ return node.get(propertyName).toString().trim(); } }else{ return ""; } } private List<String> getNames(JsonNode node){ List<String> names = new ArrayList<>(); names.addAll(node.findValuesAsText("common")); names.addAll(node.findValuesAsText("official")); return names.stream().filter(s -> !Strings.isNullOrEmpty(s)).collect(Collectors.toList()); } @Override protected void doDestroy() { demonyms = null; geoJson = null; } /** * Return a map of all demonyms to country codes * @return */ public Map<String, String> getDemonyms(){ return demonyms; } /** * Return the GeoJSON for a given country code * * @param countryCode * @return */ public String getGeoJson(String countryCode){ return geoJson.get(countryCode.toUpperCase().trim()); } /** * Returns a map of all the country names to country codes * * @return */ public Map<String, String> getCountryNames(){ return countryNames; } }