diff --git a/pom.xml b/pom.xml index 55a07976..48cdc54e 100644 --- a/pom.xml +++ b/pom.xml @@ -56,13 +56,13 @@ 1.6.14 - 3.1 + 5.4.1 1.3.2 1.3 2.3.1 5.7.2 2.8.0 - + 2.18.1 UTF-8 UTF-8 diff --git a/set-client/pom.xml b/set-client/pom.xml index cc1e9c97..8055cad6 100644 --- a/set-client/pom.xml +++ b/set-client/pom.xml @@ -36,13 +36,13 @@ jettison ${version.jettison} - + + - org.springframework - spring-webmvc - + org.glassfish.jersey.core + jersey-common + 3.1.2 diff --git a/set-client/src/main/java/eu/europeana/set/client/BaseUserSetApi.java b/set-client/src/main/java/eu/europeana/set/client/BaseUserSetApi.java index c366b312..c2e0a7fd 100644 --- a/set-client/src/main/java/eu/europeana/set/client/BaseUserSetApi.java +++ b/set-client/src/main/java/eu/europeana/set/client/BaseUserSetApi.java @@ -2,6 +2,16 @@ import eu.europeana.set.client.config.ClientConfiguration; import eu.europeana.set.client.connection.UserSetApiConnection; +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.common.http.HttpConnection; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + +import java.io.IOException; /** * Base class for client API @@ -12,25 +22,65 @@ public class BaseUserSetApi { private final ClientConfiguration configuration; - protected final UserSetApiConnection apiConnection; - - protected BaseUserSetApi(ClientConfiguration configuration, UserSetApiConnection apiConnection) { - this.configuration = configuration; - this.apiConnection = apiConnection; + private UserSetApiConnection apiConnection; + + /** + * Creates BaseUserSetApi instance with client configuration + * This allows user to insert property file + * @param configuration + * @throws SetApiClientException + */ + protected BaseUserSetApi(ClientConfiguration configuration) throws SetApiClientException { + this.configuration = configuration; + if (this.configuration.getServiceUri() == null) { + throw new SetApiClientException(" Set Api Endpoint not provided !!!"); + } + + if (this.configuration.getOauthServiceUri() == null || this.configuration.getOauthRequestParams() == null) { + throw new SetApiClientException("Oauth uri and param not provided !!!"); + } + + this.apiConnection = new UserSetApiConnection( + this.configuration.getServiceUri(), + this.configuration.getApiKey(), + getOauthToken(this.configuration.getOauthServiceUri(), this.configuration.getOauthRequestParams())); } - protected BaseUserSetApi() { - this.configuration = ClientConfiguration.getInstance(); - this.apiConnection = new UserSetApiConnection(getConfiguration().getServiceUri(), - getConfiguration().getApiKey()); + /** + * Constructor + * @throws SetApiClientException + */ + public BaseUserSetApi() throws SetApiClientException { + this(new ClientConfiguration()); + } + + private String getOauthToken(String oauthServiceUri, String oauthRequestParams ) throws SetApiClientException{ + try { + String accessToken = "access_token"; + HttpConnection connection = new HttpConnection(); + + CloseableHttpResponse response = connection.post(oauthServiceUri, oauthRequestParams, "application/x-www-form-urlencoded", null); + String body = EntityUtils.toString(response.getEntity()); + if (HttpStatus.SC_OK == response.getCode()) { + JSONObject json = new JSONObject(body); + if (json.has(accessToken)) { + return "Bearer " + json.getString(accessToken); + } else { + throw new SetApiClientException("Cannot extract authentication token from reponse:" + body); + } + } else { + throw new SetApiClientException("Error occured when calling oath service! " + response); + } + } catch (IOException | JSONException | ParseException e) { + throw new SetApiClientException("Cannot retrieve authentication token!", 0 , e); + } } public UserSetApiConnection getApiConnection() { - return apiConnection; + return apiConnection; } public ClientConfiguration getConfiguration() { - return configuration; + return configuration; } - } diff --git a/set-client/src/main/java/eu/europeana/set/client/UserSetApiClient.java b/set-client/src/main/java/eu/europeana/set/client/UserSetApiClient.java new file mode 100644 index 00000000..5ae1d68b --- /dev/null +++ b/set-client/src/main/java/eu/europeana/set/client/UserSetApiClient.java @@ -0,0 +1,77 @@ +package eu.europeana.set.client; + +import eu.europeana.set.client.config.ClientConfiguration; +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.client.model.result.RecordPreview; +import eu.europeana.set.client.web.SearchUserSetApi; +import eu.europeana.set.client.web.WebUserSetApi; +import eu.europeana.set.definitions.model.UserSet; + +import java.util.List; + +/** + * Implementation of client api + * + * @author GordeaS + * Refractored by Srishti Singh + */ + +public class UserSetApiClient extends BaseUserSetApi { + + private final WebUserSetClient webUserSetClient; + private final SearchUserSetClient searchUserSetClient; + + public UserSetApiClient(ClientConfiguration configuration) throws SetApiClientException { + super(configuration); + this.webUserSetClient = new WebUserSetClient(); + this.searchUserSetClient = new SearchUserSetClient(); + } + + public WebUserSetApi getWebUserSetApi() { + return webUserSetClient; + } + + public SearchUserSetApi getSearchUserSetApi() { + return searchUserSetClient; + } + + /** + * Web User Set Client class + */ + private class WebUserSetClient implements WebUserSetApi { + @Override + public UserSet createUserSet(String set, String profile) throws SetApiClientException { + return getApiConnection().createUserSet(set, profile); + + } + + @Override + public String deleteUserSet(String identifier) throws SetApiClientException { + return getApiConnection().deleteUserSet(identifier); + } + + @Override + public UserSet getUserSet(String identifier, String profile) throws SetApiClientException { + return getApiConnection().getUserSet(identifier, profile); + } + + @Override + public UserSet updateUserSet(String identifier, String set, String profile) throws SetApiClientException { + return getApiConnection().updateUserSet(identifier, set, profile); + } + + @Override + public List getPaginationUserSet(String identifier, String sort, String sortOrder, String page, String pageSize, String profile) throws SetApiClientException { + return getApiConnection().getPaginationUserSet(identifier, sort, sortOrder, page, pageSize, profile); + } + } + + private class SearchUserSetClient implements SearchUserSetApi { + + @Override + public List searchUserSet(String query, String[] qf, + String sort, String page, String pageSize, String facet, int facetLimit, String profile) throws SetApiClientException { + return getApiConnection().searchUserSet(query, qf, sort, page, pageSize, facet, facetLimit, profile); + } + } +} diff --git a/set-client/src/main/java/eu/europeana/set/client/config/ClientConfiguration.java b/set-client/src/main/java/eu/europeana/set/client/config/ClientConfiguration.java index aef7c72d..bd7e788b 100644 --- a/set-client/src/main/java/eu/europeana/set/client/config/ClientConfiguration.java +++ b/set-client/src/main/java/eu/europeana/set/client/config/ClientConfiguration.java @@ -1,126 +1,76 @@ package eu.europeana.set.client.config; import java.io.IOException; -import java.io.InputStream; import java.util.Properties; -import eu.europeana.set.client.exception.TechnicalRuntimeException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** * configuration for accessing remote api - * * @author GordeaS - * */ public final class ClientConfiguration { + private static final Logger LOGGER = LogManager.getLogger(ClientConfiguration.class); + protected static final String SET_CLIENT_PROPERTIES_FILE = "/set-client.user.properties"; - protected static final String PROP_SET_API_KEY = "set.api.key"; - protected static final String PROP_SET_SERVICE_URI = "set.service.uri"; - protected static final String PROP_OAUTH_SERVICE_URI = "oauth.service.uri"; - protected static final String PROP_OAUTH_REQUEST_PARAMS = "oauth.token.request.params"; + public static final String PROP_SET_API_KEY = "set.api.key"; + public static final String PROP_SET_SERVICE_URI = "set.service.uri"; + public static final String PROP_OAUTH_SERVICE_URI = "oauth.service.uri"; + public static final String PROP_OAUTH_REQUEST_PARAMS = "oauth.token.request.params"; private Properties properties; - private static ClientConfiguration singleton; - - /** - * Hide the default constructor - */ - private ClientConfiguration() { - } /** - * Accessor method for the singleton - * - * @return + * Creates ClientConfiguration instance with set client properties */ - public static synchronized ClientConfiguration getInstance() { - if (singleton == null) { - singleton = new ClientConfiguration(); - singleton.loadProperties(); - } - - return singleton; + public ClientConfiguration() { + loadProperties(SET_CLIENT_PROPERTIES_FILE); } /** - * Laizy loading of configuration properties + * CConstructor to inject properties + * @param properties */ - public synchronized void loadProperties() { - - try { - properties = new Properties(); - InputStream resourceAsStream = getClass().getResourceAsStream(SET_CLIENT_PROPERTIES_FILE); - if (resourceAsStream == null) { - throw new TechnicalRuntimeException( - "No properties file found in classpath! " + SET_CLIENT_PROPERTIES_FILE); - } - getProperties().load(resourceAsStream); - - } catch (RuntimeException | IOException e) { - throw new TechnicalRuntimeException("Cannot read configuration file: " + SET_CLIENT_PROPERTIES_FILE, e); - } - + public ClientConfiguration(Properties properties) { + this.properties = properties; } - /** - * provides access to the configuration properties. It is not recommended to use - * the properties directly, but the - * - * @return - */ - Properties getProperties() { - return properties; + private Properties loadProperties(String propertiesFile) { + try { + properties = new Properties(); + properties.load(getClass().getResourceAsStream(propertiesFile)); + } catch (IOException e) { + LOGGER.error("Error loading the properties file {}", propertiesFile); + } + return properties; } - /** - * - * @return the name of the file storing the client configuration - */ String getConfigurationFile() { return SET_CLIENT_PROPERTIES_FILE; } - /** - * This method provides access to the API key defined in the configuration file - * - * @see PROP_EUROPEANA_API_KEY - * - * @return - */ public String getApiKey() { - return getProperties().getProperty(PROP_SET_API_KEY); + return getProperty(PROP_SET_API_KEY); } - /** - * This method provides access to the search uri value defined in the - * configuration file - * - * @see PROP_EUROPEANA_SEARCH_URI - * - * @return - */ + public String getServiceUri() { - return getProperties().getProperty(PROP_SET_SERVICE_URI); + return getProperty(PROP_SET_SERVICE_URI); } - /** - * This method returns the uri of the oauth service as configured in - * - * @return - */ public String getOauthServiceUri() { - return getProperties().getProperty(PROP_OAUTH_SERVICE_URI); + return getProperty(PROP_OAUTH_SERVICE_URI); } - /** - * This method returns the request params needed to acquire a new token - * - * @return - */ public String getOauthRequestParams() { - return getProperties().getProperty(PROP_OAUTH_REQUEST_PARAMS); + return getProperty(PROP_OAUTH_REQUEST_PARAMS); + } + + private String getProperty(String propertyName) { + return properties.getProperty(propertyName); } } diff --git a/set-client/src/main/java/eu/europeana/set/client/connection/BaseApiConnection.java b/set-client/src/main/java/eu/europeana/set/client/connection/BaseApiConnection.java index 02383d75..31140588 100644 --- a/set-client/src/main/java/eu/europeana/set/client/connection/BaseApiConnection.java +++ b/set-client/src/main/java/eu/europeana/set/client/connection/BaseApiConnection.java @@ -1,156 +1,356 @@ package eu.europeana.set.client.connection; -import java.io.IOException; - +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import eu.europeana.api.commons.definitions.search.result.impl.ResultsPageImpl; +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.client.json.UserSetDeserializer; +import eu.europeana.set.client.model.result.AbstractUserSetApiResponse; +import eu.europeana.set.client.model.result.RecordPreview; +import eu.europeana.set.common.http.HttpConnection; +import eu.europeana.set.definitions.model.UserSet; +import eu.europeana.set.definitions.model.agent.Agent; +import eu.europeana.set.client.json.AgentDeserializer; +import eu.europeana.set.definitions.model.impl.BaseUserSet; +import eu.europeana.set.definitions.model.vocabulary.ProfileConstants; +import eu.europeana.set.definitions.model.vocabulary.WebUserSetFields; +import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.net.URIBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.springframework.http.ResponseEntity; -import eu.europeana.set.common.http.HttpConnection; -import eu.europeana.set.definitions.model.vocabulary.WebUserSetFields; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static eu.europeana.api.commons.definitions.vocabulary.CommonApiConstants.*; +import static eu.europeana.set.definitions.model.vocabulary.WebUserSetFields.PARAM_SORT_ORDER; +import static eu.europeana.set.definitions.model.vocabulary.WebUserSetFields.SEARCH_PATH; public class BaseApiConnection { - Logger logger = LogManager.getLogger(getClass().getName()); - - private static final String URL_RESPONSE = " . Returns body, headers and status code."; - private static final String DELETE_URL_RESPONSE = ". Returns headers and status code."; - private static final String API_ADMIN_KEY = "apiadmin"; - - private String apiKey; - private String setServiceUri = ""; - private HttpConnection httpConnection = new HttpConnection(); - - - public String getApiKey() { - return apiKey; - } - - public String getAdminApiKey() { - return API_ADMIN_KEY; - } - - public void setApiKey(String apiKey) { - this.apiKey = apiKey; - } - - public StringBuilder getUserSetServiceUri() { - StringBuilder urlBuilder = new StringBuilder(); - urlBuilder.append(setServiceUri); - - if(!setServiceUri.endsWith(WebUserSetFields.SLASH)) - urlBuilder.append(WebUserSetFields.SLASH); - - return urlBuilder; - } - - public void setUserSetServiceUri(String setServiceUri) { - this.setServiceUri = setServiceUri; - } - - public HttpConnection getHttpConnection() { - return httpConnection; - } - - public void setHttpConnection(HttpConnection httpConnection) { - this.httpConnection = httpConnection; - } - - - /** - * Create a new connection to the UserSet Service (REST API). - * - * @param apiKey - * API Key required to access the API - */ - public BaseApiConnection(String setServiceUri, String apiKey) { - this.apiKey = apiKey; - this.setServiceUri = setServiceUri; - } - - - /** - * This method makes POST request for given URL, header and JSON body parameter that returns - * response body, response headers and status code. - * @param url - * @param jsonPost - * @param requestHeaderValue - * @return The response body, response headers and status code. - * @throws IOException - */ - ResponseEntity postURL(String url, String jsonPost, String headerValue) throws IOException { - logger.trace("Call to UserSet API (POST) with body: {}. Returns body, headers and status code.", url); - return getHttpConnection().postURL(url, jsonPost, headerValue); - } - - /** - * This method makes PUT request for given URL and JSON body parameter that returns - * response body, response headers and status code. - * @param url - * @param jsonPut - * @param authorizationHeaderValue - * @return The response body, response headers and status code. - * @throws IOException - */ - ResponseEntity putURL(String url, String jsonPut, String authorizationHeaderValue) throws IOException { - logger.trace("Call to UserSet API (PUT) with body: {}. Returns body, headers and status code.", url); - - ResponseEntity response = getHttpConnection().putURL(url, jsonPut, authorizationHeaderValue); - - response.getStatusCode(); - - return response; - } - - /** - * This method makes GET request for given URL and returns - * response body, response headers and status code. - * @param url - * @return The response body, response headers and status code. - * @throws IOException - */ - public ResponseEntity getURL(String url) throws IOException { - logger.trace("Call to UserSet API (GET): {} {}", url, URL_RESPONSE); - return getHttpConnection().getURL(url); - } - - /** - * This method makes GET request for given URL and returns - * response body, response headers and status code. - * @param url - * @param authorizationHeaderValue - * @return The response body, response headers and status code. - * @throws IOException - */ - public ResponseEntity getURL(String url, String authorizationHeaderValue) throws IOException { - logger.trace("Call to UserSet API (GET): {}. Returns body, headers and status code.", url); - return getHttpConnection().getURL(url, authorizationHeaderValue); - } - - - /** - * This method makes DELETE request for given URL that returns - * response headers and status code. - * @param url - * @return The response headers and status code. - * @throws IOException - */ - ResponseEntity deleteURL(String url) throws IOException { - logger.trace("Call to UserSet API (DELETE): {} {} ", url, DELETE_URL_RESPONSE); - return getHttpConnection().deleteURL(url); - } - - /** - * This method makes DELETE request for given URL that returns - * response headers and status code. - * @param url - * @param authorizationHeaderValue - * @return The response headers and status code. - * @throws IOException - */ - ResponseEntity deleteURL(String url, String authorizationHeaderValue) throws IOException { - logger.trace("Call to UserSet API (DELETE): {}. Returns headers and status code.", url); - return getHttpConnection().deleteURL(url, authorizationHeaderValue); - } - + protected static final Logger LOGGER = LogManager.getLogger(BaseApiConnection.class); + + private static final String DELETE_URL_RESPONSE = ". Returns status code."; + private static final String ERROR_MESSAGE = "Set API Client call failed - "; + + private final HttpConnection httpConnection = new HttpConnection(); + private final String apiKey; + private final String setServiceUri; + String regularUserAuthorizationValue; + private final ObjectMapper mapper = new ObjectMapper(); + + /** + * BaseApiConnection constructor + * @param setServiceUri set api service url + * @param apiKey apikey + * @param regularUserAuthorizationValue auth value + */ + public BaseApiConnection(String setServiceUri, String apiKey, String regularUserAuthorizationValue) { + this.setServiceUri = setServiceUri; + this.apiKey = apiKey; + this.regularUserAuthorizationValue = regularUserAuthorizationValue; + + // set object mapper + SimpleModule module = new SimpleModule(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + module.addDeserializer(Agent.class, new AgentDeserializer()); + module.addDeserializer(UserSet.class, new UserSetDeserializer()); + + mapper.registerModule(module); + mapper.findAndRegisterModules(); + } + + public HttpConnection getHttpConnection() { + return httpConnection; + } + + + /** + * Fetches the get user set response (GET request) + * + * @param url + * @param authorizationHeaderValue + * @return + * @throws SetApiClientException + */ + protected UserSet getUserSetResponse(String url, String authorizationHeaderValue) throws SetApiClientException { + try { + LOGGER.trace("Call to Get UserSet API (GET) : {}.", url); + return parseSetApiResponse(getHttpConnection().get(url, null, authorizationHeaderValue), new ArrayList<>(Arrays.asList(HttpStatus.SC_OK, HttpStatus.SC_NOT_MODIFIED))); + } catch (IOException | ParseException e) { + throw new SetApiClientException(ERROR_MESSAGE + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Fetches the create user set response (GET request) + * + * @param url + * @param authorizationHeaderValue + * @return + * @throws SetApiClientException + */ + protected UserSet getCreateUserSetResponse(String url, String requestBody, String authorizationHeaderValue) throws SetApiClientException { + try { + LOGGER.trace("Call to Create UserSet API (POST) : {}.", url); + return parseSetApiResponse(getHttpConnection().post(url, requestBody, ContentType.APPLICATION_JSON.getMimeType(), authorizationHeaderValue), new ArrayList<>(Arrays.asList(HttpStatus.SC_CREATED))); + } catch (IOException | ParseException e) { + throw new SetApiClientException(ERROR_MESSAGE + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Fetches the User Set api response PUT update userset + * + * @param url url to be executed + * @param requestBody request body for POST and PUT request + * @param authorizationHeaderValue authorisation value + * @return + * @throws SetApiClientException + */ + protected UserSet getUpdateUserSetResponse(String url, String requestBody, String authorizationHeaderValue) throws SetApiClientException { + try { + LOGGER.trace("Call to Update UserSet API : {PUT}. {} ", url); + return parseSetApiResponse(getHttpConnection().put(url, requestBody, authorizationHeaderValue), new ArrayList<>(Arrays.asList(HttpStatus.SC_OK))); + } catch (IOException | ParseException e) { + throw new SetApiClientException(ERROR_MESSAGE + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + + /** + * This method makes DELETE request for given URL that returns + * response headers and status code. + * + * @param url + * @return The response headers and status code. + * @throws IOException + */ + protected String deleteURL(String url, String authorizationHeaderValue) throws SetApiClientException { + try { + LOGGER.trace("Call to UserSet API (DELETE): {} {} ", url, DELETE_URL_RESPONSE); + CloseableHttpResponse response = getHttpConnection().deleteURL(url, authorizationHeaderValue); + if (response.getCode() != HttpStatus.SC_NO_CONTENT) { + String responseBody = EntityUtils.toString(response.getEntity()); + AbstractUserSetApiResponse errorResponse = mapper.readValue(responseBody, AbstractUserSetApiResponse.class); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(ERROR_MESSAGE + " {} ", errorResponse.getMessage()); + } + throw new SetApiClientException(ERROR_MESSAGE + errorResponse.getMessage(), response.getCode()); + } + return String.valueOf(response.getCode()); + } catch (IOException | ParseException e) { + throw new SetApiClientException(ERROR_MESSAGE + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + private UserSet parseSetApiResponse(CloseableHttpResponse response, List statusToCheckList) throws SetApiClientException, IOException, ParseException { + String responseBody = EntityUtils.toString(response.getEntity()); + if (statusToCheckList.contains(response.getCode())) { + return mapper.readValue(responseBody, UserSet.class); + } else { + AbstractUserSetApiResponse errorResponse = mapper.readValue(responseBody, AbstractUserSetApiResponse.class); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(ERROR_MESSAGE + " {} ", errorResponse.getMessage()); + } + throw new SetApiClientException(ERROR_MESSAGE + errorResponse.getMessage(), response.getCode()); + } + + } + + /** + * Fetches the get user Set pagination response + * + * Check profile for the deserialization + * META - empty page (no items) , ITEMS_META - only set descriptions, not item descriptions , ITEMS - items set as set ids + * ITEMS is the default profile value + * @param url + * @param authorizationHeaderValue + * @return + * @throws SetApiClientException + */ + protected List getUserSetPaginatedResponse(String url, String authorizationHeaderValue, String profile) throws SetApiClientException { + try { + LOGGER.trace("Call to Get UserSet API (Paginated): {} ", url); + CloseableHttpResponse response = getHttpConnection().get(url, ContentType.APPLICATION_JSON.getMimeType(), authorizationHeaderValue); + String responseBody = EntityUtils.toString(response.getEntity()); + if (response.getCode() == HttpStatus.SC_OK) { + TypeReference> typeRef = new TypeReference<>() {}; + return mapper.readValue(responseBody, typeRef).getItems(); + + } else { + AbstractUserSetApiResponse errorResponse = mapper.readValue(responseBody, AbstractUserSetApiResponse.class); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(ERROR_MESSAGE + " {} ", errorResponse.getMessage()); + } + throw new SetApiClientException(ERROR_MESSAGE + errorResponse.getMessage(), response.getCode()); + } + } catch (IOException | ParseException e) { + throw new SetApiClientException(ERROR_MESSAGE + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + + /** + * Fetches the user Set search api response + * + * @param url + * @param authorizationHeaderValue + * @return + * @throws SetApiClientException + */ + protected List getSearchUserSetResponse(String url, String authorizationHeaderValue, String profile) throws SetApiClientException { + try { + LOGGER.trace("Call to UserSet API (SEARCH): {} ", url); + CloseableHttpResponse response = getHttpConnection().get(url, "application/json", authorizationHeaderValue); + String responseBody = EntityUtils.toString(response.getEntity()); + if (response.getCode() == HttpStatus.SC_OK) { + if (StringUtils.equals(profile, ProfileConstants.VALUE_PARAM_ITEMS)) { + TypeReference> typeRef = new TypeReference<>() {}; + List items = mapper.readValue(responseBody, typeRef).getItems(); + List sets = new ArrayList<>(items.size()); + for (String id: items) { + UserSet set = new BaseUserSet(); + set.setIdentifier(StringUtils.substringAfterLast(id, "/")); + sets.add(set); + } + return sets; + } + TypeReference> typeRef = new TypeReference<>() {}; + return mapper.readValue(responseBody, typeRef).getItems(); + + } else { + AbstractUserSetApiResponse errorResponse = mapper.readValue(responseBody, AbstractUserSetApiResponse.class); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(ERROR_MESSAGE + " {} ", errorResponse.getMessage()); + } + throw new SetApiClientException(ERROR_MESSAGE + errorResponse.getMessage(), response.getCode()); + } + } catch (IOException | ParseException e) { + throw new SetApiClientException(ERROR_MESSAGE + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Fetches the Set api service url with "/" at the end + */ + public StringBuilder getUserSetServiceUri() { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(this.setServiceUri); + if (!this.setServiceUri.endsWith(WebUserSetFields.SLASH)) + urlBuilder.append(WebUserSetFields.SLASH); + + return urlBuilder; + } + + /** + * Build get user Set get Url + * + * @param path + * @param profile + * @return + */ + public static URI buildGetUrls(String path, String profile) throws SetApiClientException{ + try { + URIBuilder builder = new URIBuilder(path); + if (profile != null) { + builder.addParameter(QUERY_PARAM_PROFILE, profile); + } + return builder.build(); + } catch (URISyntaxException e) { + throw new SetApiClientException("Error creating Get url - " + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Build paginated user set get url + * @param path + * @param sort + * @param sortOrder + * @param page + * @param pageSize + * @param profile + * @return + */ + public static URI buildPaginatedGetUrls(String path, String sort, + String sortOrder, String page, String pageSize, String profile) throws SetApiClientException { + try { + URIBuilder builder = new URIBuilder(path) + .addParameter(QUERY_PARAM_PAGE, page) + .addParameter(QUERY_PARAM_PAGE_SIZE, pageSize); + + if (sort != null) { + builder.addParameter(QUERY_PARAM_SORT, sort); + } + if (sortOrder != null) { + builder.addParameter(PARAM_SORT_ORDER, sortOrder); + } + if (profile != null) { + builder.addParameter(QUERY_PARAM_PROFILE, profile); + } + return builder.build(); + } catch (URISyntaxException e) { + throw new SetApiClientException("Error creating Paginated Get Urls " +e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Builds search url with the given params + * + * @param query + * @param qf + * @param sort + * @param page + * @param pageSize + * @param facet + * @param facetLimit + * @param profile + * @return search url + */ + public static URI buildSearchUrl(String query, String[] qf, String sort, String page, + String pageSize, String facet, int facetLimit, + String profile) throws SetApiClientException { + try { + URIBuilder builder = new URIBuilder(SEARCH_PATH) + .addParameter(QUERY_PARAM_QUERY, query) + .addParameter(QUERY_PARAM_PAGE, page) + .addParameter(QUERY_PARAM_PAGE_SIZE, pageSize); + + if (qf != null) { + builder.addParameter(QUERY_PARAM_QF, String.valueOf(qf)); + } + if (sort != null) { + builder.addParameter(QUERY_PARAM_SORT, sort); + } + if (facet != null) { + builder.addParameter(QUERY_PARAM_FACET, facet); + builder.addParameter("facet.limit", String.valueOf(facetLimit)); + } + if (profile != null) { + builder.addParameter(QUERY_PARAM_PROFILE, profile); + } + return builder.build(); + } catch (URISyntaxException e) { + throw new SetApiClientException("Error creating Search Urls ", HttpStatus.SC_INTERNAL_SERVER_ERROR, e); + } + } + + public String getApiKey() { + return apiKey; + } + + public String getSetServiceUri() { + return setServiceUri; + } } \ No newline at end of file diff --git a/set-client/src/main/java/eu/europeana/set/client/connection/UserSetApiConnection.java b/set-client/src/main/java/eu/europeana/set/client/connection/UserSetApiConnection.java index 8c09ee26..8dc2382d 100644 --- a/set-client/src/main/java/eu/europeana/set/client/connection/UserSetApiConnection.java +++ b/set-client/src/main/java/eu/europeana/set/client/connection/UserSetApiConnection.java @@ -1,16 +1,13 @@ package eu.europeana.set.client.connection; import java.io.IOException; -import org.apache.commons.lang3.StringUtils; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; +import java.util.List; +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.client.model.result.RecordPreview; +import eu.europeana.set.definitions.model.UserSet; +import org.apache.commons.lang3.StringUtils; import eu.europeana.api.commons.definitions.vocabulary.CommonApiConstants; -import eu.europeana.set.client.config.ClientConfiguration; -import eu.europeana.set.client.exception.TechnicalRuntimeException; -import eu.europeana.set.common.http.HttpConnection; import eu.europeana.set.definitions.model.vocabulary.WebUserSetFields; /** @@ -18,109 +15,44 @@ */ public class UserSetApiConnection extends BaseApiConnection { - String regularUserAuthorizationValue = null; - - /** - * Create a new connection to the UserSet Service (REST API). - * - * @param apiKey API Key required to access the API - */ - public UserSetApiConnection(String setServiceUri, String apiKey) { - super(setServiceUri, apiKey); - initConfigurations(); - } - - public UserSetApiConnection() { - this(ClientConfiguration.getInstance().getServiceUri(), - ClientConfiguration.getInstance().getApiKey()); - initConfigurations(); - } - - private void initConfigurations() { - // regularUserAuthorizationValue = - // ClientConfiguration.getInstance().getAuthorizationHeaderValue(); - regularUserAuthorizationValue = getOauthToken(); + public UserSetApiConnection(String setServiceUri, String apiKey, String regularUserAuthorizationValue) { + super(setServiceUri, apiKey, regularUserAuthorizationValue); } - public String getOauthToken() { - try { - - String ACCESS_TOKEN = "access_token"; - String oauthUri = ClientConfiguration.getInstance().getOauthServiceUri(); - String oauthParams = ClientConfiguration.getInstance().getOauthRequestParams(); - HttpConnection connection = new HttpConnection(); - ResponseEntity response; - response = connection.post(oauthUri, oauthParams, "application/x-www-form-urlencoded"); - - if (HttpStatus.OK == response.getStatusCode()) { - String body = response.getBody(); - JSONObject json = new JSONObject(body); - if (json.has(ACCESS_TOKEN)) { - return "Bearer " + json.getString(ACCESS_TOKEN); - } else { - throw new TechnicalRuntimeException( - "Cannot extract authentication token from reponse:" + body); - } - } else { - throw new TechnicalRuntimeException("Error occured when calling oath service! " + response); - } - } catch (IOException | JSONException e) { - throw new TechnicalRuntimeException("Cannot retrieve authentication token!", e); - } - - } /** * This method creates UserSet object from Json string. Example HTTP request for tag object: * http://localhost:8080/set/?profile=minimal * * @param set The UserSet body - * @param profile + * @param profile profile requested * @return response entity that comprises response body, headers and status code. * @throws IOException */ - public ResponseEntity createUserSet(String set, String profile) throws IOException { - + public UserSet createUserSet(String set, String profile) throws SetApiClientException { StringBuilder urlBuilder = getUserSetServiceUri(); if (StringUtils.isNotEmpty(profile)) { urlBuilder.append(WebUserSetFields.PAR_CHAR); urlBuilder.append(CommonApiConstants.QUERY_PARAM_PROFILE) .append(WebUserSetFields.EQUALS_PARAMETER).append(profile); } - String resUrl = urlBuilder.toString(); - - logger.trace("Ivoking create set: {} ", resUrl); - - /** - * Execute Europeana API request - */ - return postURL(resUrl, set, regularUserAuthorizationValue); + LOGGER.trace("Ivoking create set: {} ", resUrl); + return getCreateUserSetResponse(resUrl, set, regularUserAuthorizationValue); } /** * This method retrieves UserSet object. Example HTTP request for tag object: * http://localhost:8080/set/{identifier}.jsonld?profile=minimal where identifier is: 496 * - * @param identifier - * @param profile - * @return response entity that comprises response body, headers and status code. + * @param identifier set id + * @param profile profile requested * @throws IOException + * @return userset */ - public ResponseEntity getUserSet(String identifier, String profile) throws IOException { - - StringBuilder urlBuilder = getUserSetServiceUri(); - urlBuilder.append(identifier).append(WebUserSetFields.JSON_LD_REST); - if (StringUtils.isNotEmpty(profile)) { - urlBuilder.append(WebUserSetFields.PAR_CHAR); - urlBuilder.append(CommonApiConstants.QUERY_PARAM_PROFILE) - .append(WebUserSetFields.EQUALS_PARAMETER).append(profile); - } - - /** - * Execute Europeana API request - */ - return getURL(urlBuilder.toString(), regularUserAuthorizationValue); + public UserSet getUserSet(String identifier, String profile) throws SetApiClientException { + StringBuilder urlBuilder = getUserSetServiceUri().append(buildGetUrls(identifier + WebUserSetFields.JSON_LD_REST, profile)); + return getUserSetResponse(urlBuilder.toString(), regularUserAuthorizationValue); } /** @@ -134,9 +66,7 @@ public ResponseEntity getUserSet(String identifier, String profile) thro * @return response entity that comprises response body, headers and status code. * @throws IOException */ - public ResponseEntity updateUserSet(String identifier, String updateUserSet, - String profile) throws IOException { - + public UserSet updateUserSet(String identifier, String updateUserSet, String profile) throws SetApiClientException { StringBuilder urlBuilder = getUserSetServiceUri(); urlBuilder.append(identifier).append(WebUserSetFields.JSON_LD_REST); if (StringUtils.isNotEmpty(profile)) { @@ -144,11 +74,7 @@ public ResponseEntity updateUserSet(String identifier, String updateUser urlBuilder.append(CommonApiConstants.QUERY_PARAM_PROFILE) .append(WebUserSetFields.EQUALS_PARAMETER).append(profile); } - - /** - * Execute Europeana API request - */ - return putURL(urlBuilder.toString(), updateUserSet, regularUserAuthorizationValue); + return getUpdateUserSetResponse(urlBuilder.toString(), updateUserSet, regularUserAuthorizationValue); } /** @@ -159,15 +85,49 @@ public ResponseEntity updateUserSet(String identifier, String updateUser * @return response entity that comprises response headers and status code. * @throws IOException */ - public ResponseEntity deleteUserSet(String identifier) throws IOException { - + public String deleteUserSet(String identifier) throws SetApiClientException { StringBuilder urlBuilder = getUserSetServiceUri(); urlBuilder.append(identifier).append(WebUserSetFields.JSON_LD_REST); - - /** - * Execute Europeana API request - */ return deleteURL(urlBuilder.toString(), regularUserAuthorizationValue); } + /** + * This method fetches the get user set pagination results + * @param identifier + * @param sort + * @param sortOrder + * @param page + * @param pageSize + * @param profile + * @return + * @throws SetApiClientException + */ + public List getPaginationUserSet(String identifier, String sort, + String sortOrder, String page, String pageSize, String profile) throws SetApiClientException { + StringBuilder urlBuilder = getUserSetServiceUri().append( + buildPaginatedGetUrls(identifier + WebUserSetFields.JSON_LD_REST, sort, sortOrder, page, pageSize, profile)); + return getUserSetPaginatedResponse(urlBuilder.toString(), regularUserAuthorizationValue, profile); + + } + /** + * This method searches usersets for the given queries and params + * Example : /set/search?query=visibility:published&pageSize=1000 + * @param query + * @param qf + * @param sort + * @param page + * @param pageSize + * @param facet + * @param facetLimit + * @param profile + * @return + * @throws IOException + */ + public List searchUserSet(String query, String[] qf, String sort, String page, + String pageSize, String facet, int facetLimit, + String profile) throws SetApiClientException { + + StringBuilder urlBuilder = getUserSetServiceUri().append(buildSearchUrl(query, qf, sort, page, pageSize, facet, facetLimit, profile)); + return getSearchUserSetResponse(urlBuilder.toString(), regularUserAuthorizationValue, profile); + } } diff --git a/set-client/src/main/java/eu/europeana/set/client/exception/SetApiClientException.java b/set-client/src/main/java/eu/europeana/set/client/exception/SetApiClientException.java new file mode 100644 index 00000000..3e6a98f2 --- /dev/null +++ b/set-client/src/main/java/eu/europeana/set/client/exception/SetApiClientException.java @@ -0,0 +1,46 @@ +package eu.europeana.set.client.exception; + +public class SetApiClientException extends Exception { + + private static final long serialVersionUID = 8281933808897246375L; + private final int remoteStatusCode; + + /** + * Constructor for exception to indicate that an error occurred during invocation of the remote + * service or parsing of service response + * + * @param msg the error message + * @param remoteStatusCode the status code from the remote service + * @param t eventual exception thrown when extracting information from the remote service response + */ + public SetApiClientException(String msg, int remoteStatusCode, Throwable t) { + super(msg, t); + this.remoteStatusCode = remoteStatusCode; + } + + /** + * Constructor for exception to indicate that an error occurred during invocation of the remote + * service or parsing of service response + * + * @param msg the error message + * @param remoteStatusCode the status code from the remote service + */ + public SetApiClientException(String msg, int remoteStatusCode) { + super(msg); + this.remoteStatusCode = remoteStatusCode; + } + + /** + * Constructor for exception to indicate that an error occurred during invocation of the remote + * service, to be used when no response from the remote service has been received + * + * @param msg the error message + */ + public SetApiClientException(String msg) { + this(msg, -1); + } + + public int getRemoteStatusCode() { + return remoteStatusCode; + } +} \ No newline at end of file diff --git a/set-client/src/main/java/eu/europeana/set/client/exception/TechnicalRuntimeException.java b/set-client/src/main/java/eu/europeana/set/client/exception/TechnicalRuntimeException.java deleted file mode 100644 index f19d45d7..00000000 --- a/set-client/src/main/java/eu/europeana/set/client/exception/TechnicalRuntimeException.java +++ /dev/null @@ -1,19 +0,0 @@ -package eu.europeana.set.client.exception; - -/** - * This class is meant to be used for marking and handling technical exceptions that might occur within the system - * - * @author GrafR - */ -public class TechnicalRuntimeException extends RuntimeException { - - private static final long serialVersionUID = -2040704860209418649L; - - public TechnicalRuntimeException(String message, Exception e) { - super(message, e); - } - - public TechnicalRuntimeException(String message) { - super(message); - } -} diff --git a/set-client/src/main/java/eu/europeana/set/client/json/AgentDeserializer.java b/set-client/src/main/java/eu/europeana/set/client/json/AgentDeserializer.java new file mode 100644 index 00000000..688c9238 --- /dev/null +++ b/set-client/src/main/java/eu/europeana/set/client/json/AgentDeserializer.java @@ -0,0 +1,35 @@ +package eu.europeana.set.client.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import eu.europeana.set.definitions.model.agent.Agent; +import eu.europeana.set.definitions.model.agent.impl.Person; +import eu.europeana.set.definitions.model.agent.impl.SoftwareAgent; +import eu.europeana.set.definitions.model.vocabulary.AgentTypes; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; + +public class AgentDeserializer extends JsonDeserializer { + + @Override + public Agent deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec(); + ObjectNode root = mapper.readTree(jsonParser); + + if (root.has("type") ) { + String agentType = root.get("type").asText(); + if (StringUtils.equals(agentType, AgentTypes.PERSON.getJsonValue())) { + return mapper.readValue(root.toString(), Person.class); + } + if (StringUtils.equals(agentType, AgentTypes.SOFTWARE.getJsonValue())) { + return mapper.readValue(root.toString(), SoftwareAgent.class); + } + // There is no class for Organisation type + } + return null; + } +} diff --git a/set-client/src/main/java/eu/europeana/set/client/json/UserSetDeserializer.java b/set-client/src/main/java/eu/europeana/set/client/json/UserSetDeserializer.java new file mode 100644 index 00000000..d66662e9 --- /dev/null +++ b/set-client/src/main/java/eu/europeana/set/client/json/UserSetDeserializer.java @@ -0,0 +1,41 @@ +package eu.europeana.set.client.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import eu.europeana.set.definitions.model.UserSet; +import eu.europeana.set.definitions.model.impl.BaseUserSet; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; + +/** + * Used for Deserializing UserSet. + *

+ * Field - {@link UserSet#getIdentifier()} + * As Identifier is always null, we fetch the value from the 'id' field in the response + * exmaple : 'id' : http://data.europeana.eu/set/xyz , identifier : xyz + * + * @author srishti singh + * @since 9 December 2024 + */ +public class UserSetDeserializer extends JsonDeserializer { + + @Override + public UserSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec(); + ObjectNode root = mapper.readTree(jsonParser); + BaseUserSet set = mapper.readValue(root.toString(), BaseUserSet.class); + if (root.has("id")) { + String id = root.get("id").asText(); + String identifier = set.getIdentifier(); + if (identifier == null) { + set.setIdentifier(StringUtils.substringAfterLast(id, "/")); + } + } + return set; + } +} diff --git a/set-client/src/main/java/eu/europeana/set/client/model/result/AbstractUserSetApiResponse.java b/set-client/src/main/java/eu/europeana/set/client/model/result/AbstractUserSetApiResponse.java index 9f2b0c1a..21072443 100644 --- a/set-client/src/main/java/eu/europeana/set/client/model/result/AbstractUserSetApiResponse.java +++ b/set-client/src/main/java/eu/europeana/set/client/model/result/AbstractUserSetApiResponse.java @@ -1,14 +1,18 @@ package eu.europeana.set.client.model.result; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + /** * @author GrafR * */ -public abstract class AbstractUserSetApiResponse { +@JsonIgnoreProperties(ignoreUnknown = true) +public class AbstractUserSetApiResponse { private String action; private String success; private String error; + private String message; public String getAction() { return action; @@ -34,4 +38,11 @@ public void setError(String error) { this.error = error; } + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } } diff --git a/set-client/src/main/java/eu/europeana/set/client/model/result/RecordPreview.java b/set-client/src/main/java/eu/europeana/set/client/model/result/RecordPreview.java new file mode 100644 index 00000000..0ca37084 --- /dev/null +++ b/set-client/src/main/java/eu/europeana/set/client/model/result/RecordPreview.java @@ -0,0 +1,88 @@ +package eu.europeana.set.client.model.result; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +/** + * Class to parse the Web User Set pagination response. + * For now, we only have the fields that are required by the IIIF presentation APi to generate gallery + * @author Srishti Singh + * @since 3 December 2024 + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class RecordPreview { + + @JsonProperty("id") + private String id; + + @JsonProperty("dcDescriptionLangAware") + private Map> description; + + @JsonProperty("dcTitleLangAware") + private Map> title; + + @JsonProperty("edmPreview") + private List edmPreview; + + public RecordPreview() { + // for jackson + } + public RecordPreview(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Map> getDescription() { + return description; + } + + public void addDescription(String key, List values) { + if (this.description.get(key) != null) { + this.description.get(key).addAll(values); + } else { + this.description.put(key, values); + } + } + + public boolean hasDescription() { + return description != null && !description.isEmpty(); + } + + public Map> getTitle() { + return title; + } + + public void addTitle(String key, List values) { + if (this.title.get(key) != null) { + this.title.get(key).addAll(values); + } else { + this.title.put(key, values); + } + } + + public boolean hasTitle() { + return title != null && !title.isEmpty(); + } + + public List getEdmPreview() { + return edmPreview; + } + + public void setEdmPreview(List edmPreview) { + this.edmPreview = edmPreview; + } + + public boolean hasPreview() { + return edmPreview != null && !edmPreview.isEmpty(); + } +} diff --git a/set-client/src/main/java/eu/europeana/set/client/model/result/UserSetOperationResponse.java b/set-client/src/main/java/eu/europeana/set/client/model/result/UserSetOperationResponse.java deleted file mode 100644 index d1e3d40d..00000000 --- a/set-client/src/main/java/eu/europeana/set/client/model/result/UserSetOperationResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package eu.europeana.set.client.model.result; - -import eu.europeana.set.definitions.model.UserSet; - -public class UserSetOperationResponse extends AbstractUserSetApiResponse{ - - private UserSet set; - - private String json; - - public UserSet getUserSet() { - return set; - } - public void setUserSet(UserSet set) { - this.set = set; - } - public String getJson() { - return json; - } - public void setJson(String json) { - this.json = json; - } -} diff --git a/set-client/src/main/java/eu/europeana/set/client/web/SearchUserSetApi.java b/set-client/src/main/java/eu/europeana/set/client/web/SearchUserSetApi.java new file mode 100644 index 00000000..cd8ebd54 --- /dev/null +++ b/set-client/src/main/java/eu/europeana/set/client/web/SearchUserSetApi.java @@ -0,0 +1,29 @@ +package eu.europeana.set.client.web; + +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.definitions.model.UserSet; + +import java.util.List; + +/** + * Search Client API interface + * @author Srishti singh + * @since 20 Nov 2024 + */ +public interface SearchUserSetApi { + + /** + * This methods retrieves the search results from the db + * @param query + * @param qf + * @param sort + * @param page + * @param pageSize + * @param facet + * @param facetLimit + * @param profile + * @return + */ + List searchUserSet(String query, String[] qf, String sort, String page, String pageSize, + String facet, int facetLimit, String profile) throws SetApiClientException; +} diff --git a/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApi.java b/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApi.java index f6cb275b..56bb6a63 100644 --- a/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApi.java +++ b/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApi.java @@ -1,11 +1,14 @@ package eu.europeana.set.client.web; -import org.springframework.http.ResponseEntity; +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.client.model.result.RecordPreview; +import eu.europeana.set.definitions.model.UserSet; + +import java.util.List; /** * Client API interface * @author GordeaS - * */ public interface WebUserSetApi { @@ -15,8 +18,7 @@ public interface WebUserSetApi { * @param profile * @return response entity containing body, headers and status code. */ - public ResponseEntity createUserSet( - String requestBody, String profile); + UserSet createUserSet(String requestBody, String profile) throws SetApiClientException; /** * This method retrieves user set from database @@ -25,16 +27,16 @@ public ResponseEntity createUserSet( * @param profile * @return response entity that contains response body, headers and status code. */ - public ResponseEntity getUserSet( - String identifier, String profile); + UserSet getUserSet( + String identifier, String profile) throws SetApiClientException; /** * This method deletes user set by the given identifier * @param identifier * @return response entity containing headers and status code. */ - public ResponseEntity deleteUserSet( - String identifier); + String deleteUserSet( + String identifier) throws SetApiClientException; /** * This method updates user set by the given update string in JSON format @@ -43,7 +45,18 @@ public ResponseEntity deleteUserSet( * @param profile * @return response entity containing body, headers and status code. */ - public ResponseEntity updateUserSet( - String identifier, String requestBody, String profile); + UserSet updateUserSet(String identifier, String requestBody, String profile) throws SetApiClientException; + /** + * This method fetches the user set pagination request + * @param identifier set id + * @param sort sort fields + * @param sortOrder order of sort + * @param page page number + * @param pageSize size of the page + * @param profile profile requested + * @return + * @throws SetApiClientException + */ + List getPaginationUserSet(String identifier, String sort, String sortOrder, String page, String pageSize, String profile) throws SetApiClientException; } \ No newline at end of file diff --git a/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApiImpl.java b/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApiImpl.java deleted file mode 100644 index 722c83d8..00000000 --- a/set-client/src/main/java/eu/europeana/set/client/web/WebUserSetApiImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -package eu.europeana.set.client.web; - -import java.io.IOException; - -import org.springframework.http.ResponseEntity; - -import eu.europeana.set.client.BaseUserSetApi; -import eu.europeana.set.client.exception.TechnicalRuntimeException; - -/** - * Implementation of client api - * @author GordeaS - * - */ - -public class WebUserSetApiImpl extends BaseUserSetApi implements WebUserSetApi { - - /** - * Default constructor - */ - public WebUserSetApiImpl() { - super(); - } - - @Override - public ResponseEntity createUserSet(String set, String profile) { - - ResponseEntity res; - try { - res = apiConnection.createUserSet(set, profile); - } catch (IOException e) { - throw new TechnicalRuntimeException( - "Exception occured when invoking the UserSetJsonApi createUserSet method", e); - } - - return res; - } - - @Override - public ResponseEntity deleteUserSet(String identifier) { - ResponseEntity res; - try { - res = apiConnection.deleteUserSet(identifier); - } catch (IOException e) { - throw new TechnicalRuntimeException( - "Exception occured when invoking the UserSetJsonApi deleteUserSet method", e); - } - - return res; - } - - @Override - public ResponseEntity getUserSet(String identifier, String profile) { - - ResponseEntity res; - try { - res = apiConnection.getUserSet(identifier, profile); - } catch (IOException e) { - throw new TechnicalRuntimeException("Exception occured when invoking the UserSetJsonApi getUserSet method", - e); - } - - return res; - } - - @Override - public ResponseEntity updateUserSet(String identifier, String set, String profile) { - ResponseEntity res; - try { - res = apiConnection.updateUserSet(identifier, set, profile); - } catch (IOException e) { - throw new TechnicalRuntimeException( - "Exception occured when invoking the UserSetJsonApi updateUserSet method", e); - } - - return res; - } - -} \ No newline at end of file diff --git a/set-client/src/main/resources/.gitignore b/set-client/src/main/resources/.gitignore index 39464b50..6597be1a 100644 --- a/set-client/src/main/resources/.gitignore +++ b/set-client/src/main/resources/.gitignore @@ -1,3 +1,4 @@ -/set-client.properties +set-client.properties +**user.properties.template /log4j.xml -/log4j2.xml +/log4j2.xml \ No newline at end of file diff --git a/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseAPIConnectionTest.java b/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseAPIConnectionTest.java index b6b45df1..615f5155 100644 --- a/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseAPIConnectionTest.java +++ b/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseAPIConnectionTest.java @@ -10,18 +10,14 @@ @Disabled("needs configuration file") public class BaseAPIConnectionTest { - - private static final String SERVICE_URI = "testUri"; private static final String API_KEY_1 = "api_key"; - private static final String API_KEY_2 = "test_api_key"; - private static final String API_ADMIN_KEY = "apiadmin"; private BaseApiConnection baseApiConnection; @BeforeEach void setup() { - baseApiConnection = new BaseApiConnection(SERVICE_URI, API_KEY_1); + baseApiConnection = new BaseApiConnection(SERVICE_URI, API_KEY_1, null); } @Test @@ -30,14 +26,9 @@ public void Test_getUserSetServiceUri() { assertEquals(SERVICE_URI + WebUserSetFields.SLASH, result.toString()); result = new StringBuilder(); - baseApiConnection = new BaseApiConnection(SERVICE_URI + WebUserSetFields.SLASH, API_KEY_1); + baseApiConnection = new BaseApiConnection(SERVICE_URI + WebUserSetFields.SLASH, API_KEY_1, null); result = baseApiConnection.getUserSetServiceUri(); assertEquals(SERVICE_URI + WebUserSetFields.SLASH, result.toString()); - - assertEquals(API_KEY_1, baseApiConnection.getApiKey()); - assertEquals(API_ADMIN_KEY, baseApiConnection.getAdminApiKey()); - baseApiConnection.setApiKey(API_KEY_2); - assertEquals(API_KEY_2, baseApiConnection.getApiKey()); } } diff --git a/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseWebUserSetProtocol.java b/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseWebUserSetProtocol.java index ccebec74..32475a8d 100644 --- a/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseWebUserSetProtocol.java +++ b/set-client/src/test/java/eu/europeana/set/client/integration/web/BaseWebUserSetProtocol.java @@ -5,14 +5,13 @@ import java.io.InputStream; import java.io.InputStreamReader; +import eu.europeana.set.client.config.ClientConfiguration; +import eu.europeana.set.client.exception.SetApiClientException; +import org.apache.hc.core5.http.HttpStatus; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.BeforeEach; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import eu.europeana.set.client.web.WebUserSetApi; -import eu.europeana.set.client.web.WebUserSetApiImpl; +import eu.europeana.set.client.UserSetApiClient; import eu.europeana.set.definitions.model.UserSet; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -26,15 +25,11 @@ public class BaseWebUserSetProtocol { String START = "{"; String END = "}"; - private WebUserSetApi apiClient; + protected UserSetApiClient apiClient; @BeforeEach - public void initObjects() { - apiClient = new WebUserSetApiImpl(); - } - - public WebUserSetApi getApiClient() { - return apiClient; + public void initObjects() throws SetApiClientException { + apiClient = new UserSetApiClient(new ClientConfiguration()); } /** @@ -45,15 +40,9 @@ public WebUserSetApi getApiClient() { * @return response entity that contains response body, headers and status code. * @throws IOException */ - protected ResponseEntity storeTestUserSet(String resource, String profile) throws IOException { - + protected UserSet storeTestUserSet(String resource, String profile) throws SetApiClientException, IOException { String requestBody = getJsonStringInput(resource); - - /** - * store set - */ - ResponseEntity storedResponse = getApiClient().createUserSet(requestBody, profile); - return storedResponse; + return apiClient.getWebUserSetApi().createUserSet(requestBody, profile); } protected String getJsonStringInput(String resource) throws IOException { @@ -68,22 +57,18 @@ protected String getJsonStringInput(String resource) throws IOException { } - /** - * @param user set - */ - protected void deleteUserSet(UserSet set) { + protected void deleteUserSet(UserSet set) throws SetApiClientException { deleteUserSet(set.getIdentifier()); } - protected void deleteUserSet(String identifier) { - WebUserSetApi webUserSetApi = new WebUserSetApiImpl(); - ResponseEntity re = webUserSetApi.deleteUserSet(identifier); - assertEquals(HttpStatus.OK, re.getStatusCode()); + protected void deleteUserSet(String identifier) throws SetApiClientException { + String re = apiClient.getWebUserSetApi().deleteUserSet(identifier); + assertEquals(String.valueOf(HttpStatus.SC_OK), re); log.trace("User set deleted: /" + identifier); } - protected ResponseEntity getUserSet(UserSet set) { - return getApiClient().getUserSet(set.getIdentifier(), null); + protected UserSet getUserSet(UserSet set) throws SetApiClientException { + return apiClient.getWebUserSetApi().getUserSet(set.getIdentifier(), null); } diff --git a/set-client/src/test/java/eu/europeana/set/client/integration/web/ClientConfigurationTest.java b/set-client/src/test/java/eu/europeana/set/client/integration/web/ClientConfigurationTest.java index 54b9aa35..d75d23eb 100644 --- a/set-client/src/test/java/eu/europeana/set/client/integration/web/ClientConfigurationTest.java +++ b/set-client/src/test/java/eu/europeana/set/client/integration/web/ClientConfigurationTest.java @@ -11,8 +11,9 @@ public class ClientConfigurationTest { @Test public void clientConfiguration_loadProperties() { - assertTrue(StringUtils.isNotEmpty(ClientConfiguration.getInstance().getOauthRequestParams())); - assertTrue(StringUtils.isNotEmpty(ClientConfiguration.getInstance().getServiceUri())); - assertTrue(StringUtils.isNotEmpty(ClientConfiguration.getInstance().getOauthServiceUri())); + ClientConfiguration configuration = new ClientConfiguration(); + assertTrue(StringUtils.isNotEmpty(configuration.getOauthRequestParams())); + assertTrue(StringUtils.isNotEmpty(configuration.getServiceUri())); + assertTrue(StringUtils.isNotEmpty(configuration.getOauthServiceUri())); } } diff --git a/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolExceptionsTest.java b/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolExceptionsTest.java index 01bdc8f0..08b0021d 100644 --- a/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolExceptionsTest.java +++ b/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolExceptionsTest.java @@ -2,10 +2,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; + +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.definitions.model.UserSet; +import org.apache.hc.core5.http.HttpStatus; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; /** @@ -42,65 +44,51 @@ public class WebUserSetProtocolExceptionsTest extends BaseWebUserSetProtocol { public String UNKNOWN_PROVIDED_IDENTIFIER = "unknown_provided_identifier"; @Test - public void createWebsetUserSetWithoutBody() throws IOException { - - ResponseEntity response = getApiClient().createUserSet( - null, null); + public void createWebsetUserSetWithoutBody() { + try { + apiClient.getWebUserSetApi().createUserSet(null, null); + } catch (SetApiClientException e) { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getRemoteStatusCode()); + } - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); } - @Test public void createWebUserSetWithCorruptedBody() { - ResponseEntity response = getApiClient().createUserSet( - CORRUPTED_JSON, null); - - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + try { + apiClient.getWebUserSetApi().createUserSet(CORRUPTED_JSON, null); + } catch (SetApiClientException e) { + assertEquals(HttpStatus.SC_BAD_REQUEST, e.getRemoteStatusCode()); + } } @Test public void getWebUserSetWithWrongIdentifier() { - ResponseEntity response = getApiClient().getUserSet( - WRONG_GENERATED_IDENTIFIER, null); - assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + try { + apiClient.getWebUserSetApi().getUserSet(WRONG_GENERATED_IDENTIFIER, null); + } catch (SetApiClientException e) { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getRemoteStatusCode()); + } } @Test public void updateWebsetUserSetWithWrongIdentifierNumber() throws IOException { String requestBody = getJsonStringInput(USER_SET_CONTENT); - - ResponseEntity response = getApiClient().updateUserSet( - WRONG_GENERATED_IDENTIFIER - , requestBody - , null); - assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + try { + apiClient.getWebUserSetApi().updateUserSet(WRONG_GENERATED_IDENTIFIER, requestBody, null); + } catch (SetApiClientException e) { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getRemoteStatusCode()); + } } @Test public void updateWebUserSetWithWrongIdentifier() throws IOException { String requestBody = getJsonStringInput(USER_SET_CONTENT); - - ResponseEntity response = getApiClient().updateUserSet( - WRONG_GENERATED_IDENTIFIER - , requestBody - , null); - assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + try { + apiClient.getWebUserSetApi().updateUserSet(WRONG_GENERATED_IDENTIFIER, requestBody, null); + } catch (SetApiClientException e) { + assertEquals(HttpStatus.SC_NOT_FOUND, e.getRemoteStatusCode()); + } } -// @Test -// public void updateWebsetUserSetWithCorruptedUpdateBody() throws JsonParseException, IOException { -// -// /** -// * store set and retrieve its identifier -// */ -// UserSet set = createTestUserSet(); -// ResponseEntity response = getApiClient().updateUserSet( -// set.getIdentifier() -// , CORRUPTED_UPDATE_JSON -// , TEST_USER_TOKEN -// ); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// } - } \ No newline at end of file diff --git a/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolTest.java b/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolTest.java index dd5b9977..de290fd5 100644 --- a/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolTest.java +++ b/set-client/src/test/java/eu/europeana/set/client/integration/web/WebUserSetProtocolTest.java @@ -5,10 +5,13 @@ import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; + +import eu.europeana.set.client.exception.SetApiClientException; +import eu.europeana.set.definitions.model.UserSet; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.entity.EntityUtils; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; /** * This class aims at testing of the annotation methods. @@ -21,48 +24,48 @@ public class WebUserSetProtocolTest extends BaseWebUserSetProtocol { private static final String USER_SET_PATH = "http://data.europeana.eu/set/"; @Test - public void createUserSet() throws IOException { + public void createUserSet() throws SetApiClientException, IOException { String setId = createTestUserSet(USER_SET_CONTENT, null); assertNotNull(setId); - getApiClient().deleteUserSet(setId); + apiClient.getWebUserSetApi().deleteUserSet(setId); } /** - * This method creates and retrieves user set + * This method creates and retrieves user set * @throws IllegalArgumentException * @throws IOException */ @Test - public void retrieveUserSet() throws IllegalArgumentException, IOException { - ResponseEntity response; + public void retrieveUserSet() throws IllegalArgumentException, IOException, SetApiClientException { String testSetId = createTestUserSet(USER_SET_CONTENT, null); assertNotNull(testSetId); // get user set by ID and user identifier - response = getApiClient().getUserSet(testSetId, null); - validateResponse(response, HttpStatus.OK); + UserSet userSet = apiClient.getWebUserSetApi().getUserSet(testSetId, null); + assertNotNull(userSet); + assertEquals(testSetId, userSet.getIdentifier()); } - + @Test - public void updateUserSet() throws IOException { + public void updateUserSet() throws IOException, SetApiClientException { String testSetId = createTestUserSet(USER_SET_CONTENT, null); assertNotNull(testSetId); // updated user set value String requestBody = getJsonStringInput(USER_SET_UPDATE_CONTENT); assertNotNull(requestBody); // update user set by identifier URL - ResponseEntity updateResponse = getApiClient().updateUserSet( + UserSet updateResponse = apiClient.getWebUserSetApi().updateUserSet( testSetId, requestBody, null); - validateResponse(updateResponse, HttpStatus.OK); + assertNotNull(updateResponse); + assertEquals(testSetId, updateResponse.getIdentifier()); } - + @Test - public void deleteUserSet() throws IOException { + public void deleteUserSet() throws IOException, SetApiClientException { String testSetId = createTestUserSet(USER_SET_CONTENT,null); assertNotNull(testSetId); // delete user set by identifier URL - ResponseEntity deleteResponse = getApiClient().deleteUserSet( - testSetId); - assertEquals(HttpStatus.NO_CONTENT, deleteResponse.getStatusCode()); + String deleteResponse = apiClient.getWebUserSetApi().deleteUserSet(testSetId); + assertEquals(String.valueOf(HttpStatus.SC_NO_CONTENT), deleteResponse); } /** @@ -72,37 +75,8 @@ public void deleteUserSet() throws IOException { * @return id of created user set * @throws IOException */ - private String createTestUserSet(String content, String profile) throws IOException { - ResponseEntity response = storeTestUserSet(content, profile); - validateResponse(response, HttpStatus.CREATED); - String testSetId = matchSetId(response.getBody()); - return testSetId; - } - - /** - * This method matches response body to get user set ID - * e.g. ID 134 from "http://data.europeana.eu/set/134" - * @param body The response body - * @return The matched user set ID - */ - public String matchSetId(String body) { - String res = ""; - log.info("body: " + body); - String regex = "\\b(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]\\b"; - Pattern pat = Pattern.compile(regex); - Matcher mat = pat.matcher(body); - - while (mat.find()) { - res = mat.group(); - if (res.contains(USER_SET_PATH)) { - return res.replaceAll(USER_SET_PATH, ""); - } - } - return res; - } - - protected void validateResponse(ResponseEntity response, HttpStatus expectedStatus) { - assertNotNull(response.getBody()); - assertEquals(expectedStatus, response.getStatusCode()); + private String createTestUserSet(String content, String profile) throws SetApiClientException, IOException { + UserSet response = storeTestUserSet(content, profile); + return response.getIdentifier(); } } diff --git a/set-common/pom.xml b/set-common/pom.xml index 0f57c267..0dec8a3e 100644 --- a/set-common/pom.xml +++ b/set-common/pom.xml @@ -36,27 +36,19 @@ 1.0-SNAPSHOT - - org.springframework - spring-beans - - - - org.springframework - spring-web - - org.apache.commons commons-lang3 + - commons-httpclient - commons-httpclient - ${version.httpClient} + org.apache.httpcomponents.client5 + httpclient5 + ${version.httpClient5} + com.fasterxml.jackson.core diff --git a/set-common/src/main/java/eu/europeana/set/common/http/HttpConnection.java b/set-common/src/main/java/eu/europeana/set/common/http/HttpConnection.java index 1642de1f..359d8ad0 100644 --- a/set-common/src/main/java/eu/europeana/set/common/http/HttpConnection.java +++ b/set-common/src/main/java/eu/europeana/set/common/http/HttpConnection.java @@ -4,41 +4,46 @@ */ package eu.europeana.set.common.http; +import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.classic.methods.*; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.io.entity.StringEntity; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.DeleteMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.PutMethod; -import org.apache.commons.httpclient.params.HttpMethodParams; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; /** * The class encapsulating simple HTTP access. * - * @author GrafR + * @author Srishti Singh + * @since 26 November 2024 */ public class HttpConnection { public static final String HEADER_AUTHORIZATION = "Authorization"; - - private static final int CONNECTION_RETRIES = 3; - private static final int TIMEOUT_CONNECTION = 40000; - private static final int STATUS_OK_START = 200; - private static final int STATUS_OK_END = 299; - private HttpClient httpClient = null; + private final CloseableHttpClient httpClient; + + public HttpConnection() { + httpClient = HttpClientBuilder.create().build(); + } + + /** + *This method makes GET request for given URL. + * @param url + * @param acceptHeaderValue + * @param authorizationHeaderValue + * @return + * @throws IOException + */ + + public CloseableHttpResponse get(String url, String acceptHeaderValue, String authorizationHeaderValue) throws IOException { + HttpGet get = new HttpGet(url); + addHeaders(get, HttpHeaders.ACCEPT, acceptHeaderValue); + addHeaders(get, HEADER_AUTHORIZATION,authorizationHeaderValue); + return executeHttpClient(get); + } /** * This method makes POST request for given URL and JSON body parameter. @@ -47,41 +52,18 @@ public class HttpConnection { * @param requestBody * @param contentType * @return ResponseEntity that comprises response body in JSON format, headers - * and status code. + * and status code. * @throws IOException */ - public ResponseEntity post(String url, String requestBody, String contentType) throws IOException { - PostMethod post = buildPostMethod(url, requestBody, HttpHeaders.CONTENT_TYPE, contentType); - return fetchHttpMethodResponse(post); - } + public CloseableHttpResponse post(String url, String requestBody, String contentType, String authorizationHeaderValue) throws IOException { + HttpPost post = new HttpPost(url); + addHeaders(post, HttpHeaders.CONTENT_TYPE, contentType); + addHeaders(post, HEADER_AUTHORIZATION, authorizationHeaderValue); + post.setEntity(new StringEntity(requestBody)); + return executeHttpClient(post); + } - /** - * This method makes POST request for given URL and JSON body parameter with - * header. - * - * @param url - * @param body - * @param requestHeaderName - * @param authorizationHeaderValue - * @return ResponseEntity that comprises response body in JSON format, headers - * and status code. - * @throws IOException - */ - public ResponseEntity postURL(String url, String body, String authorizationHeaderValue) throws IOException { - PostMethod post = buildPostMethod(url, body, HEADER_AUTHORIZATION, - authorizationHeaderValue); - return fetchHttpMethodResponse(post); - } - @SuppressWarnings("deprecation") - private PostMethod buildPostMethod(String url, String body, String headerName, String headerValue) { - PostMethod post = new PostMethod(url); - if (StringUtils.isNotBlank(headerValue)) { - post.setRequestHeader(headerName, headerValue); - } - post.setRequestBody(body); - return post; - } /** * This method makes PUT request for given URL and JSON body parameter. @@ -89,199 +71,41 @@ private PostMethod buildPostMethod(String url, String body, String headerName, S * @param url * @param jsonParamValue * @return ResponseEntity that comprises response body in JSON format, headers - * and status code. + * and status code. * @throws IOException */ - public ResponseEntity putURL(String url, String jsonParamValue) throws IOException { - return putURL(url, jsonParamValue, null); - } + public CloseableHttpResponse put(String url, String jsonParamValue, String authorizationHeaderValue) throws IOException { + HttpPut put = new HttpPut(url); + addHeaders(put, HEADER_AUTHORIZATION,authorizationHeaderValue); + put.setEntity(new StringEntity(jsonParamValue)); - /** - * This method makes PUT request for given URL and JSON body parameter. - * - * @param url - * @param jsonParamValue - * @param requestHeaderName - * @param authorizationHeaderValue - * @return ResponseEntity that comprises response body in JSON format, headers - * and status code. - * @throws IOException - */ - @SuppressWarnings("deprecation") - public ResponseEntity putURL(String url, String jsonParamValue, String authorizationHeaderValue) - throws IOException { - PutMethod put = new PutMethod(url); - if (StringUtils.isNotBlank(authorizationHeaderValue)) { - put.setRequestHeader(HEADER_AUTHORIZATION, authorizationHeaderValue); - } - put.setRequestBody(jsonParamValue); + return executeHttpClient(put); - return fetchHttpMethodResponse(put); - } + } /** * This method makes DELETE request for given identifier URL. * - * @param url The identifier URL - * @return ResponseEntity that comprises response headers and status code. - * @throws IOException - */ - public ResponseEntity deleteURL(String url) throws IOException { - return deleteURL(url, null); - } - - /** - * This method makes DELETE request for given identifier URL. - * * @param url The identifier URL - * @param requestHeaderName * @param authorizationtHeaderValue * @return ResponseEntity that comprises response headers and status code. * @throws IOException */ - public ResponseEntity deleteURL(String url, String authorizationtHeaderValue) throws IOException { - DeleteMethod delete = new DeleteMethod(url); - if (StringUtils.isNotBlank(authorizationtHeaderValue)) { - delete.setRequestHeader(HEADER_AUTHORIZATION, authorizationtHeaderValue); + public CloseableHttpResponse deleteURL(String url, String authorizationtHeaderValue) throws IOException { + HttpDelete delete = new HttpDelete(url); + addHeaders(delete,HEADER_AUTHORIZATION, authorizationtHeaderValue); + return executeHttpClient(delete); } - return fetchHttpMethodResponse(delete); - } - /** - * This method builds a response entity that comprises response body, headers - * and status code for the passed HTTP method - * - * @param method The HTTP method (e.g. post, put, delete or get) - * @return response entity - * @throws IOException - */ - private ResponseEntity buildResponseEntity(HttpMethod method) throws IOException { - - MultiValueMap headers = new LinkedMultiValueMap<>(15); - for (Header header : method.getResponseHeaders()) - headers.add(header.getName(), header.getValue()); + private CloseableHttpResponse executeHttpClient(T url) throws IOException { + return httpClient.execute(url); - String res = null; - if (method.getResponseBody() != null && method.getResponseBody().length > 0) { - byte[] byteResponse = method.getResponseBody(); - res = new String(byteResponse, StandardCharsets.UTF_8); } - return new ResponseEntity<>(res, headers, HttpStatus.valueOf(method.getStatusCode())); - } - /** - * This method makes GET request for given URL. - * - * @param url - * @return ResponseEntity that comprises response body in JSON format, headers - * and status code. - * @throws IOException - */ - public ResponseEntity getURL(String url) throws IOException { - return getURL(url, null); - } - - /** - * This method makes GET request for given URL. - * - * @param url - * @param requestHeaderName - * @param authorizationHeaderValue - * @return ResponseEntity that comprises response body in JSON format, headers - * and status code. - * @throws IOException - */ - public ResponseEntity getURL(String url, String authorizationHeaderValue) throws IOException { - GetMethod get = new GetMethod(url); - if (StringUtils.isNotBlank(authorizationHeaderValue)) { - get.setRequestHeader(HEADER_AUTHORIZATION, authorizationHeaderValue); - } - - return fetchHttpMethodResponse(get); - } - - private ResponseEntity fetchHttpMethodResponse(HttpMethod http) throws IOException{ - HttpClient client = this.getHttpClient(CONNECTION_RETRIES, TIMEOUT_CONNECTION); - try { - client.executeMethod(http); - return buildResponseEntity(http); - } finally { - http.releaseConnection(); - } - } - - @SuppressWarnings("deprecation") - public String getURLContentWithBody(String url, String jsonParamValue) throws IOException { - PostMethod post = new PostMethod(url); - post.setRequestHeader("Content-Type", "application/json"); - post.setRequestBody(jsonParamValue); - - return callHttpMethod(post); - } - - public String getJsonResponse(String url) throws IOException { - GetMethod get = new GetMethod(url); - get.setRequestHeader("Accept", "application/json"); - return callHttpMethod(get); - } - - private String callHttpMethod(HttpMethod httpMethod) throws IOException { - HttpClient client = this.getHttpClient(CONNECTION_RETRIES, TIMEOUT_CONNECTION); - try { - client.executeMethod(httpMethod); - - if (httpMethod.getStatusCode() >= STATUS_OK_START && httpMethod.getStatusCode() <= STATUS_OK_END) { - InputStream responseBodyAsStream = httpMethod.getResponseBodyAsStream(); - return IOUtils.toString(responseBodyAsStream, StandardCharsets.UTF_8); - } else { - return null; - } - - } finally { - httpMethod.releaseConnection(); - } - } - - private HttpClient getHttpClient(int connectionRetry, int conectionTimeout) { - if (this.httpClient == null) { - HttpClient client = new HttpClient(); - - // configure retry handler - client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, - new DefaultHttpMethodRetryHandler(connectionRetry, false)); - - // when using a http proxy - String proxyHost = System.getProperty("http.proxyHost"); - if ((proxyHost != null) && (proxyHost.length() > 0)) { - String proxyPortSrt = System.getProperty("http.proxyPort"); - if (proxyPortSrt == null) { - proxyPortSrt = "8080"; + private void addHeaders(T url, String headerName, String headerValue) { + if (StringUtils.isNotBlank(headerValue)) { + url.setHeader(headerName, headerValue); } - int proxyPort = Integer.parseInt(proxyPortSrt); - - client.getHostConfiguration().setProxy(proxyHost, proxyPort); - } - - // configure timeouts - boolean bTimeout = false; - String connectTimeOut = System.getProperty("sun.net.client.defaultConnectTimeout"); - if ((connectTimeOut != null) && (connectTimeOut.length() > 0)) { - client.getParams().setIntParameter("sun.net.client.defaultConnectTimeout", - Integer.parseInt(connectTimeOut)); - bTimeout = true; - } - String readTimeOut = System.getProperty("sun.net.client.defaultReadTimeout"); - if ((readTimeOut != null) && (readTimeOut.length() > 0)) { - client.getParams().setIntParameter("sun.net.client.defaultReadTimeout", Integer.parseInt(readTimeOut)); - bTimeout = true; - } - if (!bTimeout) { - client.getParams().setIntParameter(HttpMethodParams.SO_TIMEOUT, conectionTimeout); - } - - this.httpClient = client; } - return this.httpClient; - } } diff --git a/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java b/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java index f794fa17..12d51e94 100644 --- a/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java +++ b/set-definitions/src/main/java/eu/europeana/set/definitions/model/impl/BaseUserSet.java @@ -3,6 +3,7 @@ import java.util.Date; import java.util.List; import java.util.Map; + import eu.europeana.set.definitions.model.BaseWebResource; import eu.europeana.set.definitions.model.UserSet; import eu.europeana.set.definitions.model.agent.Agent; @@ -13,9 +14,9 @@ /** * Europeana Sets API Specification * - * @author GrafR Modified by Srishti Singh 2-2-2021 + * @author GrafR */ -public abstract class BaseUserSet extends BasePageInfo implements UserSet { +public class BaseUserSet extends BasePageInfo implements UserSet { // EDM Collection Profile @@ -55,7 +56,10 @@ public abstract class BaseUserSet extends BasePageInfo implements UserSet { * of this set of the Entity user sets */ private List contributor; - + + public BaseUserSet() { + } + /** * depiction, primarily used y Galleries */ @@ -70,10 +74,6 @@ public abstract class BaseUserSet extends BasePageInfo implements UserSet { // Provenance information - /** - * A reference to the user agent that gathers objects together following - * implicit or explicit criteria or accrual policy. - */ private Agent creator; /** @@ -110,6 +110,7 @@ public String getIdentifier() { return identifier; } + public void setIdentifier(String sequenceIdentifier) { this.identifier = sequenceIdentifier; } @@ -284,6 +285,11 @@ public boolean isPublished() { return VisibilityTypes.PUBLISHED.getJsonValue().equals(getVisibility()); } + @Override + public void setBaseUrl(String baseUrl) { + //used only for web userset + } + @Override public boolean isBookmarksFolder() { return UserSetTypes.BOOKMARKSFOLDER.getJsonValue().equals(getType()); @@ -322,6 +328,11 @@ public Provider getProvider() { return provider; } + @Override + public boolean hasItem(String itemId) { + return getItems() != null && getItems().contains(itemId); + } + @Override public void setProvider(Provider provider) { this.provider = provider; diff --git a/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java b/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java index 4f54c40f..2d2e48ec 100644 --- a/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java +++ b/set-definitions/src/main/java/eu/europeana/set/definitions/model/vocabulary/WebUserSetFields.java @@ -16,7 +16,8 @@ public class WebUserSetFields extends WebUserSetModelFields { public static final String EQUALS_PARAMETER = "="; public static final String JSON_LD_REST = ".jsonld"; public static final String FORMAT_JSONLD = "jsonld"; - + public static final String SEARCH_PATH = "search"; + public static final int DEFAULT_PAGE = 1; // Query Params Constants diff --git a/set-integration-testing/src/main/java/eu/europeana/api/set/integration/connection/http/EuropeanaOauthClient.java b/set-integration-testing/src/main/java/eu/europeana/api/set/integration/connection/http/EuropeanaOauthClient.java index acb5bfd7..31615a73 100644 --- a/set-integration-testing/src/main/java/eu/europeana/api/set/integration/connection/http/EuropeanaOauthClient.java +++ b/set-integration-testing/src/main/java/eu/europeana/api/set/integration/connection/http/EuropeanaOauthClient.java @@ -2,10 +2,12 @@ import java.io.IOException; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import eu.europeana.api.set.integration.config.SetIntegrationConfiguration; import eu.europeana.api.set.integration.exception.TechnicalRuntimeException; @@ -13,6 +15,7 @@ /** * @author GrafR + * Currently only used in test classes */ public class EuropeanaOauthClient { @@ -52,11 +55,10 @@ public String getOauthToken(String user) { } HttpConnection connection = new HttpConnection(); - ResponseEntity response; - response = connection.post(oauthUri, oauthParams, "application/x-www-form-urlencoded"); + CloseableHttpResponse response = connection.post(oauthUri, oauthParams, "application/x-www-form-urlencoded", null); - if (HttpStatus.OK == response.getStatusCode()) { - String body = response.getBody(); + if (HttpStatus.SC_OK == response.getCode()) { + String body = EntityUtils.toString(response.getEntity()); JSONObject json = new JSONObject(body); if (json.has(accessToken)) { return "Bearer " + json.getString(accessToken); @@ -66,7 +68,7 @@ public String getOauthToken(String user) { } else { throw new TechnicalRuntimeException("Error occured when calling oath service! " + response); } - } catch (IOException | JSONException e) { + } catch (IOException | JSONException | ParseException e) { throw new TechnicalRuntimeException("Cannot retrieve authentication token!", e); } } diff --git a/set-search-api-client/src/main/java/eu/europeana/set/search/service/SearchApiClient.java b/set-search-api-client/src/main/java/eu/europeana/set/search/service/SearchApiClient.java index 475618b5..d98fab73 100644 --- a/set-search-api-client/src/main/java/eu/europeana/set/search/service/SearchApiClient.java +++ b/set-search-api-client/src/main/java/eu/europeana/set/search/service/SearchApiClient.java @@ -3,7 +3,6 @@ import java.io.IOException; -import org.apache.commons.httpclient.HttpException; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import eu.europeana.set.definitions.model.BaseWebResource; diff --git a/set-search-api-client/src/main/java/eu/europeana/set/search/service/impl/SearchApiClientImpl.java b/set-search-api-client/src/main/java/eu/europeana/set/search/service/impl/SearchApiClientImpl.java index 7e50be50..8a8df077 100644 --- a/set-search-api-client/src/main/java/eu/europeana/set/search/service/impl/SearchApiClientImpl.java +++ b/set-search-api-client/src/main/java/eu/europeana/set/search/service/impl/SearchApiClientImpl.java @@ -5,6 +5,9 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.logging.log4j.LogManager; @@ -165,20 +168,20 @@ protected List extractItemsFromSearchResponse(JSONArray valueObject, Str @Override public JSONObject searchItems(String uri, String postBody) throws SearchApiClientException { - String jsonResponse; + CloseableHttpResponse jsonResponse; try { if (postBody != null) { - jsonResponse = createHttpConnection().getURLContentWithBody(uri, postBody); + jsonResponse = createHttpConnection().post(uri, postBody, "application/json", null); } else { - jsonResponse = createHttpConnection().getJsonResponse(uri); + jsonResponse = createHttpConnection().get(uri, "application/json", null); } if (jsonResponse == null) { // HTTP Error Code throw new SearchApiClientException(SearchApiClientException.MESSAGE_INVALID_ISDEFINEDNBY, null); } - return new JSONObject(jsonResponse); - } catch (IOException e) { + return new JSONObject(EntityUtils.toString(jsonResponse.getEntity())); + } catch (IOException | ParseException e) { throw new SearchApiClientException( SearchApiClientException.MESSAGE_CANNOT_ACCESS_API + e.getMessage(), e); } catch (JSONException e) {