From f7d30e099aea5d9b5f7c19b2888a29428c91630d Mon Sep 17 00:00:00 2001 From: Costantino Perciante Date: Wed, 22 Feb 2017 16:40:16 +0000 Subject: [PATCH] added support for ticket #7207 git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/widgets/ckan-metadata-publisher-widget@144145 82a268e6-3cf1-43bd-a215-b396298e98cf --- .../client/CKanPublisherService.java | 6 +- .../client/CKanPublisherServiceAsync.java | 6 +- .../client/ui/CreateDatasetForm.java | 43 +++++----- .../TwinColumnSelectionMainPanel.java | 28 ++++-- .../server/CKANPublisherServicesImpl.java | 8 +- .../server/utils/WorkspaceUtils.java | 85 ++++++++++++------- .../shared/DatasetMetadataBean.java | 39 +++------ 7 files changed, 120 insertions(+), 95 deletions(-) diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java index 1054fb1..892f13a 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java @@ -32,11 +32,11 @@ public interface CKanPublisherService extends RemoteService { List getProfiles(String orgName); /** - * Retrieve a partially filled bean given a folder id and its owner. - * @param folderId + * Retrieve a partially filled bean given a folder id/file id and its owner. + * @param folderIdOrFileId the id of the folder of file to publish * @return @return a DatasetMetadataBean on success, null on error. */ - DatasetMetadataBean getDatasetBean(String folderId); + DatasetMetadataBean getDatasetBean(String folderIdOrFileId); /** * Try to create such dataset starting from the information contained into the toCreate bean. diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java index 5a8be48..df7f207 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java @@ -23,11 +23,11 @@ public interface CKanPublisherServiceAsync { void getLicenses(AsyncCallback callback); /** - * Retrieve a partially filled bean given a folder id and its owner. - * @param folderId + * Retrieve a partially filled bean given a folder id/file id and its owner. + * @param folderIdOrFileId the id of the folder of file to publish * @return @return a DatasetMetadataBean on success, null on error. */ - void getDatasetBean(String folderId, + void getDatasetBean(String folderIdOrFileId, AsyncCallback callback); /** diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java index 92133b1..da73973 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java @@ -222,8 +222,8 @@ public class CreateDatasetForm extends Composite{ * @param idFolderWorkspace * @param eventBus the event bus */ - public CreateDatasetForm(String idFolderWorkspace, HandlerManager eventBus) { - createDatasetFormBody(true, idFolderWorkspace, eventBus); + public CreateDatasetForm(String idFolderOrFileWorkspace, HandlerManager eventBus) { + createDatasetFormBody(true, idFolderOrFileWorkspace, eventBus); } /** @@ -256,7 +256,7 @@ public class CreateDatasetForm extends Composite{ * @param owner * @param eventBus */ - private void createDatasetFormBody(final boolean isWorkspaceRequest, final String idFolderWorkspace, final HandlerManager eventBus){ + private void createDatasetFormBody(final boolean isWorkspaceRequest, final String idFolderOrFileWorkspace, final HandlerManager eventBus){ initWidget(uiBinder.createAndBindUi(this)); this.eventBus = eventBus; @@ -282,7 +282,7 @@ public class CreateDatasetForm extends Composite{ setAlertBlock("Retrieving information, please wait...", AlertType.INFO, true); // get back the licenses and the metadata information - ckanServices.getDatasetBean(idFolderWorkspace, new AsyncCallback() { + ckanServices.getDatasetBean(idFolderOrFileWorkspace, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -339,16 +339,12 @@ public class CreateDatasetForm extends Composite{ } if(isWorkspaceRequest){ - - boolean showAlertMissingResources = bean.getResources() == null || bean.getResources().isEmpty() || bean.getResources().get(0).getChildren() == null || - bean.getResources().get(0).getChildren().isEmpty(); - // if there are not resources, for now just checked it ( and hide so that the step will be skipped) - if(showAlertMissingResources){ + if(hideManageResources()){ alertNoResources.setType(AlertType.WARNING); alertNoResources.setVisible(true); }else - resourcesTwinPanel = new TwinColumnSelectionMainPanel(bean.getResources().get(0)); + resourcesTwinPanel = new TwinColumnSelectionMainPanel(bean.getResourceRoot()); } // set organizations @@ -731,9 +727,8 @@ public class CreateDatasetForm extends Composite{ // we need to show the page to handle resources one by one from the workspace formFirstStep.setVisible(false); - boolean hideManageResources = receivedBean.getResources() == null || receivedBean.getResources().isEmpty(); - formSecondStep.setVisible(!hideManageResources); - formThirdStep.setVisible(hideManageResources); + formSecondStep.setVisible(!hideManageResources()); + formThirdStep.setVisible(hideManageResources()); // add the resources to the container panel if(workspaceResourcesContainer.getWidget() == null){ @@ -773,9 +768,8 @@ public class CreateDatasetForm extends Composite{ // swap forms if(isWorkspaceRequest){ - boolean resourcesPresent = receivedBean.getResources() != null && receivedBean.getResources().size() > 0 ? true : false; - formFirstStep.setVisible(!resourcesPresent); - formSecondStep.setVisible(resourcesPresent); + formFirstStep.setVisible(hideManageResources()); + formSecondStep.setVisible(!hideManageResources()); }else{ formFirstStep.setVisible(true); formSecondStep.setVisible(false); @@ -853,7 +847,7 @@ public class CreateDatasetForm extends Composite{ receivedBean.setSelectedOrganization(chosenOrganization); receivedBean.setGroups(groups); if(resourcesTwinPanel != null) - receivedBean.setResources(resourcesTwinPanel.getResourcesToPublish()); + receivedBean.setResourceRoot(resourcesTwinPanel.getResourcesToPublish()); Map> customFieldsMap = new HashMap>(); @@ -1122,7 +1116,7 @@ public class CreateDatasetForm extends Composite{ focusPanelTitle, popupOpenedIds ); - + // description InfoIconsLabels.preparePopupPanelAndPopover( InfoIconsLabels.DESCRIPTION_INFO_ID_POPUP, @@ -1279,7 +1273,7 @@ public class CreateDatasetForm extends Composite{ organizationsGroup.setType(ControlGroupType.ERROR); return "You must select an organization in which you want to publish"; } - + // at least one tag.. if(tagsPanel.getTags().isEmpty()){ tagsPanel.setGroupPanelType(ControlGroupType.ERROR); @@ -1425,4 +1419,15 @@ public class CreateDatasetForm extends Composite{ groupsControlGroup.setVisible(true); } + + /** + * Check if resource(s) are missing + * @return + */ + private boolean hideManageResources(){ + + return receivedBean.getResourceRoot() == null || (receivedBean.getResourceRoot().isFolder() && (receivedBean.getResourceRoot().getChildren() == null || + receivedBean.getResourceRoot().getChildren().isEmpty())); + + } } diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java index a2e8dca..352d8f5 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java @@ -1,6 +1,7 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -145,8 +146,11 @@ public class TwinColumnSelectionMainPanel extends Composite{ // Set a key provider that provides a unique key for each object. cellListLeft = new CellList(cell, ResourceElementBean.KEY_PROVIDER); - cellListLeft.setPageSize(initialBean.getChildren().size()); cellListLeft.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE); + + // set page size + int size = initialBean.isFolder() ? initialBean.getChildren().size() : 1; + cellListLeft.setPageSize(size); // Add a selection model so we can select cells. selectionModelLeft = new MultiSelectionModel(ResourceElementBean.KEY_PROVIDER); @@ -207,8 +211,11 @@ public class TwinColumnSelectionMainPanel extends Composite{ }); // set the list into the provider - Collections.sort(this.initialBean.getChildren()); - dataProviderLeft.setList(this.initialBean.getChildren()); + if(initialBean.isFolder()){ + Collections.sort(this.initialBean.getChildren()); + dataProviderLeft.setList(this.initialBean.getChildren()); + }else + dataProviderLeft.setList(Arrays.asList(this.initialBean)); // add root to breadcrumb final NavLink root = new NavLink(initialBean.getName()); @@ -478,20 +485,25 @@ public class TwinColumnSelectionMainPanel extends Composite{ } /** - * Returns the list of files to save + * Returns the root parent with the children as files to save * @return the resources to save */ - public List getResourcesToPublish(){ + public ResourceElementBean getResourcesToPublish(){ + List current = dataProviderRight.getList(); - List toReturn = new ArrayList(); - + + ResourceElementBean toReturn = new ResourceElementBean(); + List children = new ArrayList(); + for (ResourceElementBean resource : current) { if(resource.isToBeAdded() && !resource.isFolder()){ // be sure ... ResourceElementBean beanWithoutChildren = new ResourceElementBean(resource); beanWithoutChildren.setName(resource.getEditableName()); - toReturn.add(beanWithoutChildren); + children.add(beanWithoutChildren); } } + + toReturn.setChildren(children); return toReturn; } diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java index deb2371..c7d946f 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java @@ -264,10 +264,10 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C // get the list of resources and convert to ResourceBean List resources = null; - List resourcesToAdd = toCreate.getResources(); + ResourceElementBean resourcesToAdd = toCreate.getResourceRoot(); // we need to copy such resource in the .catalogue area of the user's ws - if(resourcesToAdd != null && !resourcesToAdd.isEmpty()){ + if(resourcesToAdd != null){ resources = WorkspaceUtils.copyResourcesToUserCatalogueArea(toCreate.getId(), userName, toCreate); } @@ -521,7 +521,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C logger.warn("OUT FROM PORTAL DETECTED RETURNING TRUE"); return false; } - + try{ HttpSession httpSession = this.getThreadLocalRequest().getSession(); @@ -570,7 +570,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C logger.info("Does the user have the right to publish on the catalogue? " + role); return !role.equals(RolesCkanGroupOrOrg.MEMBER); - + }catch(Exception e){ logger.error("Failed to check the user's role", e); } diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/WorkspaceUtils.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/WorkspaceUtils.java index 8201013..ae82504 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/WorkspaceUtils.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/WorkspaceUtils.java @@ -31,21 +31,22 @@ public class WorkspaceUtils { private static final String RESOURCES_NAME_SEPARATOR = "_"; /** - * Copy into the .catalogue area folder the checked resources + * Copy into the .catalogue area folder the checked resources. + * There is no difference among a single-file-publish and a folder-publish. * @param folderId * @param userName * @param bean * @return */ - public static List copyResourcesToUserCatalogueArea(String folderId, String userName, DatasetMetadataBean bean) throws Exception{ + public static List copyResourcesToUserCatalogueArea(String folderOrFileId, String userName, DatasetMetadataBean bean) throws Exception{ logger.debug("Request to copy onto catalogue area...."); List resources = new ArrayList(); WorkspaceItem copiedFolder = null; WorkspaceCatalogue userCatalogue = null; - List resourcesToAdd = bean.getResources(); + ResourceElementBean rootResource = bean.getResourceRoot(); - // in to the .catalogue area of the user's workspace + // into the .catalogue area of the user's workspace Workspace ws = HomeLibrary .getHomeManagerFactory() .getHomeManager() @@ -55,16 +56,25 @@ public class WorkspaceUtils { // Retrieve the catalogue of the user userCatalogue = ws.getCatalogue(); - // Create the folder in the catalogue - copiedFolder = userCatalogue.addWorkspaceItem(folderId, userCatalogue.getId()); // add to .catalogue root area + // get workspace item (it could be a file or a folder) + WorkspaceItem originalItem = ws.getItem(folderOrFileId); - // change description for the folder - copiedFolder.setDescription(bean.getDescription()); + // copy the folder in the catalogue if it is a folder, or create a new folder + long referenceTime = System.currentTimeMillis(); + if(originalItem.isFolder()){ + copiedFolder = userCatalogue.addWorkspaceItem(folderOrFileId, userCatalogue.getId()); // add to .catalogue root area + copiedFolder.setDescription(bean.getDescription()); + } + else{ + copiedFolder = userCatalogue.createFolder(UtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime, bean.getDescription()); + } // change name of the copied folder to match the title (append the timestamp to avoid ties) - long referenceTime = System.currentTimeMillis(); ((WorkspaceFolder)copiedFolder).rename(UtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime); + // retrieve the children + List resourcesToAdd = rootResource.getChildren(); + // copy only the selected ones for(ResourceElementBean resource : resourcesToAdd){ @@ -90,6 +100,7 @@ public class WorkspaceUtils { // postpone rename operation copiedFile.rename(resource.getName() + "_" + referenceTime); } + } return resources; } @@ -111,33 +122,45 @@ public class WorkspaceUtils { .getHomeManager() .getHome().getWorkspace(); - WorkspaceItem originalFolder = ws.getItem(folderId); + WorkspaceItem originalFolderOrFile = ws.getItem(folderId); - // set some info - String onlyAlphanumericTitle = originalFolder.getName().replaceAll("[^A-Za-z0-9.-_]", " "); // that is, remove characters different than the ones inside - // since it will (likely) be the name of the product - bean.setTitle(onlyAlphanumericTitle); - bean.setDescription(originalFolder.getDescription()); + if(!originalFolderOrFile.isFolder()){ - // Create the folder in the catalogue - Map folderItems = Utils.getGcubeItemProperties(originalFolder); + ResourceElementBean resource = new ResourceElementBean(); + resource.setDescription(originalFolderOrFile.getDescription()); + resource.setFolder(false); + resource.setEditableName(originalFolderOrFile.getName()); + resource.setName(originalFolderOrFile.getName()); + resource.setOriginalIdInWorkspace(folderId); + bean.setResourceRoot(resource); + bean.setTitle(originalFolderOrFile.getName().replaceAll("[^A-Za-z0-9.-_]", " ")); + bean.setDescription(originalFolderOrFile.getDescription()); - if(folderItems != null){ - // transform this properties - Map> tempItems = new HashMap>(folderItems.size()); + }else{ - Iterator> iterator = folderItems.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry entry = (Map.Entry) iterator - .next(); - tempItems.put(entry.getKey(), Arrays.asList(entry.getValue())); + String onlyAlphanumericTitle = originalFolderOrFile.getName().replaceAll("[^A-Za-z0-9.-_]", " "); // that is, remove characters different than the ones inside + bean.setTitle(onlyAlphanumericTitle); + bean.setDescription(originalFolderOrFile.getDescription()); + + // Create the folder in the catalogue + Map folderItems = Utils.getGcubeItemProperties(originalFolderOrFile); + + if(folderItems != null){ + // transform this properties + Map> tempItems = new HashMap>(folderItems.size()); + + Iterator> iterator = folderItems.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator + .next(); + tempItems.put(entry.getKey(), Arrays.asList(entry.getValue())); + } + bean.setCustomFields(tempItems); } - - bean.setCustomFields(tempItems); - } - // set them into the bean - bean.setResources(Arrays.asList(WorkspaceUtils.getTreeFromFolder(folderId, ws))); + // set them into the bean + bean.setResourceRoot(WorkspaceUtils.getTreeFromFolder(folderId, ws)); + } } @@ -216,4 +239,4 @@ public class WorkspaceUtils { rootElem.setEditableName(fullPath); } -} +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java index 10307af..e5423ce 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java @@ -5,23 +5,7 @@ import java.util.List; import java.util.Map; /** - * This bean will contain during ckan metadata creation the following information - * (related to the workspace folder that represents a dataset) - *
    - *
  • id -> the id that will be assigned by ckan - *
  • Title -> folder's name - *
  • Description -> folders' description - *
  • tags -> folder's custom fields keys' names - *
  • visibility -> as chosen by the creator (visible = true, not visible = false) - *
  • source -> url of the folder within the workspace - *
  • version -> during creation it is going to be 1.0 - *
  • author, maintainer -> folder's owner - *
  • custom fields -> gcube items couple - *
  • organizationsList -> list of organizations to which the user belong (and in which - * he wants to publish) - *
  • list of metadata, that is custom fields per vre - *
  • the name of the chosen profile used - *
