JSON World Bank Data in NetBeans HTML Code Completion

Continuing from yesterday, another source of data for code completion could be data extracted from JSON via an online RESTful web service, such as this one:

http://api.worldbank.org/country?format=json

I'm not trying to make the argument that it's useful to integrate World Bank data into the code completion box in the NetBeans HTML Editor, but simply that it's possible to do so (and you might have, more realistically, customer data exposed via a RESTful web service that you'd like to have available while working with a specific HTML attribute) via the annotation I described yesterday:

@HTMLAttributeCompletionRegistration(
        id = "jee-architect-cookbook-netbeans-iso6391-CountriesAttributeCompletionProvider",
        attribute = "accesskey",
        iconBase = "jee/architect/cookbook/netbeans/iso6391/bubble.png",
        content = "http://api.worldbank.org/country?format=json",
        contentType="json")

That's all the code needed because the layer entries generated from the above create a code completion provider with this result:

Again, the "accesskey" attribute doesn't make sense in the context of the above data, but it's just an example of what's possible.

I had to cheat slightly because I haven't figured out a good way to pass in the path to the required data yet, so I've hardcoded it, as you can see below in the "loadContent" method of the completion provider to which the above annotation maps, as described yesterday:

private void loadContent(String content, String contentType) throws IOException {
    if (contentType.equals("csv")) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream(content);
        if (inputStream != null) {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                codes.add(line);
            }
        }
    } else if (contentType.equals("json")) {
        try {
            URL url = new URL(content);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            if (conn.getResponseCode() != 200) {
                StatusDisplayer.getDefault().setStatusText(
                        "Failed : HTTP error code : "
                        + conn.getResponseCode());
            }
            BufferedReader br = new BufferedReader(
                    new InputStreamReader((conn.getInputStream())));
            JSONArray array = (JSONArray) JSONValue.parse(br);
            JSONArray next = (JSONArray) array.get(1);
            for (int i = 0; i < next.size(); i++) {
                    //Map m = (Map) ((JSONObject) next.get(i)).get("region");
                    //String region = m.get("value").toString();
                    //codes.add(region);
                String country = (String) ((JSONObject) next.get(i)).get("name");
                String capitalCity = (String) ((JSONObject) next.get(i)).get("capitalCity");
                codes.add(capitalCity + "/" + country);
            }
            conn.disconnect();
        } catch (MalformedURLException e) {
            Exceptions.printStackTrace(e);
        } catch (IOException e) {
            Exceptions.printStackTrace(e);
        }
    } else if (contentType.equals("basic")) {
        codes.addAll(Arrays.asList(content.split(",")));
    }
}

All the casting above seems a bit ugly but I don't know a better way to do it and, again again, that's not the point here.

Some related info that I found helpful:

And the code above is now part of the download referred to yesterday:

http://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.3/misc/CompletionRegistrationSupport
Comments:

Just a PoC I know, but rather than hard coding the available content types why not have an @ContentHandlerRegistration annotation or similar? Then you could just do a get on a Map<String, ContentHandler> where ContentHandler is a SAM interface with Iterable<String> loadContent(String content) as it's method. This would allow registering specific content handlers for specific data sources, e.g you could register "world-bank-countries+json" to handle the data in your example.

BTW, it's a tad annoying not being able to use pre or code tags, at least, when commenting here!

Posted by guest on January 01, 2013 at 06:52 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today