All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.memetix.mst.MicrosoftTranslatorAPI Maven / Gradle / Ivy

There is a newer version: 0.6.2
Show newest version
/*
 * microsoft-translator-java-api
 * 
 * Copyright 2012 Jonathan Griggs .
 *
 * 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.memetix.mst;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

/**
 *
 * MicrosoftAPI
 * 
 * Makes the generic Microsoft Translator API calls. Different service classes then
 * extend this to make the specific service calls.
 * 
 * Uses the AJAX Interface V2 - see: http://msdn.microsoft.com/en-us/library/ff512404.aspx
 * 
 * @author Jonathan Griggs
 */
public abstract class MicrosoftTranslatorAPI {
    //Encoding type
    protected static final String ENCODING = "UTF-8";
    
    protected static String apiKey;
    private static String DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
    private static String referrer;
    private static String clientId;
    private static String clientSecret;
    private static String token;
    private static long tokenExpiration = 0;
    private static String contentType = "text/plain";
    
    protected static final String PARAM_APP_ID = "appId=",
                                  PARAM_TO_LANG = "&to=",
                                  PARAM_FROM_LANG = "&from=",
                                  PARAM_TEXT_SINGLE = "&text=",
                                  PARAM_TEXT_ARRAY = "&texts=",
                                  PARAM_SPOKEN_LANGUAGE = "&language=",
                                  PARAM_SENTENCES_LANGUAGE = "&language=",
                                  PARAM_LOCALE = "&locale=",
                                  PARAM_LANGUAGE_CODES = "&languageCodes=";
    
    /**
     * Sets the API key.
     * 
     * Note: Should ONLY be used with API Keys generated prior to March 31, 2012. All new applications should obtain a ClientId and Client Secret by following 
     * the guide at: http://msdn.microsoft.com/en-us/library/hh454950.aspx
     * @param pKey The API key.
     */
    public static void setKey(final String pKey) {
    	apiKey = pKey;
    }
    
    /**
     * Sets the API key.
     * 
     * Note: Should ONLY be used with API Keys generated prior to March 31, 2012. All new applications should obtain a ClientId and Client Secret by following 
     * the guide at: http://msdn.microsoft.com/en-us/library/hh454950.aspx
     * @param pKey The API key.
     */
    public static void setContentType(final String pKey) {
    	contentType = pKey;
    }
    
    /**
     * Sets the Client ID.
     * All new applications should obtain a ClientId and Client Secret by following 
     * the guide at: http://msdn.microsoft.com/en-us/library/hh454950.aspx
     * @param pKey The Client Id.
     */
    public static void setClientId(final String pClientId) {
    	clientId = pClientId;
    }
    
    /**
     * Sets the Client Secret.
     * All new applications should obtain a ClientId and Client Secret by following 
     * the guide at: http://msdn.microsoft.com/en-us/library/hh454950.aspx
     * @param pKey The Client Secret.
     */
    public static void setClientSecret(final String pClientSecret) {
    	clientSecret = pClientSecret;
    }
    
    /**
     * Sets the Http Referrer.
     * @param pReferrer The HTTP client referrer.
     */
    public static void setHttpReferrer(final String pReferrer) {
    	referrer = pReferrer;
    }
    /**
     * Gets the OAuth access token.
     * @param clientId The Client key.
     * @param clientSecret The Client Secret
     */
    public static String getToken(final String clientId, final String clientSecret) throws Exception {
       final String params = "grant_type=client_credentials&scope=http://api.microsofttranslator.com"
               + "&client_id=" + URLEncoder.encode(clientId,ENCODING)
               + "&client_secret=" + URLEncoder.encode(clientSecret,ENCODING) ;

       final URL url = new URL(DatamarketAccessUri);
       final HttpURLConnection uc = (HttpURLConnection) url.openConnection();
       if(referrer!=null)
           uc.setRequestProperty("referer", referrer);
       uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded; charset=" + ENCODING);
       uc.setRequestProperty("Accept-Charset",ENCODING);
       uc.setRequestMethod("POST");
       uc.setDoOutput(true);

       OutputStreamWriter wr = new OutputStreamWriter(uc.getOutputStream());
       wr.write(params);
       wr.flush();

       try {
               final int responseCode = uc.getResponseCode();
               final String result = inputStreamToString(uc.getInputStream());
               if(responseCode!=200) {
                   throw new Exception("Error from Microsoft Translator API: " + result);
               }
               return result;
       } finally {
               if(uc!=null) {
                       uc.disconnect();
               }
       }
   }
    
    /**
     * Forms an HTTP request, sends it using GET method and returns the result of the request as a String.
     * 
     * @param url The URL to query for a String response.
     * @return The translated String.
     * @throws Exception on error.
     */
    private static String retrieveResponse(final URL url) throws Exception {
        if(clientId!=null&&clientSecret!=null&&System.currentTimeMillis()>tokenExpiration) {
           String tokenJson = getToken(clientId,clientSecret);
           Integer expiresIn = Integer.parseInt((String)((JSONObject)JSONValue.parse(tokenJson)).get("expires_in"));
           tokenExpiration = System.currentTimeMillis()+((expiresIn*1000)-1);
           token = "Bearer " + (String)((JSONObject)JSONValue.parse(tokenJson)).get("access_token");
        }
        final HttpURLConnection uc = (HttpURLConnection) url.openConnection();
        if(referrer!=null)
            uc.setRequestProperty("referer", referrer);
        uc.setRequestProperty("Content-Type",contentType + "; charset=" + ENCODING);
        uc.setRequestProperty("Accept-Charset",ENCODING);
        if(token!=null) {
            uc.setRequestProperty("Authorization",token);
        }
        uc.setRequestMethod("GET");
        uc.setDoOutput(true);

        try {
                final int responseCode = uc.getResponseCode();
                final String result = inputStreamToString(uc.getInputStream());
                if(responseCode!=200) {
                    throw new Exception("Error from Microsoft Translator API: " + result);
                }
                return result;
        } finally { 
        	if(uc!=null) {
    			uc.disconnect();
    		}
        }
    }
    