+ * This bean will contain during ckan metadata creation information related to the future build. * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) */ @SuppressWarnings("serial") @@ -44,7 +28,7 @@ public class DatasetMetadataBean implements Serializable { private long version; // version 1, 2 ... private boolean visibility; // Private (false) or Public(true) private List organizationList; // list of organization in which the user is present and could create the dataset - private List resources; // in case of workspace, this is the list of children of the folder + private ResourceElementBean resourceRoot; // in case of workspace, this is the directory root or the single file information private List metadataList; private List tags; // on retrieve, they are the keys of the custom fields private Map> customFields; @@ -81,7 +65,7 @@ public class DatasetMetadataBean implements Serializable { String authorName, String authorSurname, String authorEmail, String maintainer, String maintainerEmail, String ownerIdentifier, List organizationList, String selectedOrganization, - List resources, + ResourceElementBean resourceRoot, List metadataList, List groups) { super(); this.id = id; @@ -101,7 +85,7 @@ public class DatasetMetadataBean implements Serializable { this.ownerIdentifier = ownerIdentifier; this.organizationList = organizationList; this.selectedOrganization = selectedOrganization; - this.resources = resources; + this.resourceRoot = resourceRoot; this.metadataList = metadataList; this.groups = groups; } @@ -250,12 +234,12 @@ public class DatasetMetadataBean implements Serializable { this.selectedOrganization = selectedOrganization; } - public List getResources() { - return resources; + public ResourceElementBean getResourceRoot() { + return resourceRoot; } - public void setResources(List resources) { - this.resources = resources; + public void setResourceRoot(ResourceElementBean resourceRoot) { + this.resourceRoot = resourceRoot; } public String getAuthorFullName() { @@ -294,9 +278,10 @@ public class DatasetMetadataBean implements Serializable { + ", chosenProfile=" + chosenProfile + ", selectedOrganization=" + selectedOrganization + ", version=" + version + ", visibility=" + visibility - + ", organizationList=" + organizationList + ", resources=" - + resources + ", metadataList=" + metadataList + ", tags=" + + ", organizationList=" + organizationList + ", resourceRoot=" + + resourceRoot + ", metadataList=" + metadataList + ", tags=" + tags + ", customFields=" + customFields + ", groups=" + groups + "]"; } -} + +} \ No newline at end of file