Commit d278bd04 authored by Matija Obreza's avatar Matija Obreza

Added Genesys Images API support (Fixes #2)

parent 660dbee1
......@@ -16,22 +16,44 @@
package org.genesys2.client.oauth;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.activation.MimetypesFileTypeMap;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.entity.ContentType;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.genesys2.client.oauth.api.GenesysApi;
import org.genesys2.client.oauth.api.accession.AccessionJson;
import org.genesys2.client.oauth.api.images.RepositoryImage;
import org.scribe.builder.ServiceBuilder;
import org.scribe.exceptions.OAuthConnectionException;
import org.scribe.exceptions.OAuthException;
......@@ -42,13 +64,6 @@ import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Genesys API client using Scribe.
*/
......@@ -84,6 +99,9 @@ public class GenesysClient {
/** Socket read timeout. */
private int readTimeout = 120;
/** UTF8 charset */
private static Charset CHARSET_UTF8 = Charset.forName("UTF8");
static {
objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
......@@ -239,6 +257,20 @@ public class GenesysClient {
return query(Verb.GET, url, null, null);
}
/**
* Query.
*
* @param method the HTTP method
* @param url the url
* @return the string
* @throws OAuthAuthenticationException the o auth authentication exception
* @throws PleaseRetryException the please retry exception
* @throws GenesysApiException the genesys api exception
*/
public String query(Verb method, String url) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
return query(method, url, null, null);
}
/**
* Query.
*
......@@ -255,6 +287,29 @@ public class GenesysClient {
public String query(Verb method, String url, Map<String, String> queryString, String postBody)
throws OAuthAuthenticationException, PleaseRetryException, HttpRedirectException, GenesysApiException {
if (StringUtils.isBlank(postBody)) {
return query(method, url, queryString, null, null);
} else {
return query(method, url, queryString, ContentType.APPLICATION_JSON.withCharset(CHARSET_UTF8).getMimeType(), postBody.getBytes(CHARSET_UTF8));
}
}
/**
* Send object as JSON
*
* @param method
* @param url
* @param queryString
* @param object
* @return
* @throws GenesysApiException
* @throws JsonProcessingException
*/
private String query(Verb method, String url, Map<String, String> queryString, Serializable object) throws GenesysApiException, JsonProcessingException {
return query(method, url, queryString, ContentType.APPLICATION_JSON.withCharset(CHARSET_UTF8).getMimeType(), objectMapper.writeValueAsBytes(object));
}
private String query(Verb method, String url, Map<String, String> queryString, String contentType, byte[] postBody) throws GenesysApiException {
if (!tokens.hasAccessToken()) {
refreshAccessToken();
}
......@@ -272,10 +327,13 @@ public class GenesysClient {
_log.debug(method + " " + request.getCompleteUrl());
}
if (StringUtils.isNotBlank(contentType)) {
request.addHeader("Content-Type", contentType);
}
if (postBody != null) {
// System.err.println("Adding data: " + data);
request.addPayload(postBody);
request.addHeader("Content-Type", "application/json;charset=utf-8");
}
service.signRequest(tokens.accessToken(), request);
......@@ -1074,4 +1132,122 @@ public class GenesysClient {
params.put("query", query);
return query(Verb.GET, "/acn/" + instCode + "/list", params, null);
}
/**
* List existing image galleries for INSTCODE. The response is paginated, provide <code>page</page> argument to request a specific page.
*
* @param instCode institute code (MCPD INSTCODE)
* @param page 1 for first page
* @throws GenesysApiException
* @throws HttpRedirectException
* @throws PleaseRetryException
* @throws OAuthAuthenticationException
*/
public String listGalleries(String instCode, int page) throws OAuthAuthenticationException, PleaseRetryException, HttpRedirectException, GenesysApiException {
return query(Verb.GET, String.format("/img/%1$s/_galleries", instCode), Collections.singletonMap("page", Integer.toString(page)), null);
}
/**
* List UUIDs of images in an existing accession gallery.
*
* @param instCode institute code (MCPD INSTCODE)
* @param page 1 for first page
* @throws GenesysApiException
* @throws HttpRedirectException
* @throws PleaseRetryException
* @throws OAuthAuthenticationException
*/
public List<UUID> listGalleryImages(String instCode, String acceNumb)
throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException, JsonParseException, JsonMappingException, IOException {
String json = query(Verb.GET, String.format("/img/%1$s/acn/%2$s", instCode));
return objectMapper.readValue(json, new TypeReference<List<UUID>>() {
});
}
/**
* Add image to accession
*
* @param instCode institute code (MCPD INSTCODE)
* @param acceNumb accession number (MCPD ACCENUMB)
* @param file image to upload
* @throws IOException if file cannot be read
* @throws GenesysApiException
*/
public RepositoryImage uploadImage(String instCode, String acceNumb, File file) throws GenesysApiException, IOException {
String contentType = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(file.getName());
return uploadImage(instCode, acceNumb, file, contentType);
}
/**
* Add image to accession
*
* @param instCode institute code (MCPD INSTCODE)
* @param acceNumb accession number (MCPD ACCENUMB)
* @param file image to upload
*
* @throws IOException if file cannot be read
* @throws GenesysApiException
*/
public RepositoryImage uploadImage(String instCode, String acceNumb, File file, String contentType) throws GenesysApiException, IOException {
if (StringUtils.isBlank(contentType)) {
throw new GenesysApiException("Content-Type must be provided for the file " + file.getAbsolutePath());
}
// PUT file on server
String json = query(Verb.PUT, String.format("/img/%1$s/acn/%2$s", instCode, acceNumb), Collections.singletonMap("originalFilename", file.getName()), contentType,
FileUtils.readFileToByteArray(file));
// Deserialize JSON
return objectMapper.readValue(json, RepositoryImage.class);
}
/**
* Remove image from accession gallery by UUID. URL template: <code>/img/{instCode}/acn/{acceNumb:.+}/{uuid}/_metadata</code>
*
* @param instCode institute code (MCPD INSTCODE)
* @param acceNumb accession number (MCPD ACCENUMB)
* @param uuid Repository image UUID as assigned by Genesys
* @throws GenesysApiException
* @throws PleaseRetryException
* @throws OAuthAuthenticationException
*/
public void deleteImage(String instCode, String acceNumb, UUID uuid) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
query(Verb.DELETE, String.format("/img/%1$s/acn/%2$s/%3$s", instCode, acceNumb, uuid));
}
/**
* Get image metadata from Genesys
*
* @param instCode institute code (MCPD INSTCODE)
* @param acceNumb accession number (MCPD ACCENUMB)
* @param uuid Repository image UUID as assigned by Genesys
* @return the metadata
* @throws GenesysApiException
* @throws IOException
*/
public RepositoryImage getImageMetadata(String instCode, String acceNumb, UUID uuid) throws GenesysApiException, IOException {
// PUT file on server
String json = query(Verb.GET, String.format("/img/%1$s/acn/%2$s/%3$s/_metadata", instCode, acceNumb, uuid));
// Deserialize JSON
return objectMapper.readValue(json, RepositoryImage.class);
}
/**
* Set image metadata. Endpoint <b>PUT</b> <code>/img/{instCode}/acn/{acceNumb:.+}/{uuid}/_metadata</code>
*
* @param instCode institute code (MCPD INSTCODE)
* @param acceNumb accession number (MCPD ACCENUMB)
* @param uuid Repository image UUID as assigned by Genesys
* @return the metadata
* @throws GenesysApiException
* @throws IOException
*/
public RepositoryImage putImageMetadata(String instCode, String acceNumb, UUID uuid, RepositoryImage imageData) throws GenesysApiException, IOException {
String json = query(Verb.PUT, String.format("/img/%1$s/acn/%2$s/%3$s/_metadata", instCode, acceNumb, uuid), null, imageData);
// Deserialize JSON
return objectMapper.readValue(json, RepositoryImage.class);
}
}
/*
* Copyright 2016 Global Crop Diversity Trust
*
* 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 org.genesys2.client.oauth.api.images;
import java.io.Serializable;
import java.util.Date;
/**
* Data only. Copied from genesys-file-repository.
*/
public class RepositoryFile implements Serializable {
private static final long serialVersionUID = -6507809172296678924L;
private String title;
private String subject;
private String description;
private String creator;
private String created;
private String rightsHolder;
private String accessRights;
private String license;
private String format;
private String extent;
private String bibliographicCitation;
private Date dateSubmitted;
private Date modified;
private String identifier;
private String originalFilename;
private String contentType;
public String getAccessRights() {
return accessRights;
}
public String getBibliographicCitation() {
return bibliographicCitation;
}
public String getCreated() {
return created;
}
public String getCreator() {
return creator;
}
public Date getDateSubmitted() {
return dateSubmitted;
}
public String getDescription() {
return description;
}
public String getExtent() {
return extent;
}
public String getFormat() {
return format;
}
public String getIdentifier() {
return identifier;
}
public String getLicense() {
return license;
}
public Date getModified() {
return modified;
}
public String getRightsHolder() {
return rightsHolder;
}
public String getSubject() {
return subject;
}
public String getTitle() {
return title;
}
public void setAccessRights(final String accessRights) {
this.accessRights = accessRights;
}
public void setBibliographicCitation(final String bibliographicCitation) {
this.bibliographicCitation = bibliographicCitation;
}
public void setCreated(final String created) {
this.created = created;
}
public void setCreator(final String creator) {
this.creator = creator;
}
public void setDateSubmitted(final Date dateSubmitted) {
this.dateSubmitted = dateSubmitted;
}
public void setDescription(final String description) {
this.description = description;
}
public void setExtent(final String extent) {
this.extent = extent;
}
public void setFormat(final String format) {
this.format = format;
}
public void setIdentifier(final String identifier) {
this.identifier = identifier;
}
public void setLicense(final String license) {
this.license = license;
}
public void setModified(final Date modified) {
this.modified = modified;
}
public void setRightsHolder(final String rightsHolder) {
this.rightsHolder = rightsHolder;
}
public void setSubject(final String subject) {
this.subject = subject;
}
public void setTitle(final String title) {
this.title = title;
}
public void setOriginalFilename(final String originalFilename) {
this.originalFilename = originalFilename;
}
public String getOriginalFilename() {
return originalFilename;
}
public void setContentType(final String contentType) {
this.contentType = contentType;
}
public String getContentType() {
return contentType;
}
}
/*
* Copyright 2016 Global Crop Diversity Trust
*
* 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 org.genesys2.client.oauth.api.images;
import java.io.Serializable;
/**
* Data only! Copied from genesys-file-repository.
*/
public class RepositoryImage extends RepositoryFile implements Serializable {
private static final long serialVersionUID = 2831636346518244094L;
private Integer width;
private Integer height;
private Orientation orientation;
public Integer getHeight() {
return height;
}
public Orientation getOrientation() {
return orientation;
}
public Integer getWidth() {
return width;
}
public void setHeight(final Integer height) {
this.height = height;
}
public void setOrientation(final Orientation orientation) {
this.orientation = orientation;
}
public void setWidth(final Integer width) {
this.width = width;
}
/**
* Image orientation.
*/
public static enum Orientation {
/** The portrait. */
PORTRAIT,
/** The landscape. */
LANDSCAPE;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment