/**
*
*/
package au.edu.anu.datacommons.external.github;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import au.edu.anu.datacommons.external.ExternalMetadataException;
import au.edu.anu.datacommons.external.ExternalMetadataProvider;
import au.edu.anu.datacommons.external.ParamInfo;
import au.edu.anu.datacommons.webservice.bindings.Collection;
import au.edu.anu.datacommons.webservice.bindings.Creator;
import au.edu.anu.datacommons.webservice.bindings.FedoraItem;
/**
* Retrieves metadata from a GitHub repository and returns a FedoraItem object with that metadata.
*
* @author Rahul Khanna
*
*/
public class MetadataProviderGitHub implements ExternalMetadataProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(MetadataProviderGitHub.class);
private static final String API_URL = "api.github.com";
private static final ClientResponse.Status[] SUCCESS_STATUSES = {ClientResponse.Status.OK};
private static final String FRIENDLY_NAME = "GitHub";
private static final List<ParamInfo> requiredParams = new ArrayList<>(1);
static {
requiredParams.add(new ParamInfo("repoUrl", "Repository URL"));
}
@Autowired
Client client;
public MetadataProviderGitHub() {
super();
}
@Override
public String getFriendlyName() {
return FRIENDLY_NAME;
}
@Override
public String getFqClassName() {
return this.getClass().getName();
}
@Override
public List<ParamInfo> getRequiredParams() {
return requiredParams;
}
@Override
public FedoraItem retrieveMetadata(MultivaluedMap<String, String> params) throws ExternalMetadataException {
String repoUrl = getRepoUrl(params);
LOGGER.trace("Retrieving metadata from external provider at {}...", repoUrl);
WebResource webRes = client.resource(repoUrl);
ClientResponse clientResp = webRes.get(ClientResponse.class);
GitHubRepoDetailsResponse resp = null;
if (isSuccess(clientResp.getClientResponseStatus())) {
resp = webRes.get(GitHubRepoDetailsResponse.class);
} else {
String entity = clientResp.getEntity(String.class);
throw new ExternalMetadataException(MessageFormat.format("{0} returned unsuccessful HTTP Status: {1}, {2}",
FRIENDLY_NAME, clientResp.getStatus(), entity));
}
return createFedoraItem(resp);
}
private String getRepoUrl(MultivaluedMap<String, String> params) throws ExternalMetadataException {
String repoUrl;
try {
repoUrl = convertToApiUrl(params.getFirst("repoUrl"));
} catch (MalformedURLException e) {
throw new ExternalMetadataException(e);
}
return repoUrl;
}
private boolean isSuccess(Status clientResponseStatus) {
for (ClientResponse.Status iStatus : SUCCESS_STATUSES) {
if (iStatus.equals(clientResponseStatus)) {
return true;
}
}
return false;
}
/**
* Converts a GitHub repository URL from the format https://github.com/{user}/{repo} to
* https://api.github.com/repos/{user}/{repo} for API use.
*
* @param url
* URL of the HTML view of a repository
* @return URL of a JSON view of a repository as String
* @throws MalformedURLException
*/
private String convertToApiUrl(String url) throws MalformedURLException {
URL jsonUrl;
URL htmlUrl = new URL(url);
if (!htmlUrl.getHost().equalsIgnoreCase(API_URL)) {
jsonUrl = new URL(htmlUrl.getProtocol(), API_URL, htmlUrl.getPort(), "/repos" + htmlUrl.getFile());
} else {
jsonUrl = htmlUrl;
}
return jsonUrl.toString();
}
/**
* Maps metadata fields in GitHubRepoDetailsResponse to their corresponding fields in a Collection.
*
* @param gitHubResp
* GitHubRepoDetailsResponse object to read fields from
* @return FedoraItem with metadata mapped from the GitHubRepoDetailsResponse object
*/
private FedoraItem createFedoraItem(GitHubRepoDetailsResponse gitHubResp) {
Collection coll = new Collection();
// Title
coll.setTitle(gitHubResp.getName());
// Brief Description
coll.setBriefDesc(gitHubResp.getDescription());
// Creator
Creator creator = new Creator();
creator.setCitCreatorGiven(gitHubResp.getOwner().getUsername());
coll.setCreators(Arrays.asList(creator));
// Website address
coll.setWebsiteAddress(gitHubResp.getHtmlUrl());
return coll;
}
}