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
This commit is contained in:
Costantino Perciante 2016-06-06 15:24:52 +00:00
parent 66fd421732
commit 1e95f70f5f
14 changed files with 787 additions and 232 deletions

View File

@ -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

View File

@ -1,4 +0,0 @@
Manifest-Version: 1.0
Implementation-Title: Gwt-Tour
Implementation-Version: 2.0.0-SNAPSHOT

View File

@ -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

12
pom.xml
View File

@ -56,6 +56,11 @@
</dependencyManagement>
<dependencies>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
@ -150,10 +155,15 @@
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.dataaccess</groupId>
<artifactId>ckan-util-library</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId>
<scope>runtime</scope>
<scope>compile</scope>
<!-- put at provided for deploying -->
</dependency>
<dependency>

View File

@ -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));
}
}

View File

@ -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, <b>null</b> 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, <b>null</b> 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 <b>true</b> on success, <b>false</b> otherwise
*/
boolean createCKanDataset(DatasetMetadataBean toCreate);
}

View File

@ -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, <b>null</b> on error.
*/
void getLicenses(AsyncCallback<LicensesBean> callback);
/**
* Retrieve a partially filled bean given a folder id and its owner.
* @param folderId
* @param owner
* @return @return a DatasetMetadataBean on success, <b>null</b> on error.
*/
void getDatasetBean(String folderId, String owner,
AsyncCallback<DatasetMetadataBean> callback);
/**
* Try to create such dataset starting from the information contained into the toCreate bean.
* @param toCreate
* @return <b>true</b> on success, <b>false</b> otherwise
*/
void createCKanDataset(DatasetMetadataBean toCreate,
AsyncCallback<Boolean> callback);
}

View File

