diff --git a/pom.xml b/pom.xml
index d2354e2..2c17480 100644
--- a/pom.xml
+++ b/pom.xml
@@ -121,6 +121,11 @@
aslcore
provided
+
+ org.gcube.portal
+ social-networking-library
+ provided
+
org.gcube.portal
custom-portal-handler
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 ed59355..9361fab 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
@@ -5,19 +5,18 @@ import java.util.List;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.CreateDatasetForm;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.MetaDataFieldSkeleton;
-import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection.TwinColumnSelectionMainPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DataType;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetadataFieldWrapper;
-import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import com.github.gwtbootstrap.client.ui.Button;
+import com.github.gwtbootstrap.client.ui.ListBox;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.shared.GWT;
+import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
@@ -40,7 +39,35 @@ public class CKanMetadataPublisher implements EntryPoint {
//startExample();
//testMetadata();
//testSelectionPanel();
+ //testHideOption();
+ }
+ @SuppressWarnings("unused")
+ private void testHideOption() {
+
+ ListBox listBox = new ListBox(true);
+ listBox.addItem("A");
+ listBox.addItem("B");
+ listBox.addItem("C");
+ listBox.addItem("D");
+ listBox.addItem("E");
+ listBox.addItem("F");
+
+ List toHide = new ArrayList();
+ toHide.add("A");
+ toHide.add("D");
+
+ RootPanel.get("ckan-metadata-publisher-div").add(listBox);
+ SelectElement se = listBox.getElement().cast();
+
+ // hide
+ for (int i = 0; i < listBox.getItemCount(); i++) {
+ if(toHide.contains(listBox.getItemText(i))){
+ GWT.log("to hide " + listBox.getItemText(i));
+ se.getOptions().getItem(i).getStyle().setProperty("display", "none");
+ }
+ }
+
}
@SuppressWarnings("unused")
@@ -73,24 +100,24 @@ public class CKanMetadataPublisher implements EntryPoint {
//
- String folderId = "e87bfc7d-4fb0-4795-9c79-0c495500ca9c";
- ckanServices.getTreeFolder(folderId, new AsyncCallback() {
-
-
- @Override
- public void onSuccess(ResourceElementBean result) {
- if(result != null){
- RootPanel.get("ckan-metadata-publisher-div").add(new TwinColumnSelectionMainPanel(result));
- }
- }
-
- @Override
- public void onFailure(Throwable caught) {
-
- Window.alert("Failed to retrieve ResourceElementBean");
-
- }
- });
+ // String folderId = "e87bfc7d-4fb0-4795-9c79-0c495500ca9c";
+ // ckanServices.getTreeFolder(folderId, new AsyncCallback() {
+ //
+ //
+ // @Override
+ // public void onSuccess(ResourceElementBean result) {
+ // if(result != null){
+ // RootPanel.get("ckan-metadata-publisher-div").add(new TwinColumnSelectionMainPanel(result));
+ // }
+ // }
+ //
+ // @Override
+ // public void onFailure(Throwable caught) {
+ //
+ // Window.alert("Failed to retrieve ResourceElementBean");
+ //
+ // }
+ // });
}
@SuppressWarnings("unused")
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 b9b30cb..96fd6be 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
@@ -67,17 +67,17 @@ public interface CKanPublisherService extends RemoteService {
* @return true if it exists, false otherwise
*/
boolean datasetIdAlreadyExists(String title);
-
+
/**
* Retrieve the list of groups the user can choose to associate this product with.
* @return a list of groups' beans
*/
List getUserGroups();
- /**
- * Return a tree object representing the whole folder hierarchy
- * @param folderId
- * @return ResourceElementBean
- */
- ResourceElementBean getTreeFolder(String folderId);
+ // /**
+ // * Return a tree object representing the whole folder hierarchy
+ // * @param folderId
+ // * @return ResourceElementBean
+ // */
+ // ResourceElementBean getTreeFolder(String folderId);
}
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 269999d..9a2c6a9 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
@@ -68,18 +68,17 @@ public interface CKanPublisherServiceAsync {
*/
void datasetIdAlreadyExists(String title, AsyncCallback callback);
- /**
- * Return a tree object representing the whole folder hierarchy
- * @param folderId
- * @return ResourceElementBean
- */
- void getTreeFolder(String folderId,
- AsyncCallback callback);
+ // /**
+ // * Return a tree object representing the whole folder hierarchy
+ // * @param folderId
+ // * @return ResourceElementBean
+ // */
+ // void getTreeFolder(String folderId,
+ // AsyncCallback callback);
/**
* Retrieve the list of groups the user can choose to associate this product with.
* @return a list of groups' beans
*/
void getUserGroups(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 a718216..71adb23 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
@@ -43,6 +43,7 @@ import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.constants.ControlGroupType;
import com.github.gwtbootstrap.client.ui.resources.Bootstrap.Tabs;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
@@ -165,8 +166,8 @@ public class CreateDatasetForm extends Composite{
// error/info messages
protected static final String ERROR_PRODUCT_CREATION = "There was an error while trying to publish your product, sorry.. Retry later";
- protected static final String PRODUCT_CREATED_OK = "Product correctly created!";
- private static final String TRYING_TO_CREATE_PRODUCT = "Trying to create product, please wait";
+ protected static final String PRODUCT_CREATED_OK = "Product correctly published!";
+ private static final String TRYING_TO_CREATE_PRODUCT = "Trying to publish the product, please wait";
// tab panel
private TabPanel tabPanel;
@@ -209,9 +210,7 @@ public class CreateDatasetForm extends Composite{
* @param eventBus the event bus
*/
public CreateDatasetForm(HandlerManager eventBus) {
-
createDatasetFormBody(false, null, eventBus);
-
}
/**
@@ -220,40 +219,30 @@ public class CreateDatasetForm extends Composite{
* @param eventBus the event bus
*/
public CreateDatasetForm(String idFolderWorkspace, HandlerManager eventBus) {
-
createDatasetFormBody(true, idFolderWorkspace, eventBus);
-
}
/**
* Bind on events
*/
private void bind() {
-
// when a custom field is removed, remove it from the list
eventBus.addHandler(DeleteCustomFieldEvent.TYPE, new DeleteCustomFieldEventHandler() {
@Override
public void onRemoveEntry(DeleteCustomFieldEvent event) {
-
customFieldEntriesList.remove(event.getRemovedEntry());
customFields.remove(event.getRemovedEntry());
-
}
});
// on close form
eventBus.addHandler(CloseCreationFormEvent.TYPE, new CloseCreationFormEventHandler() {
-
@Override
public void onClose(CloseCreationFormEvent event) {
-
InfoIconsLabels.closeDialogBox(popupOpenedIds);
-
}
-
});
-
}
/**
@@ -284,7 +273,7 @@ public class CreateDatasetForm extends Composite{
@Override
public void onFailure(Throwable caught) {
- setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true);
+ setAlertBlock("Error while retrieving information, try to refresh the page and retry", AlertType.ERROR, true);
}
@@ -293,7 +282,7 @@ public class CreateDatasetForm extends Composite{
if(bean == null){
- setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true);
+ setAlertBlock("Error while retrieving information, try to refresh the page and retry", AlertType.ERROR, true);
}
else{
@@ -381,14 +370,14 @@ public class CreateDatasetForm extends Composite{
}
@Override
- public void onSuccess(List result) {
+ public void onSuccess(final List profiles) {
- if(result == null){
+ if(profiles == null){
setAlertBlock("Error while retrieving profiles, try later", AlertType.ERROR, true);
}
else{
- receivedBean.setMetadataList(result);
+ receivedBean.setMetadataList(profiles);
prepareMetadataList(receivedBean);
organizationsListbox.setEnabled(true);
metadataProfilesFormatListbox.setEnabled(true);
@@ -429,17 +418,21 @@ public class CreateDatasetForm extends Composite{
ckanServices.getUserGroups(new AsyncCallback>() {
@Override
- public void onSuccess(List result) {
+ public void onSuccess(List groups) {
- if(result == null){
+ if(groups == null){
setAlertBlock("Error while retrieving groups, try later", AlertType.ERROR, true);
}else{
- if(result.isEmpty())
+ if(groups.isEmpty())
return;
else{
- for (GroupBean groups : result) {
- groupsListbox.addItem(groups.getGroupTitle(), groups.getGroupName());
+
+ // add groups
+ for (GroupBean group : groups) {
+ groupsListbox.addItem(group.getGroupTitle(), group.getGroupName());
}
+
+ hideGroupsAlreadyInProfile(profiles);
groupsControlGroup.setVisible(true);
}
// everything went ok
@@ -469,16 +462,14 @@ public class CreateDatasetForm extends Composite{
}
+
/**
- * When the organization name is changed we need to retrieve the list of profiles
+ * When the organization name is changed we need to retrieve the list of profiles and groups
*/
private void organizationsListboxChangeHandlerBody() {
// remove any other product profiles
- int presentItems = metadataProfilesFormatListbox.getItemCount();
- for (int i = presentItems - 1; i >= 0; i--) {
- metadataProfilesFormatListbox.removeItem(i);
- }
+ metadataProfilesFormatListbox.clear();
// add "none" item again
metadataProfilesFormatListbox.addItem(NONE_PROFILE);
@@ -494,24 +485,61 @@ public class CreateDatasetForm extends Composite{
setAlertBlock("Retrieving profiles, 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);
+ groupsListbox.setEnabled(false);
+ groupsControlGroup.setVisible(false);
// perform remote request of profiles for the selected organization
ckanServices.getProfiles(orgName, new AsyncCallback>() {
@Override
- public void onSuccess(List result) {
+ public void onSuccess(final List profiles) {
- if(result != null){
+ if(profiles != null){
- receivedBean.setMetadataList(result);
+ receivedBean.setMetadataList(profiles);
prepareMetadataList(receivedBean);
organizationsListbox.setEnabled(true);
metadataProfilesFormatListbox.setEnabled(true);
+ groupsListbox.setEnabled(true);
- // everything went ok
- setAlertBlock("", AlertType.DEFAULT, false);
+ // try to retrieve the licenses
+ setAlertBlock("Retrieving groups, please wait...", AlertType.INFO, true);
+
+ // request groups
+ ckanServices.getUserGroups(new AsyncCallback>() {
+
+ @Override
+ public void onSuccess(List groups) {
+
+ if(groups == null){
+ setAlertBlock("Error while retrieving groups, try later", AlertType.ERROR, true);
+ }else{
+ if(groups.isEmpty())
+ return;
+ else{
+
+ // add groups
+ for (GroupBean group : groups) {
+ groupsListbox.addItem(group.getGroupTitle(), group.getGroupName());
+ }
+
+ hideGroupsAlreadyInProfile(profiles);
+ groupsListbox.setEnabled(true);
+ groupsControlGroup.setVisible(true);
+ }
+ // everything went ok
+ setAlertBlock("", AlertType.ERROR, false);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ setAlertBlock("Error while retrieving groups, try later", AlertType.ERROR, true);
+ }
+ });
}else
setAlertBlock("Error while retrieving profiles, sorry", AlertType.ERROR, true);
@@ -534,10 +562,10 @@ public class CreateDatasetForm extends Composite{
*/
private void prepareMetadataList(final DatasetMetadataBean receivedBean) {
- List beans = receivedBean.getMetadataList();
+ List profiles = receivedBean.getMetadataList();
- if(beans != null && !beans.isEmpty()){
- for(MetaDataProfileBean metadataBean: beans){
+ if(profiles != null && !profiles.isEmpty()){
+ for(MetaDataProfileBean metadataBean: profiles){
metadataProfilesFormatListbox.addItem(metadataBean.getType().getName());
@@ -547,21 +575,37 @@ public class CreateDatasetForm extends Composite{
@Override
public void onChange(ChangeEvent event) {
- String selectedItem = metadataProfilesFormatListbox.getSelectedItemText();
+ String selectedItemText = metadataProfilesFormatListbox.getSelectedItemText();
- if(selectedItem.equals(NONE_PROFILE)){
- // hide the panel
+ if(selectedItemText.equals(NONE_PROFILE)){
metadataFieldsPanel.clear();
metadataFieldsPanel.setVisible(false);
receivedBean.setChosenProfile(null);
}else{
- receivedBean.setChosenProfile(selectedItem);
+ receivedBean.setChosenProfile(selectedItemText);
metadataFieldsPanel.clear();
- addFields(selectedItem);
+ addFields(selectedItemText);
}
}
});
}
+
+ // hide elements or show them if needed (groups in profiles cannot be present again in groups listbox)
+ if(groupsControlGroup.isVisible()){
+ List groupsToHide = new ArrayList();
+ for(MetaDataProfileBean profile: profiles)
+ groupsToHide.add(profile.getType().toString());
+
+ SelectElement se = groupsListbox.getElement().cast();
+
+ for (int i = 0; i < groupsListbox.getItemCount(); i++) {
+ if(groupsToHide.contains(groupsListbox.getItemText(i))){
+ se.getOptions().getItem(i).getStyle().setProperty("display", "none");
+ }else
+ se.getOptions().getItem(i).getStyle().setProperty("display", "");
+ }
+ }
+
metadataProfilesControlGroup.setVisible(true);
}else{
// just hide this listbox
@@ -635,23 +679,16 @@ public class CreateDatasetForm extends Composite{
@Override
public void onSuccess(Boolean result) {
-
if(result){
-
alertOnContinue("Sorry but a product with such title already exists, try to change it", AlertType.WARNING);
-
}else{
-
actionsAfterOnContinue();
-
}
}
@Override
public void onFailure(Throwable caught) {
-
alertOnContinue("Sorry but there was a problem while checking if the inserted data are correct", AlertType.ERROR);
-
}
});
}
@@ -1228,6 +1265,7 @@ public class CreateDatasetForm extends Composite{
organizationsListbox.setEnabled(false);
addCustomFieldButton.setEnabled(false);
metadataProfilesFormatListbox.setEnabled(false);
+ groupsListbox.setEnabled(false);
for(CustomFieldEntry ce: customFieldEntriesList)
ce.freeze();
@@ -1290,4 +1328,23 @@ public class CreateDatasetForm extends Composite{
}
+ /**
+ * Hide the groups that are already listed in the profiles page
+ * @param profiles
+ */
+ private void hideGroupsAlreadyInProfile(List profiles) {
+
+ List groupsToHide = new ArrayList();
+ for(MetaDataProfileBean profile: profiles)
+ groupsToHide.add(profile.getType().getName());
+
+ SelectElement se = groupsListbox.getElement().cast();
+
+ for (int i = 0; i < groupsListbox.getItemCount(); i++) {
+ if(groupsToHide.contains(groupsListbox.getItemText(i))){
+ se.getOptions().getItem(i).getStyle().setProperty("display", "none");
+ }
+ }
+
+ }
}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/AssociationToGroupThread.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/AssociationToGroupThread.java
deleted file mode 100644
index df8242e..0000000
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/AssociationToGroupThread.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
-
-import java.util.List;
-
-import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
-import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg;
-import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import eu.trentorise.opendata.jackan.model.CkanGroup;
-
-/**
- * Associate the dataset to a group.
- * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
- */
-public class AssociationToGroupThread extends Thread {
-
- private static final Logger logger = LoggerFactory.getLogger(AssociationToGroupThread.class);
-
- private String groupTitle;
- private String datasetId;
- private String username;
- private DataCatalogue catalogue;
- private String organization;
- private List groups;
-
- /**
- * @param list
- * @param groupTitle
- * @param datasetId
- * @param username
- * @param catalogue
- */
- public AssociationToGroupThread(List groups, String groupTitle, String datasetId,
- String username, DataCatalogue catalogue, String organization) {
- this.groups = groups;
- this.groupTitle = groupTitle;
- this.datasetId = datasetId;
- this.username = username;
- this.catalogue = catalogue;
- this.organization = organization;
- }
-
- @Override
- public void run() {
-
- logger.info("Association thread started to put the dataset with id = "+ datasetId + " into group with title " + groupTitle + " for user " + username);
-
- // create the group
- CkanGroup group = catalogue.createGroup(groupTitle, groupTitle, "");
-
- if(group == null){
-
- logger.warn("The group doesn't exist!!! Unable to perform such association");
-
- }else{
-
- logger.debug("Group exists, going to add the user " + username + " as its admin...");
-
- // retrieve the role to be assigned according the one the user has into the organization of the dataset
- RolesCkanGroupOrOrg role = RolesCkanGroupOrOrg.valueOf(catalogue.getRoleOfUserInOrganization(username, organization, catalogue.getApiKeyFromUsername(username)).toUpperCase());
-
- if(!role.equals(RolesCkanGroupOrOrg.ADMIN))
- role = RolesCkanGroupOrOrg.MEMBER; // decrease the role to member if it is not an admin
-
- boolean assigned = catalogue.checkRoleIntoGroup(username, groupTitle, role);
-
- if(assigned){
-
- logger.debug("Admin/editor role was assigned for this group, going to associate the product to the group");
- boolean putIntoGroup = catalogue.assignDatasetToGroup(groupTitle, datasetId, catalogue.getApiKeyFromUsername(username));
- logger.info("Was product put into group? " + putIntoGroup);
-
- }
- }
-
- logger.info("Other groups to which the product should be associate are " + groups);
-
- for (GroupBean groupBean : groups) {
- boolean putIntoGroup = catalogue.assignDatasetToGroup(groupBean.getGroupTitle(), datasetId, catalogue.getApiKeyFromUsername(username));
- logger.info("Was product put into group" + groupBean + "? " + putIntoGroup);
- }
-
- }
-
-}
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 84d3406..3085555 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
@@ -12,8 +12,6 @@ import javax.servlet.http.HttpSession;
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.workspace.Workspace;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueFactory;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
@@ -21,6 +19,8 @@ import org.gcube.datacatalogue.ckanutillibrary.utils.SessionCatalogueAttributes;
import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper;
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.Utils;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.WorkspaceUtils;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
@@ -52,7 +52,6 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
public static final String TEST_SCOPE = "/gcube";
public static final String TEST_USER = "test.user";
- private final static String TEST_SEC_TOKEN = "a1e19695-467f-42b8-966d-bf83dd2382ef";
// map
private ConcurrentHashMap mapOrganizationScope = new ConcurrentHashMap();
@@ -71,7 +70,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
logger.debug("Discovering ckan instance into scope " + scopeInWhichDiscover);
instance = DataCatalogueFactory.getFactory().getUtilsPerScope(scopeInWhichDiscover);
}catch(Exception e){
- logger.warn("Unable to retrieve ckan utils in scope " + scopeInWhichDiscover + ". Error is " + e.toString());
+ logger.warn("Unable to retrieve ckan utils in scope " + scopeInWhichDiscover + ". Error is " + e.getLocalizedMessage());
}
return instance;
}
@@ -102,54 +101,6 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return user;
}
- /**
- * Get current user's token (for a given scope)
- * @param scope if it is not specified it will be retrieved from the asl
- * @return String the ckan user's token
- */
- private String getUserCKanTokenFromSession(String scope){
-
- String token = null;
-
- if(!isWithinPortal()){
- logger.warn("You are running outside the portal");
- token = TEST_SEC_TOKEN;
- }else{
-
- ASLSession aslSession = getASLSession();
- String username = aslSession.getUsername();
- logger.debug("User in session is " + username);
- if(username.equals(TEST_USER)){
-
- logger.warn("Session expired, returning null token");
- token = null;
-
- }else{
- try{
-
- HttpSession httpSession = getThreadLocalRequest().getSession();
- String scopeInWhichDiscover = (scope != null && !scope.isEmpty()) ? scope : getASLSession().getScope();
- String keyPerScope = UtilMethods.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_TOKEN_KEY, scopeInWhichDiscover);
-
- if(httpSession.getAttribute(keyPerScope) != null){
- token = (String)httpSession.getAttribute(keyPerScope);
- logger.debug("Found ckan token into session");
- }
- else{
- token = getCatalogue(scopeInWhichDiscover).getApiKeyFromUsername(username);
- httpSession.setAttribute(keyPerScope, token);
- logger.debug("Ckan token has been set for user " + username);
- }
- logger.debug("Found ckan token " + token.substring(0, 3) + "************************" +
- " for user " + username + " into scope " + scopeInWhichDiscover);
- }catch(Exception e){
- logger.error("Error while retrieving the key" , e);
- }
- }
- }
- return token;
- }
-
/**
* Retrieve the list of organizations in which the user can publish (roles ADMIN)
* @param username
@@ -367,8 +318,9 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
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.createCKanDataset(getUserCKanTokenFromSession(scope), title, null, organizationNameOrId, author,
+ String datasetId = utils.createCKanDataset(userApiKey, title, null, organizationNameOrId, author,
authorMail, maintainer, maintainerMail, version, description, licenseId,
listOfTags, customFields, resources, setPublic);
@@ -378,20 +330,23 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
toCreate.setId(datasetId);
// retrieve the url
- String datasetUrl = utils.getPortletUrl() + "?" + URLEncoder.encode("path=" + utils.getUrlFromDatasetIdOrName(getUserCKanTokenFromSession(scope), datasetId, true), "UTF-8");
+ String datasetUrl = utils.getPortletUrl() + "?" + URLEncoder.encode("path=" + utils.getUrlFromDatasetIdOrName(userApiKey, datasetId, true), "UTF-8");
toCreate.setSource(datasetUrl);
// start a thread that will associate this dataset with the group
if(toCreate.getChosenProfile() != null || toCreate.getGroups() != null){
- AssociationToGroupThread threadAssociationToGroup =
- new AssociationToGroupThread(
+ AssociationToGroupAndNotifyThread threadAssociationToGroup =
+ new AssociationToGroupAndNotifyThread(
toCreate.getGroups(),
toCreate.getChosenProfile(),
- datasetId,
+ datasetId,
+ toCreate.getTitle(),
+ aslSession.getUserFullName(),
userName,
utils,
- organizationNameOrId
+ organizationNameOrId,
+ getThreadLocalRequest()
);
threadAssociationToGroup.start();
@@ -406,7 +361,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
datasetUrl,
false, // send notification to other people
toCreate.getTags(),
- toCreate.getAuthorFullName()
+ aslSession.getUserFullName()
);
threadWritePost.start();
@@ -452,7 +407,8 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
// 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());
- String resourceId = getCatalogue(scope).addResourceToDataset(resourceBean, getUserCKanTokenFromSession(scope));
+ DataCatalogue catalogue = getCatalogue(scope);
+ String resourceId = catalogue.addResourceToDataset(resourceBean, catalogue.getApiKeyFromUsername(username));
if(resourceId != null){
logger.debug("Resource " + resource.getName() + " is now available");
@@ -490,8 +446,9 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
try{
// 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());
- deleted = getCatalogue(scope).
- deleteResourceFromDataset(resource.getOriginalIdInWorkspace(), getUserCKanTokenFromSession(scope));
+ DataCatalogue catalogue = getCatalogue(scope);
+ deleted = catalogue.
+ deleteResourceFromDataset(resource.getOriginalIdInWorkspace(), catalogue.getApiKeyFromUsername(username));
if(deleted){
logger.info("Resource described by " + resource + " deleted");
}else
@@ -562,46 +519,46 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return toReturn;
}
- @Override
- public ResourceElementBean getTreeFolder(String folderId) {
-
- if(folderId == null || folderId.isEmpty()){
- logger.warn("Empty folder id or null, returning");
- return null;
- }
- ASLSession session = getASLSession();
- try{
- if(!isWithinPortal()){
- logger.warn("Running outside the portal");
- Workspace ws = getFakeWS();
- ResourceElementBean toReturn = WorkspaceUtils.getTreeFromFolder(folderId, ws);
- logger.debug("Returning " + toReturn);
- return toReturn;
- }else{
- if(session.getUsername().equals(TEST_USER)){
- return null;
- }else{
- // TODO
- return null;
- }
- }
- }catch(Exception e){
- logger.error("Failed to build the tree", e);
- }
- return null;
- }
-
- /**
- * Retrieve the workspace for the development user
- * @return
- * @throws Exception
- */
- private Workspace getFakeWS() throws Exception{
- return HomeLibrary
- .getHomeManagerFactory()
- .getHomeManager()
- .getHome(getDevelopmentUser()).getWorkspace();
- }
+ // @Override
+ // public ResourceElementBean getTreeFolder(String folderId) {
+ //
+ // if(folderId == null || folderId.isEmpty()){
+ // logger.warn("Empty folder id or null, returning");
+ // return null;
+ // }
+ // ASLSession session = getASLSession();
+ // try{
+ // if(!isWithinPortal()){
+ // logger.warn("Running outside the portal");
+ // Workspace ws = getFakeWS();
+ // ResourceElementBean toReturn = WorkspaceUtils.getTreeFromFolder(folderId, ws);
+ // logger.debug("Returning " + toReturn);
+ // return toReturn;
+ // }else{
+ // if(session.getUsername().equals(TEST_USER)){
+ // return null;
+ // }else{
+ // // TODO
+ // return null;
+ // }
+ // }
+ // }catch(Exception e){
+ // logger.error("Failed to build the tree", e);
+ // }
+ // return null;
+ // }
+ //
+ // /**
+ // * Retrieve the workspace for the development user
+ // * @return
+ // * @throws Exception
+ // */
+ // private Workspace getFakeWS() throws Exception{
+ // return HomeLibrary
+ // .getHomeManagerFactory()
+ // .getHomeManager()
+ // .getHome(getDevelopmentUser()).getWorkspace();
+ // }
@Override
public List getUserGroups() {
@@ -611,6 +568,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
if(isWithinPortal()){
String username = session.getUsername();
+
if(username.equals(TEST_USER)){
logger.warn("Session expired");
return null;
@@ -623,10 +581,16 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
String scope = (String)httpSession.getAttribute(SessionCatalogueAttributes.SCOPE_CLIENT_PORTLET_URL);
DataCatalogue catalogue = getCatalogue(scope);
List ckanGroups = catalogue.getGroups();
+
+ String apiKey = catalogue.getApiKeyFromUsername(username);
- // TODO check role
-
+ // Members/Admin of the group
for (CkanGroup ckanGroup : ckanGroups) {
+ String role = catalogue.getRoleOfUserInGroup(username, ckanGroup.getName(), apiKey);
+
+ if(role == null)
+ continue;
+
toReturn.add(new GroupBean(ckanGroup.getTitle(), ckanGroup.getName()));
}
logger.debug("List of groups to return is " + toReturn);
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/threads/AssociationToGroupAndNotifyThread.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/threads/AssociationToGroupAndNotifyThread.java
new file mode 100644
index 0000000..a5648ae
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/threads/AssociationToGroupAndNotifyThread.java
@@ -0,0 +1,166 @@
+package org.gcube.portlets.widgets.ckandatapublisherwidget.server.threads;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.gcube.common.portal.mailing.EmailNotification;
+import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
+import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg;
+import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
+import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
+import org.gcube.vomanagement.usermanagement.UserManager;
+import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import eu.trentorise.opendata.jackan.model.CkanGroup;
+
+/**
+ * Associate the dataset to a group and send notifications to group's admins.
+ * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
+ */
+public class AssociationToGroupAndNotifyThread extends Thread {
+
+ private static final Logger logger = LoggerFactory.getLogger(AssociationToGroupAndNotifyThread.class);
+ private static final String PRODUCT_ASSOCIATED_TO_GROUP_SUBJECT = "Product $PRODUCT added to group $GROUP";
+ private static final String PRODUCT_ASSOCIATED_TO_GROUP_BODY = "Dear user,'\n'a new product named $TITLE has been just published to the Data Catalogue group $GROUP by $USER_FULLNAME.";
+
+ private String groupTitle;
+ private String datasetId;
+ private String username;
+ private String datasetTitle;
+ private String userFullName;
+ private DataCatalogue catalogue;
+ private String organization;
+ private List groups;
+ private HttpServletRequest request;
+
+ /**
+ * @param list
+ * @param groupTitle
+ * @param datasetId
+ * @param username
+ * @param catalogue
+ */
+ public AssociationToGroupAndNotifyThread(List groups, String groupTitle, String datasetId, String datasetTitle, String userFullName,
+ String username, DataCatalogue catalogue, String organization, HttpServletRequest request) {
+ this.request = request;
+ this.groups = groups;
+ this.groupTitle = groupTitle;
+ this.datasetId = datasetId;
+ this.username = username;
+ this.catalogue = catalogue;
+ this.organization = organization;
+ this.datasetTitle = datasetTitle;
+ this.userFullName = userFullName;
+ }
+
+ @Override
+ public void run() {
+
+ logger.info("Association thread started to put the dataset with id = "+ datasetId + " into group with title " + groupTitle + " for user " + username);
+
+ // create the group
+ CkanGroup group = catalogue.createGroup(groupTitle, groupTitle, "");
+
+ if(group == null){
+
+ logger.warn("The group doesn't exist! Unable to perform such association");
+
+ }else{
+
+ logger.debug("Group exists, going to add the user " + username + " as its admin...");
+
+ // retrieve the role to be assigned according the one the user has into the organization of the dataset
+ RolesCkanGroupOrOrg role = RolesCkanGroupOrOrg.valueOf(catalogue.getRoleOfUserInOrganization(username, organization, catalogue.getApiKeyFromUsername(username)).toUpperCase());
+
+ if(!role.equals(RolesCkanGroupOrOrg.ADMIN))
+ role = RolesCkanGroupOrOrg.MEMBER; // decrease the role to member if it is not an admin
+
+ boolean assigned = catalogue.checkRoleIntoGroup(username, groupTitle, role);
+
+ if(assigned){
+
+ logger.debug("Admin/editor role was assigned for this group, going to associate the product to the group");
+ boolean putIntoGroup = catalogue.assignDatasetToGroup(groupTitle, datasetId, catalogue.getApiKeyFromUsername(username));
+ logger.info("Was product put into group? " + putIntoGroup);
+
+ if(putIntoGroup)
+ notifyGroupAdmins(catalogue, groupTitle, username);
+
+ }
+ }
+
+ logger.info("Other groups to which the product should be associate are " + groups);
+
+ for (GroupBean groupBean : groups) {
+ boolean putIntoGroup = catalogue.assignDatasetToGroup(groupBean.getGroupTitle(), datasetId, catalogue.getApiKeyFromUsername(username));
+ logger.info("Was product put into group" + groupBean.getGroupTitle() + "? " + putIntoGroup);
+
+ if(putIntoGroup)
+ notifyGroupAdmins(catalogue, groupBean.getGroupTitle(), username);
+ }
+
+ }
+
+ /**
+ * Send a notification to the group admin(s) about the just added product
+ * @param username
+ * @param groupTitle
+ * @param catalogue
+ */
+ private void notifyGroupAdmins(DataCatalogue catalogue, String groupTitle, String username){
+
+ // get the groups admin
+ Map> userAndRoles = catalogue.getRolesAndUsersGroup(groupTitle);
+
+ if(userAndRoles.containsKey(RolesCkanGroupOrOrg.ADMIN)){
+
+ List admins = userAndRoles.get(RolesCkanGroupOrOrg.ADMIN);
+ List adminsEmails = new ArrayList();
+
+ for(int i = 0; i < admins.size(); i++){
+ String convertedName = UtilMethods.fromCKanUsernameToUsername(admins.get(i));
+ admins.set(i, convertedName);
+ }
+
+ // remove the same user who published the product if he/she is an admin of the group
+ int indexOfUser = admins.indexOf(username);
+ if(indexOfUser >= 0)
+ admins.remove(indexOfUser);
+
+ // further cleaning of the list (for users that are only in ckan... sysadmin for example)
+ UserManager um = new LiferayUserManager();
+ Iterator adminIt = admins.iterator();
+
+ while (adminIt.hasNext()) {
+ String admin = (String) adminIt.next();
+ try{
+ adminsEmails.add(um.getUserByUsername(admin).getEmail());
+ }catch(Exception e){
+ logger.error("User with username " + admin + " doesn't exist in Liferay");
+ adminIt.remove();
+ }
+ }
+
+ logger.info("The list of admins for group " + groupTitle + " is " + admins);
+
+ if(admins.isEmpty())
+ return;
+
+ // send the email
+ EmailNotification mailToSend = new EmailNotification(
+ adminsEmails,
+ PRODUCT_ASSOCIATED_TO_GROUP_SUBJECT.replace("$TITLE", datasetTitle).replace("$GROUP", groupTitle),
+ PRODUCT_ASSOCIATED_TO_GROUP_BODY.replace("$TITLE", datasetTitle).replace("$GROUP", groupTitle).replace("$USER_FULLNAME", userFullName),
+ request);
+ mailToSend.sendEmail();
+
+ }else
+ logger.warn("It seems there is no user with role Admin in group " + groupTitle);
+ }
+}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/WritePostCatalogueManagerThread.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/threads/WritePostCatalogueManagerThread.java
similarity index 87%
rename from src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/WritePostCatalogueManagerThread.java
rename to src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/threads/WritePostCatalogueManagerThread.java
index 21198c3..ab708a0 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/WritePostCatalogueManagerThread.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/threads/WritePostCatalogueManagerThread.java
@@ -1,12 +1,8 @@
-package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
+package org.gcube.portlets.widgets.ckandatapublisherwidget.server.threads;
-import static org.gcube.common.authorization.client.Constants.authorizationService;
-
-import java.util.ArrayList;
import java.util.List;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.Utils;
import org.slf4j.Logger;
@@ -58,7 +54,12 @@ public class WritePostCatalogueManagerThread extends Thread {
try{
// evaluate user's token for this scope
- String token = authorizationService().generateUserToken(new UserInfo(username, new ArrayList()), scope);
+ String token = Utils.tryGetElseCreateToken(username, scope);
+
+ if(token == null){
+ logger.warn("Unable to proceed, user's token is not available");
+ return;
+ }
logger.info("Started request to write application post "
+ "for new product created. Scope is " + scope + " and "
@@ -80,10 +81,8 @@ public class WritePostCatalogueManagerThread extends Thread {
}catch(Exception e){
logger.error("Failed to write the post because of the following error ", e);
}finally{
- // remove token and scope
SecurityTokenProvider.instance.reset();
ScopeProvider.instance.reset();
}
}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/Utils.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/Utils.java
index 938ca73..7347953 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/Utils.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/Utils.java
@@ -1,5 +1,7 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils;
+import static org.gcube.common.authorization.client.Constants.authorizationService;
+
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -11,7 +13,9 @@ import java.util.Map;
import javax.servlet.http.HttpSession;
import org.gcube.application.framework.core.session.ASLSession;
+import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem;
@@ -479,4 +483,28 @@ public class Utils {
return toReturn;
}
+
+ /**
+ * First check to retrieve the token, else create it
+ * @param username
+ * @param context
+ * @return the user token for the context
+ */
+ public static String tryGetElseCreateToken(String username, String context) {
+ String token = null;
+ try{
+ try{
+ logger.debug("Checking if token for user " + username + " in context " + context + " already exists...");
+ token = authorizationService().resolveTokenByUserAndContext(username, context);
+ logger.debug("It exists!");
+ }catch(ObjectNotFound e){
+ logger.info("Creating token for user " + username + " and context " + context);
+ token = authorizationService().generateUserToken(new UserInfo(username, new ArrayList()), context);
+ logger.debug("received token: "+ token.substring(0, 5) + "***********************");
+ }
+ }catch(Exception e){
+ logger.error("Failed both token retrieval and creation", e);
+ }
+ return token;
+ }
}
\ No newline at end of file
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 57aa4bb..bad7378 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
@@ -180,7 +180,7 @@ public class WorkspaceUtils {
}
/**
- * Replaces the "/" char with a custom one
+ * Replaces the "/" char with a custom one and return an editable name for the user
* @param rootElem
* @param pathSeparatorInWs
*/
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/GroupBean.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/GroupBean.java
index 7a202ad..d7aae98 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/GroupBean.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/GroupBean.java
@@ -41,5 +41,11 @@ public class GroupBean implements Serializable {
public void setGroupName(String groupName) {
this.groupName = groupName;
}
-
+
+ @Override
+ public String toString() {
+ return "GroupBean [groupTitle=" + groupTitle + ", groupName="
+ + groupName + "]";
+ }
+
}