From 1e95f70f5f1de9990fc7088239de78087528ad37 Mon Sep 17 00:00:00 2001 From: Costantino Perciante Date: Mon, 6 Jun 2016 15:24:52 +0000 Subject: [PATCH] The widget can be also called from outside the workspace now git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/widgets/ckan-metadata-publisher-widget@128994 82a268e6-3cf1-43bd-a215-b396298e98cf --- .settings/com.google.gdt.eclipse.core.prefs | 1 + META-INF/MANIFEST.MF | 4 - META-INF/clientlog4j.properties | 13 - pom.xml | 12 +- .../client/CKanMetadataPublisher.java | 4 +- .../client/CKanPublisherService.java | 18 + .../client/CKanPublisherServiceAsync.java | 18 + .../client/ui/CustomFieldEntry.java | 63 ++- .../client/ui/EditMetadataForm.java | 276 ++++++++++-- .../client/ui/EditMetadataForm.ui.xml | 42 +- .../server/CKANPublisherServicesImpl.java | 407 ++++++++++++++---- .../shared/DatasetMetadataBean.java | 75 +++- .../CKanMetadataPublisher.gwt.xml | 1 - .../ckandatapublisherwidget/client/Tests.java | 85 ++-- 14 files changed, 787 insertions(+), 232 deletions(-) delete mode 100644 META-INF/MANIFEST.MF delete mode 100644 META-INF/clientlog4j.properties diff --git a/.settings/com.google.gdt.eclipse.core.prefs b/.settings/com.google.gdt.eclipse.core.prefs index 0326a93..f629078 100644 --- a/.settings/com.google.gdt.eclipse.core.prefs +++ b/.settings/com.google.gdt.eclipse.core.prefs @@ -1,4 +1,5 @@ eclipse.preferences.version=1 +jarsExcludedFromWebInfLib= lastWarOutDir=/home/costantino/workspace/ckan-metadata-publisher-widget/target/ckan-metadata-publisher-widget-1.0.0-SNAPSHOT warSrcDir=src/main/webapp warSrcDirIsOutput=false diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF deleted file mode 100644 index 048200b..0000000 --- a/META-INF/MANIFEST.MF +++ /dev/null @@ -1,4 +0,0 @@ -Manifest-Version: 1.0 -Implementation-Title: Gwt-Tour -Implementation-Version: 2.0.0-SNAPSHOT - diff --git a/META-INF/clientlog4j.properties b/META-INF/clientlog4j.properties deleted file mode 100644 index 574c7b1..0000000 --- a/META-INF/clientlog4j.properties +++ /dev/null @@ -1,13 +0,0 @@ -log4j.rootLogger=DEBUG, A1 -log4j.appender.A1=org.apache.log4j.ConsoleAppender -log4j.appender.A1.layout=org.apache.log4j.PatternLayout - -# Print the date in ISO 8601 format -log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n - -# Print only messages of level TRACE or above in the package org.gcube -log4j.logger.org.gcube=TRACE -log4j.logger.org.gcube.application.framework.core.session=INFO -log4j.logger.com.netflix.astyanax.connectionpool=ERROR -log4j.logger.org.gcube.portal.databook.server.DBCassandraAstyanaxImpl=TRACE -log4j.logger.org.gcube.common=ERROR \ No newline at end of file diff --git a/pom.xml b/pom.xml index b1fe8d5..bc2d198 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,11 @@ + + xerces + xercesImpl + 2.9.1 + com.google.gwt gwt-servlet @@ -150,10 +155,15 @@ [2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT) provided + + org.gcube.dataaccess + ckan-util-library + 1.0.0-SNAPSHOT + org.gcube.core common-scope-maps - runtime + compile diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java index f9305c7..4ca55fe 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java @@ -22,9 +22,9 @@ public class CKanMetadataPublisher implements EntryPoint { private void startExample() { - String idFolderWorkspace = "06bc1ca7-bf1b-4797-b0a4-cb8a55a9c189"; + String idFolderWorkspace = "8b67fc1f-940d-4512-b783-105fba11c270"; String owner = "costantino.perciante"; - RootPanel.get("ckan-metadata-publisher-div").add(new EditMetadataForm(idFolderWorkspace, owner)); + RootPanel.get("ckan-metadata-publisher-div").add(new EditMetadataForm(owner)); } } 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 77da28b..bfa32a4 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 @@ -14,7 +14,25 @@ import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("ckanservices") public interface CKanPublisherService extends RemoteService { + /** + * Retrieve the list of licenses to show to the user. + * @return a LicenseBean on success, null on error. + */ LicensesBean getLicenses(); + + /** + * Retrieve a partially filled bean given a folder id and its owner. + * @param folderId + * @param owner + * @return @return a DatasetMetadataBean on success, null on error. + */ DatasetMetadataBean getDatasetBean(String folderId, String owner); + + /** + * Try to create such dataset starting from the information contained into the toCreate bean. + * @param toCreate + * @return true on success, false otherwise + */ + boolean createCKanDataset(DatasetMetadataBean toCreate); } 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 2d58bdd..ba890a7 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 @@ -12,9 +12,27 @@ import com.google.gwt.user.client.rpc.AsyncCallback; */ public interface CKanPublisherServiceAsync { + /** + * Retrieve the list of licenses to show to the user. + * @return a LicenseBean on success, null on error. + */ void getLicenses(AsyncCallback callback); + /** + * Retrieve a partially filled bean given a folder id and its owner. + * @param folderId + * @param owner + * @return @return a DatasetMetadataBean on success, null on error. + */ void getDatasetBean(String folderId, String owner, AsyncCallback callback); + /** + * Try to create such dataset starting from the information contained into the toCreate bean. + * @param toCreate + * @return true on success, false otherwise + */ + void createCKanDataset(DatasetMetadataBean toCreate, + AsyncCallback callback); + } diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CustomFieldEntry.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CustomFieldEntry.java index 4280746..e4632ab 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CustomFieldEntry.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CustomFieldEntry.java @@ -14,6 +14,10 @@ import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +/** + * A custom field entry that has two textboxes, one for the key value and the other for the value. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ public class CustomFieldEntry extends Composite { private static CustomFieldEntryUiBinder uiBinder = GWT @@ -27,35 +31,48 @@ public class CustomFieldEntry extends Composite { @UiField InputAddOn valueFieldPrepend; @UiField Button removeCustomField; + //inserted values + private String value; + private String key; + private boolean isCustomCreatedByUser; + // event bus private HandlerManager eventBus; - public CustomFieldEntry(HandlerManager eventBus) { + public CustomFieldEntry(HandlerManager eventBus, String key, String value, boolean isCustomCreatedByUser) { initWidget(uiBinder.createAndBindUi(this)); + + // save information this.eventBus = eventBus; + this.value = value; + this.key = key; + this.isCustomCreatedByUser = isCustomCreatedByUser; + + // remove the first appendbox + if(!isCustomCreatedByUser){ + this.valueFieldPrepend.removeFromParent(); + this.keyFieldPrepend.setPrependText(key + ":"); + ((TextBox)this.keyFieldPrepend.getWidget(1)).setText(value); + }else{ + + // do nothing, the user should fill key and value pair + } } - /** - * Check if it has been added by the user during form creation or comes from the workspace - * @return - */ - private boolean isCreatedCustomField(){ - - return valueFieldPrepend.isAttached(); - - } - /** * Retrieve the key value * @return */ public String getKey(){ + + if(isCustomCreatedByUser){ + + return ((TextBox)this.keyFieldPrepend.getWidget(1)).getText(); + + } - if(isCreatedCustomField()) - return ((TextBox)keyFieldPrepend.getWidget(1)).getValue(); - else - return valueFieldPrepend.get - + return key; + } /** @@ -64,13 +81,15 @@ public class CustomFieldEntry extends Composite { */ public String getValue(){ - if(isCreatedCustomField()) - return ((TextBox)valueFieldPrepend.getWidget(1)).getValue(); - else - return valueFieldPrepend.getWidgetIndex(1).get - + if(isCustomCreatedByUser){ + + return ((TextBox)this.valueFieldPrepend.getWidget(1)).getText(); + + } + + return value; } - + @UiHandler("removeCustomField") void onRemoveCustomField(ClickEvent e){ diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java index dc7296a..438587f 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java @@ -7,18 +7,20 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.apache.commons.lang.StringEscapeUtils; +import org.gcube.portlets.user.gcubewidgets.client.elements.Span; import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService; import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherServiceAsync; import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEvent; import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEventHandler; import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean; import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean; -import org.gcube.portlets.widgets.workspacesharingwidget.client.view.sharing.multisuggest.Span; import com.github.gwtbootstrap.client.ui.AlertBlock; import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.CheckBox; import com.github.gwtbootstrap.client.ui.ControlGroup; -import com.github.gwtbootstrap.client.ui.Label; +import com.github.gwtbootstrap.client.ui.HelpBlock; import com.github.gwtbootstrap.client.ui.ListBox; import com.github.gwtbootstrap.client.ui.TextArea; import com.github.gwtbootstrap.client.ui.TextBox; @@ -33,6 +35,7 @@ import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; @@ -63,6 +66,7 @@ public class EditMetadataForm extends Composite{ @UiField ListBox licenseListbox; @UiField ListBox visibilityListbox; @UiField ListBox searchableListbox; + @UiField ListBox organizationsListbox; @UiField TextBox versionTextbox; @UiField TextBox authorTextbox; @UiField TextBox authorEmailTextbox; @@ -70,9 +74,11 @@ public class EditMetadataForm extends Composite{ @UiField TextBox maintainerEmailTextbox; @UiField ControlGroup customFields; @UiField Button addCustomFieldButton; + @UiField CheckBox addResourcesCheckBox; @UiField Button createButton; @UiField Button resetButton; @UiField AlertBlock infoBlock; + @UiField AlertBlock onCreateAlertBlock; // tags list private List tagsList = new ArrayList(); @@ -84,22 +90,122 @@ public class EditMetadataForm extends Composite{ private final HandlerManager eventBus = new HandlerManager(null); // added custom field entries - List customFieldEntries = new ArrayList(); - + List customFieldEntriesList = new ArrayList(); + // dataset metadata bean private DatasetMetadataBean receivedBean; - public EditMetadataForm(String idFolderWorkspace, String owner) { + + /** + * Invoked in the most general case + * @param owner + */ + public EditMetadataForm(String user) { initWidget(uiBinder.createAndBindUi(this)); // bind on events bind(); - + // set info block setAlertBlock("Retrieving information, please wait...", AlertType.INFO, true); // disable create button createButton.setEnabled(false); + resetButton.setEnabled(false); + + // get back the licenses and the metadata information + ckanServices.getDatasetBean(null, user, new AsyncCallback() { + + @Override + public void onSuccess(DatasetMetadataBean bean) { + + if(bean != null){ + + // save it + receivedBean = bean; + + // fill the form + versionTextbox.setText(String.valueOf(bean.getVersion())); + authorTextbox.setText(bean.getAuthor()); + authorEmailTextbox.setText(bean.getAuthorEmail()); + maintainerTextbox.setText(bean.getMaintainer()); + maintainerEmailTextbox.setText(bean.getMaintainerEmail()); + + // set organizations + List organizations = bean.getOrganizationList(); + + for (String organization : organizations) { + organizationsListbox.addItem(organization); + } + + // try to retrieve the licenses + setAlertBlock("Retrieving licenses, please wait...", AlertType.INFO, true); + ckanServices.getLicenses(new AsyncCallback() { + + @Override + public void onSuccess(LicensesBean lBean) { + + if(lBean != null && !lBean.getLicenses().isEmpty()){ + + licenseBean = lBean; + + // fill the listbox + for(String license: licenseBean.getLicenses()){ + licenseListbox.addItem(license); + } + + // everything went ok + setAlertBlock("", AlertType.ERROR, false); + createButton.setEnabled(true); + resetButton.setEnabled(true); + + }else{ + setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true); + } + } + + @Override + public void onFailure(Throwable caught) { + + setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true); + + } + }); + + }else{ + + setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true); + } + + } + + @Override + public void onFailure(Throwable caught) { + + setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true); + + } + }); + + } + + /** + * Invoked when the workspace is used. + * @param idFolderWorkspace + * @param owner + */ + public EditMetadataForm(String idFolderWorkspace, String owner) { + initWidget(uiBinder.createAndBindUi(this)); + + // bind on events + bind(); + + // set info block + setAlertBlock("Retrieving information, please wait...", AlertType.INFO, true); + + // disable create button + createButton.setEnabled(false); + resetButton.setEnabled(false); // get back the licenses and the metadata information from the workspace ckanServices.getDatasetBean(idFolderWorkspace, owner, new AsyncCallback() { @@ -108,7 +214,7 @@ public class EditMetadataForm extends Composite{ public void onSuccess(DatasetMetadataBean bean) { if(bean != null){ - + // save it receivedBean = bean; @@ -121,10 +227,21 @@ public class EditMetadataForm extends Composite{ maintainerTextbox.setText(bean.getMaintainer()); maintainerEmailTextbox.setText(bean.getMaintainerEmail()); + // set organizations + List organizations = bean.getOrganizationList(); + + for (String organization : organizations) { + + organizationsListbox.addItem(organization); + + } + // retrieve custom fields Map customFieldsMap = bean.getCustomFields(); - if(customFields != null){ + GWT.log("Custom fields is " + customFieldsMap); + + if(customFieldsMap != null){ // get the keys and put them as tags Iterator> iteratorOverCustomField = customFieldsMap.entrySet().iterator(); @@ -134,19 +251,12 @@ public class EditMetadataForm extends Composite{ .next(); // these are fixed key, variable value custom fields - CustomFieldEntry toAdd = new CustomFieldEntry(eventBus); - - // remove the first appendbox - toAdd.valueFieldPrepend.removeFromParent(); - toAdd.keyFieldPrepend.setPrependText(entry.getKey() + ":"); - ((TextBox)toAdd.keyFieldPrepend.getWidget(1)).setText(entry.getValue()); - - customFieldEntries.add(toAdd); + CustomFieldEntry toAdd = new CustomFieldEntry(eventBus, entry.getKey(), entry.getValue(), false); + customFieldEntriesList.add(toAdd); customFields.add(toAdd); - final ListItem item = new ListItem(); - Label label = new Label(entry.getKey()); - item.add(label); + // add as tag + addTagElement(entry.getKey()); } } @@ -172,6 +282,7 @@ public class EditMetadataForm extends Composite{ // everything went ok setAlertBlock("", AlertType.ERROR, false); createButton.setEnabled(true); + resetButton.setEnabled(true); }else{ setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true); @@ -214,7 +325,7 @@ public class EditMetadataForm extends Composite{ @Override public void onRemoveEntry(DeleteCustomFieldEvent event) { - customFieldEntries.remove(event.getRemovedEntry()); + customFieldEntriesList.remove(event.getRemovedEntry()); customFields.remove(event.getRemovedEntry()); } @@ -225,32 +336,34 @@ public class EditMetadataForm extends Composite{ @UiHandler("addCustomFieldButton") void addCustomFieldEvent(ClickEvent e){ - CustomFieldEntry toAdd = new CustomFieldEntry(eventBus); - customFieldEntries.add(toAdd); + CustomFieldEntry toAdd = new CustomFieldEntry(eventBus, "", "", true); + customFieldEntriesList.add(toAdd); customFields.add(toAdd); } @UiHandler("createButton") void createDatasetEvent(ClickEvent e){ - + // validate data TODO boolean areDataValid = validateData(); // Collect current data and send them to the server if(areDataValid){ - + String title = titleTextBox.getValue(); String description = descriptionTextarea.getText(); String selectedLicense = licenseListbox.getSelectedItemText(); - String visibility = visibilityListbox.getValue(); - String searchable = searchableListbox.getValue(); + String visibility = visibilityListbox.getSelectedItemText(); + String searchable = searchableListbox.getSelectedItemText(); long version = Long.valueOf(versionTextbox.getValue()); String author = authorTextbox.getValue(); String authorEmail = authorEmailTextbox.getValue(); String maintainer = maintainerTextbox.getValue(); String maintainerEmail = maintainerEmailTextbox.getValue(); - + String chosenOrganization = organizationsListbox.getSelectedItemText(); + boolean addResources = addResourcesCheckBox.getValue(); + // fill the bean receivedBean.setAuthor(author); receivedBean.setAuthorEmail(authorEmail); @@ -263,24 +376,80 @@ public class EditMetadataForm extends Composite{ receivedBean.setTitle(title); receivedBean.setSearchable(searchable.equals("Yes")); receivedBean.setTags(tagsList); - + receivedBean.setSelectedOrganization(chosenOrganization); + receivedBean.setAddResources(addResources); + Map customFieldsMap = new HashMap(); - + // prepare custom fields - for(CustomFieldEntry customEntry : customFieldEntries){ - + for(CustomFieldEntry customEntry : customFieldEntriesList){ + String key = customEntry.getKey(); String value = customEntry.getValue(); customFieldsMap.put(key, value); } - - receivedBean.setCustomFields(customFieldsMap); - - // TODO invoke remote service - } - + receivedBean.setCustomFields(customFieldsMap); + + // invoke the create method + createButton.setEnabled(false); + resetButton.setEnabled(false); + + onCreateAlertBlock.setText("Trying to create dataset, please wait"); + onCreateAlertBlock.setVisible(true); + + ckanServices.createCKanDataset(receivedBean, new AsyncCallback() { + + @Override + public void onSuccess(Boolean result) { + + if(result){ + + alertOnCreate("Dataset correctly created!", AlertType.SUCCESS); + + }else{ + + alertOnCreate("Unable to create this dataset, please retry later", AlertType.ERROR); + } + + } + + @Override + public void onFailure(Throwable caught) { + + alertOnCreate("Unable to create this dataset, please retry later", AlertType.ERROR); + + } + }); + } + } + + /** + * On create show alert box and enable buttons + * @param text + * @param type + */ + private void alertOnCreate(String text, AlertType type){ + + onCreateAlertBlock.setText(text); + onCreateAlertBlock.setType(type); + onCreateAlertBlock.setVisible(true); + createButton.setEnabled(true); + resetButton.setEnabled(true); + + // hide after some seconds + Timer t = new Timer() { + + @Override + public void run() { + + onCreateAlertBlock.setVisible(false); + + } + }; + + t.schedule(2000); } /** @@ -288,7 +457,8 @@ public class EditMetadataForm extends Composite{ * @return true on success */ private boolean validateData() { - // TODO Auto-generated method stub + + return true; } @@ -306,10 +476,10 @@ public class EditMetadataForm extends Composite{ removeTags(); // delete custom fields - for (CustomFieldEntry customField : customFieldEntries) { + for (CustomFieldEntry customField : customFieldEntriesList) { customField.removeFromParent(); } - customFieldEntries.clear(); + customFieldEntriesList.clear(); } @@ -372,6 +542,32 @@ public class EditMetadataForm extends Composite{ } } + /** + * Add the tag as an element + */ + private void addTagElement(final String tag){ + + if(tagsList.contains(tag)) + return; + + final ListItem displayItem = new ListItem(); + displayItem.setStyleName("tag-style"); + Span p = new Span(tag); + + Span span = new Span("x"); + span.setTitle("Remove this tag"); + span.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent clickEvent) { + removeListItem(displayItem, tag); + } + }); + + span.setStyleName("tag-style-x"); + displayItem.add(p); + displayItem.add(span); + tagsPanel.add(displayItem); + tagsList.add(tag); + } /** * Remove a tag from the list diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml index 066cda4..d6e1895 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml @@ -93,8 +93,9 @@ Tags: - + @@ -151,16 +152,14 @@ - - - - - - - - - - + + Publish in: + + + + + @@ -234,6 +233,25 @@ + + + + Add folder content as resources + + + + Automatically add folder' files as resources of the dataset + + + + + + + + Create 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 d881c32..2088a38 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 @@ -1,33 +1,40 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.server; import java.util.ArrayList; +import java.util.Calendar; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; -import org.gcube.application.framework.core.session.ASLSession; -import org.gcube.application.framework.core.session.SessionManager; import org.gcube.common.homelibrary.home.HomeLibrary; import org.gcube.common.homelibrary.home.exceptions.InternalErrorException; import org.gcube.common.homelibrary.home.workspace.Workspace; import org.gcube.common.homelibrary.home.workspace.WorkspaceItem; +import org.gcube.common.homelibrary.home.workspace.folder.FolderItem; import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem; import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper; +import org.gcube.dataaccess.ckanutillibrary.CKanUtilsFactory; import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService; import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean; import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean; import org.gcube.vomanagement.usermanagement.UserManager; import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager; import org.gcube.vomanagement.usermanagement.model.GCubeUser; -import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.liferay.portal.service.UserLocalServiceUtil; import eu.trentorise.opendata.jackan.CheckedCkanClient; +import eu.trentorise.opendata.jackan.CkanClient; +import eu.trentorise.opendata.jackan.model.CkanDataset; import eu.trentorise.opendata.jackan.model.CkanLicense; +import eu.trentorise.opendata.jackan.model.CkanOrganization; +import eu.trentorise.opendata.jackan.model.CkanPair; +import eu.trentorise.opendata.jackan.model.CkanResource; +import eu.trentorise.opendata.jackan.model.CkanTag; /** * Server side of the data publisher. @@ -37,64 +44,87 @@ import eu.trentorise.opendata.jackan.model.CkanLicense; public class CKANPublisherServicesImpl extends RemoteServiceServlet implements CKanPublisherService{ // Logger - private static final Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class); - - //dev user - public static final String defaultUserId = "test.user"; - - //dev vre - private static final String vreID = "/gcube/devsec/devVRE"; + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class); /** - * when packaging test will fail if the user is not set to test.user - * @return . - */ - public String getDevelopmentUser() { - String user = defaultUserId; - // user = "costantino.perciante"; - return user; - } - - /** - * Retrieve the ckan portal url by querying the IS + * Get the current scope (/gcube is returned if in development) * @return */ - private String getCKANUrlFromIS(){ + private String getCurrentScope(){ - // TODO - return "https://ckan-d-d4s.d4science.org/"; + if(isWithinPortal()) + return ScopeProvider.instance.get(); + else + return "/gcube"; } /** - * Retrieve the API_KEY of the current user + * Return the ckan catalogue url for this scope. * @return */ - private String getCKANApikeyFromUser(String username){ + private String getCatalogueUrl(){ - // TODO - return "803ada7f-2080-493f-8a99-3e593e880d94"; + logger.info("Request for catalogue url"); + + try{ + String currentScope = getCurrentScope(); + return "https://" + CKanUtilsFactory.getInstance().getCkanUtilsForScope(currentScope).getCatalogueUrl(); + }catch(Exception e){ + logger.error("Failed to retrieve catalogue url information", e); + } + + return null; + } + + /** + * Retrieve the api key for this user + * @param owner + * @return + */ + private String getCKANApikeyFromUser(String owner) { + + logger.info("Request for user api key"); + + try{ + String currentScope = getCurrentScope(); + return CKanUtilsFactory.getInstance().getCkanUtilsForScope(currentScope).getApiKeyFromUser(owner); + }catch(Exception e){ + logger.error("Failed to retrieve api key for user " + owner, e); + } + + return null; } /** - * the current ASLSession - * @return the session + * Retrieve the list of organizations in which the user can publish + * @param owner + * @return */ - private ASLSession getASLSession() { + private List getUserOrganizationsList(String owner) { - String sessionID = this.getThreadLocalRequest().getSession().getId(); - String user = (String) this.getThreadLocalRequest().getSession().getAttribute(ScopeHelper.USERNAME_ATTRIBUTE); + logger.info("Request for user " + owner + " organizations list"); - if (user == null) { + try{ + String currentScope = getCurrentScope(); + List ckanOrgs = CKanUtilsFactory.getInstance().getCkanUtilsForScope(currentScope).getOrganizationsByUser(owner); - logger.warn("USER IS NULL setting " + defaultUserId + " and Running OUTSIDE PORTAL"); - user = getDevelopmentUser(); - SessionManager.getInstance().getASLSession(sessionID, user).setScope(vreID); + logger.debug("Organizations are " + ckanOrgs); - } + List orgsName = new ArrayList(); + for (CkanOrganization ckanOrganization : ckanOrgs) { + orgsName.add(ckanOrganization.getName()); + logger.debug("Organization name is " + ckanOrganization.getName()); + } - return SessionManager.getInstance().getASLSession(sessionID, user); + return orgsName; + + }catch(Exception e){ + logger.error("Failed to retrieve user's organizations", e); + } + + return null; } /** @@ -112,27 +142,51 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C } } + /** + * Find a license id given the license text. + * @param chosenLicense + * @return + */ + private String findLicenseIdByLicense(String chosenLicense) { + + logger.info("Requested license id"); + + String ckanPortalUrl = getCatalogueUrl(); + CkanClient client = new CkanClient(ckanPortalUrl); + + //retrieve the list of available licenses + List licenses = client.getLicenseList(); + + for (CkanLicense ckanLicense : licenses) { + if(ckanLicense.getTitle().equals(chosenLicense)) + return ckanLicense.getId(); + } + + return null; + } + @Override public LicensesBean getLicenses() { - logger.debug("Request for CKAN licenses"); + logger.info("Request for CKAN licenses"); // get the url and the api key of the user - String ckanPortalUrl = getCKANUrlFromIS(); - String apiKey = getCKANApikeyFromUser(""); // TODO - + String ckanPortalUrl = getCatalogueUrl(); List result = new ArrayList(); - CheckedCkanClient checkedClient = new CheckedCkanClient(ckanPortalUrl, apiKey); + CkanClient client = new CkanClient(ckanPortalUrl); //retrieve the list of available licenses - List licenses = checkedClient.getLicenseList(); + List licenses = client.getLicenseList(); for (CkanLicense ckanLicense : licenses) { + result.add(ckanLicense.getTitle()); - logger.debug("License is " + ckanLicense.getTitle()); + logger.debug("License is " + ckanLicense.getTitle() + " and id " + ckanLicense.getId()); + } + // return the bean return new LicensesBean(result); } @@ -140,21 +194,14 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C public DatasetMetadataBean getDatasetBean(String folderId, String owner){ DatasetMetadataBean bean = null; - ScopeProvider.instance.set("/gcube/devsec/devVRE"); + + logger.info("Bean request for " + folderId + " and " + owner); if(isWithinPortal()){ try{ logger.debug("Request dataset metadata bean for folder with id " + folderId + " whose owner is " + owner); - - Workspace ws = HomeLibrary - .getHomeManagerFactory() - .getHomeManager() - .getHome(owner).getWorkspace(); - - WorkspaceItem retrievedItem = ws.getItem(folderId); - // get usermanager (liferay) UserManager liferUserManager = new LiferayUserManager(); GCubeUser userOwner = liferUserManager.getUserByUsername(owner); @@ -164,42 +211,89 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C bean = new DatasetMetadataBean(); bean.setId(folderId); - bean.setDescription(retrievedItem.getDescription()); + bean.setOwnerFolderInWorkspace(owner); bean.setVersion(1); - bean.setTitle(retrievedItem.getName()); bean.setAuthor(userOwner.getFullname()); bean.setAuthorEmail(userOwner.getEmail()); bean.setMaintainer(userOwner.getFullname()); bean.setMaintainerEmail(userOwner.getEmail()); - bean.setSource(retrievedItem.getPublicLink(true)); + bean.setOrganizationList(getUserOrganizationsList(owner)); - // retrieve gcube items of the folder - Map folderItems = getGcubeItemProperties(retrievedItem); - bean.setCustomFields(folderItems); + if(folderId != null && !folderId.isEmpty()){ + + + Workspace ws = HomeLibrary + .getHomeManagerFactory() + .getHomeManager() + .getHome(owner).getWorkspace(); + + WorkspaceItem retrievedItem = ws.getItem(folderId); + + // set some info + bean.setTitle(retrievedItem.getName()); + bean.setDescription(retrievedItem.getDescription()); + + // retrieve gcube items of the folder + Map folderItems = getGcubeItemProperties(retrievedItem); + bean.setCustomFields(folderItems); + + // check the resources within the folder (skip subdirectories) + List childrenIds = new ArrayList(); + + for (WorkspaceItem file : retrievedItem.getChildren()) { + if(!file.isFolder()) // ok, it's a file + childrenIds.add(file.getId()); + } + + bean.setResourcesIds(childrenIds); + } }catch(Exception e){ logger.error("Error while retrieving folder information", e); } }else{ - - bean = new DatasetMetadataBean(); - bean.setId(folderId); - bean.setDescription("This is a fantastic description"); - bean.setVersion(1); - bean.setTitle("Dataset name"); - bean.setAuthor("Costantino Perciante"); - bean.setAuthorEmail("costantino.perciante@isti.cnr.it"); - bean.setMaintainer("Costantino Perciante"); - bean.setMaintainerEmail("costantino.perciante@isti.cnr.it"); - bean.setSource("https://dev.d4science.org/group/data-e-infrastructure-gateway/workspace"); - - // retrieve gcube items of the folder - Map folderItems = new HashMap(); - folderItems.put("tag1", "asds"); - folderItems.put("tag2", "asdsdaxcxcs"); - folderItems.put("tag3", "asasdads"); - bean.setCustomFields(folderItems); - + + try{ + + bean = new DatasetMetadataBean(); + bean.setId(folderId); + bean.setDescription("This is a fantastic description"); + bean.setVersion(1); + bean.setTitle("dataset-" + Calendar.getInstance().getTimeInMillis()); + bean.setAuthor("Costantino Perciante"); + bean.setAuthorEmail("costantino.perciante@isti.cnr.it"); + bean.setMaintainer("Costantino Perciante"); + bean.setMaintainerEmail("costantino.perciante@isti.cnr.it"); + bean.setOrganizationList(getUserOrganizationsList(owner)); + bean.setOwnerFolderInWorkspace(owner); + + if(folderId != null && !folderId.isEmpty()){ + ScopeProvider.instance.set("/gcube"); + + Workspace ws = HomeLibrary + .getHomeManagerFactory() + .getHomeManager() + .getHome(owner).getWorkspace(); + + WorkspaceItem retrievedItem = ws.getItem(folderId); + + // retrieve gcube items of the folder + Map folderItems = getGcubeItemProperties(retrievedItem); + bean.setCustomFields(folderItems); + + // check the resources within the folder (skip subdirectories) + List childrenIds = new ArrayList(); + + for (WorkspaceItem file : retrievedItem.getChildren()) { + if(!file.isFolder()) // ok, it's a file + childrenIds.add(file.getId()); + } + + bean.setResourcesIds(childrenIds); + } + }catch(Exception e){ + logger.error("Error while building bean into dev mode", e); + } } return bean; @@ -231,4 +325,155 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C return null; } + @Override + public boolean createCKanDataset(DatasetMetadataBean toCreate) { + + // retrieve ckan's catalog url + String ckanPortalUrl = getCatalogueUrl(); + + // retrieve the owner of the original folder into the workspace + String owner = toCreate.getOwnerFolderInWorkspace(); + + // retrieve the api key for this user + String apiKey = getCKANApikeyFromUser(owner); + + logger.info("Trying to create the dataset described by this bean " + toCreate + " into CKAN catalog at url " + ckanPortalUrl); + + // Checked client + CheckedCkanClient client = new CheckedCkanClient(ckanPortalUrl, apiKey); + + // create the base dataset and fill it + CkanDataset dataset = new CkanDataset(); + + // set dataset info (same id as the folder) + dataset.setId(toCreate.getId()); + + // get the name from the title + dataset.setName(nameFromTitle(toCreate.getTitle())); + dataset.setTitle(toCreate.getTitle()); + + CkanOrganization orgTest = client.getOrganization(toCreate.getSelectedOrganization()); + dataset.setOwnerOrg(orgTest.getId()); + dataset.setAuthor(toCreate.getAuthor()); + dataset.setAuthorEmail(toCreate.getAuthorEmail()); + dataset.setMaintainer(toCreate.getMaintainer()); + dataset.setMaintainerEmail(toCreate.getMaintainerEmail()); + dataset.setVersion(String.valueOf(toCreate.getVersion())); + dataset.setNotes(toCreate.getDescription()); + + logger.info("Searchable is " + toCreate.isSearchable() + " and visible is " + toCreate.getVisibility()); + + dataset.setPriv(false); + dataset.setOpen(toCreate.getVisibility()); + + // iterate over the licenses to find the id of the chosen one + String chosenLicense = toCreate.getLicense(); + String licenseId = findLicenseIdByLicense(chosenLicense); + dataset.setLicenseId(licenseId); + + // set the tags, if any + if(toCreate.getTags() != null && !toCreate.getTags().isEmpty()){ + + // convert to ckan tags + List ckanTags = new ArrayList(toCreate.getTags().size()); + for (String stringTag : toCreate.getTags()) { + ckanTags.add(new CkanTag(stringTag)); + } + + dataset.setTags(ckanTags); + } + + // set the custom fields, if any + if(toCreate.getCustomFields() != null && !toCreate.getCustomFields().isEmpty()){ + + // iterate and create + Iterator> iterator = toCreate.getCustomFields().entrySet().iterator(); + + List extras = new ArrayList(toCreate.getCustomFields().entrySet().size()); + + while (iterator.hasNext()) { + + Map.Entry entry = (Map.Entry) iterator.next(); + extras.add(new CkanPair(entry.getKey(), entry.getValue())); + + } + + dataset.setExtras(extras); + } + + // check if we need to add the resources + if(toCreate.isAddResources()){ + + logger.debug("We need to add resources to the dataset"); + + try{ + + ScopeProvider.instance.set("/gcube"); + Workspace ws = HomeLibrary + .getHomeManagerFactory() + .getHomeManager() + .getHome(toCreate.getOwnerFolderInWorkspace()).getWorkspace(); + + List resources = new ArrayList(); + + + for(String resourceId: toCreate.getResourcesIds()){ + + FolderItem item = (FolderItem)ws.getItem(resourceId); + CkanResource newResource = new CkanResource(); + newResource.setDescription(item.getDescription()); + newResource.setId(item.getId()); + newResource.setUrl(item.getPublicLink(false)); + newResource.setName(item.getName()); + newResource.setMimetype(item.getMimeType()); + + resources.add(newResource); + } + + // add to the dataset + dataset.setResources(resources); + + }catch(Exception e){ + logger.error("Unable to add those resources to the dataset", e); + } + + } + + // try to create + CkanDataset res = null; + try{ + + res = client.createDataset(dataset); + + }catch(Exception e){ + + // try to update + logger.error("Error while creating the dataset, probably it already exists. Trying to update it..", e); + res = client.updateDataset(dataset); + + } + + if(res != null) + logger.debug("Dataset created/updated " + res.getId()); + else{ + logger.error("Dataset described by " + toCreate + " not created!"); + return false; + } + + return true; + } + + /** + * Generate the catalogue's dataset name from its title + * @param title + * @return + */ + private String nameFromTitle(String title) { + String convertedName = title.replaceAll(" ", "-"); + convertedName = convertedName.toLowerCase(); + if(convertedName.endsWith("-")) + convertedName = convertedName.substring(0, convertedName.length() - 2); + + return convertedName; + } } 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 ca49a79..f8373d0 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 @@ -18,6 +18,8 @@ import java.util.Map; *
  • 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) * * @author Costantino Perciante at ISTI-CNR * (costantino.perciante@isti.cnr.it) @@ -35,11 +37,16 @@ public class DatasetMetadataBean implements Serializable { private boolean searchable; // true or false private String source; // url of the folder in the workspace private long version; // version 1, 2 ... - private String author; // folder's owner + private String author; // folder's owner fullname private String authorEmail; // folder's email owner private String maintainer; private String maintainerEmail; - + private String ownerFolderInWorkspace; // owner of the folder into the workspace + private List organizationList; // list of organization in which the user is present and could create the dataset + private String selectedOrganization; + private List resourcesIds; // in case of workspace, this is the list of children's ids + private boolean addResources; // if true, add these files as resources to the dataset + public DatasetMetadataBean(){ super(); } @@ -48,6 +55,7 @@ public class DatasetMetadataBean implements Serializable { * @param id * @param title * @param description + * @param customFields * @param tags * @param license * @param visibility @@ -58,16 +66,23 @@ public class DatasetMetadataBean implements Serializable { * @param authorEmail * @param maintainer * @param maintainerEmail + * @param ownerFolderInWorkspace + * @param organizationList + * @param selectedOrganization */ public DatasetMetadataBean(String id, String title, String description, - Map customFields, String license, boolean visibility, - boolean searchable, String source, long version, String author, - String authorEmail, String maintainer, String maintainerEmail) { + Map customFields, List tags, + String license, boolean visibility, boolean searchable, + String source, long version, String author, String authorEmail, + String maintainer, String maintainerEmail, + String ownerFolderInWorkspace, List organizationList, + String selectedOrganization) { super(); this.id = id; this.title = title; this.description = description; this.customFields = customFields; + this.tags = tags; this.license = license; this.visibility = visibility; this.searchable = searchable; @@ -77,6 +92,9 @@ public class DatasetMetadataBean implements Serializable { this.authorEmail = authorEmail; this.maintainer = maintainer; this.maintainerEmail = maintainerEmail; + this.ownerFolderInWorkspace = ownerFolderInWorkspace; + this.organizationList = organizationList; + this.selectedOrganization = selectedOrganization; } public String getId() { @@ -87,6 +105,14 @@ public class DatasetMetadataBean implements Serializable { this.id = id; } + public void setOwnerFolderInWorkspace(String ownerFolderInWorkspace) { + this.ownerFolderInWorkspace = ownerFolderInWorkspace; + } + + public String getOwnerFolderInWorkspace(){ + return ownerFolderInWorkspace; + } + public String getTitle() { return title; } @@ -191,6 +217,38 @@ public class DatasetMetadataBean implements Serializable { this.maintainerEmail = maintainerEmail; } + public List getOrganizationList() { + return organizationList; + } + + public void setOrganizationList(List organizationList) { + this.organizationList = organizationList; + } + + public String getSelectedOrganization() { + return selectedOrganization; + } + + public void setSelectedOrganization(String selectedOrganization) { + this.selectedOrganization = selectedOrganization; + } + + public List getResourcesIds() { + return resourcesIds; + } + + public void setResourcesIds(List resourcesIds) { + this.resourcesIds = resourcesIds; + } + + public boolean isAddResources() { + return addResources; + } + + public void setAddResources(boolean addResources) { + this.addResources = addResources; + } + @Override public String toString() { return "DatasetMetadataBean [id=" + id + ", title=" + title @@ -199,6 +257,11 @@ public class DatasetMetadataBean implements Serializable { + ", visibility=" + visibility + ", searchable=" + searchable + ", source=" + source + ", version=" + version + ", author=" + author + ", authorEmail=" + authorEmail + ", maintainer=" - + maintainer + ", maintainerEmail=" + maintainerEmail + "]"; + + maintainer + ", maintainerEmail=" + maintainerEmail + + ", ownerFolderInWorkspace=" + ownerFolderInWorkspace + + ", organizationList=" + organizationList + + ", selectedOrganization=" + selectedOrganization + + ", resourcesIds=" + resourcesIds + ", addResources=" + + addResources + "]"; } } diff --git a/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml b/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml index afb8ec1..2c54a6b 100644 --- a/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml +++ b/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml @@ -10,7 +10,6 @@ - children = rootFolder.getChildren(); - // - // for (WorkspaceItem workspaceItem : children) { - // System.out.println("Children with name " + workspaceItem.getName() + " and id " + workspaceItem.getId()); - // } + ScopeProvider.instance.set("/gcube"); + + Workspace ws = HomeLibrary + .getHomeManagerFactory() + .getHomeManager() + .getHome("costantino.perciante").getWorkspace(); + + List childrens = ws.getRoot().getChildren(); + for (WorkspaceItem workspaceItem : childrens) { + if(workspaceItem.getName().equals("CkanTest1137")){ + + System.out.println("Dir has id " + workspaceItem.getId()); + + List files = workspaceItem.getChildren(); + for (WorkspaceItem file : files) { + + if(!file.isFolder()) // ok, it's a file + System.out.println("item id is " + file.getId()); + + } + } + } - // get the url and the api key of the user - String ckanPortalUrl = "https://ckan-d-d4s.d4science.org/"; - String apiKey = "803ada7f-2080-493f-8a99-3e593e880d94"; - - List result = new ArrayList(); - - CheckedCkanClient checkedClient = new CheckedCkanClient(ckanPortalUrl, apiKey); - CkanClient client = new CkanClient(ckanPortalUrl); - - List list = client.getUserList(); - for (CkanUser ckanUser : list) { - - System.out.println("User -> " + ckanUser.getId() + " with fullname " + ckanUser.getFullname() + " and name " + ckanUser.getName() + " password " + ckanUser.getPassword()); - - } - } - - public static void main(String[] args) { -// try { -// test(); -// } catch (WorkspaceFolderNotFoundException | InternalErrorException -// | HomeNotFoundException | UserNotFoundException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } +// CheckedCkanClient client = new CheckedCkanClient("http://ckan-d-d4s.d4science.org", "803ada7f-2080-493f-8a99-3e593e880d94"); +// +// CkanDataset dataset = client.getDataset("34d9cc5a-9ddb-40a1-9747-8490acd318d3"); +// //client.deleteDataset("34d9cc5a-9ddb-40a1-9747-8490acd318d3"); +// System.out.println("Dataset exists " + dataset.getName()); } }