diff --git a/pom.xml b/pom.xml index 5461d6f..6ad88e5 100644 --- a/pom.xml +++ b/pom.xml @@ -93,6 +93,11 @@ portal-manager provided + + org.gcube.data-catalogue + gcubedatacatalogue-metadata-discovery + [2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT) + junit junit 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 892f13a..9615dfc 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 @@ -43,14 +43,14 @@ public interface CKanPublisherService extends RemoteService { * @param toCreate * @return the sent bean filled with the needed information */ - DatasetMetadataBean createCKanDataset(DatasetMetadataBean toCreate); + DatasetMetadataBean createCKanDataset(DatasetMetadataBean toCreate) throws Exception; /** * Add this resource to the dataset whose id is datasetId * @param resource * @param datasetId */ - ResourceElementBean addResourceToDataset(ResourceElementBean resource, String datasetId); + ResourceElementBean addResourceToDataset(ResourceElementBean resource, String datasetId) throws Exception; /** * Delete this resource from the dataset with id datasetId 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 174732e..8396c09 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 @@ -98,7 +98,7 @@ public class CreateDatasetForm extends Composite{ @UiField AlertBlock onContinueAlertBlock; @UiField AlertBlock onCreateAlertBlock; @UiField VerticalPanel metadataFieldsPanel; - @UiField ListBox metadataProfilesFormatListbox; + @UiField ListBox metadataTypeListbox; @UiField Form formFirstStep; @UiField Form formSecondStep; @UiField Form formThirdStep; @@ -132,9 +132,9 @@ public class CreateDatasetForm extends Composite{ @UiField Icon infoIconAuthorEmail; @UiField FocusPanel focusPanelAuthorEmail; @UiField Popover popoverAuthorEmail; - @UiField Icon infoIconProfiles; - @UiField FocusPanel focusPanelProfiles; - @UiField Popover popoverProfiles; + @UiField Icon infoIconTypes; + @UiField FocusPanel focusPanelTypes; + @UiField Popover popoverTypes; @UiField Icon infoIconMaintainer; @UiField FocusPanel focusPanelMaintainer; @UiField Popover popoverMaintainer; @@ -153,7 +153,7 @@ public class CreateDatasetForm extends Composite{ @UiField Icon infoIconDescription; @UiField Popover popoverDescription; @UiField FocusPanel focusPanelDescription; - @UiField ControlGroup metadataProfilesControlGroup; + @UiField ControlGroup metadataTypesControlGroup; @UiField ControlGroup productTitleGroup; @UiField ControlGroup maintainerControlGroup; @UiField ControlGroup versionControlGroup; @@ -168,9 +168,9 @@ public class CreateDatasetForm extends Composite{ private static final String NONE_PROFILE = "none"; // error/info messages - protected static final String ERROR_PRODUCT_CREATION = "There was an error while trying to publish your item, sorry.. Retry later"; + protected static final String ERROR_PRODUCT_CREATION = "There was an error while trying to publish your item."; protected static final String PRODUCT_CREATED_OK = "Item correctly published!"; - private static final String TRYING_TO_CREATE_PRODUCT = "Trying to publish the item, please wait"; + private static final String TRYING_TO_CREATE_PRODUCT = "Trying to publish the item, please wait..."; protected static final String MISSING_PUBLISH_RIGHTS = "It seems you are not authorized to publish on catalogue. Request it to the VRE manager or the portal administrator."; // tab panel @@ -267,6 +267,9 @@ public class CreateDatasetForm extends Composite{ // disable continue button continueButton.setEnabled(false); resetButton.setEnabled(false); + + // hide tags panel TODO + tagsPanel.setVisible(false); // check if the user has publishing rights setAlertBlock("Checking your permissions, please wait...", AlertType.INFO, true); @@ -314,10 +317,18 @@ public class CreateDatasetForm extends Composite{ // retrieve custom fields Map> customFieldsMap = bean.getCustomFields(); + + List vocabularyTags = bean.getTagsVocabulary(); + + // TODO vocabulary list of tags has preemption + if(vocabularyTags != null && !vocabularyTags.isEmpty()){ + + tagsPanel.setVocabulary(vocabularyTags); + + } + else if(customFieldsMap != null){ - if(customFieldsMap != null){ - - // get the keys and put them as tags + // get the keys and put them as tags Iterator>> iteratorOverCustomField = customFieldsMap.entrySet().iterator(); while (iteratorOverCustomField.hasNext()) { @@ -337,6 +348,9 @@ public class CreateDatasetForm extends Composite{ } } } + + // set it as visible anyway + tagsPanel.setVisible(true); if(isWorkspaceRequest){ // if there are not resources, for now just checked it ( and hide so that the step will be skipped) @@ -369,7 +383,7 @@ public class CreateDatasetForm extends Composite{ }); // try to retrieve the profiles - setAlertBlock("Retrieving profiles, please wait...", AlertType.INFO, true); + setAlertBlock("Retrieving types, please wait...", AlertType.INFO, true); // get the name of the organization from the title final String orgName = nameTitleOrganizationMap.get(organizationsListbox.getSelectedItemText()); @@ -379,21 +393,21 @@ public class CreateDatasetForm extends Composite{ @Override public void onFailure(Throwable caught) { - setAlertBlock("Error while retrieving profiles, retry later", AlertType.ERROR, true); + setAlertBlock("Error while retrieving types, retry later", AlertType.ERROR, true); } @Override public void onSuccess(final List profiles) { if(profiles == null){ - setAlertBlock("Error while retrieving profiles, retry later", AlertType.ERROR, true); + setAlertBlock("Error while retrieving types, retry later", AlertType.ERROR, true); } else{ - receivedBean.setMetadataList(profiles); + receivedBean.setMetadataListTypes(profiles); prepareMetadataList(receivedBean); organizationsListbox.setEnabled(true); - metadataProfilesFormatListbox.setEnabled(true); + metadataTypeListbox.setEnabled(true); // try to retrieve the licenses setAlertBlock("Retrieving licenses, please wait...", AlertType.INFO, true); @@ -494,25 +508,25 @@ public class CreateDatasetForm extends Composite{ private void organizationsListboxChangeHandlerBody() { // remove any other product profiles - metadataProfilesFormatListbox.clear(); + metadataTypeListbox.clear(); // add "none" item again - metadataProfilesFormatListbox.addItem(NONE_PROFILE); + metadataTypeListbox.addItem(NONE_PROFILE); // select "none" - metadataProfilesFormatListbox.setSelectedIndex(0); + metadataTypeListbox.setSelectedIndex(0); // get the name of the organization from the title String selectedOrganizationTitle = organizationsListbox.getSelectedItemText(); final String orgName = nameTitleOrganizationMap.get(selectedOrganizationTitle); // try to retrieve the profiles - setAlertBlock("Retrieving profiles, please wait...", AlertType.INFO, true); + setAlertBlock("Retrieving types, please wait...", AlertType.INFO, true); // disable the list of organizations name so that the user doesn't change it again // also disable the profiles and the list of groups organizationsListbox.setEnabled(false); - metadataProfilesFormatListbox.setEnabled(false); + metadataTypeListbox.setEnabled(false); groupsListbox.clear(); groupsControlGroup.setVisible(false); @@ -524,10 +538,10 @@ public class CreateDatasetForm extends Composite{ if(profiles != null){ - receivedBean.setMetadataList(profiles); + receivedBean.setMetadataListTypes(profiles); prepareMetadataList(receivedBean); organizationsListbox.setEnabled(true); - metadataProfilesFormatListbox.setEnabled(true); + metadataTypeListbox.setEnabled(true); // try to retrieve the licenses setAlertBlock("Retrieving groups, please wait...", AlertType.INFO, true); @@ -564,14 +578,14 @@ public class CreateDatasetForm extends Composite{ }); }else - setAlertBlock("Error while retrieving profiles, sorry", AlertType.ERROR, true); + setAlertBlock("Error while retrieving types, sorry", AlertType.ERROR, true); } @Override public void onFailure(Throwable caught) { - setAlertBlock("Error while retrieving profiles, sorry", AlertType.ERROR, true); + setAlertBlock("Error while retrieving types, sorry", AlertType.ERROR, true); } }); @@ -584,27 +598,27 @@ public class CreateDatasetForm extends Composite{ */ private void prepareMetadataList(final DatasetMetadataBean receivedBean) { - List profiles = receivedBean.getMetadataList(); + List profiles = receivedBean.getMetadataListTypes(); if(profiles != null && !profiles.isEmpty()){ for(MetaDataProfileBean metadataBean: profiles){ - metadataProfilesFormatListbox.addItem(metadataBean.getType().getName()); + metadataTypeListbox.addItem(metadataBean.getType().getName()); // add handler on select - metadataProfilesFormatListbox.addChangeHandler(new ChangeHandler() { + metadataTypeListbox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { - String selectedItemText = metadataProfilesFormatListbox.getSelectedItemText(); + String selectedItemText = metadataTypeListbox.getSelectedItemText(); if(selectedItemText.equals(NONE_PROFILE)){ metadataFieldsPanel.clear(); metadataFieldsPanel.setVisible(false); - receivedBean.setChosenProfile(null); + receivedBean.setChosenType(null); }else{ - receivedBean.setChosenProfile(selectedItemText); + receivedBean.setChosenType(selectedItemText); metadataFieldsPanel.clear(); addFields(selectedItemText); } @@ -628,13 +642,13 @@ public class CreateDatasetForm extends Composite{ } } - metadataProfilesControlGroup.setVisible(true); + metadataTypesControlGroup.setVisible(true); }else{ // just hide this listbox - metadataProfilesControlGroup.setVisible(false); + metadataTypesControlGroup.setVisible(false); metadataFieldsPanel.clear(); listOfMetadataFields.clear(); - receivedBean.setChosenProfile(null); + receivedBean.setChosenType(null); } } @@ -644,7 +658,7 @@ public class CreateDatasetForm extends Composite{ */ protected void addFields(String selectedItem) { - for(MetaDataProfileBean bean: receivedBean.getMetadataList()){ + for(MetaDataProfileBean bean: receivedBean.getMetadataListTypes()){ if(bean.getType().getName().equals(selectedItem)){ @@ -744,10 +758,10 @@ public class CreateDatasetForm extends Composite{ } - if(metadataProfilesFormatListbox.getSelectedItemText().equals(NONE_PROFILE)) + if(metadataTypeListbox.getSelectedItemText().equals(NONE_PROFILE)) selectedProfile.setText(""); else - selectedProfile.setText("Selected Profile is " + metadataProfilesFormatListbox.getSelectedItemText()); + selectedProfile.setText("Selected Type is " + metadataTypeListbox.getSelectedItemText()); } @@ -986,6 +1000,7 @@ public class CreateDatasetForm extends Composite{ } }else{ + alertOnCreate(ERROR_PRODUCT_CREATION, AlertType.ERROR, true); } @@ -993,7 +1008,7 @@ public class CreateDatasetForm extends Composite{ @Override public void onFailure(Throwable caught) { - alertOnCreate(ERROR_PRODUCT_CREATION, AlertType.ERROR, true); + alertOnCreate(ERROR_PRODUCT_CREATION + " Error message is : " + caught.getMessage(), AlertType.ERROR, true); } }); } @@ -1073,14 +1088,14 @@ public class CreateDatasetForm extends Composite{ popupOpenedIds ); - // profiles + // profiles (or types) InfoIconsLabels.preparePopupPanelAndPopover( InfoIconsLabels.PROFILES_INFO_ID_POPUP, InfoIconsLabels.PROFILES_INFO_TEXT, InfoIconsLabels.PROFILES_INFO_CAPTION, - infoIconProfiles, - popoverProfiles, - focusPanelProfiles, + infoIconTypes, + popoverTypes, + focusPanelTypes, popupOpenedIds ); @@ -1225,7 +1240,7 @@ public class CreateDatasetForm extends Composite{ productTitleGroup.setType(ControlGroupType.NONE); maintainerControlGroup.setType(ControlGroupType.NONE); versionControlGroup.setType(ControlGroupType.NONE); - metadataProfilesControlGroup.setType(ControlGroupType.NONE); + metadataTypesControlGroup.setType(ControlGroupType.NONE); organizationsGroup.setType(ControlGroupType.NONE); tagsPanel.setGroupPanelType(ControlGroupType.NONE); @@ -1265,8 +1280,8 @@ public class CreateDatasetForm extends Composite{ // check if metadata profile is different from none and its mandatory fields have been fulfilled if(checkSelectedMetaDataProfile()){ - metadataProfilesControlGroup.setType(ControlGroupType.ERROR); - return "You must select a metadata profile different frome none"; + metadataTypesControlGroup.setType(ControlGroupType.ERROR); + return "You must select a Type different frome none"; } if(organizationsListbox.getSelectedItemText() == null){ @@ -1288,7 +1303,7 @@ public class CreateDatasetForm extends Composite{ * @return */ private boolean checkSelectedMetaDataProfile() { - return metadataProfilesFormatListbox.getSelectedItemText().equals(NONE_PROFILE) && (metadataProfilesFormatListbox.getItemCount() != 1); + return metadataTypeListbox.getSelectedItemText().equals(NONE_PROFILE) && (metadataTypeListbox.getItemCount() != 1); } @UiHandler("resetButton") @@ -1329,7 +1344,7 @@ public class CreateDatasetForm extends Composite{ licenseListbox.setEnabled(false); organizationsListbox.setEnabled(false); addCustomFieldButton.setEnabled(false); - metadataProfilesFormatListbox.setEnabled(false); + metadataTypeListbox.setEnabled(false); groupsListbox.setEnabled(false); for(CustomFieldEntry ce: customFieldEntriesList) diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml index 6ce794e..fc82563 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml @@ -251,20 +251,19 @@ - - Item - Profile: + + Types: - + none - - - + + diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/AddResourceToDataset.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/AddResourceToDataset.java index aed866e..20f4fd9 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/AddResourceToDataset.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/AddResourceToDataset.java @@ -133,7 +133,7 @@ public class AddResourceToDataset extends Composite{ @Override public void onFailure(Throwable caught) { - showAlert("Unable to add this resource, sorry", AlertType.ERROR); + showAlert("Unable to add this resource, sorry. Error is: " + caught.getMessage(), AlertType.ERROR); } }); diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.java index b2ab9a1..37e8ae8 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.java @@ -8,6 +8,7 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.utils.InfoIc import com.github.gwtbootstrap.client.ui.ControlGroup; import com.github.gwtbootstrap.client.ui.Icon; +import com.github.gwtbootstrap.client.ui.ListBox; import com.github.gwtbootstrap.client.ui.Popover; import com.github.gwtbootstrap.client.ui.TextBox; import com.github.gwtbootstrap.client.ui.base.ListItem; @@ -39,7 +40,8 @@ public class TagsPanel extends Composite{ @UiField FocusPanel focusPanelTags; @UiField Popover popoverTags; @UiField ControlGroup tagsInsertGroup; - + @UiField ListBox tagsEnterListBox; + // regular expression for tags private static final String REGEX_TAG = "^[a-zA-Z0-9]*$"; @@ -47,8 +49,35 @@ public class TagsPanel extends Composite{ // tags list private List tagsList = new ArrayList(); + private List vocabulary; + public TagsPanel() { initWidget(uiBinder.createAndBindUi(this)); + tagsEnterListBox.setVisible(true); + } + + + /** + * Since we have a controlled vocabulary, we swap to a listbox with multiple selection + * @param vocabularyTags + */ + public void setVocabulary(List vocabularyTags) { + + if(vocabularyTags == null || vocabularyTags.isEmpty()){ + tagsEnterListBox.setVisible(false); + tagsPanel.setVisible(true); + tagsEnterTextBox.setVisible(true); + }else{ + + for (String vocabularyTag : vocabularyTags) { + tagsEnterListBox.addItem(vocabularyTag, vocabularyTag); + } + vocabulary = vocabularyTags; + tagsPanel.setVisible(false); + tagsEnterTextBox.setVisible(false); + tagsEnterListBox.setVisible(true); + } + } /** @@ -197,7 +226,19 @@ public class TagsPanel extends Composite{ * @return */ public List getTags() { - return tagsList; + + if(vocabulary == null){ + return tagsList; + }else{ + + List selected = new ArrayList(); + for(int i = 0; i < tagsEnterListBox.getItemCount(); i++){ + if(tagsEnterListBox.isItemSelected(i)) + selected.add(tagsEnterListBox.getItemText(i)); + } + return selected; + } + } /** @@ -206,6 +247,7 @@ public class TagsPanel extends Composite{ public void freeze() { tagsEnterTextBox.setEnabled(false); + tagsEnterListBox.setEnabled(false); for(int i = 0; i < tagsList.size(); i++){ // get tag widget @@ -223,8 +265,8 @@ public class TagsPanel extends Composite{ * @param none */ public void setGroupPanelType(ControlGroupType type) { - + tagsInsertGroup.setType(type); - + } } diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.ui.xml index 1574742..e0cc6b4 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.ui.xml +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/dataset/resources/TagsPanel.ui.xml @@ -12,9 +12,11 @@ * Tags: - + + @@ -25,7 +27,6 @@ - diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/utils/InfoIconsLabels.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/utils/InfoIconsLabels.java index 4af8a11..b26c2a4 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/utils/InfoIconsLabels.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/utils/InfoIconsLabels.java @@ -29,7 +29,8 @@ public class InfoIconsLabels { + "item and by means of them it can be retrieved. A tag can contain only alphanumeric characters. " + "If the tag is composed by a single word it must have a size of at least two characters." + "Examples of good tags: \"This is a sample tag\", \"tagY\". Example of bad tag: \"c\"." - + " You must push ENTER for attaching a tag."; + + " You must push ENTER for attaching a tag, or use the provided list of predefined tags. In the latter case" + + " hold down the CTRL or CMD button to select multiple options."; // LICENSES public static final String LICENSES_INFO_ID_POPUP = "licenses-popup-panel-info"; @@ -63,8 +64,8 @@ public class InfoIconsLabels { // PROFILES public static final String PROFILES_INFO_ID_POPUP = "product-profiles-popup-panel-info"; - public static final String PROFILES_INFO_CAPTION = "Item Profiles"; - public static final String PROFILES_INFO_TEXT = "Select a profile, different from none, for your item among the ones available"; + public static final String PROFILES_INFO_CAPTION = "Item Types"; + public static final String PROFILES_INFO_TEXT = "Select a type, different from none, for your item among the ones available"; // RESOURCES public static final String RESOURCES_INFO_ID_POPUP = "resouces-popup-panel-info"; 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 c93c6c6..0ad4f13 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 @@ -21,6 +21,7 @@ import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg; import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService; import org.gcube.portlets.widgets.ckandatapublisherwidget.server.threads.AssociationToGroupAndNotifyThread; import org.gcube.portlets.widgets.ckandatapublisherwidget.server.threads.WritePostCatalogueManagerThread; +import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.DiscoverTagsList; import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.Utils; import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.WorkspaceUtils; import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean; @@ -202,6 +203,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C bean.setMaintainer(userOwner.getFullname()); bean.setMaintainerEmail(userOwner.getEmail()); bean.setOrganizationList(getUserOrganizationsListAdmin(userName, scope)); + bean.setTagsVocabulary(discoverTagsVocabulary(scope)); // if the request comes from the workspace if(folderId != null && !folderId.isEmpty()){ @@ -244,106 +246,124 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C return bean; } + /** + * Discover from the IS the vocabulary of tags for this scope, if present + * @return a list of tags vocabulary + */ + private List discoverTagsVocabulary(String context) { + + String keyPerVocabulary = UtilMethods.concatenateSessionKeyScope("TAGS_VOCABULARY", context); // TODO REMOVE + + List vocabulary = (List) getThreadLocalRequest().getSession().getAttribute(keyPerVocabulary); + if(vocabulary != null){ + vocabulary = new DiscoverTagsList(context).getTagsVocabulary(); + getThreadLocalRequest().getSession().setAttribute(keyPerVocabulary, vocabulary); + } + + return vocabulary; + } + @Override - public DatasetMetadataBean createCKanDataset(DatasetMetadataBean toCreate) { + public DatasetMetadataBean createCKanDataset(DatasetMetadataBean toCreate) throws Exception{ logger.debug("Request for creating a dataset with these information " + toCreate); String userName = Utils.getCurrentUser(getThreadLocalRequest()).getUsername(); - try{ + String title = toCreate.getTitle(); + String organizationNameOrId = toCreate.getSelectedOrganization(); + String author = toCreate.getAuthorFullName(); + String authorMail = toCreate.getAuthorEmail(); + String maintainer = toCreate.getMaintainer(); + String maintainerMail = toCreate.getMaintainerEmail(); + long version = toCreate.getVersion(); + String description = toCreate.getDescription(); + String chosenLicense = toCreate.getLicense(); + String licenseId = findLicenseIdByLicense(chosenLicense); + List listOfTags = toCreate.getTags(); + Map> customFields = toCreate.getCustomFields(); - String title = toCreate.getTitle(); - String organizationNameOrId = toCreate.getSelectedOrganization(); - String author = toCreate.getAuthorFullName(); - String authorMail = toCreate.getAuthorEmail(); - String maintainer = toCreate.getMaintainer(); - String maintainerMail = toCreate.getMaintainerEmail(); - long version = toCreate.getVersion(); - String description = toCreate.getDescription(); - String chosenLicense = toCreate.getLicense(); - String licenseId = findLicenseIdByLicense(chosenLicense); - List listOfTags = toCreate.getTags(); - Map> customFields = toCreate.getCustomFields(); - boolean setPublic = toCreate.getVisibility(); + // add Type for custom fields + if(toCreate.getChosenType() != null) + customFields.put("Type", Arrays.asList(toCreate.getChosenType())); - // get the list of resources and convert to ResourceBean - List resources = null; - ResourceElementBean resourcesToAdd = toCreate.getResourceRoot(); + boolean setPublic = toCreate.getVisibility(); - // we need to copy such resource in the .catalogue area of the user's ws - if(resourcesToAdd != null){ - resources = WorkspaceUtils.copyResourcesToUserCatalogueArea(toCreate.getId(), userName, toCreate); - } + // get the list of resources and convert to ResourceBean + List resources = null; + ResourceElementBean resourcesToAdd = toCreate.getResourceRoot(); - logger.debug("The user wants to publish in organization with name " + organizationNameOrId); - String scope = getScopeFromOrgName(organizationNameOrId); - DataCatalogue utils = getCatalogue(scope); - String userApiKey = utils.getApiKeyFromUsername(userName); - - String datasetId = utils.createCKanDatasetMultipleCustomFields - (userApiKey, title, null, organizationNameOrId, author, authorMail, maintainer, - maintainerMail, version, description, licenseId, listOfTags, customFields, resources, setPublic); - - if(datasetId != null){ - - logger.info("Dataset created!"); - toCreate.setId(datasetId); - - // retrieve the url - String datasetUrl = utils.getUnencryptedUrlFromDatasetIdOrName(datasetId); - toCreate.setSource(datasetUrl); - - // add also this information as custom field - Map> addField = new HashMap>(); - addField.put(ITEM_URL_FIELD, Arrays.asList(datasetUrl)); - utils.patchProductCustomFields(datasetId, userApiKey, addField); - - // start a thread that will associate this dataset with the group - if(toCreate.getChosenProfile() != null || toCreate.getGroups() != null){ - - AssociationToGroupAndNotifyThread threadAssociationToGroup = - new AssociationToGroupAndNotifyThread( - toCreate.getGroups(), - toCreate.getChosenProfile(), - datasetUrl, - datasetId, - toCreate.getTitle(), - Utils.getCurrentUser(getThreadLocalRequest()).getFullname(), - userName, - utils, - organizationNameOrId, - getThreadLocalRequest() - ); - threadAssociationToGroup.start(); - - } - - // launch notification thread - WritePostCatalogueManagerThread threadWritePost = - new WritePostCatalogueManagerThread( - userName, - scope, - toCreate.getTitle(), - datasetUrl, - false, // send notification to other people - toCreate.getTags(), - Utils.getCurrentUser(getThreadLocalRequest()).getFullname() - ); - threadWritePost.start(); - - return toCreate; - }else{ - logger.error("Failed to create the dataset"); - } - }catch(Exception e){ - logger.error("Unable to create the dataset", e); + // we need to copy such resource in the .catalogue area of the user's ws + if(resourcesToAdd != null){ + resources = WorkspaceUtils.copyResourcesToUserCatalogueArea(toCreate.getId(), userName, toCreate); } + + logger.debug("The user wants to publish in organization with name " + organizationNameOrId); + String scope = getScopeFromOrgName(organizationNameOrId); + DataCatalogue utils = getCatalogue(scope); + String userApiKey = utils.getApiKeyFromUsername(userName); + + String datasetId = utils.createCKanDatasetMultipleCustomFields + (userApiKey, title, null, organizationNameOrId, author, authorMail, maintainer, + maintainerMail, version, description, licenseId, listOfTags, customFields, resources, setPublic); + + if(datasetId != null){ + + logger.info("Dataset created!"); + toCreate.setId(datasetId); + + // retrieve the url + String datasetUrl = utils.getUnencryptedUrlFromDatasetIdOrName(datasetId); + toCreate.setSource(datasetUrl); + + // add also this information as custom field + Map> addField = new HashMap>(); + addField.put(ITEM_URL_FIELD, Arrays.asList(datasetUrl)); + utils.patchProductCustomFields(datasetId, userApiKey, addField); + + // start a thread that will associate this dataset with the group + if(/*toCreate.getChosenType() != null ||*/ toCreate.getGroups() != null){ + + AssociationToGroupAndNotifyThread threadAssociationToGroup = + new AssociationToGroupAndNotifyThread( + toCreate.getGroups(), + null, //toCreate.getChosenType(), TODO + datasetUrl, + datasetId, + toCreate.getTitle(), + Utils.getCurrentUser(getThreadLocalRequest()).getFullname(), + userName, + utils, + organizationNameOrId, + getThreadLocalRequest() + ); + threadAssociationToGroup.start(); + + } + + // launch notification thread + WritePostCatalogueManagerThread threadWritePost = + new WritePostCatalogueManagerThread( + userName, + scope, + toCreate.getTitle(), + datasetUrl, + false, // send notification to other people + toCreate.getTags(), + Utils.getCurrentUser(getThreadLocalRequest()).getFullname() + ); + threadWritePost.start(); + + return toCreate; + }else{ + logger.error("Failed to create the dataset"); + } + return null; } @Override - public ResourceElementBean addResourceToDataset(ResourceElementBean resource, String datasetId) { + public ResourceElementBean addResourceToDataset(ResourceElementBean resource, String datasetId) throws Exception{ String username = Utils.getCurrentUser(getThreadLocalRequest()).getUsername(); logger.debug("Incoming request for creating new resource for dataset with id " + datasetId + " and organization name of the dataset is " + resource.getOrganizationNameDatasetParent()); @@ -356,29 +376,26 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C }else{ - try{ - ResourceBean resourceBean = new ResourceBean( - resource.getUrl(), - resource.getName(), - resource.getDescription(), - null, - username, - datasetId, - null); - // get the scope in which we should discover the ckan instance given the organization name in which the dataset was created - String scope = getScopeFromOrgName(resource.getOrganizationNameDatasetParent()); - DataCatalogue catalogue = getCatalogue(scope); - String resourceId = catalogue.addResourceToDataset(resourceBean, catalogue.getApiKeyFromUsername(username)); + ResourceBean resourceBean = new ResourceBean( + resource.getUrl(), + resource.getName(), + resource.getDescription(), + null, + username, + datasetId, + null); - if(resourceId != null){ - logger.debug("Resource " + resource.getName() + " is now available"); - // set its id and turn it to the client - resource.setOriginalIdInWorkspace(resourceId); - return resource; - } - }catch(Exception e){ - logger.error("Unable to create new resource", e); + // get the scope in which we should discover the ckan instance given the organization name in which the dataset was created + String scope = getScopeFromOrgName(resource.getOrganizationNameDatasetParent()); + DataCatalogue catalogue = getCatalogue(scope); + String resourceId = catalogue.addResourceToDataset(resourceBean, catalogue.getApiKeyFromUsername(username)); + + if(resourceId != null){ + logger.debug("Resource " + resource.getName() + " is now available"); + // set its id and turn it to the client + resource.setOriginalIdInWorkspace(resourceId); + return resource; } logger.debug("No resource created"); diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/DiscoverTagsList.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/DiscoverTagsList.java new file mode 100644 index 0000000..9063621 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/DiscoverTagsList.java @@ -0,0 +1,79 @@ +package org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils; + +import static org.gcube.resources.discovery.icclient.ICFactory.client; + +import java.io.StringReader; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.gcube.common.resources.gcore.utils.XPathHelper; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.datacatalogue.ckanutillibrary.shared.ex.ApplicationProfileNotFoundException; +import org.gcube.portlets.widgets.ckandatapublisherwidget.server.CKANPublisherServicesImpl; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.Query; +import org.gcube.resources.discovery.client.queries.impl.QueryBox; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; + +/** + * Discover in a given context if there is a Generic Resource containing the list of tags to be used + * within the widget + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + * + */ +public class DiscoverTagsList { + + private static final Log logger = LogFactoryUtil.getLog(CKANPublisherServicesImpl.class); + List tagsVocabulary; + + private final static String APPLICATION_PROFILE_NAME = "Tags"; + private final static String QUERY = "for $profile in collection('/db/Profiles/GenericResource')//Resource " + + "where $profile/Profile/SecondaryType/string() eq 'DataCatalogueMetadataTags' and $profile/Profile/Name/string() " + + " eq '" + APPLICATION_PROFILE_NAME + "'" + + "return $profile"; + + /** + * Discover the list of tags vocabulary if needed + */ + public DiscoverTagsList(String context) { + + String currentContext = ScopeProvider.instance.get(); + ScopeProvider.instance.set(context); + + try{ + + Query q = new QueryBox(QUERY); + + DiscoveryClient client = client(); + List appProfile = client.submit(q); + + if (appProfile == null || appProfile.size() == 0) + throw new ApplicationProfileNotFoundException("Your applicationProfile is not registered in the infrastructure"); + else{ + String elem = appProfile.get(0); + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Node node = docBuilder.parse(new InputSource(new StringReader(elem))).getDocumentElement(); + XPathHelper helper = new XPathHelper(node); + tagsVocabulary = helper.evaluate("/Resource/Profile/Body/tags/tag/text()"); + logger.trace("Retrieved tags " + tagsVocabulary); + } + }catch(Exception e){ + logger.warn("Failed to retrieve this information " + e.getMessage()); + }finally{ + ScopeProvider.instance.set(currentContext); + } + + } + + public List getTagsVocabulary() { + return tagsVocabulary; + } + +} 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 73b3830..ad41d58 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 @@ -23,14 +23,15 @@ public class DatasetMetadataBean implements Serializable { private String maintainer; private String maintainerEmail; private String ownerIdentifier; // owner of the folder into the workspace (e.g., andrea.rossi) - private String chosenProfile; // the name of the MetaDataProfile chosen + private String chosenType; // the name of the MetaDataType chosen private String selectedOrganization; 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 ResourceElementBean resourceRoot; // in case of workspace, this is the directory root or the single file information - private List metadataList; + private List metadataListTypes; private List tags; // on retrieve, they are the keys of the product + private List tagsVocabulary; // when available private Map> customFields; private List groups; @@ -66,7 +67,7 @@ public class DatasetMetadataBean implements Serializable { String maintainerEmail, String ownerIdentifier, List organizationList, String selectedOrganization, ResourceElementBean resourceRoot, - List metadataList, List groups) { + List metadataList, List groups, List tagsVocabulary) { super(); this.id = id; this.title = title; @@ -86,16 +87,25 @@ public class DatasetMetadataBean implements Serializable { this.organizationList = organizationList; this.selectedOrganization = selectedOrganization; this.resourceRoot = resourceRoot; - this.metadataList = metadataList; + this.metadataListTypes = metadataList; this.groups = groups; + this.tagsVocabulary = tagsVocabulary; } - public List getMetadataList() { - return metadataList; + public String getChosenType() { + return chosenType; } - public void setMetadataList(List metadataList) { - this.metadataList = metadataList; + public void setChosenType(String chosenType) { + this.chosenType = chosenType; + } + + public List getMetadataListTypes() { + return metadataListTypes; + } + + public void setMetadataListTypes(List metadataListTypes) { + this.metadataListTypes = metadataListTypes; } public String getId() { @@ -250,14 +260,6 @@ public class DatasetMetadataBean implements Serializable { this.authorFullName = authorFullName; } - public String getChosenProfile() { - return chosenProfile; - } - - public void setChosenProfile(String chosenProfile) { - this.chosenProfile = chosenProfile; - } - public List getGroups() { return groups; } @@ -266,6 +268,14 @@ public class DatasetMetadataBean implements Serializable { this.groups = groups; } + public List getTagsVocabulary() { + return tagsVocabulary; + } + + public void setTagsVocabulary(List tagsVocabulary) { + this.tagsVocabulary = tagsVocabulary; + } + @Override public String toString() { return "DatasetMetadataBean [id=" + id + ", title=" + title @@ -275,13 +285,13 @@ public class DatasetMetadataBean implements Serializable { + authorFullName + ", authorEmail=" + authorEmail + ", maintainer=" + maintainer + ", maintainerEmail=" + maintainerEmail + ", ownerIdentifier=" + ownerIdentifier - + ", chosenProfile=" + chosenProfile - + ", selectedOrganization=" + selectedOrganization - + ", version=" + version + ", visibility=" + visibility - + ", organizationList=" + organizationList + ", resourceRoot=" - + resourceRoot + ", metadataList=" + metadataList + ", tags=" - + tags + ", customFields=" + customFields + ", groups=" - + groups + "]"; + + ", chosenType=" + chosenType + ", selectedOrganization=" + + selectedOrganization + ", version=" + version + + ", visibility=" + visibility + ", organizationList=" + + organizationList + ", resourceRoot=" + resourceRoot + + ", metadataListTypes=" + metadataListTypes + ", tags=" + tags + + ", tagsVocabulary=" + tagsVocabulary + ", customFields=" + + customFields + ", groups=" + groups + "]"; } } \ No newline at end of file