Java で Yahoo!ローカルサーチAPI をコールするサンプルコード

## ソースコード

```java
import java.io.*;
import java.net.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;

public class LocalSearch {

  public static void main(String[] args) {
    try {
      String appid = "YOUR APPLICATION ID";
      String query = "東京タワー";
      List<Properties> pois = new LocalSearch(appid).search(query);
      for (Properties p : pois) {
        System.out.println(p.getProperty("name"));
        System.out.println(" " + p.getProperty("lat") + ", " + p.getProperty("lon"));
        System.out.println();
      }
    } catch (Exception e) {
      System.out.println("ERROR: " + e.toString());
    }
  }

  private final String appid;

  public LocalSearch(String appid) {
    this.appid = appid;
  }

  private Document get(String url, Map<String, String> headers) throws Exception {

    URL urlObj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();

    // timeout
    con.setConnectTimeout(3 * 1000);
    con.setReadTimeout(3 * 1000);

    // HTTP method
    con.setRequestMethod("GET");

    // HTTP request headers
    for (Map.Entry<String, String> header : headers.entrySet()) {
      con.addRequestProperty(header.getKey(), header.getValue());
    }

    con.connect();

    InputStream is = con.getInputStream();
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
    is.close();

    return doc;
  }

  private List<Properties> xml2pois(Document doc) throws XPathExpressionException {

    List<Properties> result = new ArrayList<Properties>();

    XPath xpath = XPathFactory.newInstance().newXPath();
    NodeList features = (NodeList) xpath.evaluate("YDF/Feature", doc, XPathConstants.NODESET);
    for (int i = 0; i < features.getLength(); i++) {
      Node feature = features.item(i);
      String type = xpath.evaluate("Geometry/Type", feature);
      if (type.equals("point")) {
        String coordinates = xpath.evaluate("Geometry/Coordinates", feature);
        String[] ll = coordinates.split(",");
        Properties p = new Properties();
        p.setProperty("name", xpath.evaluate("Name", feature));
        p.setProperty("lat", ll[1]);
        p.setProperty("lon", ll[0]);
        result.add(p);
      }
    }
    return result;
  }

  private String encode(Map<String, String> params) throws UnsupportedEncodingException {
    String encoding = "UTF-8";
    List<String> list = new ArrayList<String>();
    for (Map.Entry<String, String> header : params.entrySet()) {
      String key = URLEncoder.encode(header.getKey(), encoding);
      String val = URLEncoder.encode(header.getValue(), encoding);
      list.add(key + "=" + val);
    }
    return String.join("&", list);
  }

  public List<Properties> search(String query) throws Exception {

    String baseURL = "https://map.yahooapis.jp/search/local/V1/localSearch";

    Map<String, String> params = new LinkedHashMap<String, String>();
    params.put("query", query);
    params.put("output", "xml");
    params.put("results", "3");
    params.put("sort", "score");

    String url = baseURL + "?" + encode(params);

    Map<String, String> headers = new LinkedHashMap<String, String>();
    headers.put("User-Agent", "Yahoo AppID: " + appid);

    Document doc = get(url, headers);
    return xml2pois(doc);
  }
}
```

## 実行結果

```
$ javac LocalSearch.java 
$ java LocalSearch
東京タワー大展望台　club333特設ステージ
 35.65870316, 139.74540779

東京タワー
 34.729707500000, 136.519455833333

マザー牧場ＣＡＦＥ東京タワー店
 35.658703055556, 139.745407777778
```

## 参考資料

- [YOLP\(地図\):Yahoo\!ローカルサーチAPI \- Yahoo\!デベロッパーネットワーク](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/localsearch.html)
- [Yahoo\!デベロッパーネットワーク:WebAPIの使い方\(GETリクエスト\) \- Yahoo\!デベロッパーネットワーク](https://developer.yahoo.co.jp/appendix/request/rest/get.html)