<commit_before>/**
 * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.smarthome.binding.yahooweather.discovery;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.URI;
import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.binding.yahooweather.YahooWeatherBindingConstants;
import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService;
import org.eclipse.smarthome.config.discovery.DiscoveryResult;
import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

/**
 * The {@link YahooWeatherDiscoveryService} is responsible for discovering a weather Thing
 * of the local city from the IP address
 * 
 * @author <NAME> - Initial contribution
 */

public class YahooWeatherDiscoveryService extends AbstractDiscoveryService {

	private static final Logger logger = LoggerFactory.getLogger(YahooWeatherDiscoveryService.class);

	public YahooWeatherDiscoveryService() {
		super(YahooWeatherBindingConstants.SUPPORTED_THING_TYPES_UIDS,10,false);
	}

	public Set<ThingTypeUID> getSupportedThingTypes() {
		return YahooWeatherBindingConstants.SUPPORTED_THING_TYPES_UIDS;
	}

	/**
	 * Download url content to a String
	 * @param url as String
	 * @return String with body
	 */
	private String downloadData(String urlString) {
		String downloadDataString = null;
		try {
			URL url = new URL(urlString);
			URLConnection connection = url.openConnection();
			downloadDataString = IOUtils.toString(connection.getInputStream());
		} catch (MalformedURLException e) {
			logger.debug("Constructed url '{}' is not valid: {}", urlString, e.getMessage());
		} catch (IOException e) {
			logger.error("Error accessing url '{}' : {} ",urlString, e.getMessage());
		}		

		return downloadDataString;
	}

	/**
	 * Retrieves an element from Json based on the path
	 * @param Json 
	 * @param path to find 
	 * @return JsonElement from the path 
	 */
	private static JsonElement getAtPath(JsonElement e, String path) {
		JsonElement current = e;
		String ss[] = path.split("/");
		for (int i = 0; i < ss.length; i++) {
			current = current.getAsJsonObject().get(ss[i]);
		}
		return current;
	}

	/**
	 * Retrieves the woeid (Where On Earth IDentifier) used for determining the location
	 * used in the Yahoo Weather interface
	 * @param Coordinate in form latitude,longitude as String
	 * @return Json text from woeid service as String 
	 */
	private String getWoeidData (String coordinate) {
		String query=  "SELECT * FROM geo.placefinder WHERE text='" + coordinate + "' and gflags='R'";
		String url =null;
		try{
			URI uri = new URI ("https://query.yahooapis.com/v1/public/yql",false);
			uri.setQuery ("q=" + query + "&format=json");
			url = uri.toString();
		} catch (Exception e) {
			logger.debug("Error while getting location ID: {}", e.getMessage());}
		return downloadData(url);
	}

	/**
	 * Retrieves the location based on the IP address
	 * 
	 * @return Json text as String with location data 
	 */
	private String getGeoFromIpData() {
		String url = "http://freegeoip.net/json/";
		return downloadData(url);
	}

	/**
	 * Discover the location and the woeid then submits the result
	 */
	private void discoverLocation(){
		String locationName = null;
		String locationWoeid = null;	
		try{
			JsonElement locationData =  new JsonParser().parse(getGeoFromIpData());
			locationName = getAtPath(locationData, "city").getAsString()+ ", " + getAtPath(locationData, "country_name").getAsString();
			String locationCoords = getAtPath(locationData, "latitude").getAsString()+ ", " + getAtPath(locationData, "longitude").getAsString();
			logger.debug ("Location from IP: '{}' coordinates: '{}'", locationName,locationCoords);

			JsonElement woeidData = new JsonParser().parse(getWoeidData (locationCoords));
			locationName = getAtPath(woeidData, "query/results/Result/city").getAsString() + ", " + getAtPath(woeidData, "query/results/Result/country").getAsString();
			locationWoeid = getAtPath(woeidData, "query/results/Result/woeid").getAsString();
			logger.debug ("Location from locationID: '{}' is: '{}'", locationWoeid,locationName);
		} catch (Exception e) {
			logger.debug("Error while getting location ID: {}", e.getMessage());}

		if (locationWoeid !=null){
			submitDiscoveryResults(locationName, locationWoeid);}
	}

	/**
	 * Submit the discovered location to the Smarthome inbox
	 * @param locationName
	 * @param locationWoeid
	 */
	private void submitDiscoveryResults(String locationName,
			String locationWoeid) {
		ThingUID uid = new ThingUID(YahooWeatherBindingConstants.THING_TYPE_WEATHER, locationWoeid );
		if(uid!=null) {
			Map<String, Object> properties = new HashMap<>(1);
			properties.put("location" ,locationWoeid);
			DiscoveryResult result = DiscoveryResultBuilder.create(uid)
					.withProperties(properties)
					.withLabel("Yahoo weather " + locationName)
					.build();
			thingDiscovered(result);
		}
	}

	@Override
	protected void activate() {
		super.activate();
		discoverLocation();
	}

