Java tutorial
/* * Copyright 2013 MachineLinking S.r.l. * * Licensed 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 com.machinelinking.api.client; import org.apache.commons.io.IOUtils; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * The official client for the <a href="http://machinelininking.com/">MachineLinking API</i>. * * @author Michele Mostarda (michele@machinelinking.com) */ public class APIClient { private static final String DEFAULT_SERVICE_URL = "http://api.machinelinking.com"; private static final int DEFAULT_CONN_TIMEOUT = 60 * 1000; private static final String LANG_SERVICE = "/lang/"; private static final String ANNOTATE_SERVICE = "/annotate/"; private static final String COMPARE_SERVICE = "/compare/"; private static final String SUMMARY_SERVICE = "/summary/"; private final String serviceURL; private final int connTimeout; private final String appId; private final String appKey; public APIClient(String appId, String appKey, String serviceURL, int connTimeout) { this.appId = appId; this.appKey = appKey; this.serviceURL = serviceURL; this.connTimeout = connTimeout; } public APIClient(String appId, String appKey, int connTimeout) { this(appId, appKey, DEFAULT_SERVICE_URL, connTimeout); } public APIClient(String appId, String appKey) { this(appId, appKey, DEFAULT_CONN_TIMEOUT); } public GuessedLanguageResponse guessLanguage(String textToAnalyze, Map<String, Object> properties) throws IOException, APIClientException { properties.put(ParamsValidator.text, URLEncoder.encode(textToAnalyze, "UTF8")); InputStream is = null; try { is = sendRequest(serviceURL + LANG_SERVICE, "lang", properties); return parseLangResponse(is); } finally { if (is != null) is.close(); } } public GuessedLanguageResponse guessLanguage(String textToAnalyze) throws IOException, APIClientException { return guessLanguage(textToAnalyze, new HashMap<String, Object>()); } public AnnotationResponse annotate(String textToAnalyze, Map<String, Object> properties) throws IOException, APIClientException { properties.put(ParamsValidator.text, URLEncoder.encode(textToAnalyze, "UTF8")); final InputStream is = sendRequest(serviceURL + ANNOTATE_SERVICE, "annotate", properties); return parseAnnotateResponse(is); } public AnnotationResponse annotate(String textToAnalyze) throws IOException, APIClientException { return annotate(textToAnalyze, new HashMap<String, Object>()); } public CompareResponse compare(ComparisonMethod compareMethod, String text1, String text2, Map<String, Object> properties) throws IOException, APIClientException { properties.put(ParamsValidator.func, compareMethod.name()); properties.put(ParamsValidator.text1, text1); properties.put(ParamsValidator.text2, text2); final InputStream is = sendRequest(serviceURL + COMPARE_SERVICE, "compare", properties); return parseCompareResponse(is); } public CompareResponse compare(ComparisonMethod compareMethod, String text1, String text2) throws IOException, APIClientException { return compare(compareMethod, text1, text2, new HashMap<String, Object>()); } public SummaryResponse summarize(CompressionMethod compressionMethod, float compressionRatio, String text, Map<String, Object> properties) throws IOException, APIClientException { properties.put(ParamsValidator.func, compressionMethod.name()); properties.put(ParamsValidator.compression_ratio, compressionRatio); properties.put(ParamsValidator.text, text); final InputStream is = sendRequest(serviceURL + SUMMARY_SERVICE, "summarize", properties); return parseSummaryResponse(is); } public SummaryResponse summarize(CompressionMethod compressionMethod, float compressionRatio, String text) throws IOException, APIClientException { return summarize(compressionMethod, compressionRatio, text, new HashMap<String, Object>()); } private InputStream sendRequest(String service, String group, Map<String, Object> properties) throws IOException { try { URL url = new URL(service); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(connTimeout); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setDoOutput(true); properties.put(ParamsValidator.app_id, appId); properties.put(ParamsValidator.app_key, appKey); StringBuilder data = ParamsValidator.getInstance().buildRequest(group, properties); httpURLConnection.addRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); DataOutputStream dataOutputStream = new DataOutputStream(httpURLConnection.getOutputStream()); dataOutputStream.write(data.toString().getBytes()); dataOutputStream.close(); if (httpURLConnection.getResponseCode() == 200) { return httpURLConnection.getInputStream(); } else { return httpURLConnection.getErrorStream(); } } catch (MalformedURLException e) { throw new IllegalStateException(e); } } private void checkError(JSONObject rootResponse) throws APIClientException { final JSONObject error = rootResponse.optJSONObject("error"); if (error != null) try { throw new APIClientException( String.format("An error occurred while invoking API. Message: [%s], code: [%d]", error.getString("msg"), error.getInt("code"))); } catch (JSONException jsone) { throw new IllegalArgumentException("Invalid error message.", jsone); } } private GuessedLanguageResponse parseLangResponse(InputStream is) throws IOException, APIClientException { try { final JSONObject jsonResponse = new JSONObject(IOUtils.toString(is)); checkError(jsonResponse); final JSONObject annotation = jsonResponse.getJSONObject("annotation"); final String lang = annotation.getString("lang"); final int cost = annotation.getInt("cost"); return new GuessedLanguageResponse(lang, cost); } catch (JSONException jsone) { throw new APIClientException("An error occurred while parsing the lang service response.", jsone); } } private Clazz[] toClasses(JSONArray classes) throws JSONException { if (classes == null) return null; Clazz[] response = new Clazz[classes.length()]; for (int i = 0; i < classes.length(); i++) { JSONObject clazzJSON = classes.getJSONObject(i); response[i] = new Clazz(clazzJSON.getString("label"), toURLOrFail(clazzJSON.getString("url")), clazzJSON.getString("resource"), clazzJSON.getDouble("prob")); } return response; } private Category[] toCategories(JSONArray categories) throws JSONException { if (categories == null) return null; Category[] response = new Category[categories.length()]; for (int i = 0; i < categories.length(); i++) { JSONObject clazzJSON = categories.getJSONObject(i); response[i] = new Category(clazzJSON.getString("label"), toURLOrFail(clazzJSON.getString("url"))); } return response; } private External[] toExternals(JSONArray externals) throws JSONException { if (externals == null) return null; External[] response = new External[externals.length()]; for (int i = 0; i < externals.length(); i++) { JSONObject clazzJSON = externals.getJSONObject(i); response[i] = new External(clazzJSON.getString("label"), toURLOrFail(clazzJSON.getString("url")), clazzJSON.getString("resource")); } return response; } private Alt[] toAlts(JSONArray alts) throws JSONException { if (alts == null) return null; Alt[] response = new Alt[alts.length()]; for (int i = 0; i < alts.length(); i++) { JSONObject clazzJSON = alts.getJSONObject(i); response[i] = new Alt(clazzJSON.getString("form"), clazzJSON.getDouble("freq")); } return response; } private Cross[] toCrosses(JSONArray crosses) throws JSONException { if (crosses == null) return null; Cross[] response = new Cross[crosses.length()]; for (int i = 0; i < crosses.length(); i++) { JSONObject clazzJSON = crosses.getJSONObject(i); response[i] = new Cross(clazzJSON.getString("lang"), clazzJSON.getString("page")); } return response; } private Topic[] toTopics(JSONArray topicsJSON) throws JSONException { if (topicsJSON == null) return new Topic[0]; JSONObject topicJSON; final Topic[] topics = new Topic[topicsJSON.length()]; for (int i = 0; i < topics.length; i++) { topicJSON = topicsJSON.getJSONObject(i); topics[i] = new Topic(topicJSON.getString("label"), toURLOrFail(topicJSON.getString("url")), (float) topicJSON.getDouble("prob")); } return topics; } private NGram[] toNGrams(JSONArray ngramsArray) throws JSONException { JSONObject span; final NGram[] response = new NGram[ngramsArray.length()]; for (int i = 0; i < ngramsArray.length(); i++) { span = ngramsArray.getJSONObject(i).getJSONObject("span"); response[i] = new NGram(span.getInt("start"), span.getInt("end")); } return response; } private Image[] toImages(JSONArray images) throws JSONException { if (images == null) return null; Image[] response = new Image[images.length()]; for (int i = 0; i < images.length(); i++) { JSONObject clazzJSON = images.getJSONObject(i); response[i] = new Image(toURLOrFail(clazzJSON.getString("image")), toURLOrFail(clazzJSON.getString("thumb"))); } return response; } private JSONObject parseAndCheckErrors(InputStream is) throws IOException, APIClientException { final JSONObject jsonResponse; try { jsonResponse = new JSONObject(IOUtils.toString(is)); } catch (JSONException jsone) { throw new APIClientException("An error occurred while parsing the API response.", jsone); } checkError(jsonResponse); return jsonResponse; } private AnnotationResponse parseAnnotateResponse(InputStream is) throws IOException, APIClientException { try { final JSONObject jsonResponse = parseAndCheckErrors(is); final JSONObject annotation = jsonResponse.getJSONObject("annotation"); final String lang = annotation.getString("lang"); final int cost = annotation.getInt("cost"); JSONArray keywordsJSON = annotation.getJSONArray("keyword"); JSONObject keywordJSON, sense; Keyword keyword; final Keyword[] keywords = new Keyword[keywordsJSON.length()]; for (int i = 0; i < keywordsJSON.length(); i++) { keywordJSON = keywordsJSON.getJSONObject(i); sense = keywordJSON.optJSONObject("sense"); keyword = new Keyword(keywordJSON.getString("form"), (float) keywordJSON.getDouble("rel"), sense != null ? sense.getString("page") : null, sense != null ? (float) sense.getDouble("prob") : 0, keywordJSON.optString("abstract"), toClasses(keywordJSON.optJSONArray("class")), toCategories(keywordJSON.optJSONArray("category")), toExternals(keywordJSON.optJSONArray("external")), toAlts(keywordJSON.optJSONArray("alt")), toCrosses(keywordJSON.optJSONArray("cross")), toTopics(keywordJSON.optJSONArray("topic")), toNGrams(keywordJSON.getJSONArray("ngram")), toImages(keywordJSON.optJSONArray("image"))); keywords[i] = keyword; } return new AnnotationResponse(lang, keywords, toTopics(annotation.optJSONArray("topic")), cost); } catch (JSONException jsone) { throw new APIClientException("An error occurred while parsing the /annotate JSON data.", jsone); } } private CompareResponse parseCompareResponse(InputStream is) throws APIClientException, IOException { try { final JSONObject jsonResponse = parseAndCheckErrors(is); final JSONObject annotation = jsonResponse.getJSONObject("annotation"); final int cost = annotation.getInt("cost"); final float similarity = (float) annotation.getDouble("value"); return new CompareResponse(cost, similarity); } catch (JSONException jsone) { throw new APIClientException("An error occurred while parsing the /compare JSON data.", jsone); } } private SummaryResponse parseSummaryResponse(InputStream is) throws APIClientException, IOException { try { final JSONObject jsonResponse = parseAndCheckErrors(is); final JSONObject annotation = jsonResponse.getJSONObject("annotation"); final int cost = annotation.getInt("cost"); JSONArray summariesJSON = annotation.getJSONArray("summary"); final Summary[] summaries = new Summary[summariesJSON.length()]; for (int i = 0; i < summariesJSON.length(); i++) { JSONObject summaryJSON = summariesJSON.getJSONObject(i); summaries[i] = new Summary(summaryJSON.getString("sentence"), (float) summaryJSON.getDouble("weight"), summaryJSON.getInt("start"), summaryJSON.getInt("end")); } return new SummaryResponse(cost, summaries); } catch (JSONException jsone) { throw new APIClientException("An error occurred while parsing the /compare JSON data.", jsone); } } private URL toURLOrFail(String urlTxt) { try { return new URL(urlTxt); } catch (MalformedURLException e) { throw new IllegalStateException( String.format("Invalid value returned from API. Expected URL found [%s]", urlTxt)); } } }