package org.gcube.portlets.widgets.ckan2zenodopublisher.server; import java.util.Date; 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.DOI_dv; 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 DOI_dv publishOnZenodo(ZenodoItem zenodoItem) throws Exception { LOG.info("publishOnZenodo called"); try { if (isOutFromPortal()) { PortalUtils.getCurrentContext(this.getThreadLocalRequest(), true); PortalUtils.getCurrentToken(this.getThreadLocalRequest(), true); } LOG.debug("publishOnZenodo called with metadata: "+zenodoItem.getMetadata()); 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); //fixing issue #26166 Date thePublicationDate = zenodoDepositionPreview.getMetadata().getPublication_date(); LOG.debug("Publication_Date before update is: " + thePublicationDate); zenodoDepositionPreview = client.updatedMetadata(zenodoDepositionPreview); // Step 2 : publish Resources if (toUpload.size() > 0) { LOG.debug("Trying to publish the set of CKAN resources: " + toUpload.toString()); //fixing issue #26166 zenodoDepositionPreview.getMetadata().setPublication_date(thePublicationDate); LOG.debug("Publication_Date before uploadFiles is: " + zenodoDepositionPreview.getMetadata().getPublication_date()); 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()); //fixing issue #26166 LOG.debug("Publication_Date before publish is: " + thePublicationDate); zenodoDepositionPreview.getMetadata().setPublication_date(thePublicationDate); // Finalize LOG.debug("Calling publish on Zenodo for: " + zenodoDepositionPreview); zenodoDepositionPreview = client.publish(zenodoDepositionPreview, item); return new DOI_dv(zenodoDepositionPreview.getDoi(), zenodoDepositionPreview.getDoi_url()); // 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 | TransformationException 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); } 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("zenodoItem getLicenses as list: " + zenodoItem.getMetadata().getLicenseIDs()); //LOG.debug("setting licenses at null"); //zenodoItem.getMetadata().setLicenseIDs(null); 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; } } }