diff --git a/CHANGELOG.md b/CHANGELOG.md index 23536e1..c0bc9ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ - Support to "split" on source values (https://support.d4science.org/issues/19534) - Support to "append" to target elements (https://support.d4science.org/issues/19535) - Multiple Date Format parsing (https://support.d4science.org/issues/19540) - +- Automatically set item URL if missing. ### Fixes - Default filter resource is applied in class Ckan2ZenodoImpl.java (https://support.d4science.org/issues/19528) +- Fixed error message for missing profile. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). \ No newline at end of file diff --git a/src/main/java/org/gcube/data/publishing/ckan2zenodo/Ckan2ZenodoImpl.java b/src/main/java/org/gcube/data/publishing/ckan2zenodo/Ckan2ZenodoImpl.java index 1423a5c..c4ad68e 100644 --- a/src/main/java/org/gcube/data/publishing/ckan2zenodo/Ckan2ZenodoImpl.java +++ b/src/main/java/org/gcube/data/publishing/ckan2zenodo/Ckan2ZenodoImpl.java @@ -38,6 +38,8 @@ public class Ckan2ZenodoImpl implements Ckan2Zenodo{ public CkanItemDescriptor read(String itemName) throws GcatException { try{ return GCat.getByID(itemName); + }catch(GcatException e) { + throw e; }catch(Throwable e) { log.warn("Unable to load "+itemName+" from gCat",e); throw new GcatException("Unable to load item from gCat"); diff --git a/src/main/java/org/gcube/data/publishing/ckan2zenodo/TransformerManager.java b/src/main/java/org/gcube/data/publishing/ckan2zenodo/TransformerManager.java index f735574..487d5f3 100644 --- a/src/main/java/org/gcube/data/publishing/ckan2zenodo/TransformerManager.java +++ b/src/main/java/org/gcube/data/publishing/ckan2zenodo/TransformerManager.java @@ -31,7 +31,8 @@ public class TransformerManager { if (r.profile().name().equals(profile)) return new Translator(IS.readMappings(r),IS.readResourceFilters(r)); } - throw new ConfigurationException("No transformer found for profile "+profile); + throw new ConfigurationException("No specific mapping for the catalogue item has been configured. " + + "By continuing with the upload some metadata might not be upload to Zenodo."); } diff --git a/src/main/java/org/gcube/data/publishing/ckan2zenodo/clients/GCat.java b/src/main/java/org/gcube/data/publishing/ckan2zenodo/clients/GCat.java index 87a4c3c..4c30a7e 100644 --- a/src/main/java/org/gcube/data/publishing/ckan2zenodo/clients/GCat.java +++ b/src/main/java/org/gcube/data/publishing/ckan2zenodo/clients/GCat.java @@ -1,19 +1,169 @@ package org.gcube.data.publishing.ckan2zenodo.clients; +import static org.gcube.common.authorization.client.Constants.authorizationService; +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.Property; +import org.gcube.common.scope.api.ScopeProvider; import org.gcube.data.publishing.ckan2zenodo.model.CkanItemDescriptor; +import org.gcube.data.publishing.ckan2zenodo.model.faults.GcatException; import org.gcube.gcat.client.Item; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.impl.XQuery; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.media.multipart.MultiPartFeature; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Slf4j public class GCat { - - public static CkanItemDescriptor getByID(String itemName) throws MalformedURLException { - return new CkanItemDescriptor(new Item().read(itemName)); + @AllArgsConstructor + @Getter + @Setter + @NoArgsConstructor + @ToString + private static class ResolverRequest{ + private String gcube_scope; + private String entity_context="dataset"; + private String entity_name; } - - + + + public static CkanItemDescriptor getByID(String itemName) throws MalformedURLException,GcatException { + CkanItemDescriptor toReturn=new CkanItemDescriptor(new Item().read(itemName)); + try { + String itemUrl=toReturn.getItemUrl(); + new URL(itemUrl); + }catch(Exception e) { + log.debug("Invalid item url for item "+itemName+". Retrieving it.. "); + String itemUrl=getItemUrl(toReturn); + + log.warn("Setting following item URL "+itemUrl+" on item "+toReturn.getName()); + toReturn.setItemUrl(itemUrl); + updateItem(toReturn); + } + return toReturn; + } + + public static void updateItem(CkanItemDescriptor toUpdate) throws MalformedURLException { new Item().update(toUpdate.getName(), toUpdate.getContent()); } + + + + + private static String getItemUrl(CkanItemDescriptor toUpdate) throws GcatException { + try{ + String baseUrl=getResolverBaseUrl(); + + log.debug("Resolver BaseUrl : "+baseUrl); + + ResolverRequest request=new ResolverRequest( + getCurrentScope(),"dataset",toUpdate.getName()); + + log.debug("Sending request : "+request); + + + Client webClient = ClientBuilder.newClient() + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); + webClient.register(MultiPartFeature.class); + + Response resp= webClient.target(baseUrl). +// path("ctlg"). + queryParam("gcube-token", SecurityTokenProvider.instance.get()).request(MediaType.TEXT_PLAIN) + .post(Entity.entity(request, MediaType.APPLICATION_JSON)); + + + if(resp.getStatus()<200||resp.getStatus()>=300) { + String remoteMessage=resp.readEntity(String.class); + Integer httpCode=resp.getStatus(); + GcatException e=new GcatException("Resolver Response ["+httpCode+"] : "+remoteMessage); + throw e; + }else return resp.readEntity(String.class); + + }catch(Exception e) { + log.error("Unable to retrieve itemUrl",e); + throw new GcatException("Unable to retrieve itemUrl",e); + } + } + + + private static String getCurrentScope(){ + try{ + String token=SecurityTokenProvider.instance.get(); + log.debug("Token is : "+token); + if(token==null) throw new Exception("Security Token is null"); + AuthorizationEntry entry = authorizationService().get(token); + return entry.getContext(); + }catch(Exception e ){ + log.debug("Unable to resolve token, checking scope provider..",e); + return ScopeProvider.instance.get(); + } + } + + + private static String getResolverBaseUrl() throws Exception { + try { + XQuery query = queryFor(ServiceEndpoint.class); + + query.addCondition("$resource/Profile/Name/text() eq 'HTTP-URI-Resolver'").setResult("$resource/Profile/AccessPoint"); + + DiscoveryClient client = clientFor(AccessPoint.class); + + List endpoints = client.submit(query); + + if (endpoints.size() == 0) + throw new Exception("No Resolver available"); + + //Building map of Access Points linked for EntryName + Map mapEntryNameForAP = new HashMap(endpoints.size()); + + //Printing all access points + for (AccessPoint accessPoint : endpoints) { + mapEntryNameForAP.put(accessPoint.name(), accessPoint); + + //Adding couple (EntryName,AccessPoint) + Map propertyMap = accessPoint.propertyMap(); + + if(propertyMap!=null) { + + for (String key: propertyMap.keySet()) { + System.out.println("Property value: "+propertyMap.get(key).value()); + //... + + } + } + } + + //Direct access to endpoint for Catalogue Resolver + AccessPoint accessPoint = mapEntryNameForAP.get("ctlg"); + return accessPoint.address(); + }catch(Throwable t) { + throw new Exception("Unable to retrieve resolver URL ",t); + } + } } diff --git a/src/main/java/org/gcube/data/publishing/ckan2zenodo/model/CkanItemDescriptor.java b/src/main/java/org/gcube/data/publishing/ckan2zenodo/model/CkanItemDescriptor.java index 10429b6..340c5db 100644 --- a/src/main/java/org/gcube/data/publishing/ckan2zenodo/model/CkanItemDescriptor.java +++ b/src/main/java/org/gcube/data/publishing/ckan2zenodo/model/CkanItemDescriptor.java @@ -167,4 +167,9 @@ public class CkanItemDescriptor { throw new InvalidItemException("Unable to set DOI",t); } } + + public CkanItemDescriptor setItemUrl(String toSet) { + getDocument().set(ITEM_URL,toSet); + return this; + } } diff --git a/src/test/java/org/gcube/tests/GCatTests.java b/src/test/java/org/gcube/tests/GCatTests.java index 0d71e73..b76fe35 100644 --- a/src/test/java/org/gcube/tests/GCatTests.java +++ b/src/test/java/org/gcube/tests/GCatTests.java @@ -7,6 +7,7 @@ import javax.ws.rs.WebApplicationException; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.data.publishing.ckan2zenodo.clients.GCat; import org.gcube.data.publishing.ckan2zenodo.model.CkanItemDescriptor; +import org.gcube.data.publishing.ckan2zenodo.model.faults.GcatException; import org.gcube.gcat.client.Item; import org.gcube.gcat.client.Profile; import org.junit.Test; @@ -15,7 +16,7 @@ public class GCatTests { @Test - public void getProfile() throws MalformedURLException { + public void getProfile() throws MalformedURLException, GcatException { TokenSetter.set("/pred4s/preprod/preVRE"); System.out.println(SecurityTokenProvider.instance.get()); CkanItemDescriptor item=GCat.getByID("sampleontable_in_prevre");