package org.gcube.portlets.widgets.ckan2zenodopublisher.server; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.gcube.data.publishing.ckan2zenodo.Ckan2Zenodo; import org.gcube.data.publishing.ckan2zenodo.Ckan2ZenodoImpl; import org.gcube.data.publishing.ckan2zenodo.model.CkanItemDescriptor; import org.gcube.data.publishing.ckan2zenodo.model.CkanResource; import org.gcube.data.publishing.ckan2zenodo.model.faults.ConfigurationException; import org.gcube.data.publishing.ckan2zenodo.model.faults.GcatException; import org.gcube.data.publishing.ckan2zenodo.model.faults.TransformationException; import org.gcube.data.publishing.ckan2zenodo.model.faults.ZenodoException; import org.gcube.data.publishing.ckan2zenodo.model.report.EnvironmentReport; import org.gcube.data.publishing.ckan2zenodo.model.zenodo.DepositionMetadata; import org.gcube.data.publishing.ckan2zenodo.model.zenodo.ZenodoDeposition; import org.gcube.portlets.widgets.ckan2zenodopublisher.client.CkanToZenodoPublisherService; import org.gcube.portlets.widgets.ckan2zenodopublisher.server.configuration.ZenodoFieldsDescriptionsReader; import org.gcube.portlets.widgets.ckan2zenodopublisher.server.converter.ItemToZenodoConverter; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.CatalogueItem; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.ItemTranslateError; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.ItemTranslateError.ERROR_TYPE; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.ZenodoError; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.wrapped.ZenodoFile; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.wrapped.ZenodoItem; import org.gcube.portlets.widgets.ckan2zenodopublisher.shared.wrapped.ZenodoMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.liferay.portal.service.UserLocalServiceUtil; /** * The server side implementation of the RPC service. * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * * Jan 15, 2020 */ @SuppressWarnings("serial") public class CkanToZenodoPublisherServiceImpl extends RemoteServiceServlet implements CkanToZenodoPublisherService { private static Logger LOG = LoggerFactory.getLogger(CkanToZenodoPublisherServiceImpl.class); /* (non-Javadoc) * @see org.gcube.portlets.widgets.ckan2zenodopublisher.client.CkanToZenodoPublisherService#publishOnZenodo(org.gcube.portlets.widgets.ckan2zenodopublisher.shared.wrapped.ZenodoItem) */ @Override public String publishOnZenodo(ZenodoItem zenodoItem) throws Exception { LOG.info("publishOnZenodo called"); try { if(isOutFromPortal()) { PortalUtils.getCurrentContext(this.getThreadLocalRequest(), true); PortalUtils.getCurrentToken(this.getThreadLocalRequest(), true); } Ckan2Zenodo client = new Ckan2ZenodoImpl(); // Get the item representation CkanItemDescriptor itemDescr = client.read(zenodoItem.getName()); // Get a preview of the deposition to be published ZenodoDeposition zenodoDepositionPreview = null; try { zenodoDepositionPreview = client.translate(itemDescr); } catch (ConfigurationException e) { LOG.info("Using forceTranslation for: " + itemDescr.getItemUrl()); zenodoDepositionPreview = client.forceTranslation(itemDescr); } //(EVENTUALLY) UPDATING BASIC INFO CHANGED BY FORM ON CLIENT-SIDE //Basic info zenodoDepositionPreview.setTitle(zenodoItem.getTitle()); //Updating Deposition Metadata potentially changed on client-side ZenodoMetadata metadata = zenodoItem.getMetadata(); DepositionMetadata depositionMetadata = zenodoDepositionPreview.getMetadata(); depositionMetadata = ItemToZenodoConverter.updateMetadataInfoOfDepositionMetadata(metadata, depositionMetadata); zenodoDepositionPreview.setMetadata(depositionMetadata); //Loading Filtered resources according to VRE policies List filteredResources = loadFilterResources(zenodoItem.getName()); HashSet toUpload = new HashSet(); //Adding for publishing only the resources selected on clien-side if(zenodoItem.getFiles()!=null) { for (ZenodoFile zf : zenodoItem.getFiles()) { for (CkanResource ckanResource : filteredResources) { if(zf.getId().compareTo(ckanResource.getId())==0 && zf.getIsAlreadyPublished()==false) { if(CkanToZenodoUtil.isNotEmpty(zf.getFilename())) { ckanResource.setName(zf.getFilename()); //only the filename can be changed on clien-side toUpload.add(ckanResource); } } } } } //Actually publish to zenodo : // Step 1 : metadata client= new Ckan2ZenodoImpl(); LOG.debug("Calling updatedMetadata for: "+zenodoDepositionPreview); zenodoDepositionPreview = client.updatedMetadata(zenodoDepositionPreview); //Step 2 : publish Resources if(toUpload.size()>0) { LOG.debug("Trying to publish the set of CKAN resources: "+toUpload.toString()); Future future_Dep=client.uploadFiles(toUpload, zenodoDepositionPreview); while(!future_Dep.isDone()) { LOG.debug("Waiting for completed future computation (publishing of resources on Zenodo)..."); Thread.sleep(2000); } zenodoDepositionPreview = future_Dep.get(600,TimeUnit.SECONDS); } // Get the item representation CkanItemDescriptor item=client.read(zenodoItem.getName()); //Finalize LOG.debug("Calling publish on Zenodo for: "+zenodoDepositionPreview); zenodoDepositionPreview = client.publish(zenodoDepositionPreview, item); return zenodoDepositionPreview.getDoi(); //throw new ZenodoException(); }catch (TimeoutException e) { String error = "I'm waiting too time to upload the files to Zenodo. Check by yourself the result later"; LOG.error(error, e); String clientError = String.format("%s", error); throw new Exception(clientError); } catch (ZenodoException e) { String error = ZenodoException.class.getName()+" during upload to Zenodo the catalogue item: "+zenodoItem.getName(); LOG.error(error, e); //String clientError = String.format("%s", e.getRemoteMessage()); ZenodoError zenodoError = new ZenodoError(e); zenodoError.setRemoteMessage(e.getRemoteMessage()); zenodoError.setResponseHTTPCode(e.getResponseHTTPCode()); throw zenodoError; } catch (Exception e) { String error = "Error during upload to Zenodo the catalogue item: "+zenodoItem.getName(); LOG.error(error, e); String clientError = String.format("%s. %s", error, e.getMessage()); throw new Exception(clientError); } } /* (non-Javadoc) * @see org.gcube.portlets.widgets.ckan2zenodopublisher.client.CkanToZenodoPublisherService#convertToZenodoItem(org.gcube.portlets.widgets.ckan2zenodopublisher.shared.CatalogueItem) */ @Override public ZenodoItem convertToZenodoItem(CatalogueItem item) throws Exception { LOG.info("convertToZenodoItem called"); try { if(isOutFromPortal()) { PortalUtils.getCurrentContext(this.getThreadLocalRequest(), true); PortalUtils.getCurrentToken(this.getThreadLocalRequest(), true); } Ckan2Zenodo client = new Ckan2ZenodoImpl(); // Get the item representation CkanItemDescriptor itemDescr = client.read(item.getItemId()); // Get a preview of the deposition to be published ZenodoDeposition zdDeposition = null; ItemTranslateError itemTrError = null; try { zdDeposition = client.translate(itemDescr); } catch (ConfigurationException e) { LOG.info(ConfigurationException.class.getSimpleName() + " thrown, trying to use forceTranslation for: " + itemDescr.getName()); itemTrError = new ItemTranslateError(e.getMessage(), ERROR_TYPE.INFO); zdDeposition = client.forceTranslation(itemDescr); } //Loading Filtered resources according to VRE policies List filteredResources = loadFilterResources(item.getItemId()); LOG.debug("Loaded filtered resources: "+filteredResources); //Converting ZenodoDeposition to ZenodoItem ZenodoItem zenodoItem = ItemToZenodoConverter.toZenodoItem(zdDeposition); //Adding ItemTranslateError eventually occurred by calling client.translate zenodoItem.setTranslateError(itemTrError); //Adding the filtered resources List resources = ItemToZenodoConverter.toZenodoFiles(filteredResources, false); zenodoItem.addFiles(resources); //I'M SETTING THE ID BECAUSE THE NAME IS NULL INTO BEAN PASSED FROM PORTLET SIDE //TODO I'M WAITING FOR itemName retrieved from ckan2zenodo library zenodoItem.setName(item.getItemId()); LOG.debug("Returning item: "+zenodoItem); return zenodoItem; } catch (ZenodoException e) { String error = ZenodoException.class.getName()+" on converting the catalogue item with id: "+item.getItemId(); LOG.error(error, e); //String clientError = String.format("%s. %s", error, e.getRemoteMessage()); ZenodoError zenodoError = new ZenodoError(e); zenodoError.setRemoteMessage(e.getRemoteMessage()); zenodoError.setResponseHTTPCode(e.getResponseHTTPCode()); throw zenodoError; } catch (Exception e) { String error = "Error on converting the catalogue item with id: "+item.getItemId(); LOG.error(error, e); String clientError = String.format("%s. %s", error, e.getMessage()); throw new Exception(clientError); } } /* (non-Javadoc) * @see org.gcube.portlets.widgets.ckan2zenodopublisher.client.CkanToZenodoPublisherService#convertToZenodoItem(org.gcube.portlets.widgets.ckan2zenodopublisher.shared.CatalogueItem) */ @Override public Map readFieldsDescriptions() throws Exception { LOG.info("readFieldsDescriptions called"); try { if(isOutFromPortal()) { PortalUtils.getCurrentContext(this.getThreadLocalRequest(), true); PortalUtils.getCurrentToken(this.getThreadLocalRequest(), true); } return ZenodoFieldsDescriptionsReader.readProperties(); } catch (Exception e) { String error = "Unable to read the file of properties with the fields desciptions"; LOG.error(error, e); String clientError = String.format("%s. %s", error, e.getMessage()); throw new Exception(clientError); } } @Override public Boolean checkZenodoEnvironment() { LOG.info("checkZenodoEnvironment called"); boolean isZenodoConfigured = false; try { if(isOutFromPortal()) { PortalUtils.getCurrentContext(this.getThreadLocalRequest(), true); PortalUtils.getCurrentToken(this.getThreadLocalRequest(), true); } LOG.info("readFieldsDescriptions called"); Ckan2Zenodo client = new Ckan2ZenodoImpl(); EnvironmentReport report = client.checkEnvironment(); LOG.info("EnvironmentReport returned: "+report); isZenodoConfigured = report.isok(); } catch (Exception e) { LOG.error("Error occurred during checkEnvironment: ", e); } LOG.info("Is Zenodo Environment configured? " + isZenodoConfigured); return isZenodoConfigured; } /** * Load filter resources. * * @param itemName the item name * @return the list * @throws GcatException the gcat exception * @throws ConfigurationException the configuration exception * @throws TransformationException the transformation exception */ private List loadFilterResources(String itemName) throws GcatException, ConfigurationException, TransformationException { Ckan2Zenodo client = new Ckan2ZenodoImpl(); // Get the item representation CkanItemDescriptor itemDescr=client.read(itemName); //Filter resources according to VRE policies return client.filterResources(itemDescr); } /** * Online or in development mode?. * * @return true if you're running into the portal, false if in development */ private boolean isOutFromPortal() { try { UserLocalServiceUtil.getService(); return false; } catch (com.liferay.portal.kernel.bean.BeanLocatorException ex) { LOG.debug("Development Mode ON"); return true; } } }