/* Copyright 2013 Rustici Software 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.rusticisoftware.tincan; import org.apache.commons.codec.binary.Base64; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.rusticisoftware.tincan.documents.ActivityProfileDocument; import com.rusticisoftware.tincan.documents.AgentProfileDocument; import com.rusticisoftware.tincan.documents.Document; import com.rusticisoftware.tincan.documents.StateDocument; import com.rusticisoftware.tincan.exceptions.*; import com.rusticisoftware.tincan.lrsresponses.*; import com.rusticisoftware.tincan.http.HTTPPart; import com.rusticisoftware.tincan.http.HTTPRequest; import com.rusticisoftware.tincan.http.HTTPResponse; import com.rusticisoftware.tincan.internal.MultipartParser; import com.rusticisoftware.tincan.json.Mapper; import com.rusticisoftware.tincan.json.StringOfJSON; import com.rusticisoftware.tincan.v10x.StatementsQuery; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.util.*; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.util.*; import org.eclipse.jetty.util.ssl.SslContextFactory; import lombok.Data; import lombok.NoArgsConstructor; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.*; /** * Class used to communicate with a TCAPI endpoint synchronously */ // TODO: handle extended on all requests @Data @NoArgsConstructor public class RemoteLRS implements LRS { private static long TIMEOUT_CONNECT = 5 * 1000; private static Boolean _ourClient = false; private static HttpClient _httpClient; private static HttpClient httpClient() throws Exception { if (_httpClient == null ) { _httpClient = new HttpClient(new SslContextFactory()); _httpClient.setConnectTimeout(TIMEOUT_CONNECT); _httpClient.setFollowRedirects(false); _httpClient.setCookieStore(new HttpCookieStore.Empty()); _httpClient.start(); _ourClient = true; } return _httpClient; } /** * Get the connect timeout value for the default HTTP client * * @deprecated set your own HTTP client using {@link #setHttpClient(HttpClient client)} */ @Deprecated public static long getHTTPClientConnectTimeout() { return _httpClient.getConnectTimeout(); } /** * Set the connect timeout value for the default HTTP client * * @deprecated set your own HTTP client using {@link #setHttpClient(HttpClient client)} */ @Deprecated public static void setHTTPClientConnectTimeout(long timeout) { _httpClient.setConnectTimeout(timeout); } public static void setHttpClient(HttpClient client) throws Exception { if (_httpClient != null && _ourClient) { _httpClient.stop(); _httpClient.destroy(); } _ourClient = false; _httpClient = client; } public static void destroy() throws Exception { setHttpClient(null); } private URL endpoint; private TCAPIVersion version = this.getVersion(); private String username; private String password; private String auth; private HashMap extended; private Boolean prettyJSON = false; public RemoteLRS(TCAPIVersion version) { this.setVersion(version); } private void setEndpoint(URL url) throws MalformedURLException { String strUrl = url.toString(); if (! strUrl.substring(strUrl.length() - 1).equals("/")) { strUrl += "/"; url = new URL(strUrl); } this.endpoint = url; } public void setEndpoint(String str) throws MalformedURLException { this.setEndpoint(new URL(str)); } public void setUsername(String str) { this.username = str; if (this.password != null) { this.setAuth(this.calculateBasicAuth()); } } public void setPassword(String str) { this.password = str; if (this.username != null) { this.setAuth(this.calculateBasicAuth()); } } /** * Alternate Getter method for readability of code */ public Boolean usePrettyJSON() { return this.getPrettyJSON(); } public String calculateBasicAuth() { return "Basic " + Base64.encodeBase64String( (this.getUsername() + ":" + this.getPassword()).getBytes() ); } private HTTPResponse makeSyncRequest(HTTPRequest req) { String url; if (req.getResource().toLowerCase().startsWith("http")) { url = req.getResource(); } else { url = this.endpoint.toString(); if (! url.endsWith("/") && ! req.getResource().startsWith("/")) { url += "/"; } url += req.getResource(); } if (req.getQueryParams() != null) { String qs = ""; Iterator it = req.getQueryParams().entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); if (qs != "") { qs += "&"; } try { qs += URLEncoder.encode(entry.getKey().toString(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue().toString(), "UTF-8"); } catch (UnsupportedEncodingException ex) {} } if (qs != "") { url += "?" + qs; } } final HTTPResponse response = new HTTPResponse(); try { final Request webReq = httpClient(). newRequest(url). method(HttpMethod.fromString(req.getMethod())). header("X-Experience-API-Version", this.version.toString()); if (this.auth != null) { webReq.header("Authorization", this.auth); } if (req.getHeaders() != null) { Iterator it = req.getHeaders().entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); webReq.header(entry.getKey().toString(), entry.getValue().toString()); } } OutputStreamContentProvider content = new OutputStreamContentProvider(); FutureResponseListener listener = new FutureResponseListener(webReq); try (OutputStream output = content.getOutputStream()) { if (req.getPartList() == null || req.getPartList().size() <= 0) { if (req.getContentType() != null) { webReq.header("Content-Type", req.getContentType()); } else if (req.getMethod() != "GET") { webReq.header("Content-Type", "application/octet-stream"); } webReq.content(content).send(listener); if (req.getContent() != null) { output.write(req.getContent()); } output.close(); } else { MultiPartOutputStream multiout = new MultiPartOutputStream(output); webReq.header("Content-Type", "multipart/mixed; boundary=" + multiout.getBoundary()); webReq.content(content).send(listener); if (req.getContentType() != null) { multiout.startPart(req.getContentType()); } else { multiout.startPart("application/octet-stream"); } if (req.getContent() != null) { multiout.write(req.getContent()); } for (HTTPPart part : req.getPartList()) { multiout.startPart(part.getContentType(), new String[]{ "Content-Transfer-Encoding: binary", "X-Experience-API-Hash: " + part.getSha2() }); multiout.write(part.getContent()); } multiout.close(); } } ContentResponse httpResponse = listener.get(); response.setStatus(httpResponse.getStatus()); response.setStatusMsg(httpResponse.getReason()); for (HttpField header : httpResponse.getHeaders()) { response.setHeader(header.getName(), header.getValue()); } if (response.getContentType() != null && response.getContentType().contains("multipart/mixed")) { String boundary = response.getContentType().split("boundary=")[1]; MultipartParser responseHandler = new MultipartParser(listener.getContent(), boundary); ArrayList<Statement> statements = new ArrayList<Statement>(); for (int i = 1; i < responseHandler.getSections().size(); i++) { responseHandler.parsePart(i); if (i == 1) { if (responseHandler.getHeaders().get("Content-Type").contains("application/json")) { JsonNode statementsNode = (new StringOfJSON(new String(responseHandler.getContent())).toJSONNode()); if (statementsNode.findPath("statements").isMissingNode()) { statements.add(new Statement(statementsNode)); } else { statementsNode = statementsNode.findPath("statements"); for (JsonNode obj : statementsNode) { statements.add(new Statement(obj)); } } } else { throw new Exception("The first part of this response had a Content-Type other than \"application/json\""); } } else { response.setAttachment(responseHandler.getHeaders().get("X-Experience-API-Hash"), responseHandler.getContent()); } } StatementsResult responseStatements = new StatementsResult(); responseStatements.setStatements(statements); response.setContentBytes(responseStatements.toJSONNode(TCAPIVersion.V101).toString().getBytes()); } else { response.setContentBytes(listener.getContent()); } } catch (Exception ex) { response.setStatus(400); response.setStatusMsg("Exception in RemoteLRS.makeSyncRequest(): " + ex); } return response; } private StatementLRSResponse getStatement(HashMap<String, String> params) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.GET.asString()); request.setResource("statements"); request.setQueryParams(params); HTTPResponse response = makeSyncRequest(request); int status = response.getStatus(); StatementLRSResponse lrsResponse = new StatementLRSResponse(request, response); if (status == 200) { lrsResponse.setSuccess(true); try { JsonNode contentNode = (new StringOfJSON(response.getContent())).toJSONNode(); if (! (contentNode.findPath("statements").isMissingNode())) { contentNode = contentNode.findPath("statements").get(0); } Statement stmt = new Statement (contentNode); for (Map.Entry<String, byte[]> entry : response.getAttachments().entrySet()) { for (Attachment a : stmt.getAttachments()) { if (entry.getKey().equals(a.getSha2())) { a.setContent(entry.getValue()); } } } lrsResponse.setContent(stmt); } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } private LRSResponse getDocument(String resource, Map<String, String> queryParams, Document document) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.GET.asString()); request.setResource(resource); request.setQueryParams(queryParams); HTTPResponse response = makeSyncRequest(request); LRSResponse lrsResponse = new LRSResponse(request, response); if (response.getStatus() == 200) { document.setContent(response.getContentBytes()); document.setContentType(response.getContentType()); document.setTimestamp(response.getLastModified()); document.setEtag(response.getEtag()); lrsResponse.setSuccess(true); } else if (response.getStatus() == 404) { lrsResponse.setSuccess(true); } else { lrsResponse.setSuccess(false); } return lrsResponse; } private LRSResponse deleteDocument(String resource, Map<String, String> queryParams) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.DELETE.asString()); request.setResource(resource); request.setQueryParams(queryParams); HTTPResponse response = makeSyncRequest(request); LRSResponse lrsResponse = new LRSResponse(request, response); if (response.getStatus() == 204) { lrsResponse.setSuccess(true); } else { lrsResponse.setSuccess(false); } return lrsResponse; } private LRSResponse saveDocument(String resource, Map<String, String> queryParams, Document document) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.PUT.asString()); request.setResource(resource); request.setQueryParams(queryParams); request.setContentType(document.getContentType()); request.setContent(document.getContent()); if (document.getEtag() != null) { request.setHeaders(new HashMap<String, String>()); request.getHeaders().put("If-Match", document.getEtag()); } HTTPResponse response = makeSyncRequest(request); LRSResponse lrsResponse = new LRSResponse(request, response); if (response.getStatus() == 204) { lrsResponse.setSuccess(true); } else { lrsResponse.setSuccess(false); } return lrsResponse; } private LRSResponse updateDocument(String resource, Map<String, String> queryParams, Document document) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.POST.asString()); request.setResource(resource); request.setQueryParams(queryParams); request.setContentType(document.getContentType()); request.setContent(document.getContent()); if (document.getEtag() != null) { request.setHeaders(new HashMap<String, String>()); request.getHeaders().put("If-Match", document.getEtag()); } HTTPResponse response = makeSyncRequest(request); LRSResponse lrsResponse = new LRSResponse(request, response); if (response.getStatus() == 204) { lrsResponse.setSuccess(true); } else { lrsResponse.setSuccess(false); } return lrsResponse; } private ProfileKeysLRSResponse getProfileKeys(String resource, HashMap<String, String> queryParams) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.GET.asString()); request.setResource(resource); request.setQueryParams(queryParams); HTTPResponse response = makeSyncRequest(request); ProfileKeysLRSResponse lrsResponse = new ProfileKeysLRSResponse(request, response); if (response.getStatus() == 200) { lrsResponse.setSuccess(true); try { Iterator it = Mapper.getInstance().readValue(response.getContent(), ArrayNode.class).elements(); lrsResponse.setContent(new ArrayList<String>()); while (it.hasNext()) { lrsResponse.getContent().add(it.next().toString()); } } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public AboutLRSResponse about() { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.GET.asString()); request.setResource("about"); HTTPResponse response = makeSyncRequest(request); int status = response.getStatus(); AboutLRSResponse lrsResponse = new AboutLRSResponse(request, response); if (status == 200) { lrsResponse.setSuccess(true); try { lrsResponse.setContent(new About(response.getContent())); } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public StatementLRSResponse saveStatement(Statement statement) { StatementLRSResponse lrsResponse = new StatementLRSResponse(); lrsResponse.setRequest(new HTTPRequest()); lrsResponse.getRequest().setResource("statements"); lrsResponse.getRequest().setContentType("application/json"); try { lrsResponse.getRequest().setContent(statement.toJSON(this.getVersion(), this.usePrettyJSON()).getBytes("UTF-8")); } catch (IOException ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); return lrsResponse; } if (statement.hasAttachmentsWithContent()) { lrsResponse.getRequest().setPartList(statement.getPartList()); } if (statement.getId() == null) { lrsResponse.getRequest().setMethod(HttpMethod.POST.asString()); } else { lrsResponse.getRequest().setMethod(HttpMethod.PUT.asString()); lrsResponse.getRequest().setQueryParams(new HashMap<String, String>()); lrsResponse.getRequest().getQueryParams().put("statementId", statement.getId().toString()); } lrsResponse.setResponse(makeSyncRequest(lrsResponse.getRequest())); int status = lrsResponse.getResponse().getStatus(); lrsResponse.setContent(statement); // TODO: handle 409 conflict, etc. if (status == 200) { lrsResponse.setSuccess(true); String content = lrsResponse.getResponse().getContent(); try { lrsResponse.getContent().setId(UUID.fromString(Mapper.getInstance().readValue(content, ArrayNode.class).get(0).textValue())); } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else if (status == 204) { lrsResponse.setSuccess(true); } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public StatementsResultLRSResponse saveStatements(List<Statement> statements) { StatementsResultLRSResponse lrsResponse = new StatementsResultLRSResponse(); if (statements.size() == 0) { lrsResponse.setSuccess(true); return lrsResponse; } ArrayNode rootNode = Mapper.getInstance().createArrayNode(); for (Statement statement : statements) { rootNode.add(statement.toJSONNode(version)); } lrsResponse.setRequest(new HTTPRequest()); lrsResponse.getRequest().setResource("statements"); lrsResponse.getRequest().setMethod(HttpMethod.POST.asString()); lrsResponse.getRequest().setContentType("application/json"); try { lrsResponse.getRequest().setContent(Mapper.getWriter(this.usePrettyJSON()).writeValueAsBytes(rootNode)); } catch (JsonProcessingException ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); return lrsResponse; } lrsResponse.getRequest().setPartList(new ArrayList<HTTPPart>()); for (Statement statement: statements) { if (statement.hasAttachmentsWithContent()) { lrsResponse.getRequest().getPartList().addAll(statement.getPartList()); } } HTTPResponse response = makeSyncRequest(lrsResponse.getRequest()); int status = response.getStatus(); lrsResponse.setResponse(response); if (status == 200) { lrsResponse.setSuccess(true); lrsResponse.setContent(new StatementsResult()); try { Iterator it = Mapper.getInstance().readValue(response.getContent(), ArrayNode.class).elements(); for (int i = 0; it.hasNext(); ++i) { lrsResponse.getContent().getStatements().add(statements.get(i)); lrsResponse.getContent().getStatements().get(i).setId(UUID.fromString(((JsonNode) it.next()).textValue())); } } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public StatementLRSResponse retrieveStatement(String id) { return retrieveStatement(id, false); } @Override public StatementLRSResponse retrieveVoidedStatement(String id) { return retrieveVoidedStatement(id, false); } @Override public StatementLRSResponse retrieveStatement(String id, boolean attachments) { HashMap<String, String> params = new HashMap<String, String>(); params.put("statementId", id); params.put("attachments", String.valueOf(attachments)); return getStatement(params); } @Override public StatementLRSResponse retrieveVoidedStatement(String id, boolean attachments) { String paramName = (this.getVersion() == TCAPIVersion.V095) ? "statementId" : "voidedStatementId"; HashMap<String, String> params = new HashMap<String, String>(); params.put(paramName, id); params.put("attachments", String.valueOf(attachments)); return getStatement(params); } @Override public StatementsResultLRSResponse queryStatements(StatementsQueryInterface query) { // Setup empty query object if null was passed in if (query == null) { query = (this.getVersion() == TCAPIVersion.V095) ? new com.rusticisoftware.tincan.v095.StatementsQuery() : new StatementsQuery(); } // Choke if the query parameters don't match the LRS version if (this.getVersion() != query.getVersion()) { throw new IncompatibleTCAPIVersion( "Attempted to issue " + this.getVersion() + " query using a " + query.getVersion() + " set of query parameters."); } StatementsResultLRSResponse lrsResponse = new StatementsResultLRSResponse(); lrsResponse.setRequest(new HTTPRequest()); lrsResponse.getRequest().setMethod(HttpMethod.GET.asString()); lrsResponse.getRequest().setResource("statements"); try { lrsResponse.getRequest().setQueryParams(query.toParameterMap()); } catch (IOException ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); return lrsResponse; } HTTPResponse response = makeSyncRequest(lrsResponse.getRequest()); lrsResponse.setResponse(response); if (response.getStatus() == 200) { lrsResponse.setSuccess(true); try { lrsResponse.setContent(new StatementsResult(new StringOfJSON(response.getContent()))); for (Statement stmt : lrsResponse.getContent().getStatements()) { if (stmt.hasAttachments()) { for (Map.Entry<String, byte[]> entry : response.getAttachments().entrySet()) { for (Attachment a : stmt.getAttachments()) { if (entry.getKey().equals(a.getSha2())) { a.setContent(entry.getValue()); } } } } } } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public StatementsResultLRSResponse moreStatements(String moreURL) { if (moreURL == null) { return null; } // moreURL is relative to the endpoint's server root URL endpoint = this.getEndpoint(); String url = endpoint.getProtocol() + "://" + endpoint.getHost() + (endpoint.getPort() == -1 ? "" : ":" + endpoint.getPort()) + moreURL; HTTPRequest request = new HTTPRequest(); request.setResource(url); request.setMethod(HttpMethod.GET.asString()); HTTPResponse response = makeSyncRequest(request); StatementsResultLRSResponse lrsResponse = new StatementsResultLRSResponse(request, response); if (response.getStatus() == 200) { lrsResponse.setSuccess(true); try { lrsResponse.setContent(new StatementsResult(new StringOfJSON(response.getContent()))); } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public ProfileKeysLRSResponse retrieveStateIds(Activity activity, Agent agent, UUID registration) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("activityId", activity.getId().toString()); queryParams.put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); if (registration != null) { queryParams.put("registration", registration.toString()); } return getProfileKeys("activities/state", queryParams); } @Override public StateLRSResponse retrieveState(String id, Activity activity, Agent agent, UUID registration) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("stateId", id); queryParams.put("activityId", activity.getId().toString()); queryParams.put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); StateDocument stateDocument = new StateDocument(); stateDocument.setId(id); stateDocument.setActivity(activity); stateDocument.setAgent(agent); LRSResponse lrsResp = getDocument("activities/state", queryParams, stateDocument); StateLRSResponse lrsResponse = new StateLRSResponse(lrsResp.getRequest(), lrsResp.getResponse()); lrsResponse.setSuccess(lrsResp.getSuccess()); if (lrsResponse.getResponse().getStatus() == 200) { lrsResponse.setContent(stateDocument); } return lrsResponse; } @Override public LRSResponse saveState(StateDocument state) { HashMap<String,String> queryParams = new HashMap<String,String>(); queryParams.put("stateId", state.getId()); queryParams.put("activityId", state.getActivity().getId().toString()); queryParams.put("agent", state.getAgent().toJSON(this.getVersion(), this.usePrettyJSON())); return saveDocument("activities/state", queryParams, state); } @Override public LRSResponse updateState(StateDocument state) { HashMap<String,String> queryParams = new HashMap<String,String>(); queryParams.put("stateId", state.getId()); queryParams.put("activityId", state.getActivity().getId().toString()); queryParams.put("agent", state.getAgent().toJSON(this.getVersion(), this.usePrettyJSON())); return updateDocument("activities/state", queryParams, state); } @Override public LRSResponse deleteState(StateDocument state) { Map queryParams = new HashMap<String, String>(); queryParams.put("stateId", state.getId()); queryParams.put("activityId", state.getActivity().getId().toString()); queryParams.put("agent", state.getAgent().toJSON()); if (state.getRegistration() != null ) { queryParams.put("registration", state.getRegistration().toString()); } return deleteDocument("activities/state", queryParams); } @Override public LRSResponse clearState(Activity activity, Agent agent, UUID registration) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("activityId", activity.getId().toString()); queryParams.put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); if (registration != null) { queryParams.put("registration", registration.toString()); } return deleteDocument("activities/state", queryParams); } @Override public ActivityLRSResponse retrieveActivity(Activity activity) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.GET.asString()); request.setResource("activities"); request.setQueryParams(new HashMap<String, String>()); request.getQueryParams().put("activityId", activity.getId().toString()); HTTPResponse response = makeSyncRequest(request); int status = response.getStatus(); ActivityLRSResponse lrsResponse = new ActivityLRSResponse(request, response); if (status == 200) { lrsResponse.setSuccess(true); try { lrsResponse.setContent(new Activity(new StringOfJSON(response.getContent()))); } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public ProfileKeysLRSResponse retrieveActivityProfileIds(Activity activity) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("activityId", activity.getId().toString()); return getProfileKeys("activities/profile", queryParams); } @Override public ActivityProfileLRSResponse retrieveActivityProfile(String id, Activity activity) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", id); queryParams.put("activityId", activity.getId().toString()); ActivityProfileDocument profileDocument = new ActivityProfileDocument(); profileDocument.setId(id); profileDocument.setActivity(activity); LRSResponse lrsResp = getDocument("activities/profile", queryParams, profileDocument); ActivityProfileLRSResponse lrsResponse = new ActivityProfileLRSResponse(lrsResp.getRequest(), lrsResp.getResponse()); lrsResponse.setSuccess(lrsResp.getSuccess()); if (lrsResponse.getResponse().getStatus() == 200) { lrsResponse.setContent(profileDocument); } return lrsResponse; } @Override public LRSResponse saveActivityProfile(ActivityProfileDocument profile) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", profile.getId()); queryParams.put("activityId", profile.getActivity().getId().toString()); return saveDocument("activities/profile", queryParams, profile); } @Override public LRSResponse updateActivityProfile(ActivityProfileDocument profile) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", profile.getId()); queryParams.put("activityId", profile.getActivity().getId().toString()); return updateDocument("activities/profile", queryParams, profile); } @Override public LRSResponse deleteActivityProfile(ActivityProfileDocument profile) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", profile.getId()); queryParams.put("activityId", profile.getActivity().getId().toString()); // TODO: need to pass Etag? return deleteDocument("activities/profile", queryParams); } @Override public PersonLRSResponse retrievePerson(Agent agent) { HTTPRequest request = new HTTPRequest(); request.setMethod(HttpMethod.GET.asString()); request.setResource("agents"); request.setQueryParams(new HashMap<String, String>()); request.getQueryParams().put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); HTTPResponse response = makeSyncRequest(request); int status = response.getStatus(); PersonLRSResponse lrsResponse = new PersonLRSResponse(request, response); if (status == 200) { lrsResponse.setSuccess(true); try { lrsResponse.setContent(new Person(new StringOfJSON(response.getContent()))); } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; } @Override public ProfileKeysLRSResponse retrieveAgentProfileIds(Agent agent) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); return getProfileKeys("agents/profile", queryParams); } @Override public AgentProfileLRSResponse retrieveAgentProfile(String id, Agent agent) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", id); queryParams.put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); AgentProfileDocument profileDocument = new AgentProfileDocument(); profileDocument.setId(id); profileDocument.setAgent(agent); LRSResponse lrsResp = getDocument("agents/profile", queryParams, profileDocument); AgentProfileLRSResponse lrsResponse = new AgentProfileLRSResponse(lrsResp.getRequest(), lrsResp.getResponse()); lrsResponse.setSuccess(lrsResp.getSuccess()); if (lrsResponse.getResponse().getStatus() == 200) { lrsResponse.setContent(profileDocument); } return lrsResponse; } @Override public LRSResponse saveAgentProfile(AgentProfileDocument profile) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", profile.getId()); queryParams.put("agent", profile.getAgent().toJSON(this.getVersion(), this.usePrettyJSON())); return saveDocument("agents/profile", queryParams, profile); } @Override public LRSResponse updateAgentProfile(AgentProfileDocument profile) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", profile.getId()); queryParams.put("agent", profile.getAgent().toJSON(this.getVersion(), this.usePrettyJSON())); return updateDocument("agents/profile", queryParams, profile); } @Override public LRSResponse deleteAgentProfile(AgentProfileDocument profile) { HashMap<String, String> queryParams = new HashMap<String, String>(); queryParams.put("profileId", profile.getId()); queryParams.put("agent", profile.getAgent().toJSON(this.getVersion(), this.usePrettyJSON())); // TODO: need to pass Etag? return deleteDocument("agents/profile", queryParams); } }