com.smartlogic.ses.client.SESClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Semaphore-SES-Client Show documentation
Show all versions of Semaphore-SES-Client Show documentation
Client for the Smartlogic Semaphore Semantic Enhancement Server
// ----------------------------------------------------------------------
// Product: Semantic Enhancement Server Java API
//
// (c) 2009 Smartlogic Semaphore Ltd
// ----------------------------------------------------------------------
package com.smartlogic.ses.client;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.smartlogic.ses.client.exceptions.NoSuchTermException;
import com.smartlogic.ses.client.exceptions.SESException;
public class SESClient {
Logger logger = LoggerFactory.getLogger(this.getClass());
public enum DetailLevel {
MINIMAL, FULL
}
private String protocol = "http";
private String host;
private int port = 80;
private String path;
private String ontology;
private String template = "service.xml";
private int connectionTimeoutMS;
private int socketTimeoutMS;
private String language;
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
private String apiToken;
public String getApiToken() {
return apiToken;
}
public void setApiToken(String apiToken) {
this.apiToken = apiToken;
}
private String proxyHost;
public String getProxyHost() {
return proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public int getProxyPort() {
return proxyPort;
}
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
private int proxyPort;
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void setPort(String port) {
this.port = Integer.parseInt(port);
}
public String getPath() throws SESException {
if (path == null) {
if (getUrl() != null) {
try {
path = (new URL(getUrl())).getPath();
} catch (MalformedURLException e) {
throw new SESException(String.format("Malformd URL: '%s'", this.getUrl()));
}
}
}
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getOntology() {
return ontology;
}
public void setOntology(String ontology) {
this.ontology = ontology;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
public int getConnectionTimeoutMS() {
return connectionTimeoutMS;
}
public void setConnectionTimeoutMS(int connectionTimeoutMS) {
this.connectionTimeoutMS = connectionTimeoutMS;
}
public int getSocketTimeoutMS() {
return socketTimeoutMS;
}
public void setSocketTimeoutMS(int socketTimeoutMS) {
this.socketTimeoutMS = socketTimeoutMS;
}
private File saveFile = null;
public File getSaveFile() {
return saveFile;
}
public void setSaveFile(File saveFile) {
this.saveFile = saveFile;
}
/**
* Return all terms from the ontology
*
* @return List of all descendants
* @throws SESException
* SES exception
*/
public Map getAllTerms() throws SESException {
return getAllDescendents(null, null);
}
public Map getAllTerms(SESFilter sesFilter) throws SESException {
logger.info("getTerms - entry");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=allterms");
query.append(getFilterString(sesFilter));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
Map returnData =
(semaphore.getTerms() != null) ? semaphore.getTerms().getTerms() : new HashMap<>();
logger.debug("getTermDetails - exit");
return returnData;
}
/**
* Return all terms from the ontology underneath the supplied term (deprecated?)
*
* @param parentId
* ID of the parent term
* @param hierarchyType
* The hierarchical relationship type to use
* @return List of all descendants
* @throws SESException
* SES exception
*/
public Map getAllDescendents(String parentId, String hierarchyType)
throws SESException {
return getAllDescendants(parentId, hierarchyType, null);
}
/**
* Return all terms from the ontology underneath the supplied term
*
* @param parentId
* ID of the parent term
* @param hierarchyType
* The hierarchical relationship type to use
* @return List of all descendants
* @throws SESException
* SES exception
*/
public Map getAllDescendants(String parentId, String hierarchyType)
throws SESException {
return getAllDescendants(parentId, hierarchyType, null);
}
/**
* Return all terms from the ontology underneath the supplied term
*
* @param parentId
* ID of the parent term
* @param hierarchyType
* The hierarchical relationship type to use
* @param filter
* Any SES filter to apply
* @return List of all descendants
* @throws SESException
* SES exception
*/
public Map getAllDescendants(String parentId, String hierarchyType,
SESFilter filter) throws SESException {
logger.info("getAllDescendents - entry");
Map returnData;
if (parentId == null) {
returnData = this.browse(null, filter);
} else {
returnData = new HashMap<>();
Term parentTerm = this.getTermDetails(parentId, DetailLevel.FULL, filter);
returnData.put(parentTerm.getId().getValue(), parentTerm);
}
Collection termsToGet = new HashSet<>();
Collection missingTerms = new HashSet<>();
boolean termsFetched = false;
do {
termsFetched = false;
for (Term term : returnData.values()) {
if (term == null) {
continue;
}
for (Hierarchy hierarchy : term.getHierarchies()) {
if ((hierarchyType != null) && (!hierarchyType.equalsIgnoreCase(hierarchy.getType()))) {
continue;
}
// We don't want to go up the hierarchy
if ("Broader Term".equalsIgnoreCase(hierarchy.getType())) {
continue;
}
for (Field field : hierarchy.getFields().values()) {
if (!returnData.containsKey(field.getId()) && !missingTerms.contains(field.getId())) {
termsToGet.add(field.getId());
}
}
}
if (termsToGet.size() > 500) {
break;
}
}
if (termsToGet.size() > 0) {
Map fetchedTerms =
this.getTermDetails(termsToGet.toArray(new String[0]), DetailLevel.FULL, filter);
for (String fetchedId : fetchedTerms.keySet()) {
Term term = fetchedTerms.get(fetchedId);
if (term != null) {
returnData.put(fetchedId, term);
}
}
for (String termRequested : termsToGet) {
if (!returnData.containsKey(termRequested)) {
logger.trace("Referenced term \"" + termRequested + "\" does not exist in SES index");
missingTerms.add(termRequested); // I asked for this term, but didn't get it
}
}
termsFetched = true;
termsToGet.clear();
}
} while (termsFetched);
logger.debug("getAllDescendents - exit: " + returnData.size());
return returnData;
}
/**
* Return the mapped concepts from the Semantic Enhancement Server
*
* @param query
* The query text
* @return map from term id to term
* @throws SESException
* SES exception
*/
public Map getMappedConcepts(String query) throws SESException {
return getMappedConcepts(query, 0, null);
}
/**
* Return the mapped concepts from the Semantic Enhancement Server
*
* @param query
* The query text
* @param minDocs
* - the mininum frequency for terms to be returned
* @param stopStage
* - the stage at which the mapping process should stop (1=exacts only, 2=exacts and
* inexact)
* @return map from term id to term
* @throws SESException
* SES exception
*/
public Map getMappedConcepts(String query, int minDocs, int stopStage)
throws SESException {
SESFilter sesFilter = new SESFilter();
sesFilter.setMinDocs(minDocs);
return getMappedConcepts(query, stopStage, sesFilter);
}
public Map getMappedConcepts(String query, SESFilter sesFilter)
throws SESException {
return getMappedConcepts(query, 0, sesFilter);
}
public Map getMappedConcepts(String query, int stopStage, SESFilter sesFilter)
throws SESException {
logger.info("mapConcepts - entry: '" + query + "'");
URL url = null;
try {
StringBuffer cgiQuery = new StringBuffer();
cgiQuery.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
cgiQuery.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
cgiQuery.append(getFilterString(sesFilter));
if (stopStage != 0) {
cgiQuery.append("&stop_cm_after_stage=" + stopStage);
}
cgiQuery.append("&service=conceptmap");
cgiQuery.append("&query=" + URLEncoder.encode(query, "UTF8"));
cgiQuery.append(getLanguageChoice());
url = getURLImpl(cgiQuery.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.debug("mapConcepts - exit: '" + query + "'");
if (semaphore.getTerms() != null) {
return semaphore.getTerms().getTerms();
}
return new HashMap<>();
}
/**
* Return the terms from the Semantic Enhancement Server matching the search term
*
* @param query
* The search text
* @return map from term id to term
* @throws SESException
* SES exception
*/
public Map search(String query) throws SESException {
return search(query, new SESFilter());
}
/**
* Return the terms from the Semantic Enhancement Server matching the search term
*
* @param query
* The search text
* @param sesFilter
* - container for any filters that need to be applied
* @return map from term id to term
* @throws SESException
* SES exception
*/
public Map search(String query, SESFilter sesFilter) throws SESException {
logger.info("getTerms - entry");
URL url = null;
try {
StringBuffer cgiQuery = new StringBuffer();
cgiQuery.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
cgiQuery.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
cgiQuery.append("&service=search");
cgiQuery.append("&query=" + URLEncoder.encode(query, "UTF8"));
cgiQuery.append(getFilterString(sesFilter));
cgiQuery.append(getLanguageChoice());
url = getURLImpl(cgiQuery.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
Map returnData =
(semaphore.getTerms() != null) ? semaphore.getTerms().getTerms() : new HashMap<>();
logger.debug("getTermDetails - exit");
return returnData;
}
private String dateFormat = null;
private synchronized void setDateFormat() throws SESException {
VersionInfo versionInfo = this.getVersion();
String version = versionInfo.getVersion();
logger.debug("setDateFormat - version: {}", version);
if (version != null) {
// This is SES > 4.0.36
dateFormat = "yyyy-MM-dd'T'HH:mm:ss";
} else {
dateFormat = "yyyyMMddHHmmss";
}
}
private SimpleDateFormat getDateFormatter() throws SESException {
if (dateFormat == null) {
setDateFormat();
}
return new SimpleDateFormat(dateFormat);
}
private String getFilterString(SESFilter sesFilter) throws SESException {
if (sesFilter == null) {
return "";
}
StringBuilder path = new StringBuilder();
try {
if (sesFilter.getMinDocs() != SESFilter.UNDEFINED_INT) {
path.append("&mindocs=" + sesFilter.getMinDocs());
}
if (sesFilter.getPrefixResultsLimit() != SESFilter.UNDEFINED_INT) {
path.append("&prefix_results_limit=" + sesFilter.getPrefixResultsLimit());
}
if (sesFilter.getPrefixResultsInternalLimit() != SESFilter.UNDEFINED_INT) {
path.append("&prefix_results_internal_limit=" + sesFilter.getPrefixResultsInternalLimit());
}
if (sesFilter.getClasses() != null) {
for (String className : sesFilter.getClasses()) {
path.append("&class=" + URLEncoder.encode(className, "UTF8"));
}
}
if (sesFilter.getFacets() != null) {
for (String facetName : sesFilter.getFacets()) {
path.append("&facet=" + URLEncoder.encode(facetName, "UTF8"));
}
}
if (sesFilter.getModifiedBeforeDate() != null) {
path.append("&filter=MODIFIED_BEFORE=" +
getDateFormatter().format(sesFilter.getModifiedBeforeDate()));
}
if (sesFilter.getModifiedAfterDate() != null) {
path.append("&filter=MODIFIED_AFTER=" +
getDateFormatter().format(sesFilter.getModifiedAfterDate()));
}
if (sesFilter.getExcludeAttributes() != null) {
for (String attribute : sesFilter.getExcludeAttributes()) {
path.append("&filter=ATN=" + URLEncoder.encode(attribute, "UTF8"));
}
}
if (sesFilter.getIncludeAttributes() != null) {
for (String attribute : sesFilter.getIncludeAttributes()) {
path.append("&filter=AT=" + URLEncoder.encode(attribute, "UTF8"));
}
}
if (sesFilter.getStartTermZthesIds() != null) {
for (String startTermZthesId : sesFilter.getStartTermZthesIds()) {
path.append("&filter=DE=" + URLEncoder.encode(startTermZthesId, "UTF8"));
}
}
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncodingException: " + e.getMessage());
}
return path.toString();
}
/**
* Return the language part of the SES request. For backwards compliance, we need to supply this
* as "lang" and "language".
*
* @return The language part of the SES request
* @throws UnsupportedEncodingException
*/
private String getLanguageChoice() throws UnsupportedEncodingException {
if (language == null) {
return "";
}
String encodedLanguage = URLEncoder.encode(language, "UTF8");
return "&lang=" + encodedLanguage + "&language=" + encodedLanguage;
}
/**
* Return the terms from the Semantic Enhancement Server matching the search term
*
* @param query
* The search term
* @return collection of matching termssorted alphabetically
* @throws SESException
* SES exception
*/
public Collection sortedSearch(String query) throws SESException {
return sortTerms(search(query).values());
}
/**
* Return the minimal amount of data for the terms - just the name and id will be populated
*
* @param ids
* Array of IDs
* @return minimally populated terms in a map keyed by term id
* @throws SESException
* SES exception
*/
public Map getTermDetails(String[] ids) throws SESException {
return getTermDetails(ids, DetailLevel.MINIMAL, null);
}
/**
* Return the minimal amount of data for one term - just the name and id will be populated
*
* @param id
* The ID for which you wish details to be returned
* @return minimally populated term
* @throws SESException
* SES exception
* @throws NoSuchTermException
* Exception if no such term
*/
public Term getTermDetails(String id) throws SESException, NoSuchTermException {
return getTermDetails(id, DetailLevel.MINIMAL);
}
public Map getTermDetailsByName(String name)
throws SESException, NoSuchTermException {
logger.info("getTermDetails - entry");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=term");
query.append("&term=" + URLEncoder.encode(name, "UTF8"));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.debug("getTermDetails - exit");
if (semaphore.getTerms() != null) {
return semaphore.getTerms().getTerms();
}
return new HashMap<>();
}
/**
* Return the full details of the selected terms
*
* @param ids
* Array of IDs
* @param detailLevel
* - the extent to which the term details should be populated
* @return the terms matching the supplied ids
* @throws SESException
* SES exception
*/
public Map getTermDetails(String[] ids, DetailLevel detailLevel)
throws SESException {
return getTermDetails(ids, detailLevel, null);
}
/**
* Return the full details of the selected terms
*
* @param ids
* Array of IDs
* @param detailLevel
* - the extent to which the term details should be populated
* @param sesFilter
* Any SES filter to apply
* @return the terms matching the supplied ids
* @throws SESException
* SES exception
*/
public Map getTermDetails(String[] ids, DetailLevel detailLevel,
SESFilter sesFilter) throws SESException {
logger.info("getTermDetails - entry");
List urls = new ArrayList<>();
URL url = null;
try {
StringBuffer basepath = new StringBuffer();
basepath.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
basepath.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
if (detailLevel == DetailLevel.FULL) {
basepath.append("&service=term");
} else if (detailLevel == DetailLevel.MINIMAL) {
basepath.append("&service=termlite");
} else {
logger.warn("Invalid detail level requested");
}
basepath.append(getLanguageChoice());
basepath.append(getFilterString(sesFilter));
basepath.append("&id=");
String sep = "";
StringBuffer path = new StringBuffer(basepath);
for (String id : ids) {
if (this.getPath().length() + path.length() + id.length() > 2048) {
url = getURLImpl(path.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
urls.add(url);
path = new StringBuffer(basepath);
}
path.append(sep + URLEncoder.encode(id, "UTF8"));
sep = ",";
}
url = getURLImpl(path.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
urls.add(url);
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Map termdetails = new HashMap<>();
for (URL u : urls) {
Semaphore semaphore = getSemaphore(u);
logger.debug("getTermDetails - exit");
if (semaphore.getTerms() != null) {
termdetails.putAll(semaphore.getTerms().getTerms());
}
}
// Go through and fill in the gaps that might have been left by missing terms
// Unless of course we are filtering the results, in which case the missing terms
// are the ones we don't want to see...
if (sesFilter == null) {
for (String id : ids) {
if (!termdetails.containsKey(id)) {
termdetails.put(id, null);
}
}
}
return termdetails;
}
/**
* Sends requests which updates documents counter for term
*
* @param id
* ID of term to update
* @param newValue
* The new count value for the term
* @throws SESException
* SES exception
*/
public void updateFrequency(String id, Integer newValue) throws SESException {
logger.info("updateFrequency - id: '" + id + "'");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=updatefreq");
query.append("&id=" + URLEncoder.encode(id, "UTF8"));
query.append(getLanguageChoice());
query.append("&new_value=" + URLEncoder.encode(newValue.toString(), "UTF8"));
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
getSemaphore(url);
return;
}
/**
* Sends request which increases popularity counter for term
*
* @param id
* ID of term to update
* @throws SESException
* SES exception
*/
public void increasePopularity(String id) throws SESException {
logger.info("increasePopularity - id: '" + id + "'");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=increase_popularity");
query.append("&id=" + URLEncoder.encode(id, "UTF8"));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
getSemaphore(url);
return;
}
/**
* Return details of the term with the selected id. If there is no such term, null will be
* returned
*
* @param id
* ID of term to return details for
* @param detailLevel
* Level of detail for the results
* @return the term matching the supplied id, or null if no such term exists
* @throws SESException
* SES exception
* @throws NoSuchTermException
* "no such term" exception can be thrown
*/
public Term getTermDetails(String id, DetailLevel detailLevel)
throws SESException, NoSuchTermException {
return getTermDetails(id, detailLevel, null);
}
/**
* Return details of the term with the selected id. If there is no such term, null will be
* returned
*
* @param id
* ID of the term to return details for
* @param detailLevel
* Level of detail for the results
* @param sesFilter
* Any SES filter to apply
* @return the term matching the supplied id, or null if no such term exists
* @throws SESException
* SES exception
* @throws NoSuchTermException
* "no such term" exception can be thrown
*/
public Term getTermDetails(String id, DetailLevel detailLevel, SESFilter sesFilter)
throws SESException, NoSuchTermException {
logger.info("getTermDetails - entry: '" + id + "'");
Map termMap = getTermDetails(new String[] { id }, detailLevel, sesFilter);
logger.info("getTermDetails - exit: '" + termMap.get(id) + "'");
return termMap.get(id);
}
/**
* Return the terms (in brief) that match the supplied prefix
*
* @param prefix
* Prefix text for terms
* @return all matching term hints
* @throws SESException
* SES exception
*/
public Map getTermHints(String prefix) throws SESException {
SESFilter sesFilter = new SESFilter();
return getTermHints(prefix, sesFilter);
}
/**
* Return the terms (in brief) that match the supplied prefix
*
* @param prefix
* Prefix text for terms
* @param minDocs
* the minimum frequency for returned terms
* @return all matching term hints
* @throws SESException
* SES exception
*/
@Deprecated
public Map getTermHints(String prefix, int minDocs) throws SESException {
logger.info("getTermHints - entry: '" + prefix + "'");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&mindocs=" + minDocs);
query.append("&service=PREFIX");
query.append("&term_prefix=" + URLEncoder.encode(prefix, "UTF8"));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.info("getTermHints - exit");
if (semaphore.getTermHints() != null) {
return semaphore.getTermHints().getTermHints();
}
return new HashMap<>();
}
/**
* Return the terms (in brief) that match the supplied prefix
*
* @param prefix
* Prefix text for terms
* @param sesFilter
* the filter that should be applied to the results
* @return all matching term hints
* @throws SESException
* SES exception
*/
public Map getTermHints(String prefix, SESFilter sesFilter)
throws SESException {
logger.info("getTermHints - entry: '" + prefix + "'");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append(getFilterString(sesFilter));
query.append("&service=PREFIX");
query.append("&term_prefix=" + URLEncoder.encode(prefix, "UTF8"));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.info("getTermHints - exit");
if (semaphore.getTermHints() != null) {
return semaphore.getTermHints().getTermHints();
}
return new HashMap<>();
}
/**
* Return the top level terms
*
* @return the set of terms
* @throws SESException
* SES exception
*/
public Map browse() throws SESException {
return browse(null);
}
/**
* Return the terms related to the presented term id
*
* @param id
* The term ID
* @return the terms returned by the browse command
* @throws SESException
* SES exception
*/
public Map browse(String id) throws SESException {
return browse(id, null);
}
/**
* Return the terms related to the presented term id
*
* @param id
* The term ID
* @param sesFilter
* Any SES filter
* @return the terms returned by the browse command
* @throws SESException
* SES exception
*/
public Map browse(String id, SESFilter sesFilter) throws SESException {
logger.info("browse - entry: " + id);
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=browse");
if (id != null) {
query.append("&id=" + URLEncoder.encode(id, "UTF8"));
} else {
query.append("&filter_hierarchy=false");
}
query.append(getFilterString(sesFilter));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
Map terms = semaphore.getTerms().getTerms();
if (terms == null) {
terms = new HashMap<>();
}
if (semaphore.getBrowseTerm() != null) {
terms.put(semaphore.getBrowseTerm().getId().getValue(), semaphore.getBrowseTerm());
}
logger.debug("browse - exit");
return terms;
}
private URL getURLImpl(String query) throws SESException {
if (this.getUrl() != null) {
try {
return new URL(this.getUrl() + query);
} catch (MalformedURLException e) {
throw new SESException(String.format("Malformd URL: '%s'", this.getUrl()));
}
} else {
try {
return new URL(getProtocol(), getHost(), getPort(), getPath() + query);
} catch (MalformedURLException e) {
throw new SESException(String.format("Malformd URL: '%s' '%s' %d '%s' '%s'", getProtocol(),
getHost(), getPort(), getPath(), query));
}
}
}
/**
* Return the A to Z terms for the supplied prefix
*
* @param prefix
* The letter/number (prefix) or "all"
* @return the terms marked as use for A to Z starting with the supplied prefix
* @throws SESException
* SES exception
*/
public Map getAtoZTerms(String prefix) throws SESException {
return getAtoZTerms(prefix, null);
}
/**
* Return the A to Z terms for the supplied prefix
*
* @param prefix
* The letter/number (prefix) or "all"
* @param sesFilter
* The SES filter
* @return the terms marked as use for A to Z starting with the supplied prefix
* @throws SESException
* SES exception
*/
public Map getAtoZTerms(String prefix, SESFilter sesFilter) throws SESException {
logger.info("getAtoZTerms - entry: " + prefix);
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?TBDB=" + URLEncoder.encode(getOntology(), "UTF8"));
query.append("&template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=az");
query.append("&az=" + URLEncoder.encode(prefix, "UTF8"));
query.append(getFilterString(sesFilter));
query.append(getLanguageChoice());
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.debug("getAtoZTerms - exit");
if (semaphore.getTerms() != null) {
return semaphore.getTerms().getTerms();
}
return new HashMap<>();
}
public Collection listModels() throws SESException {
logger.info("listModels - entry");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=modelslist");
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.info("listModels - exit: " + semaphore.getModels().size());
return semaphore.getModels();
}
/**
* Return the A to Z terms for the supplied prefix sorted alphabetically (case insensitive)
*
* @param prefix
* The letter/number (prefix) or "all"
* @return the terms marked as use for A to Z starting with the supplied prefix, sorted
* alphabetically
* @throws SESException
* SES exception
*/
public Collection getSortedAtoZTerms(String prefix) throws SESException {
Map termMap = getAtoZTerms(prefix);
return sortTerms(termMap.values());
}
public VersionInfo getVersion() throws SESException {
logger.info("getVersion - entry");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=versions");
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.info("getVersion - exit: " + semaphore.getModels().size());
return semaphore.getVersionInfo();
}
public OMStructure getStructure() throws SESException {
logger.info("getOMStructure - entry");
StringBuffer query = new StringBuffer();
query.append("/" + getOntology());
if (getLanguage() != null) {
query.append("/" + getLanguage());
}
Semaphore semaphore = getSemaphore(getURLImpl(query.toString()));
logger.info("getOMStructure - exit");
return semaphore.getOmStructure();
}
public StatisticsInfo getStatistics() throws SESException {
logger.info("getStatistics - entry");
URL url = null;
try {
StringBuffer query = new StringBuffer();
query.append("?template=" + URLEncoder.encode(getTemplate(), "UTF8"));
query.append("&service=stats");
url = getURLImpl(query.toString());
if (logger.isDebugEnabled()) {
logger.debug("URL: " + url.toExternalForm());
}
} catch (UnsupportedEncodingException e) {
throw new SESException("UnsupportedEncodingException: " + e.getMessage());
}
Semaphore semaphore = getSemaphore(url);
logger.info("getStatistics - exit");
return semaphore.getStatisticsInfo();
}
private Collection sortTerms(Collection termsToSort) {
Collection treeSet = new TreeSet<>(new AlphabeticalTermComparator());
treeSet.addAll(termsToSort);
return treeSet;
}
protected Semaphore getSemaphore(URL url) throws SESException {
if (logger.isInfoEnabled()) {
logger.info("getSemaphore - entry: '" + url.toExternalForm() + "'");
}
Semaphore semaphore = null;
HttpGet httpGet = null;
try {
Builder requestConfigBuilder = RequestConfig.copy(RequestConfig.DEFAULT)
.setSocketTimeout(getSocketTimeoutMS()).setConnectTimeout(getConnectionTimeoutMS())
.setConnectionRequestTimeout(getConnectionTimeoutMS());
if ((getProxyHost() != null) && (getProxyHost().length() > 0) && (getProxyPort() > 0)) {
HttpHost proxy = new HttpHost(getProxyHost(), getProxyPort(), "http");
requestConfigBuilder.setProxy(proxy);
}
RequestConfig requestConfig = requestConfigBuilder.build();
SSLContextBuilder builder = new SSLContextBuilder();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),
NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(sslsf).build();
if (logger.isDebugEnabled()) {
logger.debug("About to make HTTP request: " + url.toExternalForm());
}
httpGet = new HttpGet(url.toExternalForm());
if (getApiToken() != null) {
httpGet.addHeader("Authorization", getApiToken());
}
HttpResponse response = httpClient.execute(httpGet);
if (logger.isDebugEnabled()) {
logger.debug("HTTP request complete: " + url.toExternalForm());
}
if (response == null) {
throw new SESException("Null response from http client: " + url.toExternalForm());
}
if (response.getStatusLine() == null) {
throw new SESException("Null status line from http client: " + url.toExternalForm());
}
int statusCode = response.getStatusLine().getStatusCode();
if (logger.isDebugEnabled()) {
logger.debug("HTTP request complete: " + statusCode + " " + url.toExternalForm());
}
if (statusCode != HttpStatus.SC_OK) {
throw new SESException(
"Status code " + statusCode + " received from URL: " + url.toExternalForm());
}
HttpEntity entity = response.getEntity();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
entity.writeTo(byteArrayOutputStream);
if (saveFile != null) {
saveRequestAndResponse(saveFile, url, byteArrayOutputStream.toByteArray());
}
InputSource inputSource =
new InputSource(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
// Read the semaphore object from the returned XML
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setValidating(false);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document xmlDocument = documentBuilder.parse(inputSource);
semaphore = new Semaphore(xmlDocument.getDocumentElement());
} catch (ParserConfigurationException e) {
throw new SESException("ParserConfigurationException: " + e.getMessage());
} catch (IOException e) {
throw new SESException("IOException: " + e.getMessage());
} catch (SAXException e) {
throw new SESException("SAXException: " + e.getMessage());
} catch (KeyManagementException e) {
throw new SESException("KeyManagementException: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
throw new SESException("NoSuchAlgorithmException: " + e.getMessage());
} finally {
if (logger.isDebugEnabled()) {
logger.debug("getSemaphore - about to abort the connection " + url.toExternalForm());
}
if (httpGet != null) {
httpGet.abort();
}
if (logger.isDebugEnabled()) {
logger.debug("getSemaphore - about to release connection " + url.toExternalForm());
}
if (logger.isDebugEnabled()) {
logger.debug("getSemaphore - connection released " + url.toExternalForm());
}
}
if (logger.isInfoEnabled()) {
logger.info("getSemaphore - exit: '" + url.toExternalForm() + "'");
}
return semaphore;
}
private void saveRequestAndResponse(File saveFile, URL url, byte[] response) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(saveFile);
fileOutputStream.write(url.toExternalForm().getBytes("UTF-8"));
fileOutputStream.write("\n\n".getBytes());
fileOutputStream.write(response);
fileOutputStream.close();
} catch (Exception e) {
logger.warn(String.format("{} thrown saving request: {}", e.getClass().getSimpleName(),
e.getMessage()));
}
}
private class AlphabeticalTermComparator implements Comparator {
@Override
public int compare(Term term1, Term term2) {
if (term1 == null) {
return 1;
}
if (term2 == null) {
return -1;
}
if (term1.getName() == null) {
return 1;
}
if (term2.getName() == null) {
return -1;
}
if (term1.getName().getValue() == null) {
return 1;
}
if (term2.getName().getValue() == null) {
return -1;
}
return term1.getName().getValue().toLowerCase()
.compareTo(term2.getName().getValue().toLowerCase());
}
}
}