package me.osm.gazetteer.web.api; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import me.osm.gazetteer.web.Configuration; import me.osm.gazetteer.web.ESNodeHolder; import me.osm.gazetteer.web.GazetteerWeb; import me.osm.gazetteer.web.api.meta.Endpoint; import me.osm.gazetteer.web.api.renders.SitemapRender; import me.osm.gazetteer.web.api.renders.XMLSitemapRender; import me.osm.gazetteer.web.imp.IndexHolder; import org.apache.commons.lang3.StringUtils; import org.elasticsearch.action.count.CountResponse; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHitField; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.json.JSONObject; import org.restexpress.Request; import org.restexpress.Response; import org.restexpress.domain.metadata.UriMetadata; public class Sitemap implements DocumentedApi { private static final int pageSize = GazetteerWeb.config().getSiteMapMapgeSize(); private static final Pattern p = Pattern.compile(".*sitemap([0-9]+)\\.xml(\\.gz)?"); private static final Configuration config = GazetteerWeb.config(); public void read(Request req, Response res) { try { String path = req.getPath(); if(path.endsWith ("sitemap_index.xml")) { XMLSitemapRender render = new XMLSitemapRender(config); renderIndex(render); ChannelBuffer body = ChannelBuffers.wrappedBuffer(render.toString().getBytes("UTF-8")); res.setBody(body); res.setContentType("text/xml"); } else { Matcher matcher = p.matcher(path); if(matcher.matches()) { XMLSitemapRender render = new XMLSitemapRender(config); renderPage(Integer.valueOf(matcher.group(1)), render); ChannelBuffer body = ChannelBuffers.wrappedBuffer(render.toString().getBytes("UTF-8")); res.setBody(body); res.setContentType("text/xml"); } } } catch (Exception e) { res.setException(e); } } public static void renderPage(int page, SitemapRender render) throws UnsupportedEncodingException { Client client = ESNodeHolder.getClient(); SearchRequestBuilder searchQ = client.prepareSearch("gazetteer") .setTypes(IndexHolder.LOCATION) .addField("id") .addField("timestamp") .setQuery(QueryBuilders.termsQuery("type", config.listSiteMapTypes())) .setExplain(false); searchQ.setSize(pageSize); searchQ.setFrom(page * pageSize); SearchResponse searchResponse = searchQ.get(); render.pageBegin(); for(SearchHit hit : searchResponse.getHits().getHits()) { String id = hit.getId(); if(StringUtils.startsWith(id, "adrpnt") || StringUtils.startsWith(id, "poipnt") || StringUtils.startsWith(id, "hghway")) { id = StringUtils.substringBefore(id, "--"); } JSONObject obj = new JSONObject(); for(Map.Entry<String, SearchHitField> field : hit.getFields().entrySet()) { obj.put(field.getKey(), field.getValue().getValue().toString()); } render.feature(id, obj); } render.pageEnd(); } public static void renderIndex(SitemapRender render) throws UnsupportedEncodingException { Client client = ESNodeHolder.getClient(); CountResponse countResponse = client.prepareCount("gazetteer") .setTypes(IndexHolder.LOCATION) .setQuery(QueryBuilders.termsQuery("type", config.listSiteMapTypes())).get(); long count = countResponse.getCount(); render.indexBegin(); for(int i = 0; i <= count / pageSize; i++) { render.page(i); } render.indexEnd(); } @Override public Endpoint getMeta(UriMetadata uriMetadata) { Endpoint meta = new Endpoint(uriMetadata.getPattern(), "sitemap", "Generates sitemap and sitemap_index files."); return meta; } }