You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/05/06 10:05:32 UTC

camel git commit: CAMEL-9273: More options to weather. Thanks to Arno Noordover for the patch.

Repository: camel
Updated Branches:
  refs/heads/master 31e2df5e7 -> 426922a26


CAMEL-9273: More options to weather. Thanks to Arno Noordover for the patch.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/426922a2
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/426922a2
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/426922a2

Branch: refs/heads/master
Commit: 426922a2607420ba0175da27145d520e80120291
Parents: 31e2df5
Author: Claus Ibsen <da...@apache.org>
Authored: Fri May 6 12:05:04 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri May 6 12:05:04 2016 +0200

----------------------------------------------------------------------
 components/camel-weather/readme.MD              |  27 ++++
 .../component/weather/WeatherConfiguration.java |  98 ++++++++-------
 .../component/weather/WeatherLanguage.java      |  46 +++++++
 .../camel/component/weather/WeatherQuery.java   | 125 +++++++++++++++++++
 .../weather/CurrentWeatherConsumerTest.java     |  11 +-
 .../src/test/resources/log4j.properties         |   2 +-
 6 files changed, 262 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/426922a2/components/camel-weather/readme.MD
----------------------------------------------------------------------
diff --git a/components/camel-weather/readme.MD b/components/camel-weather/readme.MD
new file mode 100644
index 0000000..0c680f6
--- /dev/null
+++ b/components/camel-weather/readme.MD
@@ -0,0 +1,27 @@
+#Description of Weather API
+
+##Types of queries
+
+There are five type of queries:
+
+1. current weather (contexts weather, group, find and box/city);
+2. forecast (5 days per 3 hours, context forecast)
+3. forecast/daily (context forecast/daily); you must provide cnt parameter
+4. history (context history/city and maybe also history/station)
+5. station (contexts station, box/station and station/find)
+
+##Locations
+
+1. by name of the city and the country code (q={city name},{country code})
+2. by id of the city (id={city ID}); The current weather can also be
+asked for a group of id's using the context group
+3. by latitude and longtitude (lat={lat}&lon={lon})
+4. by box (bbox=12,32,15,37,10), you must also provide cluster=yes/no; context
+must be box/city or box/station
+5. find cities/station around location defined by lat/lon; context
+must be find or station/find. You must provide a cnt parameter.
+
+
+##Note
+The history by station isn't documented at the OpenWeather website but
+is mentioned in the issue
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/426922a2/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherConfiguration.java b/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherConfiguration.java
index 4dc2dba..f4da1b9 100644
--- a/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherConfiguration.java
+++ b/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherConfiguration.java
@@ -16,19 +16,16 @@
  */
 package org.apache.camel.component.weather;
 
-import java.net.URL;
 import java.util.Scanner;
 
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriParams;
 import org.apache.camel.spi.UriPath;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.ObjectMapper;
 
+import static org.apache.camel.component.weather.WeatherLanguage.en;
 import static org.apache.camel.component.weather.WeatherMode.JSON;
 import static org.apache.camel.component.weather.WeatherUnits.METRIC;
-import static org.apache.camel.util.ObjectHelper.isEmpty;
 import static org.apache.camel.util.ObjectHelper.notNull;
 
 @UriParams
