package me.osm.gazetteer.web.imp; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import java.util.Set; import me.osm.gazetteer.web.ESNodeHolder; import me.osm.gazetteer.web.utils.FileUtils; import me.osm.gazetteer.web.utils.FileUtils.LineHandler; import me.osm.gazetteer.web.utils.OSMDocSinglton; import me.osm.osmdoc.model.Tag.TagValueType; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; import org.elasticsearch.client.AdminClient; import org.elasticsearch.client.IndicesAdminClient; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.LoggerFactory; public class IndexHolder { public static final String POI_CLASS = "poi_class"; public static final String LOCATION = "location"; public static void dropIndex() { IndicesAdminClient indices = ESNodeHolder.getClient().admin().indices(); if(indices.exists(new IndicesExistsRequest("gazetteer")).actionGet().isExists()) { indices.delete(new DeleteIndexRequest("gazetteer")).actionGet(); } } public static void createIndex() { AdminClient admin = ESNodeHolder.getClient().admin(); JSONObject settings = readJSON("/gazetteer_schema.json"); settings.getJSONObject("mappings").put(LOCATION, readJSON("/mappings/location.json")); JSONObject moreTagsProperties = new JSONObject(); for(Entry<String, String> e : OSMDocSinglton.get().getFacade().listMoreTagsTypes().entrySet()) { moreTagsProperties.put(e.getKey(), getPropertyMapping(e.getValue())); } settings.getJSONObject("mappings").getJSONObject(LOCATION) .getJSONObject("properties").getJSONObject("more_tags").put("properties", moreTagsProperties); settings.getJSONObject("mappings").put(POI_CLASS, readJSON("/mappings/poi_class.json")); JSONObject indexSettings = settings.getJSONObject("settings"); addSynonyms(indexSettings); CreateIndexRequestBuilder request = admin.indices().prepareCreate("gazetteer") .setSettings(indexSettings.toString()) .addMapping(LOCATION, settings.getJSONObject("mappings").getJSONObject(LOCATION).toString()) .addMapping(POI_CLASS, settings.getJSONObject("mappings").getJSONObject(POI_CLASS).toString()); LoggerFactory.getLogger(IndexHolder.class).info("Update mappings"); request.get(); } @SuppressWarnings("unchecked") public static List<String[]> getCharFilterReplaces() { List<String[]> res = new ArrayList<>(); JSONObject mapping = readJSON("/gazetteer_schema.json"); JSONObject charFilter = mapping.getJSONObject("settings").getJSONObject("analysis").optJSONObject("char_filter"); if(charFilter != null) { for(String k : (Set<String>)charFilter.keySet()) { JSONObject filter = charFilter.getJSONObject(k); if("mapping".equals(filter.optString("type"))){ JSONArray mappings = filter.getJSONArray("mappings"); for(int i = 0; i < mappings.length(); i++ ) { String fDef = mappings.getString(i); String[] split = StringUtils.splitByWholeSeparator(fDef, "=>"); if(split.length == 2) { res.add(split); } } } } } return res; } private static JSONObject getPropertyMapping(String value) { JSONObject result = new JSONObject(); switch (TagValueType.valueOf(value)) { case BOOLEAN: result.put("type", "boolean"); break; case DATE: result.put("type", "date"); break; case NUMBER: result.put("type", "double"); break; case OPEN_HOURS: result.put("type", "object"); result.put("index", "not_analyzed"); break; case URL: result.put("type", "string"); result.put("index", "not_analyzed"); break; case PHONE: result.put("type", "string"); result.put("index", "not_analyzed"); break; case WIKI: result.put("type", "string"); result.put("index", "not_analyzed"); break; case ENUM: result.put("type", "string"); result.put("index", "not_analyzed"); break; default: result.put("type", "string"); result.put("index", "not_analyzed"); break; } return result; } private static JSONObject readJSON(String resource) { try { return new JSONObject(IOUtils.toString(IndexHolder.class.getResourceAsStream( resource))); } catch (Exception e) { throw new RuntimeException("couldn't read index settings", e); } } private static void addSynonyms(JSONObject indexSettings) { final JSONArray synonims = fillFormResources(); File confSynonims = new File("config/synonims/"); if(confSynonims.exists()) { for(File f : confSynonims.listFiles()) { if(f.getName().endsWith(".syn") && f.isFile()) { fillFormFile(f, synonims); } } } indexSettings.getJSONObject("analysis").getJSONObject("filter") .getJSONObject("synonym_filter").put("synonyms", synonims); } private static void fillFormFile(File f, final JSONArray synonims) { FileUtils.handleLines(f, new LineHandler() { @Override public void handle(String s) { if(!s.startsWith("#")) { synonims.put(s); } } }); } private static JSONArray fillFormResources() { final JSONArray synonims = new JSONArray(); FileUtils.handleLines(IndexHolder.class.getResourceAsStream("/synonims"), new LineHandler() { @Override public void handle(String s) { if(!s.startsWith("#")) { synonims.put(s); } } }); return synonims; } }