	@Override
	protected void startScan() {
		discoverLocation();
	}

}    
<commit_msg>Update of Example for discovery - Discover local city weather (from ipaddress) based on recommendations of dnobel<commit_after>/**
 * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.smarthome.binding.yahooweather.discovery;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.URI;
import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.binding.yahooweather.YahooWeatherBindingConstants;
import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService;
import org.eclipse.smarthome.config.discovery.DiscoveryResult;
import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

/**
 * The {@link YahooWeatherDiscoveryService} is responsible for discovering a weather Thing
 * of the local city from the IP address
 * 
 * @author <NAME> - Initial contribution
 */

public class YahooWeatherDiscoveryService extends AbstractDiscoveryService {

	private static final Logger logger = LoggerFactory.getLogger(YahooWeatherDiscoveryService.class);

	public YahooWeatherDiscoveryService() {
		super(YahooWeatherBindingConstants.SUPPORTED_THING_TYPES_UIDS,10);
	}

	public Set<ThingTypeUID> getSupportedThingTypes() {
		return YahooWeatherBindingConstants.SUPPORTED_THING_TYPES_UIDS;
	}

	/**
	 * Download url content to a String
	 * @param url as String
	 * @return String with body
	 */
	private String downloadData(String urlString) {
		String downloadDataString = null;
		try {
			URL url = new URL(urlString);
			URLConnection connection = url.openConnection();
			downloadDataString = IOUtils.toString(connection.getInputStream());
		} catch (MalformedURLException e) {
			logger.debug("Constructed url '{}' is not valid: {}", urlString, e.getMessage());
		} catch (IOException e) {
			logger.error("Error accessing url '{}' : {} ",urlString, e.getMessage());
		}		

		return downloadDataString;
	}

	/**
	 * Retrieves an element from Json based on the path
	 * @param Json 
	 * @param path to find 
	 * @return JsonElement from the path 
	 */
	private static JsonElement getAtPath(JsonElement e, String path) {
		JsonElement current = e;
		String ss[] = path.split("/");
		for (int i = 0; i < ss.length; i++) {
			current = current.getAsJsonObject().get(ss[i]);
		}
		return current;
	}

	/**
	 * Retrieves the woeid (Where On Earth IDentifier) used for determining the location
	 * used in the Yahoo Weather interface
	 * @param Coordinate in form latitude,longitude as String
	 * @return Json text from woeid service as String 
	 */
	private String getWoeidData (String coordinate) {
		String query=  "SELECT * FROM geo.placefinder WHERE text='" + coordinate + "' and gflags='R'";
		String url =null;
		try{
			URI uri = new URI ("https://query.yahooapis.com/v1/public/yql",false);
			uri.setQuery ("q=" + query + "&format=json");
			url = uri.toString();
		} catch (Exception e) {
			logger.debug("Error while getting location ID: {}", e.getMessage());}
		return downloadData(url);
	}

	/**
	 * Retrieves the location based on the IP address
	 * 
	 * @return Json text as String with location data 
	 */
	private String getGeoFromIpData() {
		String url = "http://freegeoip.net/json/";
		return downloadData(url);
	}

	/**
	 * Discover the location and the woeid then submits the result
	 */
	private void discoverLocation(){
		String locationName = null;
		String locationWoeid = null;	
		try{
			JsonElement locationData =  new JsonParser().parse(getGeoFromIpData());
			locationName = getAtPath(locationData, "city").getAsString()+ ", " + getAtPath(locationData, "country_name").getAsString();
			String locationCoords = getAtPath(locationData, "latitude").getAsString()+ ", " + getAtPath(locationData, "longitude").getAsString();
			logger.debug ("Location from IP: '{}' coordinates: '{}'", locationName,locationCoords);

			JsonElement woeidData = new JsonParser().parse(getWoeidData (locationCoords));
			locationName = getAtPath(woeidData, "query/results/Result/city").getAsString() + ", " + getAtPath(woeidData, "query/results/Result/country").getAsString();
			locationWoeid = getAtPath(woeidData, "query/results/Result/woeid").getAsString();
			logger.debug ("Location from locationID: '{}' is: '{}'", locationWoeid,locationName);
		} catch (Exception e) {
			logger.debug("Error while getting location ID: {}", e.getMessage());}

		if (locationWoeid !=null){
			submitDiscoveryResults(locationName, locationWoeid);}
	}

	/**
	 * Submit the discovered location to the Smarthome inbox
	 * @param locationName
	 * @param locationWoeid
	 */
	private void submitDiscoveryResults(String locationName,
			String locationWoeid) {
		ThingUID uid = new ThingUID(YahooWeatherBindingConstants.THING_TYPE_WEATHER, locationWoeid );
		if(uid!=null) {
			Map<String, Object> properties = new HashMap<>(1);
			properties.put("location" ,locationWoeid);
			DiscoveryResult result = DiscoveryResultBuilder.create(uid)
					.withProperties(properties)
					.withLabel("Yahoo weather " + locationName)
					.build();
			thingDiscovered(result);
		}
	}

	@Override
	protected void startBackgroundDiscovery() {
		discoverLocation();
	}

	@Override
	protected void startScan() {
		discoverLocation();
	}

}    

{'fraction_non_alphanumeric': 0.11668975069252077, 'fraction_numerical': 0.0025969529085872575, 'mean_word_length': 4.71930693069307, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '24455', 'n_tokens_mistral': 3767, 'n_tokens_neox': 3462, 'n_words': 890}