@@ -47,11 +44,19 @@ public class WeatherConfiguration {
     @UriParam
     private String lon;
     @UriParam
+    private String rightLon;
+    @UriParam
+    private String topLat;
+    @UriParam
+    private Integer zoom;
+    @UriParam
     private String period = "";
     @UriParam(defaultValue = "JSON")
     private WeatherMode mode = JSON;
     @UriParam(defaultValue = "METRIC")
     private WeatherUnits units = METRIC;
+    @UriParam(defaultValue = "en")
+    private WeatherLanguage language = en;
     @UriParam
     private String headerName;
 
@@ -142,6 +147,7 @@ public class WeatherConfiguration {
 
     /**
      * Latitude of location. You can use lat and lon options instead of location.
+     * For boxed queries this is the bottom latitude.
      */
     public void setLat(String lat) {
         this.lat = lat;
@@ -153,6 +159,7 @@ public class WeatherConfiguration {
 
     /**
      * Longitude of location. You can use lat and lon options instead of location.
+     * For boxed queries this is the left longtitude.
      */
     public void setLon(String lon) {
         this.lon = lon;
@@ -169,57 +176,58 @@ public class WeatherConfiguration {
         return appid;
     }
 
+    String getQuery() throws Exception {
+        return new WeatherQuery(this.component, this).getQuery();
+    }
 
-    public String getQuery() throws Exception {
-        return getQuery(getLocation());
+    String getQuery(String location) throws Exception {
+        return new WeatherQuery(this.component, this).getQuery(location);
     }
 
-    public String getQuery(String location) throws Exception {
-        String answer = "http://api.openweathermap.org/data/2.5/";
+    public WeatherLanguage getLanguage() {
+        return language;
+    }
 
-        if (lat != null && lon != null) {
-            location = "lat=" + lat + "&lon=" + lon;
-        } else if (isEmpty(location) || "current".equals(location)) {
-            location = getCurrentGeoLocation();
-        } else {
-            // assuming the location is a town or country
-            location = "q=" + location;
-        }
-        
-        if (isEmpty(getPeriod())) {
-            answer += "weather?" + location;
-        } else {
-            answer += "forecast/daily?" + location + "&cnt=" + getPeriod();
-        }
+    /**
+     * Language of the response.
+     */
+    public void setLanguage(WeatherLanguage language) {
+        this.language = language;
+    }
 
-        // append the desired measurement unit if not the default (which is metric)
-        if (getUnits() != METRIC) {
-            answer += "&units=" + getUnits().name().toLowerCase();
-        }
+    public String getRightLon() {
+        return rightLon;
+    }
 
-        // append the desired output mode if not the default (which is json)
-        if (getMode() != JSON) {
-            answer += "&mode=" + getMode().name().toLowerCase();
-        }
+    /**
+     * For boxed queries this is the right longtitude. Needs to be used
+     * in combination with topLat and zoom.
+     */
+    public void setRightLon(String rightLon) {
+        this.rightLon = rightLon;
+    }
 
-        if (getAppid() != null) {
-            answer += "&APPID=" + getAppid();
-        }
-        
-        return answer;
+    public String getTopLat() {
+        return topLat;
     }
 
-    private String getCurrentGeoLocation() throws Exception {
-        String geoLocation = component.getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, new URL("http://freegeoip.io/json/"));
-        if (isEmpty(geoLocation)) {
-            throw new IllegalStateException("Got the unexpected value '" + geoLocation + "' for the geolocation");
-        }
+    /**
+     * For boxed queries this is the top latitude. Needs to be used
+     * in combination with rightLon and zoom.
+     */
+    public void setTopLat(String topLat) {
+        this.topLat = topLat;
+    }
 
-        ObjectMapper mapper = new ObjectMapper();
-        JsonNode node = mapper.readValue(geoLocation, JsonNode.class);
-        JsonNode latitudeNode = notNull(node.get("latitude"), "latitude");
-        JsonNode longitudeNode = notNull(node.get("longitude"), "longitude");
+    public Integer getZoom() {
+        return zoom;
+    }
 
-        return "lat=" + latitudeNode + "&lon=" + longitudeNode;
+    /**
+     * For boxed queries this is the zoom. Needs to be used
+     * in combination with rightLon and topLat.
+     */
+    public void setZoom(Integer zoom) {
+        this.zoom = zoom;
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/426922a2/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherLanguage.java
----------------------------------------------------------------------
diff --git a/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherLanguage.java b/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherLanguage.java
new file mode 100644
index 0000000..ec4f35f
--- /dev/null
+++ b/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherLanguage.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.weather;
+
+/**
+ * All available languages for the weather API.
+ */
+public enum WeatherLanguage {
+    en,
+    ru,
+    it,
+    es,
+    sp,
+    uk,
+    ua,
+    de,
+    pt,
+    ro,
+    pl,
+    fi,
+    nl,
+    fr,
+    bg,
+    sv,
+    se,
+    zh_tw,
+    zh,
+    zh_cn,
+    tr,
+    hr,
+    ca;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/426922a2/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherQuery.java
----------------------------------------------------------------------
diff --git a/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherQuery.java b/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherQuery.java
new file mode 100644
index 0000000..bf6edb4
--- /dev/null
+++ b/components/camel-weather/src/main/java/org/apache/camel/component/weather/WeatherQuery.java
@@ -0,0 +1,125 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.weather;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import static org.apache.camel.component.weather.WeatherMode.JSON;
+import static org.apache.camel.component.weather.WeatherUnits.METRIC;
+import static org.apache.camel.util.ObjectHelper.isEmpty;
+import static org.apache.camel.util.ObjectHelper.notNull;
+
+/**
+ * Logic for determining the query based on the provided
+ * configuration.
+ */
+public class WeatherQuery {
+    private final WeatherConfiguration weatherConfiguration;
+    private final WeatherComponent component;
+
+    public WeatherQuery(WeatherComponent component, WeatherConfiguration weatherConfiguration) {
+        this.component = component;
+        this.weatherConfiguration = weatherConfiguration;
+    }
+
+    public String getQuery() throws Exception {
+        return getQuery(weatherConfiguration.getLocation());
+    }
+
+    public String getQuery(String location) throws Exception {
+        String answer = "http://api.openweathermap.org/data/2.5/";
+
+        if (weatherConfiguration.getLat() != null && weatherConfiguration.getLon() != null
+                && weatherConfiguration.getRightLon() == null && weatherConfiguration.getTopLat() == null) {
+            location = "lat=" + weatherConfiguration.getLat() + "&lon=" + weatherConfiguration.getLon();
+        } else if (weatherConfiguration.getLat() != null && weatherConfiguration.getLon() != null
+                && weatherConfiguration.getRightLon() != null && weatherConfiguration.getTopLat() != null) {
+            location = "bbox=" + weatherConfiguration.getLon() + ","
+                    + weatherConfiguration.getLat() + ","
+                    + weatherConfiguration.getRightLon() + ","
+                    + weatherConfiguration.getTopLat() + ","
+                    + weatherConfiguration.getZoom() + "&cluster=yes";
+        } else if (isEmpty(location) || "current".equals(location)) {
+            location = getCurrentGeoLocation();
+        } else {
+            // assuming the location is a town or country
+            location = "q=" + location;
+        }
+
+        location = location + "&lang=" + weatherConfiguration.getLanguage();
+
+        if (weatherConfiguration.getTopLat() != null && weatherConfiguration.getRightLon() != null) {
+            answer += "box?" + location;
+        } else if (isEmpty(weatherConfiguration.getPeriod())) {
+            answer += "weather?" + location;
+        } else {
+            answer += "forecast/daily?" + location + "&cnt=" + weatherConfiguration.getPeriod();
+        }
+
+        // append the desired measurement unit if not the default (which is metric)
+        if (weatherConfiguration.getUnits() != METRIC) {
+            answer += "&units=" + weatherConfiguration.getUnits().name().toLowerCase();
+        }
+
+        // append the desired output mode if not the default (which is json)
+        if (weatherConfiguration.getMode() != JSON) {
+            answer += "&mode=" + weatherConfiguration.getMode().name().toLowerCase();
+        }
+
+        if (weatherConfiguration.getAppid() != null) {
+            answer += "&APPID=" + weatherConfiguration.getAppid();
+        }
+
+        return answer;
+
+    }
+
+    /**
+     * TODO: shouldn't this method be moved to a class of its own perhaps with an interface
+     * that gets injected. For testing purposes you can inject your own version when testing this
+     * class.
+     */
+
+    String getCurrentGeoLocation() throws Exception {
+        HttpClient httpClient = new HttpClient();
+        GetMethod getMethod = new GetMethod("http://freegeoip.io/json/");
+        try {
+            int statusCode = httpClient.executeMethod(getMethod);
+            if (statusCode != HttpStatus.SC_OK) {
+                throw new IllegalStateException("Got the unexpected http-status '" + getMethod.getStatusLine() + "' for the geolocation");
+            }
+            String geoLocation = component.getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, getMethod.getResponseBodyAsStream());
+            if (isEmpty(geoLocation)) {
+                throw new IllegalStateException("Got the unexpected value '" + geoLocation + "' for the geolocation");
+            }
+
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode node = mapper.readValue(geoLocation, JsonNode.class);
+            JsonNode latitudeNode = notNull(node.get("latitude"), "latitude");
+            JsonNode longitudeNode = notNull(node.get("longitude"), "longitude");
+
+            return "lat=" + latitudeNode + "&lon=" + longitudeNode;
+        } finally {
+            getMethod.releaseConnection();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/426922a2/components/camel-weather/src/test/java/org/apache/camel/component/weather/CurrentWeatherConsumerTest.java
----------------------------------------------------------------------
diff --git a/components/camel-weather/src/test/java/org/apache/camel/component/weather/CurrentWeatherConsumerTest.java b/components/camel-weather/src/test/java/org/apache/camel/component/weather/CurrentWeatherConsumerTest.java
index eceed0b..b1436ec 100644
--- a/components/camel-weather/src/test/java/org/apache/camel/component/weather/CurrentWeatherConsumerTest.java
+++ b/components/camel-weather/src/test/java/org/apache/camel/component/weather/CurrentWeatherConsumerTest.java
@@ -21,11 +21,20 @@ import org.apache.camel.builder.RouteBuilder;
 public class CurrentWeatherConsumerTest extends BaseWeatherConsumerTest {
 
     @Override
+    protected void checkWeatherContent(String weather) {
+        log.debug("The weather in {} format is {}{}", new Object[] {WeatherMode.XML, LS, weather});
+
+        //assertStringContains(weather, "<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+        assertStringContains(weather, "<coord");
+        assertStringContains(weather, "<temperature");
+    }
+
+    @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                from("weather:foo?appid=9162755b2efa555823cfe0451d7fff38").to("mock:result");
+                from("weather:foo?appid=9162755b2efa555823cfe0451d7fff38&lon=4&lat=52&rightLon=6&topLat=54").to("mock:result");
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/426922a2/components/camel-weather/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/components/camel-weather/src/test/resources/log4j.properties b/components/camel-weather/src/test/resources/log4j.properties
index 33efa4c..fb0280d 100644
--- a/components/camel-weather/src/test/resources/log4j.properties
+++ b/components/camel-weather/src/test/resources/log4j.properties
@@ -18,7 +18,7 @@
 #
 # The logging properties used for testing.
 #
-log4j.rootLogger=INFO, file
+log4j.rootLogger=DEBUG, file
 
 #log4j.logger.org.apache.camel=DEBUG
 #log4j.logger.org.apache.camel.component.weather=DEBUG