@ -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){

View File

@ -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<String> tagsList = new ArrayList<String>();
@ -84,22 +90,122 @@ public class EditMetadataForm extends Composite{
private final HandlerManager eventBus = new HandlerManager(null);
// added custom field entries
List<CustomFieldEntry> customFieldEntries = new ArrayList<CustomFieldEntry>();
List<CustomFieldEntry> customFieldEntriesList = new ArrayList<CustomFieldEntry>();
// 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<DatasetMetadataBean>() {
@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<String> 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<LicensesBean>() {
@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<DatasetMetadataBean>() {
@ -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<String> organizations = bean.getOrganizationList();
for (String organization : organizations) {
organizationsListbox.addItem(organization);
}
// retrieve custom fields
Map<String, String> customFieldsMap = bean.getCustomFields();
if(customFields != null){
GWT.log("Custom fields is " + customFieldsMap);
if(customFieldsMap != null){
// get the keys and put them as tags
Iterator<Entry<String, String>> 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<String, String> customFieldsMap = new HashMap<String, String>();
// 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<Boolean>() {
@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

View File

@ -93,8 +93,9 @@
Tags:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="Enter one or more tag for the dataset"
b:id="tags" ui:field="tagsEnterTextBox" />
<b:TextBox alternateSize="LARGE"
placeholder="Enter one or more tag for the dataset" b:id="tags"
ui:field="tagsEnterTextBox" />
</b:Controls>
</b:ControlGroup>
@ -151,16 +152,14 @@
</b:Controls>
</b:ControlGroup>
<!-- <b:ControlGroup> -->
<!-- <b:ControlLabel for="source" title="Dataset source"> -->
<!-- Source: -->
<!-- </b:ControlLabel> -->
<!-- <b:Controls> -->
<!-- <b:TextBox alternateSize="LARGE" -->
<!-- placeholder="http://example.com/dataset.json" b:id="source" -->
<!-- title="Dataset source" ui:field="sourceTextbox" /> -->
<!-- </b:Controls> -->
<!-- </b:ControlGroup> -->
<b:ControlGroup>
<b:ControlLabel for="organization" title="Organizations">Publish in:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="organization" alternateSize="LARGE"
title="Publish in this organization" ui:field="organizationsListbox">
</b:ListBox>
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="version" title="Dataset version">
@ -234,6 +233,25 @@
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:Controls>
<b:CheckBox
title="Automatically add the folder content to the dataset as resource"
checked="true" ui:field="addResourcesCheckBox">
<b>Add folder content as resources</b>
</b:CheckBox>
<span style="float:right; width:256px; color: #aaaaaa;">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" />
Automatically add folder' files as resources of the dataset
</span>
</b:Controls>
</b:ControlGroup>
<!-- Alert block on create -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="onCreateAlertBlock" styleName="{style.block-alert-style}">
</b:AlertBlock>
<b:Button title="Create dataset" ui:field="createButton"
type="PRIMARY" block="true">Create</b:Button>

View File

@ -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<String> 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<CkanOrganization> 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<String> orgsName = new ArrayList<String>();
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<CkanLicense> 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<String> result = new ArrayList<String>();
CheckedCkanClient checkedClient = new CheckedCkanClient(ckanPortalUrl, apiKey);
CkanClient client = new CkanClient(ckanPortalUrl);
//retrieve the list of available licenses
List<CkanLicense> licenses = checkedClient.getLicenseList();
List<CkanLicense> 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<String, String> 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<String, String> folderItems = getGcubeItemProperties(retrievedItem);
bean.setCustomFields(folderItems);
// check the resources within the folder (skip subdirectories)
List<String> childrenIds = new ArrayList<String>();
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<String, String> folderItems = new HashMap<String, String>();
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<String, String> folderItems = getGcubeItemProperties(retrievedItem);
bean.setCustomFields(folderItems);
// check the resources within the folder (skip subdirectories)
List<String> childrenIds = new ArrayList<String>();
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<CkanTag> ckanTags = new ArrayList<CkanTag>(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<Entry<String, String>> iterator = toCreate.getCustomFields().entrySet().iterator();
List<CkanPair> extras = new ArrayList<CkanPair>(toCreate.getCustomFields().entrySet().size());
while (iterator.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) 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<CkanResource> resources = new ArrayList<CkanResource>();
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;
}
}

View File

@ -18,6 +18,8 @@ import java.util.Map;
* <li> version -> during creation it is going to be 1.0
* <li> author, maintainer -> folder's owner
* <li> custom fields -> gcube items <key, value> couple
* <li> organizationsList -> list of organizations to which the user belong (and in which
* he wants to publish)
* </ul>
* @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<String> organizationList; // list of organization in which the user is present and could create the dataset
private String selectedOrganization;
private List<String> 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<String, String> customFields, String license, boolean visibility,
boolean searchable, String source, long version, String author,
String authorEmail, String maintainer, String maintainerEmail) {
Map<String, String> customFields, List<String> tags,
String license, boolean visibility, boolean searchable,
String source, long version, String author, String authorEmail,
String maintainer, String maintainerEmail,
String ownerFolderInWorkspace, List<String> 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<String> getOrganizationList() {
return organizationList;
}
public void setOrganizationList(List<String> organizationList) {
this.organizationList = organizationList;
}
public String getSelectedOrganization() {
return selectedOrganization;
}
public void setSelectedOrganization(String selectedOrganization) {
this.selectedOrganization = selectedOrganization;
}
public List<String> getResourcesIds() {
return resourcesIds;
}
public void setResourcesIds(List<String> 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 + "]";
}
}

View File

@ -10,7 +10,6 @@
<set-property name="bootstrap.responsiveDesign" value="true" />
<inherits name='org.gcube.portlets.user.gcubewidgets.WidgetFactory' />
<inherits name="org.gcube.portlets.user.workspace.WorkspaceTree" />
<!-- Specify the app entry point class. -->
<entry-point

View File

@ -1,67 +1,52 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.homelibrary.home.HomeLibrary;
import org.gcube.common.homelibrary.home.exceptions.HomeNotFoundException;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.exceptions.UserNotFoundException;
import org.gcube.common.homelibrary.home.workspace.Workspace;
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
import org.gcube.common.homelibrary.home.workspace.exceptions.ItemNotFoundException;
import org.gcube.common.homelibrary.home.workspace.exceptions.WorkspaceFolderNotFoundException;
import eu.trentorise.opendata.jackan.CheckedCkanClient;
import eu.trentorise.opendata.jackan.CkanClient;
import eu.trentorise.opendata.jackan.model.CkanUser;
import org.gcube.common.scope.api.ScopeProvider;
import org.junit.Test;
public class Tests {
//@Test
public static void test() throws WorkspaceFolderNotFoundException, InternalErrorException, HomeNotFoundException, UserNotFoundException {
public void test() throws WorkspaceFolderNotFoundException, InternalErrorException, HomeNotFoundException, UserNotFoundException, ItemNotFoundException{
// String username ="costantino.perciante";
// ScopeProvider.instance.set("/gcube/devsec/devVRE");
//
// Workspace ws = HomeLibrary
// .getHomeManagerFactory()
// .getHomeManager()
// .getHome(username).getWorkspace();
//
// System.out.println("Created workspace reference");
//
// WorkspaceFolder rootFolder = ws.getRoot();
// System.out.println("Root folder has id " + rootFolder.getId());
//
// List<WorkspaceItem> 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<WorkspaceItem> childrens = ws.getRoot().getChildren();
for (WorkspaceItem workspaceItem : childrens) {
if(workspaceItem.getName().equals("CkanTest1137")){
System.out.println("Dir has id " + workspaceItem.getId());
List<? extends WorkspaceItem> 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<String> result = new ArrayList<String>();
CheckedCkanClient checkedClient = new CheckedCkanClient(ckanPortalUrl, apiKey);
CkanClient client = new CkanClient(ckanPortalUrl);
List<CkanUser> 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());
}
}