    /**
     * Fetches the JSON response, parses the JSON Response, returns the result of the request as a String.
     * 
     * @param url The URL to query for a String response.
     * @return The translated String.
     * @throws Exception on error.
     */
    protected static String retrieveString(final URL url) throws Exception {
    	try {
    		final String response = retrieveResponse(url);    		
            return jsonToString(response);
    	} catch (Exception ex) {
    		throw new Exception("[microsoft-translator-api] Error retrieving translation : " + ex.getMessage(), ex);
    	}
    }
    
    /**
     * Fetches the JSON response, parses the JSON Response as an Array of JSONObjects,
     * retrieves the String value of the specified JSON Property, and returns the result of 
     * the request as a String Array.
     * 
     * @param url The URL to query for a String response.
     * @return The translated String[].
     * @throws Exception on error.
     */
    protected static String[] retrieveStringArr(final URL url, final String jsonProperty) throws Exception {
    	try {
    	    final String response = retrieveResponse(url);    		
            return jsonToStringArr(response,jsonProperty);
    	} catch (Exception ex) {
    		throw new Exception("[microsoft-translator-api] Error retrieving translation.", ex);
    	}
    }
    
    /**
     * Fetches the JSON response, parses the JSON Response as an array of Strings
     * and returns the result of the request as a String Array.
     * 
     * Overloaded to pass null as the JSON Property (assume only Strings instead of JSONObjects)
     * 
     * @param url The URL to query for a String response.
     * @return The translated String[].
     * @throws Exception on error.
     */
    protected static String[] retrieveStringArr(final URL url) throws Exception {
    	return retrieveStringArr(url,null);
    }
    
    /**
     * Fetches the JSON response, parses the JSON Response, returns the result of the request as an array of integers.
     * 
     * @param url The URL to query for a String response.
     * @return The translated String.
     * @throws Exception on error.
     */
    protected static Integer[] retrieveIntArray(final URL url) throws Exception {
    	try {
    		final String response = retrieveResponse(url);    		
            return jsonToIntArr(response);
    	} catch (Exception ex) {
    		throw new Exception("[microsoft-translator-api] Error retrieving translation : " + ex.getMessage(), ex);
    	}
    }
    
    private static Integer[] jsonToIntArr(final String inputString) throws Exception {
    	final JSONArray jsonArr = (JSONArray)JSONValue.parse(inputString);
        Integer[] intArr = new Integer[jsonArr.size()];
        int i = 0;
        for(Object obj : jsonArr) {
        	intArr[i] = ((Long)obj).intValue();
        	i++;
        }
        return intArr;
    }
    
    private static String jsonToString(final String inputString) throws Exception {
        String json = (String)JSONValue.parse(inputString);
        return json.toString();
    }
    
    // Helper method to parse a JSONArray. Reads an array of JSONObjects and returns a String Array
    // containing the toString() of the desired property. If propertyName is null, just return the String value.
    private static String[] jsonToStringArr(final String inputString, final String propertyName) throws Exception {
        final JSONArray jsonArr = (JSONArray)JSONValue.parse(inputString);
        String[] values = new String[jsonArr.size()];
        
        int i = 0;
        for(Object obj : jsonArr) {
            if(propertyName!=null&&propertyName.length()!=0) {
                final JSONObject json = (JSONObject)obj;
                if(json.containsKey(propertyName)) {
                    values[i] = json.get(propertyName).toString();
                }
            } else {
                values[i] = obj.toString();
            }
            i++;
        }
        return values;
    }
    
    /**
     * Reads an InputStream and returns its contents as a String.
     * Also effects rate control.
     * @param inputStream The InputStream to read from.
     * @return The contents of the InputStream as a String.
     * @throws Exception on error.
     */
    private static String inputStreamToString(final InputStream inputStream) throws Exception {
    	final StringBuilder outputBuilder = new StringBuilder();
    	
    	try {
    		String string;
    		if (inputStream != null) {
    			BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, ENCODING));
    			while (null != (string = reader.readLine())) {
                            // Need to strip the Unicode Zero-width Non-breaking Space. For some reason, the Microsoft AJAX
                            // services prepend this to every response
                            outputBuilder.append(string.replaceAll("\uFEFF", ""));
    			}
    		}
    	} catch (Exception ex) {
    		throw new Exception("[microsoft-translator-api] Error reading translation stream.", ex);
    	}
    	
    	return outputBuilder.toString();
    }
    
    //Check if ready to make request, if not, throw a RuntimeException
    protected static void validateServiceState() throws Exception {
        if(apiKey!=null&&apiKey.length()<16) {
            throw new RuntimeException("INVALID_API_KEY - Please set the API Key with your Bing Developer's Key");
        } else if (apiKey==null&&(clientId==null||clientSecret==null)) {
            throw new RuntimeException("Must provide a Windows Azure Marketplace Client Id and Client Secret - Please see http://msdn.microsoft.com/en-us/library/hh454950.aspx for further documentation");
        }
    }
    
    protected static String buildStringArrayParam(Object[] values) {
        StringBuilder targetString = new StringBuilder("[\""); 
        String value;
        for(Object obj : values) {
            if(obj!=null) {
                value = obj.toString();
                if(value.length()!=0) {
                    if(targetString.length()>2)
                        targetString.append(",\"");
                    targetString.append(value);
                    targetString.append("\"");
                }
            }
        }
        targetString.append("]");
        return targetString.toString();
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy