package controllers; import com.google.common.base.Strings; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.node.JsonNodeFactory; import org.codehaus.jackson.node.ObjectNode; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import play.cache.Cached; import play.libs.F; import play.libs.WS; import play.libs.XPath; import play.mvc.Controller; import play.mvc.Result; /** * @author sondre */ public class Yr extends Controller { public static final int CACHE_EXPIRATION_OBSERVATIONS = 10 * 60; public static final String YR_FORECAST_URL = "http://www.yr.no/sted/%1$s/%2$s/%3$s/%4$s/varsel.xml"; public static Result observations(final String country, final String county, final String municipality, final String place) { if(Strings.isNullOrEmpty(country) || Strings.isNullOrEmpty(county) || Strings.isNullOrEmpty(municipality) || Strings.isNullOrEmpty(place)) { return badRequest("Empty or illegal values provided"); } final F.Promise<JsonNode> weatherObservationPromise = WS.url(String.format(YR_FORECAST_URL, country, county, municipality, place)) .get() .map(new F.Function<WS.Response, JsonNode>() { @Override public JsonNode apply(WS.Response response) throws Throwable { final NodeList weatherStations = XPath.selectNodes("//weatherstation", response.asXml()); final Node stationXmlNode = weatherStations.item(0); final JsonNodeFactory jsonNodeFactory = JsonNodeFactory.instance; final ObjectNode stationJsonNode = jsonNodeFactory.objectNode(); stationJsonNode.put("id", stationXmlNode.getAttributes().getNamedItem("stno").getNodeValue()); stationJsonNode.put("name", stationXmlNode.getAttributes().getNamedItem("name").getNodeValue()); final ObjectNode positionNode = jsonNodeFactory.objectNode(); positionNode.put("longitude", Float.valueOf(XPath.selectText("//weatherstation/@lon", stationXmlNode)).floatValue()); positionNode.put("latitude", Float.valueOf(XPath.selectText("//weatherstation/@lat", stationXmlNode)).floatValue()); stationJsonNode.put("position", positionNode); final ObjectNode observationNode = jsonNodeFactory.objectNode(); observationNode.put("description", XPath.selectText("//symbol/@name", stationXmlNode)); observationNode.put("timestamp", XPath.selectText("//symbol/@time", stationXmlNode)); stationJsonNode.put("observation", observationNode); final ObjectNode temperatureNode = jsonNodeFactory.objectNode(); final NamedNodeMap temperatureElementAttributes = XPath.selectNode("//temperature", stationXmlNode).getAttributes(); temperatureNode.put("value", temperatureElementAttributes.getNamedItem("value").getNodeValue()); temperatureNode.put("unit", temperatureElementAttributes.getNamedItem("unit").getNodeValue()); temperatureNode.put("timestamp", XPath.selectText("//temperature/@time", stationXmlNode)); stationJsonNode.put("temperature", temperatureNode); return stationJsonNode; } }); return async(weatherObservationPromise.map(new F.Function<JsonNode, Result>() { @Override public Result apply(JsonNode jsonNode) throws Throwable { return ok(jsonNode); } })); } @Cached(key = "observationsBergen", duration = CACHE_EXPIRATION_OBSERVATIONS) public static Result observationsBergen() { return observations("Norge", "Hordaland", "Bergen", "Bergen"); } }