responseClass)
+ throws HttpRosetteAPIException {
+ throw new UnsupportedOperationException("Asynchronous operations are not yet supported");
+ }
+
+ /**
+ * Sends a GET request to Analytics API.
+ *
+ * Returns a Response.
+ *
+ * @param urlStr Analytics API end point.
+ * @param clazz Response class
+ * @return Response
+ * @throws HttpRosetteAPIException
+ */
+ private T sendGetRequest(String urlStr, Class clazz) throws HttpRosetteAPIException {
+ HttpGet get = new HttpGet(urlStr);
+ for (Header header : additionalHeaders) {
+ get.addHeader(header);
+ }
+
+ try (CloseableHttpResponse httpResponse = httpClient.execute(get)) {
+ T resp = getResponse(httpResponse, clazz);
+ responseHeadersToExtendedInformation(resp, httpResponse);
+ return resp;
+ } catch (IOException e) {
+ throw new RosetteRuntimeException(IO_EXCEPTION_MESSAGE, e);
+ }
+ }
+
+ /**
+ * Sends a POST request to Analytics API.
+ *
+ * Returns a Response.
+ *
+ * @param urlStr Analytics API end point.
+ * @param clazz Response class
+ * @return Response
+ * @throws IOException
+ */
+ private T sendPostRequest(Object request, String urlStr, Class clazz)
+ throws IOException, URISyntaxException {
+ ObjectWriter writer = mapper.writer().without(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+ boolean notPlainText = false;
+ if (request instanceof DocumentRequest) {
+ Object rawContent = ((DocumentRequest) request).getRawContent();
+ if (rawContent instanceof String) {
+ writer = writer.withView(DocumentRequestMixin.Views.Content.class);
+ } else if (rawContent != null) {
+ notPlainText = true;
+ }
+ } else if (request instanceof AdmRequest) {
+ notPlainText = true;
+ }
+
+ URIBuilder uriBuilder = new URIBuilder(urlStr);
+
+ if (AnnotatedText.class.isAssignableFrom(clazz) || AdmResponse.class.equals(clazz)) {
+ //TODO: change output=rosette to Accept: model/vnd.rosette.annotated-data-model header
+ uriBuilder.addParameter("output", "rosette");
+ }
+
+ final ObjectWriter finalWriter = writer;
+
+ HttpPost post = new HttpPost(uriBuilder.build());
+ for (Header header : additionalHeaders) {
+ post.addHeader(header);
+ }
+
+ //TODO: add compression!
+ if (notPlainText) {
+ setupMultipartRequest((Request) request, finalWriter, post);
+ } else {
+ setupPlainRequest(request, finalWriter, post);
+ }
+
+ HttpRosetteAPIException lastException = null;
+ int numRetries = this.failureRetries;
+ while (numRetries-- > 0) {
+ try (CloseableHttpResponse response = httpClient.execute(post)) {
+ T resp = getResponse(response, clazz);
+ // TODO: Remove in a future release
+ Header ridHeader = response.getFirstHeader("X-RosetteAPI-DocumentRequest-Id");
+ if (ridHeader != null && ridHeader.getValue() != null) {
+ LOG.debug("DocumentRequest ID {}", ridHeader.getValue());
+ }
+ Header bsidHeader = response.getFirstHeader("X-BabelStreetAPI-DocumentRequest-Id");
+ if (bsidHeader != null && bsidHeader.getValue() != null) {
+ LOG.debug("DocumentRequest ID {}", bsidHeader.getValue());
+ }
+ if (resp instanceof Response) {
+ responseHeadersToExtendedInformation((Response)resp, response);
+ }
+ return resp;
+ } catch (HttpRosetteAPIException e) {
+ // only 5xx errors are worthy retrying, others throw right away
+ if (e.getHttpStatusCode() < 500) {
+ throw e;
+ } else {
+ lastException = e;
+ }
+ }
+ }
+ throw lastException;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void responseHeadersToExtendedInformation(T resp, HttpResponse response) {
+ for (Header header : response.getAllHeaders()) {
+ if (resp.getExtendedInformation() != null
+ && resp.getExtendedInformation().containsKey(header.getName())) {
+ Set