feature_23491
Francesco Mangiacrapa 3 years ago
parent 1f741268fb
commit be42e8ad2f

@ -6,13 +6,7 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
@ -25,8 +19,8 @@
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
@ -34,5 +28,6 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

@ -12,7 +12,7 @@
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
<property name="context-root" value="ckan-metadata-publisher-widget"/>
<property name="java-output-path" value="/ckan-metadata-publisher-widget/target/ckan-metadata-publisher-widget-1.0.0-SNAPSHOT/WEB-INF/classes"/>

@ -0,0 +1,7 @@
<root>
<facet id="jst.jaxrs">
<node name="libprov">
<attribute name="provider-id" value="jaxrs-no-op-library-provider"/>
</node>
</facet>
</root>

@ -4,4 +4,5 @@
<installed facet="jst.web" version="2.3"/>
<installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.jaxrs" version="2.0"/>
</faceted-project>

@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.0.0-SNAPSHOT] - 2021-02-11
**Enhancements**
[#19764] Porting ckan-metadata-publisher-widget to catalogue-util-library
[#20680] Ported to SHUB
[#19568] Unify and extend the tags allowed values
[#20828] Revisited title size and format
[#20868] Redesigned the "Manage Resources" user experience
[#21068] Add Resources facility: only HTTPS URLs must be allowed
## [v1.6.2] - 2021-02-08
**Bug Fixes**

@ -13,7 +13,7 @@
<groupId>org.gcube.portlets.widgets</groupId>
<artifactId>ckan-metadata-publisher-widget</artifactId>
<version>1.6.2</version>
<version>2.0.0-SNAPSHOT</version>
<name>gCube Ckan metadata publisher widget</name>
<description>

@ -9,13 +9,14 @@
<set-property name="bootstrap.responsiveDesign" value="true" />
<inherits name='com.github.gwtbootstrap.datetimepicker.Datetimepicker' />
<inherits name='com.github.gwtbootstrap.datepicker.Datepicker' />
<inherits name='org.gcube.datacatalogue.ckanutillibrary.CkanUtilLibrary' />
<inherits name='org.gcube.datacatalogue.utillibrary.CkanUtilLibrary' />
<inherits name='org.gcube.portlets.user.gcubewidgets.WidgetFactory' />
<inherits name='com.google.gwt.json.JSON'/>
<inherits
name='org.gcube.portlets.widgets.openlayerbasicwidgets.olbasicwidgets' />
<inherits name='org.gcube.portlets.widgets.openlayerbasicwidgets.olbasicwidgets' />
<inherits name='org.gcube.portlets.widgets.wsexplorer.WorkspaceExplorer' />
<!-- Specify the app entry point class. -->
<entry-point

@ -4,9 +4,9 @@ import java.util.ArrayList;
import java.util.List;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.openlayerwidget.GeoJsonAreaSelectionDialog;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection.TwinColumnSelectionMainPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.form.CreateDatasetForm;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.metadata.MetaDataFieldSkeleton;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace.SelectResourceByWEMainPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.DataTypeWrapper;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.MetadataFieldWrapper;
@ -51,6 +51,8 @@ public class CKanMetadataPublisher implements EntryPoint {
// startTwinColumn();
//testSpatialWidget();
//testManageResources();
}
@ -256,38 +258,28 @@ public class CKanMetadataPublisher implements EntryPoint {
// test resources
@SuppressWarnings("unused")
private void startTwinColumn() {
TwinColumnSelectionMainPanel resourcesTwinPanel;
private void testManageResources() {
Modal m = new Modal();
m.setTitle("Title ......");
m.setWidth("1200px");
m.getElement().getStyle().setMarginLeft(-30, Unit.PCT);
ResourceElementBean r = new ResourceElementBean();
r.setFolder(true);
r.setName("Root");
r.setFolder(false);
r.setName("Mangiacrapra_Introducing_myself.pptx");
r.setParent(null);
r.setChildrenSize(5);
r.setOriginalIdInWorkspace("8489e2ab-7487-404f-97ff-5aecc35c241f");
ResourceElementBean parent = new ResourceElementBean();
parent.setOriginalIdInWorkspace("91409eba-0bf6-4aa5-8d73-3536bf181587");
r.setParent(parent);
List<ResourceElementBean> children = new ArrayList<ResourceElementBean>();
SelectResourceByWEMainPanel resourcesSelectByWEMainPanel = new SelectResourceByWEMainPanel(r);
// random strings
for (int i = 0; i < 10; i++) {
ResourceElementBean child = new ResourceElementBean();
child.setFolder(false);
child.setName("BLUE_ECONOMY_WP6_TECHNO_ECONOMIC_ANALYSIS_MODEL.CITE.PPTX" + i);
child.setEditableName("BLUE_ECONOMY_WP6_TECHNO_ECONOMIC_ANALYSIS_MODEL.CITE.PPTX" + i);
child.setParent(r);
child.setFullPath("/" + "BLUE_ECONOMY_WP6_TECHNO_ECONOMIC_ANALYSIS_MODEL.CITE.PPTX" + + i);
children.add(child);
}
r.setChildren(children);
// create random childs
resourcesTwinPanel = new TwinColumnSelectionMainPanel(r);
m.add(resourcesTwinPanel);
m.add(resourcesSelectByWEMainPanel);
m.show();
}

@ -1,46 +0,0 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.icons.Images;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.Image;
/**
* Cell that renders left side panel objects
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class ResourceCellLeft extends AbstractCell<ResourceElementBean>{
private static final Images image = GWT.create(Images.class);
private static final String tipFile = "Hold down the Control (ctrl) or Command button to select multiple options";
private static final String tipFolder = "Click on the folder to navigate it";
@Override
public void render(com.google.gwt.cell.client.Cell.Context context,
ResourceElementBean value, SafeHtmlBuilder sb) {
if (value == null || value.isToBeAdded()) {
return;
}
Image file = new Image(image.fileIcon());
Image folder = new Image(image.folderIcon());
file.setWidth("15px");
file.setHeight("15px");
folder.setWidth("15px");
folder.setHeight("15px");
String whichTip = value.isFolder() ? tipFolder : tipFile;
sb.appendHtmlConstant("<div title='" + value.getName() + "( " + whichTip + " )" + "' style='overflow-x:hidden;white-space:nowrap;text-overflow:ellipsis;max-width:240px; min-height:30px; padding-top:5px;'>");
sb.appendHtmlConstant("<span style='margin-left:5px;'>");
sb.appendHtmlConstant(value.isFolder() ? folder.toString() : file.toString());
sb.appendHtmlConstant("</span>");
sb.appendHtmlConstant("<span style='margin-left:10px;'>");
sb.appendHtmlConstant("<b>");
sb.appendEscaped(value.getName());
sb.appendHtmlConstant("</b>");
sb.appendHtmlConstant("</span>");
sb.appendHtmlConstant("</div>");
}
}

@ -1,65 +0,0 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.icons.Images;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.Image;
/**
* Cell that renders right side panel objects
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class ResourceCellRight extends AbstractCell<ResourceElementBean>{
private static final Images image = GWT.create(Images.class);
private static final String tip = "Hold down the Control (CTRL) or Command button to select multiple options. Double click to access "
+ "this resource information";
public ResourceCellRight() {
super("keydown", "dblclick");
}
@Override
public void render(com.google.gwt.cell.client.Cell.Context context,
ResourceElementBean value, SafeHtmlBuilder sb) {
if (value == null || !value.isToBeAdded() || value.isFolder()) {
return;
}
Image file = new Image(image.fileIcon());
file.setWidth("15px");
file.setHeight("15px");
sb.appendHtmlConstant("<div title='" + value.getName() + "( " + tip + " )" + "' style='overflow-x:hidden;white-space:nowrap;text-overflow:ellipsis;max-width:240px; min-height:30px; padding-top:5px;'>");
sb.appendHtmlConstant("<span style='margin-left:5px'>");
sb.appendHtmlConstant(file.toString());
sb.appendHtmlConstant("</span>");
sb.appendHtmlConstant("<span style='margin-left:10px'>");
sb.appendHtmlConstant("<b>");
sb.appendEscaped(value.getEditableName());
sb.appendHtmlConstant("</b>");
sb.appendHtmlConstant("</span>");
sb.appendHtmlConstant("</div>");
}
@Override
public void onBrowserEvent(com.google.gwt.cell.client.Cell.Context context,
Element parent, ResourceElementBean value, NativeEvent event,
ValueUpdater<ResourceElementBean> valueUpdater) {
if(value == null || TwinColumnSelectionMainPanel.isFroozen())
return;
super.onBrowserEvent(context, parent, value, event, valueUpdater);
ResourceInfoForm info = new ResourceInfoForm(value, valueUpdater);
if(TwinColumnSelectionMainPanel.detailContainer.getWidget() != null)
TwinColumnSelectionMainPanel.detailContainer.clear();
TwinColumnSelectionMainPanel.detailContainer.add(info);
TwinColumnSelectionMainPanel.detailContainer.setVisible(true);
}
}

@ -1,88 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.legend-style {
width: 100%;
padding: 10px;
margin-bottom: 0px;
font-size: 14px;
}
.panel-style {
padding: 5px;
border: 1px solid #bbb;
border-radius: 5px;
height: 400px;
width: 95%;
}
.labels-style {
color: #999;
}
.controls-style {
margin-left: 10px !important;
}
.control-group {
margin-bottom: 0px !important;
}
</ui:style>
<g:HTMLPanel styleName="{style.panel-style}">
<b:Form type="VERTICAL" width="100%">
<!-- <b:Fieldset styleName="{style.fieldset-border-style}"> -->
<b:Legend styleName="{style.legend-style}">
<b>Resource Information</b>
<b:Button ui:field="closeButton" type="LINK" title="Close details"></b:Button>
</b:Legend>
<b:ControlGroup ui:field="controlName" styleName="{style.control-group}">
<b:ControlLabel for="name" styleName="{style.labels-style}"
title="The name the resource will have on the catalogue">
<b>Name:</b>
</b:ControlLabel>
<b:Controls styleName="{style.controls-style}">
<b:TextBox placeholder="Resource name" b:id="name"
enabled="true" title="The name the resource will have on the catalogue"
ui:field="resourceName" />
</b:Controls>
</b:ControlGroup>
<b:ControlGroup styleName="{style.control-group}">
<b:ControlLabel for="path" title="Resource path"
styleName="{style.labels-style}">
<b>Path:</b>
</b:ControlLabel>
<b:Controls styleName="{style.controls-style}">
<b:TextBox placeholder="Resource path" b:id="path"
readOnly="true" title="Resource path" ui:field="resourcePath" />
</b:Controls>
</b:ControlGroup>
<b:ControlGroup styleName="{style.control-group}">
<b:ControlLabel for="description" styleName="{style.labels-style}"
title="The description the resource will have on the catalogue">
<b>Description:</b>
</b:ControlLabel>
<b:Controls styleName="{style.controls-style}">
<b:TextArea placeholder="Resource description" b:id="description"
title="The description the resource will have on the catalogue"
ui:field="resourceDescription"></b:TextArea>
</b:Controls>
</b:ControlGroup>
<b:ControlGroup styleName="{style.control-group}">
<b:ControlLabel for="format" styleName="{style.labels-style}"
title="The MIME type">
<b>Format:</b>
</b:ControlLabel>
<b:Controls styleName="{style.controls-style}">
<b:TextBox placeholder="Resource format" b:id="format"
title="The MIME type" ui:field="resourceFormat" readOnly="true" />
</b:Controls>
</b:ControlGroup>
<g:HorizontalPanel width="100%" ui:field="commandPanel">
<!-- <b:Button ui:field="cancelButton">Cancel</b:Button> -->
<b:Button ui:field="updateResourceButton" type="PRIMARY">Update</b:Button>
</g:HorizontalPanel>
<!-- </b:Fieldset> -->
</b:Form>
</g:HTMLPanel>
</ui:UiBinder>

@ -1,101 +0,0 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.cellview.client.AbstractPager;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.HasRows;
/**
* Basically a scroll panel
* Partially changed from the code at http://samples.gwtproject.org/samples/Showcase/Showcase.html#!CwCellList
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class ShowMorePagerPanel extends AbstractPager{
/**
* The default increment size.
*/
public static final int DEFAULT_INCREMENT = 10;
/**
* The increment size.
*/
private int incrementSize = DEFAULT_INCREMENT;
/**
* The last scroll position.
*/
private int lastScrollPos = 0;
/**
* The scrollable panel.
*/
private final ScrollPanel scrollable = new ScrollPanel();
/**
* Construct a new {@link ShowMorePagerPanel}.
*/
public ShowMorePagerPanel() {
initWidget(scrollable);
// Do not let the scrollable take tab focus.
scrollable.getElement().setTabIndex(-1);
// Handle scroll events.
scrollable.addScrollHandler(new ScrollHandler() {
public void onScroll(ScrollEvent event) {
// If scrolling up, ignore the event.
int oldScrollPos = lastScrollPos;
lastScrollPos = scrollable.getVerticalScrollPosition();
if (oldScrollPos >= lastScrollPos) {
return;
}
HasRows display = getDisplay();
if (display == null) {
return;
}
int maxScrollTop = scrollable.getWidget().getOffsetHeight()
- scrollable.getOffsetHeight();
if (lastScrollPos >= maxScrollTop) {
// We are near the end, so increase the page size.
int newPageSize = Math.min(
display.getVisibleRange().getLength() + incrementSize,
display.getRowCount());
display.setVisibleRange(0, newPageSize);
}
}
});
}
/**
* Get the number of rows by which the range is increased when the scrollbar
* reaches the bottom.
* @return the increment size
*/
public int getIncrementSize() {
return incrementSize;
}
@Override
public void setDisplay(HasRows display) {
assert display instanceof Widget : "display must extend Widget";
scrollable.setWidget((Widget) display);
super.setDisplay(display);
}
/**
* Set the number of rows by which the range is increased when the scrollbar
* reaches the bottom.
* @param incrementSize the incremental number of rows
*/
public void setIncrementSize(int incrementSize) {
this.incrementSize = incrementSize;
}
@Override
protected void onRangeOrRowCountChanged() {
}
}

@ -1,571 +0,0 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import com.github.gwtbootstrap.client.ui.Breadcrumbs;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.FluidContainer;
import com.github.gwtbootstrap.client.ui.NavLink;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.BorderStyle;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.HasKeyboardPagingPolicy.KeyboardPagingPolicy;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
/**
* The twin column panels for selection of the files to attach to the catalague product.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Francesco Mangiacrapa at ISTI-CNR
*/
public class TwinColumnSelectionMainPanel extends Composite{
@UiField
VerticalPanel leftContainer;
@UiField
VerticalPanel rightContainer;
@UiField
VerticalPanel buttonsPanel;
@UiField
Button allToRightButton;
@UiField
Button toRightButton;
@UiField
Button toLeftButton;
@UiField
Button allToLeftButton;
// @UiField
// Popover popoverResourceSelection;
// @UiField
// Button resourceInfoButton;
@UiField
Breadcrumbs breadcrumbs;
@UiField
FluidContainer mainContainerResourcesSelection;
// @UiField
// Button getResources;
@UiField
public static SimplePanel detailContainer;
/**
* The breadcrumb subpath with the linked folder
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
private class PathBean{
NavLink link;
ResourceElementBean resourceFolder;
PathBean(NavLink link, ResourceElementBean resourceFolder){
this.link = link;
this.resourceFolder = resourceFolder;
}
}
private static boolean frozen = false;
private List<PathBean> pathListBeans = new ArrayList<PathBean>();
private static final String PANEL_BORDER_COLOR = "#8899a6";
private static final String PANEL_HEIGHT = "400px";
private ShowMorePagerPanel showMorePanelLeft = new ShowMorePagerPanel();
private ShowMorePagerPanel showMorePanelRight = new ShowMorePagerPanel();
private CellList<ResourceElementBean> cellListLeft;
private CellList<ResourceElementBean> cellListRight;
private ListDataProvider<ResourceElementBean> dataProviderLeft = new ListDataProvider<ResourceElementBean>();
private ListDataProvider<ResourceElementBean> dataProviderRight = new ListDataProvider<ResourceElementBean>();
private MultiSelectionModel<ResourceElementBean> selectionModelRight;
private MultiSelectionModel<ResourceElementBean> selectionModelLeft;
private final ResourceElementBean initialBean;
// private final static HTML aboutHeader = new HTML("<b>Resource Manager</b>");
// private final static HTML aboutBody = new HTML("<p style='text-align:justify;'>Move the files you want to attach to the product on the right panel below."
// + " Please consider that any complex hierarchy structure you may have will be flatten.</p>");
// private static final short PATH_THRESHOLD = 1; // TODO
private static TwinColumnSelectionMainPanelUiBinder uiBinder = GWT
.create(TwinColumnSelectionMainPanelUiBinder.class);
interface TwinColumnSelectionMainPanelUiBinder extends
UiBinder<Widget, TwinColumnSelectionMainPanel> {
}
public TwinColumnSelectionMainPanel(ResourceElementBean initialBean) {
initWidget(uiBinder.createAndBindUi(this));
frozen = false;
GWT.log(initialBean.toString());
this.initialBean = initialBean;
buttonsPanel.getElement().getStyle().setMarginTop(50, Unit.PCT);
allToRightButton.getElement().getStyle().setMarginBottom(4, Unit.PX);
toRightButton.getElement().getStyle().setMarginBottom(4, Unit.PX);
toLeftButton.getElement().getStyle().setMarginBottom(4, Unit.PX);
allToLeftButton.getElement().getStyle().setMarginBottom(4, Unit.PX);
buttonsPanel.getElement().setAttribute("align", "center");
// popoverResourceSelection.setPlacement(Placement.LEFT);
// popoverResourceSelection.setHeading(aboutHeader.getHTML());
// popoverResourceSelection.setText(aboutBody.getHTML());
// resourceInfoButton.getElement().getStyle().setFloat(Float.RIGHT);
// resourceInfoButton.getElement().getStyle().setPaddingRight(0, Unit.PX);
mainContainerResourcesSelection.getElement().getStyle().setPadding(10, Unit.PX);
breadcrumbs.getElement().getStyle().setBackgroundColor("white");
breadcrumbs.getElement().getStyle().setFontWeight(FontWeight.BOLD);
breadcrumbs.getElement().getStyle().setMarginLeft(0, Unit.PX);
mainContainerResourcesSelection.getElement().getStyle().setMarginLeft(10, Unit.PX);
mainContainerResourcesSelection.getElement().getStyle().setMarginBottom(20, Unit.PX);
mainContainerResourcesSelection.getElement().getStyle().setMarginTop(0, Unit.PX);
prepareHandlers();
initLeftSidePanel(initialBean);
initRightSidePanel();
}
/**
* Initialize the left side panel
*/
private void initLeftSidePanel(final ResourceElementBean initialBean) {
// initialize the left side list
ResourceCellLeft cell = new ResourceCellLeft();
// Set a key provider that provides a unique key for each object.
cellListLeft = new CellList<ResourceElementBean>(cell, ResourceElementBean.KEY_PROVIDER);
cellListLeft.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE);
// set page size
int size = initialBean.isFolder() ? initialBean.getChildren().size() : 1;
cellListLeft.setPageSize(size);
// Add a selection model so we can select cells.
selectionModelLeft = new MultiSelectionModel<ResourceElementBean>(ResourceElementBean.KEY_PROVIDER);
cellListLeft.setSelectionModel(selectionModelLeft);
// perform an action on selection
selectionModelLeft.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
if(frozen)
return;
Iterator<ResourceElementBean> selectedObjectsIterator = selectionModelLeft.getSelectedSet().iterator();
while (selectedObjectsIterator.hasNext()) {
ResourceElementBean selectedBean = selectedObjectsIterator.next();
if(selectedBean.isFolder()){
// a single folder selected
if(selectionModelLeft.getSelectedSet().size() == 1){
// update path
final NavLink navElem = new NavLink(selectedBean.getName());
navElem.getElement().getStyle().setFontWeight(FontWeight.BOLD);
final PathBean pathBean = new PathBean(navElem, selectedBean);
navElem.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
removeStartingFromBreadcrumbs(navElem, pathBean);
GWT.log("Clicked on element " + pathBean.resourceFolder.getName());
//breadcrumbsUpdater();
ResourceElementBean folder = pathBean.resourceFolder;
Collections.sort(folder.getChildren());
dataProviderLeft.setList(folder.getChildren());
dataProviderLeft.refresh();
}
});
pathListBeans.add(pathBean);
breadcrumbs.add(navElem);
//breadcrumbsUpdater();
Collections.sort(selectedBean.getChildren());
GWT.log("Children " + selectedBean.getChildren());
dataProviderLeft.setList(selectedBean.getChildren());
cellListLeft.setPageSize(selectedBean.getChildren().size());
dataProviderLeft.refresh();
}
selectionModelLeft.setSelected(selectedBean, false);
}
}
// enable the buttons that allows to move the objects to the right
enableMoveToRightButtons(selectionModelLeft.getSelectedSet());
}
});
// set the list into the provider
if(initialBean.isFolder()){
Collections.sort(this.initialBean.getChildren());
dataProviderLeft.setList(this.initialBean.getChildren());
}else
dataProviderLeft.setList(Arrays.asList(this.initialBean));
// add root to breadcrumb
final NavLink root = new NavLink(initialBean.getName());
final PathBean pathBean = new PathBean(root, initialBean);
root.getElement().getStyle().setFontWeight(FontWeight.BOLD);
pathListBeans.add(pathBean);
breadcrumbs.add(root);
root.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
removeStartingFromBreadcrumbs(root, pathBean);
//breadcrumbsUpdater();
// set back the root content list
dataProviderLeft.setList(initialBean.getChildren());
cellListLeft.setPageSize(initialBean.getChildren().size());
dataProviderLeft.refresh();
}
});
// set the cell list into the provider
dataProviderLeft.addDataDisplay(cellListLeft);
// manage showMorePanelLeft
showMorePanelLeft.setDisplay(cellListLeft);
showMorePanelLeft.setHeight(PANEL_HEIGHT);
showMorePanelLeft.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
showMorePanelLeft.getElement().getStyle().setBorderWidth(2, Unit.PX);
showMorePanelLeft.getElement().getStyle().setBorderColor(PANEL_BORDER_COLOR);
// add the list to the leftContainerPanel
leftContainer.add(showMorePanelLeft);
}
/**
* Update the path
* @param navElem
* @param pathBean
*/
public void removeStartingFromBreadcrumbs(NavLink navElem, PathBean pathBean){
// remove data after
Iterator<Widget> iteratorBreadcrumb = breadcrumbs.iterator();
Iterator<PathBean> iteratorListPath = pathListBeans.iterator();
boolean delete = false;
while(iteratorBreadcrumb.hasNext()){
Widget current = iteratorBreadcrumb.next();
if(delete){
current.removeFromParent();
iteratorBreadcrumb.remove();
}
if(!delete && navElem.equals(current))
delete = true;
}
delete = false;
while(iteratorListPath.hasNext()){
PathBean current = iteratorListPath.next();
if(delete)
iteratorListPath.remove();
if(!delete && pathBean.equals(current))
delete = true;
}
}
/**
* Initialize the left side panel
*/
private void initRightSidePanel() {
// initialize the left side list
ResourceCellRight cell = new ResourceCellRight();
// Set a key provider that provides a unique key for each object.
cellListRight = new CellList<ResourceElementBean>(cell, ResourceElementBean.KEY_PROVIDER);
cellListRight.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE);
cellListRight.setValueUpdater(new ValueUpdater<ResourceElementBean>() {
@Override
public void update(ResourceElementBean value) {
// just redraw the list
cellListRight.redraw();
}
});
// Add a selection model so we can select cells.
selectionModelRight = new MultiSelectionModel<ResourceElementBean>(ResourceElementBean.KEY_PROVIDER);
cellListRight.setSelectionModel(selectionModelRight);
// perform an action on selection
selectionModelRight.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
if(frozen)
return;
enableMoveToLeftButtons(selectionModelRight.getSelectedSet());
}
});
// set the cell list into the provider
dataProviderRight.addDataDisplay(cellListRight);
// manage showMorePanelRight
showMorePanelRight.setDisplay(cellListRight);
showMorePanelRight.setHeight(PANEL_HEIGHT);
showMorePanelRight.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
showMorePanelRight.getElement().getStyle().setBorderWidth(2, Unit.PX);
showMorePanelRight.getElement().getStyle().setBorderColor(PANEL_BORDER_COLOR);
// add the list to the leftContainerPanel
rightContainer.add(showMorePanelRight);
}
/**
* Enable/disable the buttons to move objects from left to right properly.
* @param setselectedItemsLeft
*/
private void enableMoveToRightButtons(Set<ResourceElementBean> setselectedItemsLeft){
if(setselectedItemsLeft == null || setselectedItemsLeft.isEmpty()){
allToRightButton.setEnabled(false);
toRightButton.setEnabled(false);
}
else if(setselectedItemsLeft.size() > 1){
allToRightButton.setEnabled(true);
toRightButton.setEnabled(false);
}
else{
allToRightButton.setEnabled(false);
toRightButton.setEnabled(true);
}
}
/**
* Enable/disable the buttons to move objects from right to left properly.
* @param setselectedItemsRight
*/
private void enableMoveToLeftButtons(Set<ResourceElementBean> setselectedItemsRight){
if(setselectedItemsRight == null || setselectedItemsRight.isEmpty()){
allToLeftButton.setEnabled(false);
allToLeftButton.setEnabled(false);
}
else if(setselectedItemsRight.size() > 1){
allToLeftButton.setEnabled(true);
toLeftButton.setEnabled(false);
}
else{
allToLeftButton.setEnabled(false);
toLeftButton.setEnabled(true);
}
}
/**
* Prepare the buttons' handlers
*/
private void prepareHandlers() {
allToRightButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
moveToRight(selectionModelLeft.getSelectedSet());
}
});
toRightButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
moveToRight(selectionModelLeft.getSelectedSet());
}
});
allToLeftButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
moveToLeft(selectionModelRight.getSelectedSet());
}
});
toLeftButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
moveToLeft(selectionModelRight.getSelectedSet());
}
});
}
/**
* Move to right elements
* @param set the elements to move
*/
private void moveToRight(Set<ResourceElementBean> setSelected){
if(setSelected == null || setSelected.isEmpty())
return;
Iterator<ResourceElementBean> iterator = setSelected.iterator();
while (iterator.hasNext()) {
ResourceElementBean resourceElementBean = iterator
.next();
resourceElementBean.setToBeAdded(true);
int indexRight = dataProviderRight.getList().indexOf(resourceElementBean);
if(indexRight >= 0)
dataProviderRight.getList().set(indexRight, resourceElementBean);
else{
dataProviderRight.getList().add(resourceElementBean);
Collections.sort(dataProviderRight.getList());
dataProviderRight.refresh();
}
int indexLeft = dataProviderLeft.getList().indexOf(resourceElementBean);
dataProviderLeft.getList().set(indexLeft, resourceElementBean);
}
}
/**
* Move to left elements
* @param setSelected the elements to move
*/
private void moveToLeft(Set<ResourceElementBean> setSelected){
if(setSelected == null || setSelected.isEmpty())
return;
Iterator<ResourceElementBean> iterator = setSelected.iterator();
while (iterator.hasNext()) {
ResourceElementBean resourceElementBean = iterator.next();
resourceElementBean.setToBeAdded(false);
}
Collections.sort(dataProviderLeft.getList());
dataProviderLeft.refresh();
dataProviderRight.refresh();
}
/**
* Freeze the panel
*/
public void freeze() {
frozen = true;
Iterator<Widget> iteratorOverPath = breadcrumbs.iterator();
while (iteratorOverPath.hasNext()) {
Widget widget = iteratorOverPath.next();
if(widget instanceof NavLink)
((NavLink)widget).setActive(false);
}
allToRightButton.setEnabled(false);
toRightButton.setEnabled(false);
allToLeftButton.setEnabled(false);
toLeftButton.setEnabled(false);
}
/**
* Returns the root parent with the children as files to save
* @return the resources to save
*/
public ResourceElementBean getResourcesToPublish(){
List<ResourceElementBean> current = dataProviderRight.getList();
ResourceElementBean toReturn = new ResourceElementBean();
List<ResourceElementBean> children = new ArrayList<ResourceElementBean>();
for (ResourceElementBean resource : current) {
if(resource.isToBeAdded() && !resource.isFolder()){ // be sure ...
ResourceElementBean beanWithoutChildren = new ResourceElementBean(resource);
beanWithoutChildren.setName(resource.getEditableName());
children.add(beanWithoutChildren);
}
}
toReturn.setChildren(children);
return toReturn;
}
/**
* @return the freezed
*/
public static boolean isFroozen() {
return frozen;
}
// @UiHandler("getResources")
// void getResources(ClickEvent ce){
// getResourcesToPublish();
// }
//
// /**
// * Short the current path if needed
// */
// private void breadcrumbsUpdater(){
//
// // ignore first and last elem
// boolean reduce = (pathListBeans.size() - 2) > PATH_THRESHOLD;
//
// GWT.log("Is to reduce? " + reduce);
//
// GWT.log("Full size is " + pathListBeans.size());
//
// if(!reduce){
// GWT.log("Restore");
// for(int i = 0; i < pathListBeans.size(); i++){
// PathBean bean = pathListBeans.get(i);
// GWT.log("Elem is " + bean.resourceFolder);
// bean.link.setText(bean.resourceFolder.getName());
// bean.link.setVisible(true);
// }
// }else{
// for(int i = 1; i < pathListBeans.size(); i++){
// PathBean bean = pathListBeans.get(i);
//
// if(i == (pathListBeans.size() - 1)){
// bean.link.setText(bean.resourceFolder.getName());
// bean.link.setVisible(true);
// }else if(i == (pathListBeans.size() - 2)){
// GWT.log("The last to modify ****" + bean.resourceFolder.getName());
// bean.link.setText("...");
// bean.link.setVisible(true);
// }else{
// bean.link.setText(bean.resourceFolder.getName());
// bean.link.setVisible(false);
// }
// }
// }
// GWT.log("Updated list is " + pathListBeans.toString());
// }
}

@ -1,58 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:m="urn:import:org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection">
<ui:style>
</ui:style>
<g:HTMLPanel>
<b:FluidContainer ui:field="mainContainerResourcesSelection">
<!-- <b:FluidRow> -->
<!-- <b:Column offset="6" size="1"> -->
<!-- <b:Popover ui:field="popoverResourceSelection" html="true"> -->
<!-- <b:Button ui:field="resourceInfoButton" type="LINK" icon="INFO_SIGN" -->
<!-- size="LARGE"></b:Button> -->
<!-- </b:Popover> -->
<!-- </b:Column> -->
<!-- </b:FluidRow> -->
<b:FluidRow>
<b:Column size="11">
<b:Breadcrumbs ui:field="breadcrumbs" divider=">"
title="Current path">
</b:Breadcrumbs>
</b:Column>
</b:FluidRow>
<b:FluidRow>
<b:Column size="3" ui:field="leftColumn">
<!-- <b:Button enabled="true" type="LINK" ui:field="goRootButton">Root
level</b:Button> -->
<!-- <b:Button enabled="true" type="LINK" ui:field="goUpButton">Go up</b:Button> -->
<g:VerticalPanel ui:field="leftContainer" width="100%">
</g:VerticalPanel>
</b:Column>
<b:Column size="1" ui:field="centralPanel">
<g:VerticalPanel ui:field="buttonsPanel">
<b:Button ui:field="allToRightButton" name="toRight"
enabled="false" title="Add selected files" text=">>" />
<b:Button ui:field="toRightButton" name="toRight"
enabled="false" title="Add selected file" text=">" />
<b:Button ui:field="toLeftButton" name="toLeft" enabled="false"
title="Remove selected file" text="&lt;" />
<b:Button ui:field="allToLeftButton" name="toRight"
enabled="false" title="Remove selected files" text="&lt;&lt;" />
</g:VerticalPanel>
</b:Column>
<b:Column size="3" ui:field="rightColumn">
<g:VerticalPanel ui:field="rightContainer" width="100%"></g:VerticalPanel>
</b:Column>
<b:Column size="3" ui:field="detailColumn">
<g:SimplePanel ui:field="detailContainer" width="100%"></g:SimplePanel>
</b:Column>
<!-- <b:Column size="2"> -->
<!-- <m:ResourceInfoForm ui:field="resourceInfoForm"></m:ResourceInfoForm> -->
<!-- </b:Column> -->
</b:FluidRow>
</b:FluidContainer>
<!-- <b:Button ui:field="getResources">Get Resources</b:Button> -->
</g:HTMLPanel>
</ui:UiBinder>

@ -1,6 +1,7 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.form;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -15,7 +16,6 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.CloseCre
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.CloseCreationFormEventHandler;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEvent;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEventHandler;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection.TwinColumnSelectionMainPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.metadata.CategoryPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.metadata.CustomFieldEntry;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.metadata.MetaDataFieldSkeleton;
@ -24,6 +24,8 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.resources.Ad
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.resources.AddedResourcesSummary;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.tags.TagsPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.utils.InfoIconsLabels;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.utils.WizardCreator;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace.SelectResourceByWEMainPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.licenses.LicenseBean;
@ -45,6 +47,7 @@ import com.github.gwtbootstrap.client.ui.TextArea;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.constants.ControlGroupType;
import com.github.gwtbootstrap.client.ui.constants.ResizeType;
import com.github.gwtbootstrap.client.ui.resources.Bootstrap.Tabs;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SelectElement;
@ -163,11 +166,13 @@ public class CreateDatasetForm extends Composite{
@UiField ControlGroup versionControlGroup;
@UiField ControlGroup organizationsGroup;
@UiField ControlGroup groupsControlGroup;
@UiField HTMLPanel wizardCreatorPanel;
// Create a remote service proxy to talk to the server-side ckan service.
private final CKanPublisherServiceAsync ckanServices = GWT.create(CKanPublisherService.class);
private static final String REGEX_TITLE_PRODUCT_SUBWORD = "[^a-zA-Z0-9_.-]";
//private static final String REGEX_TITLE_PRODUCT_SUBWORD = "[^a-zA-Z0-9_.-]";
private static final String REGEX_MAIL = "\\b[\\w.%-]+@[-.\\w]+\\.[A-Za-z]{2,4}\\b";
private static final String NONE_PROFILE = "none";
@ -205,13 +210,18 @@ public class CreateDatasetForm extends Composite{
private boolean isWorkspaceRequest = false;
// resource table
private TwinColumnSelectionMainPanel resourcesTwinPanel;
//private TwinColumnSelectionMainPanel resourcesTwinPanel;
// resource table
private SelectResourceByWEMainPanel resourcesSelectByWEMainPanel;
// List of opened popup'ids
private List<String> popupOpenedIds = new ArrayList<String>();
// map of organization name title
private Map<String, String> nameTitleOrganizationMap = new HashMap<String, String>();
private WizardCreator wizCreator;
/**
* Invoked in the most general case
@ -265,6 +275,18 @@ public class CreateDatasetForm extends Composite{
initWidget(uiBinder.createAndBindUi(this));
this.eventBus = eventBus;
this.isWorkspaceRequest = isWorkspaceRequest;
List<String> listOfSteps = null;
if(isWorkspaceRequest) {
listOfSteps = Arrays.asList("Edit Common Metadata","Select Item Resources", "Edit Item Specific Metadata & Publish");
}else {
listOfSteps = Arrays.asList("Edit Common Metadata", "Edit Item Specific Metadata & Publish");
}
this.wizCreator = new WizardCreator(listOfSteps);
wizardCreatorPanel.add(wizCreator);
this.descriptionTextarea.setResize(ResizeType.VERTICAL);
bind();
prepareInfoIcons();
@ -361,7 +383,8 @@ public class CreateDatasetForm extends Composite{
alertNoResources.setType(AlertType.WARNING);
alertNoResources.setVisible(true);
}else
resourcesTwinPanel = new TwinColumnSelectionMainPanel(bean.getResourceRoot());
//resourcesSelectByWEMainPanel = new TwinColumnSelectionMainPanel(bean.getResourceRoot());
resourcesSelectByWEMainPanel = new SelectResourceByWEMainPanel(bean.getResourceRoot());
}
// set organizations
@ -426,6 +449,13 @@ public class CreateDatasetForm extends Composite{
setAlertBlock("An unknow error occurred while retrieving types, sorry", AlertType.ERROR, true);
}
else{
GWT.log("Profile returned are: "+profiles.size());
if(!GWT.isProdMode()) {
for (MetaDataProfileBean profile : profiles) {
GWT.log("Profile title: "+profile.getTitle() + ", type: "+profile.getType());
}
}
receivedBean.setMetadataList(profiles);
prepareMetadataList(receivedBean);
@ -850,13 +880,22 @@ public class CreateDatasetForm extends Composite{
// we need to show the page to handle resources one by one from the workspace
formFirstStep.setVisible(false);
formSecondStep.setVisible(!hideManageResources());
formThirdStep.setVisible(hideManageResources());
boolean hideManageRes = hideManageResources();
int stepActive = -1;
if(hideManageRes) {
stepActive = 3;
}else {
stepActive = 2;
}
formSecondStep.setVisible(!hideManageRes);
formThirdStep.setVisible(hideManageRes);
activeWizardStep(stepActive);
// add the resources to the container panel
if(workspaceResourcesContainer.getWidget() == null){
workspaceResourcesContainer.getElement().getStyle().setMarginLeft(20, Unit.PX);
workspaceResourcesContainer.add(resourcesTwinPanel);
workspaceResourcesContainer.add(resourcesSelectByWEMainPanel);
}
}else{
@ -864,6 +903,7 @@ public class CreateDatasetForm extends Composite{
// this is not a workspace request
formFirstStep.setVisible(false);
formThirdStep.setVisible(true);
activeWizardStep(2);
}
@ -873,6 +913,12 @@ public class CreateDatasetForm extends Composite{
selectedProfile.setText("Selected Type is " + metadataTypeListbox.getSelectedItemText());
}
private void activeWizardStep(int step) {
if(wizCreator!=null) {
wizCreator.activeStep(step);
}
}
@UiHandler("goBackButtonFirstStep")
@ -880,6 +926,7 @@ public class CreateDatasetForm extends Composite{
// swap forms
formFirstStep.setVisible(true);
activeWizardStep(1);
formSecondStep.setVisible(false);
formThirdStep.setVisible(false);
@ -891,11 +938,21 @@ public class CreateDatasetForm extends Composite{
// swap forms
if(isWorkspaceRequest){
formFirstStep.setVisible(hideManageResources());
formSecondStep.setVisible(!hideManageResources());
boolean hideManageRes = hideManageResources();
int stepActive = -1;
if(hideManageRes) {
stepActive = 1;
}else {
stepActive = 2;
}
formFirstStep.setVisible(hideManageRes);
formSecondStep.setVisible(!hideManageRes);
activeWizardStep(stepActive);
}else{
formFirstStep.setVisible(true);
formSecondStep.setVisible(false);
activeWizardStep(1);
}
formThirdStep.setVisible(false);
@ -907,6 +964,7 @@ public class CreateDatasetForm extends Composite{
// swap forms
formSecondStep.setVisible(false);
formThirdStep.setVisible(true);
activeWizardStep(3);
}
@ -1022,8 +1080,12 @@ public class CreateDatasetForm extends Composite{
receivedBean.setSelectedOrganization(chosenOrganization);
receivedBean.setGroups(groups);
receivedBean.setGroupsForceCreation(groupsToForceCreation);
if(resourcesTwinPanel != null)
receivedBean.setResourceRoot(resourcesTwinPanel.getResourcesToPublish());
if(resourcesSelectByWEMainPanel != null) {
receivedBean.setResourceRoot(resourcesSelectByWEMainPanel.getResourcesToPublish());
}
receivedBean.setCustomFields(customFieldsMap);
// alert
@ -1358,7 +1420,7 @@ public class CreateDatasetForm extends Composite{
}
};
t.schedule(10000);
t.schedule(15000);
}
}
@ -1381,17 +1443,23 @@ public class CreateDatasetForm extends Composite{
productTitleGroup.setType(ControlGroupType.ERROR);
return "Missing title";
}
if(title.length()<2) {
productTitleGroup.setType(ControlGroupType.ERROR);
return "The field title is too short";
}
// better check for the title
String[] splittedTitle = title.split(" ");
//String[] splittedTitle = title.split(" ");
/* No check, see #20828
for (String word : splittedTitle) {
String replaced = word.replaceAll(REGEX_TITLE_PRODUCT_SUBWORD, "");
if(!replaced.equals(word)){
productTitleGroup.setType(ControlGroupType.ERROR);
return "Please note not all characters are allowed for the title";
}
}
}*/
// email reg expression
String maintainerMail = maintainerEmailTextbox.getText();
@ -1490,8 +1558,8 @@ public class CreateDatasetForm extends Composite{
}
// freeze table of resources
if(resourcesTwinPanel != null)
resourcesTwinPanel.freeze();
if(resourcesSelectByWEMainPanel != null)
resourcesSelectByWEMainPanel.freeze();
}
/**
@ -1568,8 +1636,8 @@ public class CreateDatasetForm extends Composite{
*/
private boolean hideManageResources(){
return receivedBean.getResourceRoot() == null || receivedBean.getResourceRoot().isFolder() && (receivedBean.getResourceRoot().getChildren() == null ||
receivedBean.getResourceRoot().getChildren().isEmpty());
return receivedBean.getResourceRoot() == null || receivedBean.getResourceRoot().isFolder() && (receivedBean.getResourceRoot().getChildrenSize() == null ||
receivedBean.getResourceRoot().getChildrenSize()==0);
}
}

@ -1,6 +1,7 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:m="urn:import:org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.tags">
<ui:style>
.form-main-style {
@ -8,16 +9,17 @@
}
.fieldset-border-style {
border: 1px groove #444;
-webkit-box-shadow: 0px 0px 0px 0px #000;
box-shadow: 0px 0px 0px 0px #000;
padding: 10px;
border: 1px groove #444 !important;
box-shadow: 0px 0px 0px 0px #000 !important;
padding: 10px !important;
margin: 5px !important;
}
.legend-style {
width: auto;
padding: 10px;
margin-bottom: 0px;
width: auto !important;
padding: 10px !important;
margin-bottom: 0 !important;
border-bottom: 0 !important;
}
@external .form-horizontal .input-large;
@ -45,11 +47,14 @@
font-weight: bold;
}
.the-margin-left{
.the-margin-gotoitem {
margin-left: 5px;
margin-top: 10px;
margin-bottom: 10px;
}
</ui:style>
<g:HTMLPanel ui:field="createDatasetMainPanel">
<g:HTMLPanel ui:field="wizardCreatorPanel"></g:HTMLPanel>
<b:Form type="HORIZONTAL" styleName="{style.form-main-style}"
ui:field="formFirstStep" visible="true">
<b:Fieldset styleName="{style.fieldset-border-style}">
@ -63,8 +68,9 @@
</b:Legend>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="infoBlock" styleName="{style.block-alert-style}"></b:AlertBlock>
<b:AlertBlock type="INFO" close="false"
animation="true" visible="false" ui:field="infoBlock"
styleName="{style.block-alert-style}"></b:AlertBlock>
<b:ControlGroup ui:field="productTitleGroup">
<b:ControlLabel for="title" title="Item title">
@ -72,13 +78,15 @@
Title :
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="Item title"
width="90%" b:id="title" title="Item title" ui:field="titleTextBox" />
<b:TextBox alternateSize="LARGE"
placeholder="Item title" width="90%" b:id="title"
title="Item title" ui:field="titleTextBox" />
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverTitle" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelTitle">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconTitle" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconTitle" />
</g:FocusPanel>
</b:Popover>
</span>
@ -86,18 +94,21 @@
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="description" title="Item description">
<b:ControlLabel for="description"
title="Item description">
Description:
</b:ControlLabel>
<b:Controls>
<b:TextArea placeholder="eg. Some useful notes about the item"
width="90%" alternateSize="LARGE" b:id="description" title="Item description"
<b:TextArea
placeholder="eg. Some useful notes about the item" width="90%"
alternateSize="LARGE" b:id="description" title="Item description"
ui:field="descriptionTextarea"></b:TextArea>
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverDescription" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelDescription">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconDescription" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconDescription" />
</g:FocusPanel>
</b:Popover>
</span>
@ -117,7 +128,8 @@
<b:Popover ui:field="popoverLicenses" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelLicenses">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconLicenses" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconLicenses" />
</g:FocusPanel>
</b:Popover>
</span>
@ -125,7 +137,8 @@
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="licenseUrl" title="Selected License'url">Selected
<b:ControlLabel for="licenseUrl"
title="Selected License'url">Selected
License Url:</b:ControlLabel>
<b:Controls>
<b:Paragraph ui:field="unavailableUrl" visible="true">
@ -137,7 +150,8 @@
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="visibility" title="Visibility of the item">Visibility:</b:ControlLabel>
<b:ControlLabel for="visibility"
title="Visibility of the item">Visibility:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="visibility" title="Item visibility"
width="91%" ui:field="visibilityListbox">
@ -148,7 +162,8 @@
<b:Popover ui:field="popoverVisibility" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelVisibility">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconVisibility" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconVisibility" />
</g:FocusPanel>
</b:Popover>
</span>
@ -161,7 +176,8 @@
to publish the item">Publish in:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="organization" alternateSize="LARGE"
width="91%" title="Publish in this organization" ui:field="organizationsListbox">
width="91%" title="Publish in this organization"
ui:field="organizationsListbox">
</b:ListBox>
</b:Controls>
</b:ControlGroup>
@ -172,8 +188,9 @@
Version:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="1.0" b:id="version"
width="90%" title="Item version" ui:field="versionTextbox" />
<b:TextBox alternateSize="LARGE" placeholder="1.0"
b:id="version" width="90%" title="Item version"
ui:field="versionTextbox" />
</b:Controls>
</b:ControlGroup>
@ -184,13 +201,14 @@
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" width="90%"
placeholder="Joe Bloggs" enabled="false" b:id="author" title="Item author"
ui:field="authorTextbox" />
placeholder="Joe Bloggs" enabled="false" b:id="author"
title="Item author" ui:field="authorTextbox" />
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverAuthor" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelAuthor">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconAuthor" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconAuthor" />
</g:FocusPanel>
</b:Popover>
</span>
@ -198,7 +216,8 @@
</b:ControlGroup>
<b:ControlGroup ui:field="authorEmailControlGroup">
<b:ControlLabel for="email" title="Item author's email">
<b:ControlLabel for="email"
title="Item author's email">
<font color="red">*</font>
Author Email:
</b:ControlLabel>
@ -210,7 +229,8 @@
<b:Popover ui:field="popoverAuthorEmail" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelAuthorEmail">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconAuthorEmail" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconAuthorEmail" />
</g:FocusPanel>
</b:Popover>
</span>
@ -218,18 +238,20 @@
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="maintainer" title="Item maintainer">
<b:ControlLabel for="maintainer"
title="Item maintainer">
Maintainer:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="Joe Bloggs"
width="90%" b:id="maintainer" title="Item maintainer"
ui:field="maintainerTextbox" />
<b:TextBox alternateSize="LARGE"
placeholder="Joe Bloggs" width="90%" b:id="maintainer"
title="Item maintainer" ui:field="maintainerTextbox" />
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverMaintainer" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelMaintainer">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconMaintainer" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconMaintainer" />
</g:FocusPanel>
</b:Popover>
</span>
@ -237,18 +259,21 @@
</b:ControlGroup>
<b:ControlGroup ui:field="maintainerControlGroup">
<b:ControlLabel for="emailMaintaner" title="Item author's email">
<b:ControlLabel for="emailMaintaner"
title="Item author's email">
Maintainer Email:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="maintainer@example.com"
width="90%" b:id="emailMaintaner" title="Item author"
<b:TextBox alternateSize="LARGE"
placeholder="maintainer@example.com" width="90%"
b:id="emailMaintaner" title="Item author"
ui:field="maintainerEmailTextbox" />
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverMaintainerEmail" html="true"
animation="true" placement="LEFT">
<b:Popover ui:field="popoverMaintainerEmail"
html="true" animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelMaintainerEmail">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconMaintainerEmail" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconMaintainerEmail" />
</g:FocusPanel>
</b:Popover>
</span>
@ -256,7 +281,8 @@
</b:ControlGroup>
<b:ControlGroup ui:field="metadataTypesControlGroup">
<b:ControlLabel for="metadataTypes" title="Item profile types">Types:</b:ControlLabel>
<b:ControlLabel for="metadataTypes"
title="Item profile types">Types:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="metadataTypes" alternateSize="LARGE"
width="91%" title="The item type to be used"
@ -267,7 +293,8 @@
<b:Popover ui:field="popoverTypes" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelTypes">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconTypes" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconTypes" />
</g:FocusPanel>
</b:Popover>
</span>
@ -276,10 +303,11 @@
<b:ControlGroup ui:field="groupsControlGroup"
visible="false">
<b:ControlLabel for="groups" title="The groups for this item">Item Groups:</b:ControlLabel>
<b:ControlLabel for="groups"
title="The groups for this item">Item Groups:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="groups" alternateSize="LARGE" width="91%"
multipleSelect="true"
<b:ListBox b:id="groups" alternateSize="LARGE"
width="91%" multipleSelect="true"
title="The groups for this item (Hold CTRL or Command button for multiple selection)"
ui:field="groupsListbox">
</b:ListBox>
@ -287,7 +315,8 @@
<b:Popover ui:field="popoverGroups" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelGroups">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconGroups" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconGroups" />
</g:FocusPanel>
</b:Popover>
</span>
@ -301,12 +330,12 @@
</b:AlertBlock>
<!-- Alert block on continue -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="onContinueAlertBlock">
<b:AlertBlock type="INFO" close="false"
animation="true" visible="false" ui:field="onContinueAlertBlock">
</b:AlertBlock>
<b:Button title="Continue" ui:field="continueButton" type="PRIMARY"
block="true">Continue</b:Button>
<b:Button title="Continue" ui:field="continueButton"
type="PRIMARY" block="true">Continue</b:Button>
<b:Button title="Reset" ui:field="resetButton" block="true">Reset</b:Button>
</b:Fieldset>
@ -317,25 +346,22 @@
ui:field="formSecondStep" visible="false">
<b:Fieldset styleName="{style.fieldset-border-style}">
<b:Legend styleName="{style.legend-style}">
Manage Resources
Select Item Resources
</b:Legend>
<b:ControlGroup>
<b:Controls>
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverResources" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelResources">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconResources" />
</g:FocusPanel>
</b:Popover>
</span>
</b:Controls>
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverResources" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelResources">
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconResources" />
</g:FocusPanel>
</b:Popover>
</span>
<g:SimplePanel ui:field="workspaceResourcesContainer"
width="95%" visible="true"></g:SimplePanel>
</b:ControlGroup>
<g:SimplePanel ui:field="workspaceResourcesContainer"
width="100%" visible="true">
</g:SimplePanel>
<b:Button title="Continue" ui:field="continueThirdStep"
type="PRIMARY" block="true">Continue</b:Button>
@ -357,7 +383,8 @@
</small>
</b:Legend>
<b:Paragraph ui:field="selectedProfile" styleName="{style.selected-profile}"></b:Paragraph>
<b:Paragraph ui:field="selectedProfile"
styleName="{style.selected-profile}"></b:Paragraph>
<!-- Here will be placed the metadata fields formats -->
<g:VerticalPanel ui:field="metadataFieldsPanel"
@ -374,7 +401,8 @@
<b:Popover ui:field="popoverCustomFields" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelCustomFields">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconCustomFields" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIconCustomFields" />
</g:FocusPanel>
</b:Popover>
</span>
@ -384,18 +412,22 @@
</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 type="INFO" close="false"
animation="true" visible="false" ui:field="onCreateAlertBlock"
styleName="{style.block-alert-style}">
</b:AlertBlock>
<g:HorizontalPanel ui:field="goToDatasetButtonPanel" visible="false">
<g:HorizontalPanel
ui:field="goToDatasetButtonPanel" visible="false">
<g:Label>Go to the Item</g:Label>
<b:Button title="Go to the Item" ui:field="goToDatasetButton"
type="LINK" visible="false" styleName="{style.the-margin-left}"></b:Button>
<b:Button title="Go to the Item"
ui:field="goToDatasetButton" type="LINK" visible="false"
styleName="{style.the-margin-gotoitem}"></b:Button>
</g:HorizontalPanel>
<b:Button title="Add resources to the just created item"
block="true" type="PRIMARY" visible="false" ui:field="addResourcesButton">Add Resources</b:Button>
block="true" type="PRIMARY" visible="false"
ui:field="addResourcesButton">Add Resources</b:Button>
<b:Button title="Create Item" ui:field="createButton"
type="PRIMARY" block="true">Create</b:Button>

@ -319,8 +319,9 @@ public class MetaDataFieldSkeleton extends Composite{
// get vocabulary fields
List<String> vocabulary = field.getVocabulary();
GWT.log("Vocabulary: "+field.getFieldName());
for (String term : vocabulary) {
GWT.log("Adding term: "+term);
tempListBox.addItem(term);
}

@ -7,9 +7,11 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElement
import com.github.gwtbootstrap.client.ui.AlertBlock;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.ControlGroup;
import com.github.gwtbootstrap.client.ui.TextArea;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.constants.ControlGroupType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@ -53,6 +55,8 @@ public class AddResourceToDataset extends Composite{
@UiField Button addResourceButton;
@UiField AlertBlock infoBlock;
@UiField Button goToDatasetButton;
@UiField ControlGroup urlControlGroup;
@UiField ControlGroup nameControlGroup;
public AddResourceToDataset(HandlerManager eventBus, String datasetId, String datasetOrg, String owner, final String datasetUrl) {
initWidget(uiBinder.createAndBindUi(this));
@ -80,15 +84,33 @@ public class AddResourceToDataset extends Composite{
@UiHandler("addResourceButton")
void onAddButtonClick(ClickEvent e){
infoBlock.setVisible(false);
urlControlGroup.setType(ControlGroupType.NONE);
nameControlGroup.setType(ControlGroupType.NONE);
// validation
if(resourceUrlTextBox.getText().isEmpty() || resourceNameTextBox.getText().isEmpty()){
if (resourceUrlTextBox.getText().isEmpty()) {
showAlert("Url and name fields cannot be empty", AlertType.ERROR);
showAlert("'URL' field cannot be empty", AlertType.ERROR);
urlControlGroup.setType(ControlGroupType.ERROR);
return;
}
// validation
if (resourceNameTextBox.getText().isEmpty() || resourceNameTextBox.getText().isEmpty()) {
showAlert("'Name' field cannot be empty", AlertType.ERROR);
nameControlGroup.setType(ControlGroupType.ERROR);
return;
}
//THE URL must be HTTPS, see #21068
if(!(resourceUrlTextBox.getText().toLowerCase().startsWith("https://"))){
showAlert("The URL must be HTTPS, so start with \"https://\" (e.g. https://your-resource.com)", AlertType.ERROR);
urlControlGroup.setType(ControlGroupType.ERROR);
return;
}
// collect data and build up the bean
@ -163,6 +185,6 @@ public class AddResourceToDataset extends Composite{
}
};
t.schedule(4000);
t.schedule(8000);
}
}

@ -1,6 +1,7 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui" xmlns:g="urn:import:com.google.gwt.user.client.ui">
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
.form-main-style {
margin-left: 10px;
@ -57,18 +58,24 @@
</small>
</b:Legend>
<b:ControlGroup>
<b:Alert type="INFO" close="false">The URL of the resource you are
publishing (only HTTPS URLs are allowed). If your resource is a file that you own on your
desktop, please upload that file to your workspace and generate a
public URL for that file.</b:Alert>
<b:ControlGroup ui:field="urlControlGroup">
<b:ControlLabel for="url" title="File url">
<font color="red">*</font>
URL:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="http://example.com/image.jpg"
b:id="url" title="Product's title" ui:field="resourceUrlTextBox" />
<b:TextBox alternateSize="LARGE"
placeholder="https://example.com/image.jpg" b:id="url"
title="Product's title" ui:field="resourceUrlTextBox" />
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:ControlGroup ui:field="nameControlGroup">
<b:ControlLabel for="name" title="Resource name">
<font color="red">*</font>
Name:
@ -80,19 +87,22 @@
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="description" title="Resource description">
<b:ControlLabel for="description"
title="Resource description">
Description:
</b:ControlLabel>
<b:Controls>
<b:TextArea alternateSize="LARGE"
placeholder="Some useful notes about data" b:id="description"
title="Resource description" ui:field="resourceDescriptionTextArea" />
title="Resource description"
ui:field="resourceDescriptionTextArea" />
</b:Controls>
</b:ControlGroup>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" animation="true" visible="false"
close="false" ui:field="infoBlock" styleName="{style.block-alert-style}"></b:AlertBlock>
<b:AlertBlock type="INFO" animation="true"
visible="false" close="false" ui:field="infoBlock"
styleName="{style.block-alert-style}"></b:AlertBlock>
<!-- Add resource button -->
<b:Button title="Add resource" ui:field="addResourceButton"

@ -48,7 +48,7 @@ public class TagsPanel extends Composite{
@UiField ListBox tagsEnterListBox;
// regular expression for tags
private static final String REGEX_TAG = "^[a-zA-Z0-9]*$";
private static final String REGEX_TAG = "^[a-zA-Z0-9._-]*$";
// tags list
private List<String> tagsList = new ArrayList<String>();

@ -1,7 +1,7 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.utils;
import org.gcube.portlets.user.gcubewidgets.client.popup.GCubeDialog;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection.ResourceInfoForm;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace.ResourceInfoForm;
import com.github.gwtbootstrap.client.ui.Paragraph;
import com.google.gwt.core.shared.GWT;

@ -26,7 +26,7 @@ public class InfoIconsLabels {
public static final String TAGS_INFO_ID_POPUP = "tags-popup-panel-info";
public static final String TAGS_INFO_CAPTION = "Tags";
public static final String TAGS_INFO_TEXT = "Tags are meaningful information that can be associated to the "
+ "item and by means of them it can be retrieved. A tag can contain only alphanumeric characters. "
+ "item and by means of them it can be retrieved. A tag can contain only alphanumeric characters or symbols . (dot) - (hyphen minus) _ (underscore)."
+ "If the tag is composed by a single word it must have a size of at least two characters."
+ "Examples of good tags: \"This is a sample tag\", \"tagY\". Example of bad tag: \"c\"."
+ " You must push ENTER for attaching a tag, or use the provided list of predefined tags. In the latter case"
@ -70,8 +70,8 @@ public class InfoIconsLabels {
// RESOURCES
public static final String RESOURCES_INFO_ID_POPUP = "resouces-popup-panel-info";
public static final String RESOURCES_INFO_CAPTION = "Manage resource items";
public static final String RESOURCES_INFO_TEXT = "Move the files you want to attach to the item on the right panel below. Double click on the item for changing resource's name or description."
+ " Please consider that any complex hierarchy structure you may have will be flatten.";
public static final String RESOURCES_INFO_TEXT = "Select the files you want to attach to the publishing item. Click on 'Pencil' for changing resource's name or description. Click on 'Trash' to remove the resource."
+ " You can add others files by using the 'Add files from...' facility: (i) to navigate a folder perform a 'double click' on it; (ii) to choose a file select it and press 'Select'. Please consider that any complex hierarchy structure you may have will be flatten.";
// CUSTOM FIELDS
public static final String CUSTOM_FIELDS_INFO_ID_POPUP = "custom-fields-popup-panel-info";
@ -80,7 +80,7 @@ public class InfoIconsLabels {
// TITLE
public static final String TITLE_INFO_ID_POPUP = "title-popup-panel-info";
public static final String TITLE_INFO_TEXT = "Item Title must contain only alphanumer characters, dots, underscore or hyphen minus. No others symbols are allowed. Please note that this field will be always visible, despite the item's visibility.";
public static final String TITLE_INFO_TEXT = "The title of the item. Please note that this field will be always visible, despite the item's visibility.";
public static final String TITLE_INFO_CAPTION = "Item Title";
// DESCRIPTION

@ -0,0 +1,154 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.utils;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* The Class WizardCreator.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 15, 2021
*/
public class WizardCreator extends Composite {
/** The ui binder. */
private static WizardCreatorUiBinder uiBinder = GWT.create(WizardCreatorUiBinder.class);
/**
* The Interface WizardCreatorUiBinder.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 15, 2021
*/
interface WizardCreatorUiBinder extends UiBinder<Widget, WizardCreator> {
}
/** The title of steps. */
private List<String> titleOfSteps;
/** The html steps. */
private List<HTML> htmlSteps;
/** The wizard container. */
@UiField
HTMLPanel theWizardContainer;
/**
* Instantiates a new wizard creator.
*
* @param titleOfSteps the title of steps
*/
public WizardCreator(List<String> titleOfSteps) {
initWidget(uiBinder.createAndBindUi(this));
this.titleOfSteps = titleOfSteps;
createSteps();
}
/**
* Creates the steps.
*/
private void createSteps() {
if(titleOfSteps==null)
return;
int i = 1;
htmlSteps = new ArrayList<>(titleOfSteps.size());
for (String step : titleOfSteps) {
HTML toHML = createStep(i, step);
htmlSteps.add(toHML);
theWizardContainer.add(toHML);
i++;
}
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
activeStep(1);
}
});
}
/**
* Active step.
*
* @param stepNumber the step number
*/
public void activeStep(int stepNumber) {
disableAllBadge();
int index = stepNumber-1;
if(index>=0) {
HTML html = htmlSteps.get(index);
html.getElement().addClassName("current");
// NodeList<Element> spans = html.getElement().getElementsByTagName("span");
// if(spans!=null && spans.getLength()>0) {
// Element el = spans.getItem(0);
// el.addClassName("badge-inverse");
// }
}
}
private void disableAllBadge() {
for (HTML html : htmlSteps) {
html.getElement().removeClassName("current");
// NodeList<Element> spans = html.getElement().getElementsByTagName("span");
// if(spans!=null && spans.getLength()>0) {
// Element el = spans.getItem(0);
// el.removeClassName("badge-inverse");
// }
}
}
/**
* Creates the step.
*
* @param stepNumber the step number
* @param stepTitle the step title
* @return the string
*/
private HTML createStep(int stepNumber, String stepTitle) {
StringBuilder builder = new StringBuilder();
builder.append("<span class=\"badge-wiz\">");
builder.append(stepNumber+".");
builder.append("</span>");
builder.append(" "+stepTitle);
return new HTML(builder.toString());
}
public static class HTMLNoDiv extends HTML{
public static HTML noDiv(String theHtml) {
HTML html = new HTML() {
};
html.setHTML(theHtml);
return html;
}
}
}

@ -0,0 +1,10 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<g:HTMLPanel addStyleNames="wizard-creator"
ui:field="theWizardContainer">
</g:HTMLPanel>
</ui:UiBinder>

@ -0,0 +1,59 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import com.google.gwt.event.shared.GwtEvent;
/**
* The Class RemovePublishingResourceEvent.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 9, 2021
*/
public class RemovePublishingResourceEvent extends GwtEvent<RemovePublishingResourceEventHandler> {
/** The type. */
public static Type<RemovePublishingResourceEventHandler> TYPE = new Type<RemovePublishingResourceEventHandler>();
/** The resource. */
private ResourceElementBean resource;
/**
* Instantiates a new removes the publishing resource event.
*
* @param resource the resource
*/
public RemovePublishingResourceEvent(ResourceElementBean resource) {
this.resource = resource;
}
/**
* Gets the resource.
*
* @return the resource
*/
public ResourceElementBean getResource() {
return resource;
}
/**
* Gets the associated type.
*
* @return the associated type
*/
@Override
public Type<RemovePublishingResourceEventHandler> getAssociatedType() {
return TYPE;
}
/**
* Dispatch.
*
* @param handler the handler
*/
@Override
protected void dispatch(RemovePublishingResourceEventHandler handler) {
handler.onRemoveResource(this);
}
}

@ -0,0 +1,22 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace;
import com.google.gwt.event.shared.EventHandler;
// TODO: Auto-generated Javadoc
/**
* The Interface RemovePublishingResourceEventHandler.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 9, 2021
*/
public interface RemovePublishingResourceEventHandler extends EventHandler {
/**
* On remove resource.
*
* @param removeResourceEvent the remove resource event
*/
void onRemoveResource(RemovePublishingResourceEvent removeResourceEvent);
}

@ -1,4 +1,4 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection;
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
@ -8,7 +8,6 @@ import com.github.gwtbootstrap.client.ui.TextArea;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.ControlGroupType;
import com.github.gwtbootstrap.client.ui.constants.IconType;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.Unit;
@ -53,11 +52,7 @@ public class ResourceInfoForm extends Composite{
UiBinder<Widget, ResourceInfoForm> {
}
public ResourceInfoForm() {
initWidget(uiBinder.createAndBindUi(this));
}
public ResourceInfoForm(final ResourceElementBean resource, final ValueUpdater<ResourceElementBean> valueUpdater) {
public ResourceInfoForm(final ResourceElementBean resource) {
initWidget(uiBinder.createAndBindUi(this));
resourceBean = resource;
@ -80,8 +75,9 @@ public class ResourceInfoForm extends Composite{
if(newName == null || newName.isEmpty()){
showError(controlName);
}else{
resourceBean.setName(newName);
resourceBean.setEditableName(newName);
valueUpdater.update(resourceBean);
clearPanel();
}
}
});
@ -125,10 +121,6 @@ public class ResourceInfoForm extends Composite{
return resourceDescription.getText();
}
public void setResourceDescription(String resourceDescription) {
this.resourceDescription.setText(resourceDescription);
}
public void removeError(ControlGroup control) {
control.setType(ControlGroupType.NONE);
}
@ -140,4 +132,8 @@ public class ResourceInfoForm extends Composite{
protected void clearPanel() {
this.removeFromParent();
}
public ResourceElementBean getResourceBean() {
return resourceBean;
}
}

@ -0,0 +1,100 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.legend-style {
width: 100%;
padding: 10px;
margin-bottom: 0px;
font-size: 14px;
}
.panel-style {
padding: 5px;
border: 1px solid #bbb;
border-radius: 5px;
height: 320px;
width: 700px;
margin-bottom: 20px;
}
.labels-style {
color: #999;
}
.controls-style {
margin-left: 10px !important;
}
.control-group {
margin-bottom: 0px !important;
}
.custom-input input {
width: 350px;
}
.custom-input textarea {
width: 355px;
}
</ui:style>
<g:HTMLPanel addStyleNames="{style.panel-style}">
<b:Form type="HORIZONTAL" width="100%">
<b:Fieldset addStyleNames="{style.custom-input}">
<b:Legend addStyleNames="{style.legend-style}">
<b>Resource Information</b>
<b:Button ui:field="closeButton" type="LINK"
title="Close details"></b:Button>
</b:Legend>
<b:ControlGroup ui:field="controlName">
<b:ControlLabel for="name"
title="The name the resource will have on the catalogue">
<b>Name:</b>
</b:ControlLabel>
<b:Controls>
<b:TextBox placeholder="Resource name" b:id="name"
enabled="true"
title="The name the resource will have on the catalogue"
ui:field="resourceName" />
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="path" title="Resource path">
<b>Path:</b>
</b:ControlLabel>
<b:Controls>
<b:TextBox placeholder="Resource path" b:id="path"
readOnly="true" title="Resource path" ui:field="resourcePath" />
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="description"
title="The description the resource will have on the catalogue">
<b>Description:</b>
</b:ControlLabel>
<b:Controls>
<b:TextArea placeholder="Type here the resource description"
b:id="description"
title="The description the resource will have on the catalogue"
ui:field="resourceDescription"></b:TextArea>
</b:Controls>
</b:ControlGroup>
<b:ControlGroup visible="false">
<b:ControlLabel for="format" title="The MIME type">
<b>Format:</b>
</b:ControlLabel>
<b:Controls>
<b:TextBox placeholder="Resource format" b:id="format"
title="The MIME type" ui:field="resourceFormat" readOnly="true" />
</b:Controls>
</b:ControlGroup>
<g:HorizontalPanel width="100%"
ui:field="commandPanel">
<!-- <b:Button ui:field="cancelButton">Cancel</b:Button> -->
<b:Button ui:field="updateResourceButton" type="PRIMARY">Update</b:Button>
</g:HorizontalPanel>
</b:Fieldset>
</b:Form>
</g:HTMLPanel>
</ui:UiBinder>

@ -0,0 +1,305 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import org.gcube.portlets.widgets.wsexplorer.client.explore.WorkspaceResourcesEnhancedExplorerPanel;
import org.gcube.portlets.widgets.wsexplorer.client.notification.WorkspaceExplorerSelectNotification.WorskpaceExplorerSelectNotificationListener;
import org.gcube.portlets.widgets.wsexplorer.client.view.grid.ItemsTable.DISPLAY_FIELD;
import org.gcube.portlets.widgets.wsexplorer.shared.Item;
import com.github.gwtbootstrap.client.ui.AccordionGroup;
import com.github.gwtbootstrap.client.ui.Alert;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.Label;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.constants.LabelType;
import com.google.gwt.core.client.GWT;
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.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* The Class SelectResourceByWEMainPanel.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 5, 2021
*/
public class SelectResourceByWEMainPanel extends Composite {
/** The ui binder. */
private static SelectResourceByWEMainPanelUiBinder uiBinder = GWT.create(SelectResourceByWEMainPanelUiBinder.class);
private static boolean frozen = false;
private final ResourceElementBean initialBean;
@UiField
VerticalPanel wsContainer;
@UiField
FlowPanel selectResourcesContainer;
@UiField
Alert showAlert;
@UiField
Button buttSelectResource;
@UiField
AccordionGroup buttPickResources;
@UiField
HTMLPanel containerPickResources;
@UiField
Label labelNothing;
private Item selectedWEItem;
public final static HandlerManager eventBus = new HandlerManager(null);
private Map<String, SelectedResourceWidget> mapSelectedResources = new HashMap<String, SelectedResourceWidget>();
/**
* The Interface SelectResourceByWEMainPanelUiBinder.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 5, 2021
*/
interface SelectResourceByWEMainPanelUiBinder extends UiBinder<Widget, SelectResourceByWEMainPanel> {
}
/**
* Instantiates a new select resource by WE main panel.
*/
public SelectResourceByWEMainPanel(ResourceElementBean initialBean) {
initWidget(uiBinder.createAndBindUi(this));
SelectResourceByWEMainPanel.frozen = false;
this.initialBean = initialBean;
this.labelNothing.setType(LabelType.INFO);
try {
String wsFolderId = null;
//remove this?
if(initialBean.isFolder()) {
wsFolderId = initialBean.getOriginalIdInWorkspace();
}else {
//is file
if(initialBean.getParent()!=null) {
wsFolderId = initialBean.getParent().getOriginalIdInWorkspace();
}
}
//wsFolderId = initialBean.getRootIdInWorkspace()!=null?initialBean.getRootIdInWorkspace():wsFolderId;
//loads the WE only if the root is not null
if(wsFolderId!=null) {
DISPLAY_FIELD[] displayFields = new DISPLAY_FIELD[] { DISPLAY_FIELD.ICON, DISPLAY_FIELD.NAME,
DISPLAY_FIELD.OWNER, DISPLAY_FIELD.CREATION_DATE};
WorkspaceResourcesEnhancedExplorerPanel workspaceExplorerPanel = new WorkspaceResourcesEnhancedExplorerPanel(wsFolderId,false,null, null,false,null,displayFields);
WorskpaceExplorerSelectNotificationListener wsResourceExplorerListener = new WorskpaceExplorerSelectNotificationListener() {
@Override
public void onSelectedItem(Item item) {
GWT.log("Listener Selected Item " + item);
selectedWEItem = item;
}
@Override
public void onFailed(Throwable throwable) {
// Log.error(throwable.getLocalizedMessage());
throwable.printStackTrace();
}
@Override
public void onAborted() {
}
@Override
public void onNotValidSelection() {
selectedWEItem = null;
}
};
workspaceExplorerPanel.addWorkspaceExplorerSelectNotificationListener(wsResourceExplorerListener);
wsContainer.add(workspaceExplorerPanel);
}else {
containerPickResources.setVisible(false);
}
// if(rootName!=null) {
// buttPickResources.setHeading("Add files from "+rootName);
// }
} catch (Exception e) {
e.printStackTrace();
}
if(!initialBean.isFolder()) {
addSelectResource(initialBean.getOriginalIdInWorkspace(), initialBean.getName(),initialBean.getFullPath(), initialBean.isFolder());
}
addHandlers();
}
private void addHandlers() {
buttSelectResource.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(selectedWEItem!=null && !selectedWEItem.isFolder()) {
addSelectResource(selectedWEItem.getId(), selectedWEItem.getName(), selectedWEItem.getPath(), selectedWEItem.isFolder());
}
}
});
eventBus.addHandler(RemovePublishingResourceEvent.TYPE, new RemovePublishingResourceEventHandler() {
@Override
public void onRemoveResource(RemovePublishingResourceEvent removeResourceEvent) {
if(removeResourceEvent.getResource()!=null) {
removePublishingResource(removeResourceEvent.getResource());
}
}
});
}
private void removePublishingResource(ResourceElementBean resource) {
SelectedResourceWidget theRW = mapSelectedResources.get(resource.getOriginalIdInWorkspace());
if(theRW!=null) {
selectResourcesContainer.remove(theRW);
mapSelectedResources.remove(resource.getOriginalIdInWorkspace());
}
showNothingResourceSelected();
}
public void addSelectResource(String wsItemId, String name, String path, boolean isFolder) {
SelectedResourceWidget selWidg = mapSelectedResources.get(wsItemId);
if (selWidg != null) {
showAlertMsg(AlertType.WARNING,"Item '" + name + "' already selected",true);
return;
}
ResourceElementBean rb = new ResourceElementBean();
rb.setOriginalIdInWorkspace(wsItemId);
rb.setName(name);
rb.setFullPath(path);
rb.setEditableName(name);
rb.setFolder(isFolder);
selWidg = new SelectedResourceWidget(rb);
mapSelectedResources.put(wsItemId, selWidg);
selectResourcesContainer.add(selWidg);
showNothingResourceSelected();
}
private void showNothingResourceSelected() {
if(mapSelectedResources.size()==0) {
labelNothing.setVisible(true);
}else
labelNothing.setVisible(false);
}
private void showAlertMsg(AlertType type, String txt, boolean autoHide) {
showAlert.setType(type);
showAlert.setText(txt);
showAlert.setVisible(true);
showAlert.setClose(true);
if(autoHide) {
Timer timer = new Timer() {
@Override
public void run() {
showAlert.setVisible(false);
}
};
timer.schedule(5000);
}
}
public void freeze() {
GWT.log("called freeze into selected resources");
frozen = true;
selectResourcesContainer.getElement().setAttribute("disabled", "disabled");
containerPickResources.getElement().setAttribute("disabled", "disabled");
//buttPickResources.getElement().getStyle().setProperty("pointer-events","none");
buttSelectResource.setEnabled(false);
}
/**
* Returns the root parent with the children as files to save
* @return the resources to save
*/
public ResourceElementBean getResourcesToPublish(){
ResourceElementBean toReturn = new ResourceElementBean();
List<ResourceElementBean> children = new ArrayList<ResourceElementBean>();
for (String wsItemId : mapSelectedResources.keySet()) {
SelectedResourceWidget selecWC = mapSelectedResources.get(wsItemId);
ResourceElementBean theResource = selecWC.getResourceBean();
theResource.setToBeAdded(true);
if(!theResource.isFolder()){ // be sure ...
children.add(theResource);
}
}
toReturn.setToPublish(children);
GWT.log("resources to publish are: "+toReturn.getToPublish());
return toReturn;
}
/**
* @return the freezed
*/
public static boolean isFroozen() {
return frozen;
}
}

@ -0,0 +1,54 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.important {
font-weight: bold;
}
.custom-header {
margin: 0 !important;
font-size: 18px !important;
color: #222 !important;
}
.max-height-250 {
max-height: 250px;
overflow-y: auto;
}
.margin-top-10 {
margin-top: 10px;
}
.margin-top-30 {
margin-top: 30px;
}
</ui:style>
<g:HTMLPanel width="100%">
<g:HTMLPanel>
<b:Heading size="1" addStyleNames="{style.custom-header}">Selected Items</b:Heading>
<b:Alert ui:field="showAlert" visible="false"></b:Alert>
<g:FlowPanel ui:field="selectResourcesContainer"
width="100%">
<b:Label ui:field="labelNothing">no file selected</b:Label>
</g:FlowPanel>
</g:HTMLPanel>
<g:HTMLPanel ui:field="containerPickResources"
addStyleNames="{style.margin-top-30}">
<b:AccordionGroup ui:field="buttPickResources"
heading="Add files from..." defaultOpen="false"
addStyleNames="accordion-no-border-inner">
<b:FluidRow addStyleNames="{style.max-height-250}">
<g:VerticalPanel ui:field="wsContainer">
</g:VerticalPanel>
</b:FluidRow>
<b:Button ui:field="buttSelectResource"
addStyleNames="{style.margin-top-10}">Select</b:Button>
</b:AccordionGroup>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>

@ -0,0 +1,133 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.workspace;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.constants.ButtonType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
/**
* The Class SelectResourceWidget.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 12, 2021
*/
public class SelectedResourceWidget extends Composite {
/** The ui binder. */
private static SelectedResourceWidgetUiBinder uiBinder = GWT.create(SelectedResourceWidgetUiBinder.class);
/**
* The Interface SelectResourceWidgetUiBinder.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Mar 12, 2021
*/
interface SelectedResourceWidgetUiBinder extends UiBinder<Widget, SelectedResourceWidget> {
}
/**
* Instantiates a new select resource widget.
*/
public SelectedResourceWidget() {
initWidget(uiBinder.createAndBindUi(this));
}
/** The button delete. */
@UiField
Button buttonDelete;
/** The button edit. */
@UiField
Button buttonEdit;
/** The field name. */
@UiField
Label fieldName;
@UiField
Label fieldDescription;
/** The edit panel. */
@UiField
HTMLPanel editPanel;
/** The resource bean. */
private ResourceElementBean resourceBean;
/**
* Instantiates a new select resource widget.
*
* @param rb the rb
*/
public SelectedResourceWidget(ResourceElementBean rb) {
initWidget(uiBinder.createAndBindUi(this));
buttonEdit.setType(ButtonType.LINK);
buttonDelete.setType(ButtonType.LINK);
this.resourceBean = rb;
updateFields();
addHandlers();
}
private void updateFields() {
this.fieldName.setText(resourceBean.getEditableName());
if(resourceBean.getDescription()!=null && !resourceBean.getDescription().isEmpty()) {
this.fieldDescription.setVisible(true);
this.fieldDescription.setText(resourceBean.getDescription());
}else
this.fieldDescription.setVisible(false);
}
/**
* Adds the handlers.
*/
private void addHandlers() {
buttonEdit.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
editPanel.clear();
ResourceInfoForm resourceInformationInfo = new ResourceInfoForm(resourceBean) {
protected void onUnload() {
super.onUnload();
updateFields();
};
};
editPanel.add(resourceInformationInfo);
}
});
buttonDelete.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
SelectResourceByWEMainPanel.eventBus.fireEvent(new RemovePublishingResourceEvent(resourceBean));
}
});
}
/**
* Gets the resource bean.
*
* @return the resource bean
*/
public ResourceElementBean getResourceBean() {
return resourceBean;
}
}

@ -0,0 +1,57 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<ui:style>
.important {
font-weight: bold;
}
.selected-resources {
}
.selected-resources td {
vertical-align: middle !important;
}
.margin-bottom-8 {
margin-bottom: 8px;
}
.descr-text {
font-style: italic;
padding-left: 105px;
font-size: 12px;
}
.title-text {
font-weight: bold;
font-size: 14px;
display: inline;
vertical-align: middle;
color: #222;
}
.icon-my-style {
font-size: 1.2em;
margin-right: 10px;
margin-left: 10px;
vertical-align: middle;
}
</ui:style>
<g:HTMLPanel addStyleNames="{style.margin-bottom-8}">
<g:FlowPanel addStyleNames="{style.selected-resources}">
<!-- <b:Icon type="PUSHPIN" addStyleNames="{style.icon-my-style}"></b:Icon> -->
<b:Button ui:field="buttonEdit" icon="PENCIL"
title="Edit the resource information" />
<b:Button ui:field="buttonDelete" icon="TRASH"
title="Remove this resource" />
<g:Label ui:field="fieldName"
addStyleNames="{style.title-text}"></g:Label>
<g:Label ui:field="fieldDescription" visible="false"
addStyleNames="{style.descr-text}"></g:Label>
</g:FlowPanel>
<g:HTMLPanel ui:field="editPanel"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>

@ -49,4 +49,87 @@
.GeoJson-DialogBox{
width: 100% !important;
}
}
.accordion-no-border-inner {
border: 1px solid #e5e5e5 !important;
border-radius: 4px !important;
padding: 6px 12px !important;
}
.accordion-no-border-inner .accordion-inner {
border-top: 0 !important;
padding: 4px 4px !important;
}
/* WIZARD-CREATOR CLASSES */
.wizard-creator {
width: 100%;
border-collapse: separate;
display: table;
border-spacing: 5px;
}
.wizard-creator div {
padding: 10px 12px 10px;
background: #efefef;
position: relative;
/*display: inline-block;*/
display: table-cell;
}
.wizard-creator div:before {
width: 0;
height: 0;
border-top: 20px inset transparent;
border-bottom: 20px inset transparent;
border-left: 20px solid #fff;
position: absolute;
content: "";
top: 0;
left: 0;
}
.wizard-creator div:after {
width: 0;
height: 0;
border-top: 20px inset transparent;
border-bottom: 20px inset transparent;
border-left: 20px solid #efefef;
position: absolute;
content: "";
top: 0;
right: -20px;
z-index: 2;
}
.wizard-creator div:first-child:before,
.wizard-creator div:last-child:after {
border: none;
}
.wizard-creator div:first-child {
border-radius: 4px 0 0 4px;
}
.wizard-creator div:last-child {
border-radius: 0 4px 4px 0;
}
.wizard-creator .badge-wiz {
margin: 0 5px 0 18px;
}
.wizard-creator div:first-child .badge {
margin-left: 0;
}
.wizard-creator .current {
background: #007ACC;
color: #fff;
}
.wizard-creator .current:after {
border-left-color: #007ACC;
}

@ -5,7 +5,6 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -14,15 +13,18 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpSession;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.SessionCatalogueAttributes;
import org.gcube.datacatalogue.ckanutillibrary.shared.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.storagehubwrapper.server.StorageHubWrapper;
import org.gcube.common.storagehubwrapper.server.tohl.Workspace;
import org.gcube.datacatalogue.utillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.utillibrary.server.DataCatalogueFactory;
import org.gcube.datacatalogue.utillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.datacatalogue.utillibrary.server.utils.SessionCatalogueAttributes;
import org.gcube.datacatalogue.utillibrary.shared.ResourceBean;
import org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanGroup;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanLicense;
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.CatalogueRoleManager;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.DiscoverTagsList;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.GenericUtils;
@ -41,15 +43,14 @@ import org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.geojson.GeoJsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import eu.trentorise.opendata.jackan.model.CkanGroup;
import eu.trentorise.opendata.jackan.model.CkanLicense;
/**
* Server side of the data publisher.
@ -61,7 +62,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
// Logger
//private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class);
private static final Log logger = LogFactoryUtil.getLog(CKANPublisherServicesImpl.class);
private static final Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class);
private static final String ITEM_URL_FIELD = "Item URL";
private static final String SYS_TYPE = "system:type";
private static final String TAGS_VOCABULARY_KEY = "TAGS_VOCABULARY";
@ -69,10 +70,24 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
// map <orgName, scope>
private ConcurrentHashMap<String, String> mapOrganizationScope = new ConcurrentHashMap<String, String>();
/**
* Dev mode set contexts.
*/
private void devModeSetContexts() {
if (!isWithinPortal()) {
logger.info("DETECTED DEV MODE");
GenericUtils.getCurrentContext(getThreadLocalRequest(), true);
GenericUtils.getCurrentToken(getThreadLocalRequest(), true);
}
}
/**
* Retrieve an instance of the library for the scope
* Retrieve an instance of the library for the scope.
*
* @param scope if it is null it is evaluated from the session
* @return
* @return the catalogue
*/
public DataCatalogue getCatalogue(String scope){
@ -89,11 +104,13 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
/**
* Retrieve the list of organizations in which the user can publish (roles ADMIN/EDITOR)
* @param username
* Retrieve the list of organizations in which the user can publish (roles ADMIN/EDITOR).
*
* @param username the username
* @param scope the scope
* @return the list of organizations
* @throws GroupRetrievalFault
* @throws UserManagementSystemException
* @throws UserManagementSystemException the user management system exception
* @throws GroupRetrievalFault the group retrieval fault
*/
private List<OrganizationBean> getUserOrganizationsListAdmin(String username, String scope) throws UserManagementSystemException, GroupRetrievalFault {
@ -119,7 +136,8 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
/**
* Online or in development mode?
* Online or in development mode?.
*
* @return true if you're running into the portal, false if in development
*/
private boolean isWithinPortal() {
@ -132,11 +150,25 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return false;
}
}
/**
* Gets the workspace from storage hub.
*
* @return the workspace from storage hub
* @throws Exception
* the exception
*/
protected Workspace getWorkspaceFromStorageHub() throws Exception {
GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest());
StorageHubWrapper storageHubWrapper = WorkspaceUtils.getStorageHubWrapper(this.getThreadLocalRequest(), null, user);
return storageHubWrapper.getWorkspace();
}
/**
* Find a license id given the license text.
* @param chosenLicense
* @return
*
* @param chosenLicense the chosen license
* @return the string
*/
private String findLicenseIdByLicense(String chosenLicense) {
@ -146,6 +178,11 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
/**
* Gets the licenses.
*
* @return the licenses
*/
@Override
public List<LicenseBean> getLicenses() {
@ -154,6 +191,13 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
String scope = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
logger.info("Request for CKAN licenses for scope " + scope);
String keyPerScope = CatalogueUtilMethods.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_LICENSES_KEY, scope);
// if(!isWithinPortal()){
// logger.info("DEV MODE returning funny licenses...");
// List<LicenseBean> licenses = new ArrayList<LicenseBean>();
// licenses.add(new LicenseBean("AFL-3.0", "https://opensource.org/licenses/AFL-3.0"));
// return licenses;
// }
List<LicenseBean> licensesBean = null;
if(httpSession.getAttribute(keyPerScope) != null){
@ -179,7 +223,15 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return licensesBean;
}
/**
* Gets the dataset bean.
*
* @param folderId the folder id
* @return the dataset bean
* @throws Exception the exception
*/
@Override
public DatasetBean getDatasetBean(String folderId) throws Exception{
@ -194,7 +246,6 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
String scope = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
logger.debug("Scope recovered from session is " + scope);
logger.debug("Request dataset metadata bean for folder with id " + folderId
+ " whose owner is " + userName);
@ -218,7 +269,8 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
// if the request comes from the workspace
if(folderId != null && !folderId.isEmpty()){
WorkspaceUtils.handleWorkspaceResources(folderId, userName, bean);
Workspace workspace = getWorkspaceFromStorageHub();
WorkspaceUtils.toWorkspaceResource(folderId, userName, bean, workspace);
}
}catch(Exception e){
@ -237,11 +289,11 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
bean.setVersion(1);
String onlyAlphanumeric = "test-creation-blablabla".replaceAll("[^A-Za-z0-9]", "");
bean.setTitle(onlyAlphanumeric + Calendar.getInstance().getTimeInMillis());
bean.setAuthorName("Costantino");
bean.setAuthorSurname("Perciante");
bean.setAuthorEmail("costantino.perciante@isti.cnr.it");
bean.setMaintainer("Costantino Perciante");
bean.setMaintainerEmail("costantino.perciante@isti.cnr.it");
bean.setAuthorName("Francesco");
bean.setAuthorSurname("Mangiacrapa");
bean.setAuthorEmail("francesco.mangiacrapa@isti.cnr.it");
bean.setMaintainer("Francesco Mangiacrapa");
bean.setMaintainerEmail("francesco.mangiacrapa@isti.cnr.it");
//UPDATED By Francesco
String scope = GenericUtils.getCurrentContext(this.getThreadLocalRequest(), false);
@ -252,7 +304,8 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
bean.setOwnerIdentifier(userName);
if(folderId != null && !folderId.isEmpty()){
WorkspaceUtils.handleWorkspaceResources(folderId, userName, bean);
Workspace workspace = getWorkspaceFromStorageHub();
WorkspaceUtils.toWorkspaceResource(folderId, userName, bean, workspace);
}
}catch(Exception e){
logger.error("Error while building bean into dev mode", e);
@ -265,9 +318,10 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
/**
* Discover from the IS the vocabulary of tags for this scope, if present
* Discover from the IS the vocabulary of tags for this scope, if present.
*
* @param context the context
* @return a list of tags vocabulary
* @throws Exception
*/
private List<String> discoverTagsVocabulary(String context){
@ -286,15 +340,30 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return vocabulary;
}
/**
* Gets the tags for organization.
*
* @param orgName the org name
* @return the tags for organization
* @throws Exception the exception
*/
@Override
public List<String> getTagsForOrganization(String orgName) throws Exception{
return discoverTagsVocabulary(getScopeFromOrgName(orgName));
}
/**
* Creates the C kan dataset.
*
* @param toCreate the to create
* @return the dataset bean
* @throws Exception the exception
*/
@Override
public DatasetBean createCKanDataset(DatasetBean toCreate) throws Exception{
try{
devModeSetContexts();
logger.info("Request for creating a dataset with these information " + toCreate);
String userName = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
String title = toCreate.getTitle();
@ -319,21 +388,43 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
// get the list of resources and convert to ResourceBean
List<ResourceBean> resources = null;
ResourceElementBean resourcesToAdd = toCreate.getResourceRoot();
// we need to copy such resource in the .catalogue area of the user's ws
//converting to resources to be added
if(resourcesToAdd != null){
resources = WorkspaceUtils.copyResourcesToUserCatalogueArea(toCreate.getId(), userName, toCreate);
Workspace workspace = getWorkspaceFromStorageHub();
resources = WorkspaceUtils.toResources(toCreate, workspace, userName);
}
logger.debug("The user wants to publish in organization with name " + organizationNameOrId);
String scope = getScopeFromOrgName(organizationNameOrId);
DataCatalogue utils = getCatalogue(scope);
String userApiKey = utils.getApiKeyFromUsername(userName);
String datasetId = utils.createCKanDatasetMultipleCustomFields
(userApiKey, title, null, organizationNameOrId, author, authorMail, maintainer,
maintainerMail, version, description, licenseId, listOfTags, customFields, resources, setPublic);
if (!isWithinPortal()) {
logger.debug("Should be added:");
for (String key : customFields.keySet()) {
logger.debug("Custom field with key: "+key+", value: "+customFields.get(key));
}
}
String datasetId = utils.createCkanDatasetMultipleCustomFields(userName,
title,
null,
organizationNameOrId,
author,
authorMail,
maintainer,
maintainerMail,
version,
description,
licenseId,
listOfTags,
customFields,
resources,
setPublic,
true,
true);
if(datasetId != null){
logger.info("Dataset created!");
@ -344,44 +435,52 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
toCreate.setSource(datasetUrl);
// add also this information as custom field
/**
* TODO NEEDED TO BE CHECK
*
* OLD CODE NOT NEEDED. NOW IT IS PERFORMED BY gCAT
Map<String, List<String>> addField = new HashMap<String, List<String>>();
addField.put(ITEM_URL_FIELD, Arrays.asList(datasetUrl));
utils.patchProductCustomFields(datasetId, userApiKey, addField, false);
*/
//TODO SHOULD BE NOTIFIED by gCAT
// start a thread that will associate this dataset with the group
if(/*toCreate.getChosenType() != null ||*/ toCreate.getGroups() != null){
AssociationToGroupAndNotifyThread threadAssociationToGroup =
new AssociationToGroupAndNotifyThread(
toCreate.getGroups(),
toCreate.getGroupsForceCreation(),
null, //toCreate.getChosenType(), TODO
datasetUrl,
datasetId,
toCreate.getTitle(),
GenericUtils.getCurrentUser(getThreadLocalRequest()).getFullname(),
userName,
utils,
organizationNameOrId,
getThreadLocalRequest()
);
threadAssociationToGroup.start();
}
// launch notification thread
WritePostCatalogueManagerThread threadWritePost =
new WritePostCatalogueManagerThread(
userName,
scope,
toCreate.getTitle(),
datasetUrl,
false, // send notification to other people
toCreate.getTags(),
GenericUtils.getCurrentUser(getThreadLocalRequest()).getFullname(),
GenericUtils.getCurrentClientUrl(getThreadLocalRequest())
);
threadWritePost.start();
// if(/*toCreate.getChosenType() != null ||*/ toCreate.getGroups() != null){
//
// AssociationToGroupAndNotifyThread threadAssociationToGroup =
// new AssociationToGroupAndNotifyThread(
// toCreate.getGroups(),
// toCreate.getGroupsForceCreation(),
// null, //toCreate.getChosenType(), TODO
// datasetUrl,
// datasetId,
// toCreate.getTitle(),
// GenericUtils.getCurrentUser(getThreadLocalRequest()).getFullname(),
// userName,
// utils,
// organizationNameOrId,
// getThreadLocalRequest()
// );
// threadAssociationToGroup.start();
//
// }
//
// // launch notification thread
// WritePostCatalogueManagerThread threadWritePost =
// new WritePostCatalogueManagerThread(
// userName,
// scope,
// toCreate.getTitle(),
// datasetUrl,
// false, // send notification to other people
// toCreate.getTags(),
// GenericUtils.getCurrentUser(getThreadLocalRequest()).getFullname(),
// GenericUtils.getCurrentClientUrl(getThreadLocalRequest())
// );
// threadWritePost.start();
return toCreate;
}else{
@ -390,83 +489,91 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}catch(Exception e){
logger.error("Error while creating item ", e);
throw new Exception("An error occurred while creating the item " + e.getMessage());
throw new Exception(e.getMessage());
}
return null;
}
/**
* Adds the resource to dataset.
*
* @param resource the resource
* @param datasetId the dataset id
* @return the resource element bean
* @throws Exception the exception
*/
@Override
public ResourceElementBean addResourceToDataset(ResourceElementBean resource, String datasetId) throws Exception{
logger.info("called addResourceToDataset");
devModeSetContexts();
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
logger.debug("Incoming request for creating new resource for dataset with id " + datasetId + " and organization name of the dataset is " + resource.getOrganizationNameDatasetParent());
logger.debug("Owner is " + username + " and resource is " + resource);
if(!isWithinPortal()){
logger.warn("Running outside the portal");
ResourceBean resourceBean = new ResourceBean(
resource.getUrl(),
resource.getName(),
resource.getDescription(),
null,
username,
datasetId,
null);
// get the scope in which we should discover the ckan instance given the organization name in which the dataset was created
String scope = getScopeFromOrgName(resource.getOrganizationNameDatasetParent());
DataCatalogue catalogue = getCatalogue(scope);
String resourceId = catalogue.addResourceToDataset(resourceBean, resource.getOrganizationNameDatasetParent(), username);
if(resourceId != null){
logger.info("Resource " + resource.getName() + " is now available");
// set its id and turn it to the client
resource.setOriginalIdInWorkspace(resourceId);
return resource;
}else{
ResourceBean resourceBean = new ResourceBean(
resource.getUrl(),
resource.getName(),
resource.getDescription(),
null,
username,
datasetId,
null);
// get the scope in which we should discover the ckan instance given the organization name in which the dataset was created
String scope = getScopeFromOrgName(resource.getOrganizationNameDatasetParent());
DataCatalogue catalogue = getCatalogue(scope);
String resourceId = catalogue.addResourceToDataset(resourceBean, catalogue.getApiKeyFromUsername(username));
if(resourceId != null){
logger.debug("Resource " + resource.getName() + " is now available");
// set its id and turn it to the client
resource.setOriginalIdInWorkspace(resourceId);
return resource;
}
logger.debug("No resource created");
return null;
}
logger.debug("No resource created");
return null;
}
/**
* Delete resource from dataset.
*
* @param resource the resource
* @return true, if successful
* @throws Exception the exception
*/
@Override
public boolean deleteResourceFromDataset(ResourceElementBean resource) throws Exception{
logger.debug("Request for deleting resource " + resource);
boolean deleted = false;
if(!isWithinPortal()){
logger.warn("Running outside the portal");
return deleted;
}else{
devModeSetContexts();
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());
DataCatalogue catalogue = getCatalogue(scope);
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
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());
DataCatalogue catalogue = getCatalogue(scope);
deleted = catalogue.
deleteResourceFromDataset(resource.getOriginalIdInWorkspace(), catalogue.getApiKeyFromUsername(username));
if(deleted){
logger.info("Resource described by " + resource + " deleted");
}else
logger.error("Resource described by " + resource + " NOT deleted");
}catch(Exception e){
logger.error("Error while trying to delete resource described by " + resource, e);
throw new Exception("Error while trying to delete resource." + e.getMessage());
}
return deleted;
deleted = catalogue.deleteResourceFromDataset(resource.getOriginalIdInWorkspace(),username);
if(deleted){
logger.info("Resource described by " + resource + " deleted");
}else
logger.error("Resource described by " + resource + " NOT deleted");
}catch(Exception e){
logger.error("Error while trying to delete resource described by " + resource, e);
throw new Exception("Error while trying to delete resource." + e.getMessage());
}
return deleted;
}
/**
* Gets the profiles.
*
* @param orgName the org name
* @return the profiles
* @throws Exception the exception
*/
@Override
public List<MetaDataProfileBean> getProfiles(String orgName) throws Exception{
@ -484,6 +591,14 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return toReturn;
}
/**
* Dataset id already exists.
*
* @param title the title
* @param orgName the org name
* @return true, if successful
* @throws Exception the exception
*/
@Override
public boolean datasetIdAlreadyExists(String title, String orgName) throws Exception{
if(title == null || title.isEmpty())
@ -505,18 +620,23 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
*/
private String getScopeFromOrgName(String orgName){
logger.debug("Request for scope related to orgName " + orgName + "[ map that will be used is " + mapOrganizationScope.toString() + " ]");
logger.info("Request for scope related to orgName " + orgName + " [map that will be used is " + mapOrganizationScope.toString() + "]");
if(orgName == null || orgName.isEmpty())
throw new IllegalArgumentException("orgName cannot be empty or null!");
String toReturn = null;
if(isWithinPortal()){
if(mapOrganizationScope.containsKey(orgName))
if(mapOrganizationScope.containsKey(orgName)) {
toReturn = mapOrganizationScope.get(orgName);
else{
}else{
try{
String evaluatedScope = GenericUtils.retrieveScopeFromOrganizationName(orgName);
//see #20801
if(evaluatedScope==null || evaluatedScope.isEmpty()) {
logger.warn("Scope detected for OrganizationName: "+orgName+" is null or empty, skipping filling 'mapOrganizationScope' and returning null");
return toReturn;
}
mapOrganizationScope.put(orgName, evaluatedScope);
toReturn = evaluatedScope;
}catch(Exception e){
@ -528,17 +648,26 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
toReturn = GenericUtils.getCurrentContext(this.getThreadLocalRequest(), false);
mapOrganizationScope.put(orgName, toReturn);
}
logger.debug("Returning scope " + toReturn);
logger.info("Returning scope " + toReturn);
return toReturn;
}
/**
* Gets the user groups.
*
* @param orgName the org name
* @return the user groups
*/
@Override
public List<OrganizationBean> getUserGroups(String orgName) {
List<OrganizationBean> toReturn = new ArrayList<OrganizationBean>();
if(isWithinPortal()){
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
GCubeUser user = GenericUtils.getCurrentUser(getThreadLocalRequest());
String username = null;
if(user!=null)
username = user.getUsername();
logger.debug("Request for user " + username + " groups. Organization name is " + orgName);
@ -557,10 +686,9 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
//Fixing Incident #12563
try{
DataCatalogue catalogue = getCatalogue(scope);
String apiKey = catalogue.getApiKeyFromUsername(username);
//Fixing Incident #12563
if(apiKey!=null && !apiKey.isEmpty()){
Map<String, Map<CkanGroup, RolesCkanGroupOrOrg>> mapRoleGroup = catalogue.getUserRoleByGroup(username, apiKey);
if(username!=null && !username.isEmpty()){
Map<String, Map<CkanGroup, RolesCkanGroupOrOrg>> mapRoleGroup = catalogue.getUserRoleByGroup(username);
Set<Entry<String, Map<CkanGroup, RolesCkanGroupOrOrg>>> set = mapRoleGroup.entrySet();
for (Entry<String, Map<CkanGroup, RolesCkanGroupOrOrg>> entry : set) {
Set<Entry<CkanGroup, RolesCkanGroupOrOrg>> subSet = entry.getValue().entrySet();
@ -583,6 +711,13 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
/**
* Checks if is publisher user.
*
* @param isWorkspaceRequest the is workspace request
* @return true, if is publisher user
* @throws Exception the exception
*/
@Override
public boolean isPublisherUser(boolean isWorkspaceRequest) throws Exception{
@ -651,6 +786,13 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
}
/**
* Checks if is geo JSON valid.
*
* @param geoJson the geo json
* @return true, if is geo JSON valid
* @throws Exception the exception
*/
@Override
public boolean isGeoJSONValid(String geoJson) throws Exception {
try{

@ -1,160 +1,161 @@
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.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
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 Log logger = LogFactoryUtil.getLog(AssociationToGroupAndNotifyThread.class);
private static final String PRODUCT_ASSOCIATED_TO_GROUP_SUBJECT = "Item $TITLE added to group $GROUP";
private static final String PRODUCT_ASSOCIATED_TO_GROUP_BODY = "Dear user,<br> a new item named '<b>$TITLE</b>' has been "
+ "just published by $USER_FULLNAME in <b>$GROUP</b> .<br>"
+ "You can find it here $DATASET_URL";
private String groupTitle;
private String datasetId;
private String username;
private String datasetTitle;
private String userFullName;
private DataCatalogue catalogue;
// private String organization;
private List<OrganizationBean> groups;
private HttpServletRequest request;
private String datasetUrl;
private List<OrganizationBean> groupsForceCreation;
/**
* @param list
* @param groupTitle
* @param datasetId
* @param username
* @param catalogue
*/
public AssociationToGroupAndNotifyThread(List<OrganizationBean> groups, List<OrganizationBean> groupsForceCreation, String groupTitle, String datasetUrl, String datasetId, String datasetTitle, String userFullName,
String username, DataCatalogue catalogue, String organization, HttpServletRequest request) {
this.request = request;
this.groups = groups == null ? new ArrayList<OrganizationBean>() : groups;
this.groupsForceCreation = groupsForceCreation;
this.groupTitle = groupTitle;
this.datasetId = datasetId;
this.username = username;
this.catalogue = catalogue;
// this.organization = organization;
this.datasetTitle = datasetTitle;
this.userFullName = userFullName;
this.datasetUrl = datasetUrl;
}
@Override
public void run() {
logger.info("Association thread started to put the dataset with id = "+ datasetId + " into group with title " + groupTitle + " for user " + username);
// force creation of groups if needed
if(groupsForceCreation != null){
logger.info("Groups that must be created before association are " + groupsForceCreation);
for (OrganizationBean groupToForce : groupsForceCreation) {
try{
CkanGroup group = catalogue.createGroup(groupToForce.getName(), groupToForce.getTitle(), "");
if(group == null)
logger.error("Unable to retrieve or create group with name " + groupToForce);
else
groups.add(new OrganizationBean(group.getTitle(), group.getName(), false, groupToForce.isPropagateUp()));
}catch(Exception e){
logger.error("Failed to check if a group with this info " + groupToForce + " already exists or can be created");
}
}
}
logger.info("Other groups to which the product should be associate are " + groups);
if(groups != null)
for (OrganizationBean groupBean : groups) {
boolean putIntoGroup = catalogue.assignDatasetToGroup(groupBean.getName(), datasetId, catalogue.getApiKeyFromUsername(username), groupBean.isPropagateUp());
logger.info("Was product put into group" + groupBean.getTitle() + "? " + putIntoGroup);
if(putIntoGroup)
notifyGroupAdmins(catalogue, groupBean.getName() ,groupBean.getTitle(), 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 groupName, String groupTitle, String username){
// get the groups admin
Map<RolesCkanGroupOrOrg, List<String>> userAndRoles = catalogue.getRolesAndUsersGroup(groupName);
if(userAndRoles.containsKey(RolesCkanGroupOrOrg.ADMIN)){
List<String> admins = userAndRoles.get(RolesCkanGroupOrOrg.ADMIN);
List<String> adminsEmails = new ArrayList<String>();
for(int i = 0; i < admins.size(); i++){
String convertedName = CatalogueUtilMethods.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<String> 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).replace("$DATASET_URL", datasetUrl),
request);
mailToSend.sendEmail();
}else
logger.warn("It seems there is no user with role Admin in group " + groupTitle);
}
}
//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.server.DataCatalogue;
//import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
//import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg;
//import org.gcube.datacatalogue.ckanutillibrary.shared.jackan.model.CkanGroup;
//import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
//import org.gcube.vomanagement.usermanagement.UserManager;
//import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
//
//import com.liferay.portal.kernel.log.Log;
//import com.liferay.portal.kernel.log.LogFactoryUtil;
//
//
//
///**
// * 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 Log logger = LogFactoryUtil.getLog(AssociationToGroupAndNotifyThread.class);
// private static final String PRODUCT_ASSOCIATED_TO_GROUP_SUBJECT = "Item $TITLE added to group $GROUP";
// private static final String PRODUCT_ASSOCIATED_TO_GROUP_BODY = "Dear user,<br> a new item named '<b>$TITLE</b>' has been "
// + "just published by $USER_FULLNAME in <b>$GROUP</b> .<br>"
// + "You can find it here $DATASET_URL";
//
// private String groupTitle;
// private String datasetId;
// private String username;
// private String datasetTitle;
// private String userFullName;
// private DataCatalogue catalogue;
// // private String organization;
// private List<OrganizationBean> groups;
// private HttpServletRequest request;
// private String datasetUrl;
// private List<OrganizationBean> groupsForceCreation;
//
// /**
// * @param list
// * @param groupTitle
// * @param datasetId
// * @param username
// * @param catalogue
// */
// public AssociationToGroupAndNotifyThread(List<OrganizationBean> groups, List<OrganizationBean> groupsForceCreation, String groupTitle, String datasetUrl, String datasetId, String datasetTitle, String userFullName,
// String username, DataCatalogue catalogue, String organization, HttpServletRequest request) {
// this.request = request;
// this.groups = groups == null ? new ArrayList<OrganizationBean>() : groups;
// this.groupsForceCreation = groupsForceCreation;
// this.groupTitle = groupTitle;
// this.datasetId = datasetId;
// this.username = username;
// this.catalogue = catalogue;
// // this.organization = organization;
// this.datasetTitle = datasetTitle;
// this.userFullName = userFullName;
// this.datasetUrl = datasetUrl;
// }
//
// @Override
// public void run() {
//
// logger.info("Association thread started to put the dataset with id = "+ datasetId + " into group with title " + groupTitle + " for user " + username);
//
// // force creation of groups if needed
// if(groupsForceCreation != null){
// logger.info("Groups that must be created before association are " + groupsForceCreation);
// for (OrganizationBean groupToForce : groupsForceCreation) {
// try{
// CkanGroup group = catalogue.createGroup(groupToForce.getName(), groupToForce.getTitle(), "");
// if(group == null)
// logger.error("Unable to retrieve or create group with name " + groupToForce);
// else
// groups.add(new OrganizationBean(group.getTitle(), group.getName(), false, groupToForce.isPropagateUp()));
// }catch(Exception e){
// logger.error("Failed to check if a group with this info " + groupToForce + " already exists or can be created");
// }
// }
//
// }
//
// logger.info("Other groups to which the product should be associate are " + groups);
//
// if(groups != null)
// for (OrganizationBean groupBean : groups) {
// boolean putIntoGroup = catalogue.assignDatasetToGroup(groupBean.getName(), datasetId, groupBean.isPropagateUp());
// logger.info("Was product put into group" + groupBean.getTitle() + "? " + putIntoGroup);
// if(putIntoGroup)
// notifyGroupAdmins(catalogue, groupBean.getName() ,groupBean.getTitle(), 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 groupName, String groupTitle, String username){
//
// // get the groups admin
// Map<RolesCkanGroupOrOrg, List<String>> userAndRoles = catalogue.getRolesAndUsersGroup(groupName);
//
// if(userAndRoles.containsKey(RolesCkanGroupOrOrg.ADMIN)){
//
// List<String> admins = userAndRoles.get(RolesCkanGroupOrOrg.ADMIN);
// List<String> adminsEmails = new ArrayList<String>();
//
// for(int i = 0; i < admins.size(); i++){
// String convertedName = CatalogueUtilMethods.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<String> 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).replace("$DATASET_URL", datasetUrl),
// request);
// mailToSend.sendEmail();
//
// }else
// logger.warn("It seems there is no user with role Admin in group " + groupTitle);
// }
//}

@ -1,325 +1,322 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.server.threads;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.List;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.GCoreEndPointReaderSocial;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.GenericUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import eu.trentorise.opendata.jackan.internal.org.apache.http.Header;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpEntity;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.ClientProtocolException;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpPost;
import eu.trentorise.opendata.jackan.internal.org.apache.http.entity.StringEntity;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder;
import eu.trentorise.opendata.jackan.internal.org.apache.http.util.EntityUtils;
/**
* Let the Product Catalogue Manager write a post in a VRE and alert there is a new product
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
public class WritePostCatalogueManagerThread extends Thread {
public static final String APPLICATION_ID_CATALOGUE_MANAGER = "org.gcube.datacatalogue.ProductCatalogue";
private static final String NOTIFICATION_MESSAGE = "Dear members,\n$USER_FULLNAME just published the item '$PRODUCT_TITLE'.\nYou can find it at: $PRODUCT_URL\n";
private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "2/tokens/generate-application-token";
private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "2/posts/write-post-app";
private static final String MEDIATYPE_JSON = "application/json";
private static final Log logger = LogFactoryUtil.getLog(WritePostCatalogueManagerThread.class);
private String username;
private String scope;
private String productTitle;
private String productUrl;
private boolean enableNotification;
private List<String> hashtags;
private String userFullName;
private String userCurrentUrl;
/**
* @param token
* @param scope
* @param productTitle
* @param productUrl
* @param enableNotification
* @param hashtags
* @param userFullName
*/
public WritePostCatalogueManagerThread(
String username, String scope,
String productTitle, String productUrl, boolean enableNotification,
List<String> hashtags, String userFullName, String userCurrentUrl) {
super();
this.username = username;
this.scope = scope;
this.productTitle = productTitle;
this.productUrl = productUrl;
this.enableNotification = enableNotification;
this.hashtags = hashtags;
this.userFullName = userFullName;
this.userCurrentUrl = userCurrentUrl;
}
@Override
public void run() {
try{
// evaluate user's token for this scope
String token = GenericUtils.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 "
+ "token is " + token.substring(0, 10) + "****************");
// set token and scope
ScopeProvider.instance.set(scope);
SecurityTokenProvider.instance.set(token);
//see Feature #17577
/*final String profilePageURL = GCubePortalConstants.PREFIX_GROUP_URL + extractOrgFriendlyURL(userCurrentUrl) + GCubePortalConstants.USER_PROFILE_FRIENDLY_URL;
userFullName = "<a class=\"link\" href=\"" + profilePageURL + "?"+
Base64.getEncoder().encodeToString(GCubeSocialNetworking.USER_PROFILE_OID.getBytes())+"="+
Base64.getEncoder().encodeToString(username.getBytes())+"\">"+userFullName+
"</a> ";
*/
userFullName = "@"+username;
// write
writeProductPost(
productTitle,
productUrl,
userFullName,
hashtags,
enableNotification
);
}catch(Exception e){
logger.error("Failed to write the post because of the following error ", e);
}finally{
SecurityTokenProvider.instance.reset();
ScopeProvider.instance.reset();
}
}
public static String extractOrgFriendlyURL(String portalURL) {
String groupRegEx = "/group/";
if (portalURL.contains(groupRegEx)) {
String[] splits = portalURL.split(groupRegEx);
String friendlyURL = splits[1];
if (friendlyURL.contains("/")) {
friendlyURL = friendlyURL.split("/")[0];
} else {
friendlyURL = friendlyURL.split("\\?")[0].split("\\#")[0];
}
return "/"+friendlyURL;
}
return null;
}
/**
* Send notification to vre members about the created product by writing a post.
* @param productName the title of the product
* @param productUrl the url of the product
* @param hashtags a list of product's hashtags
*/
private static void writeProductPost(String productName, String productUrl, String userFullname, List<String> hashtags, boolean enablePostNotification){
// discover service endpoint for the social networking library
String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
String basePath = new GCoreEndPointReaderSocial(currentScope).getBasePath();
if(basePath == null){
logger.error("Unable to write a post because there is no social networking service available");
}else{
// check base path form
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String pathTokenApp = basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser;
String tokenApp = requireAppToken(client, pathTokenApp);
if(tokenApp != null){
String pathWritePost = basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + tokenApp;
writePost(client, pathWritePost, productName, productUrl, userFullname, hashtags, enablePostNotification);
}
}catch(Exception e){
logger.error("Failed to create a post", e);
}
}
}
/**
* Require the application token
* @param tokenUser
* @param basePath
* @param client
* @return
*/
private static String requireAppToken(CloseableHttpClient client, String path){
String token = null;
try{
JSONObject request = new JSONObject();
request.put("app_id", APPLICATION_ID_CATALOGUE_MANAGER);
HttpResponse response = performRequest(client, path, request.toJSONString());
int statusTokenGenerate = response.getStatusLine().getStatusCode();
if(statusTokenGenerate == HttpURLConnection.HTTP_CREATED){
// extract token
JSONObject obj = getJSONObject(response);
if(((Boolean) obj.get("success")))
token = (String)obj.get("result");
else
return null;
}else if(statusTokenGenerate == HttpURLConnection.HTTP_MOVED_TEMP
|| statusTokenGenerate == HttpURLConnection.HTTP_MOVED_PERM
|| statusTokenGenerate == HttpURLConnection.HTTP_SEE_OTHER){
// re-execute
Header[] locations = response.getHeaders("Location");
Header lastLocation = locations[locations.length - 1];
String realLocation = lastLocation.getValue();
logger.debug("New location is " + realLocation);
token = requireAppToken(client, realLocation);
}else
return null;
}catch(Exception e){
logger.error("Failed to retrieve application token", e);
}
logger.info("Returning app token " + (token != null ? token.substring(0, 10) + "*************************" : null));
return token;
}
/**
* Write post request
* @param client
* @param applicationToken
* @param productName
* @param productUrl
* @param userFullname
* @param hashtags
*/
private static void writePost(CloseableHttpClient client, String path, String productName, String productUrl, String userFullname, List<String> hashtags,
boolean enablePostNotification) {
try{
// replace
String message = NOTIFICATION_MESSAGE.replace("$PRODUCT_TITLE", productName).replace("$PRODUCT_URL", productUrl).replace("$USER_FULLNAME", userFullname);
if(hashtags != null && !hashtags.isEmpty())
for (String hashtag : hashtags) {
String modifiedHashtag = hashtag.replaceAll(" ", "_").replace("_+", "_");
if(modifiedHashtag.endsWith("_"))
modifiedHashtag = modifiedHashtag.substring(0, modifiedHashtag.length() - 1);
message += " #" + modifiedHashtag; // ckan accepts tag with empty spaces, we don't
}
JSONObject request = new JSONObject();
request.put("text", message);
request.put("enable_notification", enablePostNotification);
logger.info("The post that is going to be written is ->\n" + request.toJSONString());
HttpResponse response = performRequest(client, path, request.toJSONString());
int statusWritePost = response.getStatusLine().getStatusCode();
if(statusWritePost == HttpURLConnection.HTTP_CREATED){
// extract token
JSONObject obj = getJSONObject(response);
if(((Boolean) obj.get("success")))
logger.info("Post written");
else
logger.info("Failed to write the post " + obj.get("message"));
}else if(statusWritePost == HttpURLConnection.HTTP_MOVED_TEMP
|| statusWritePost == HttpURLConnection.HTTP_MOVED_PERM
|| statusWritePost == HttpURLConnection.HTTP_SEE_OTHER){
// re-execute
Header[] locations = response.getHeaders("Location");
Header lastLocation = locations[locations.length - 1];
String realLocation = lastLocation.getValue();
logger.debug("New location is " + realLocation);
writePost(client, realLocation, productName, productUrl, userFullname, hashtags, enablePostNotification);
}else
throw new RuntimeException("Failed to write the post ");
}catch(Exception e){
logger.error("Failed to write the post ", e);
}
}
/**
* Convert the json response to a map
* @param response
* @return
*/
private static JSONObject getJSONObject(HttpResponse response){
JSONObject toReturn = null;
HttpEntity entity = response.getEntity();
if (entity != null) {
try {
String jsonString = EntityUtils.toString(response.getEntity());
JSONParser parser = new JSONParser();
toReturn = (JSONObject)parser.parse(jsonString);
}catch(Exception e){
logger.error("Failed to read json object", e);
}
}
logger.debug("Returning " + toReturn.toJSONString());
return toReturn;
}
/**
* Perform an http request post request with json entity
* @throws IOException
* @throws ClientProtocolException
*/
private static HttpResponse performRequest(CloseableHttpClient client, String path, String entity) throws ClientProtocolException, IOException{
HttpPost request = new HttpPost(path);
StringEntity stringEntity = new StringEntity(entity);
stringEntity.setContentType(MEDIATYPE_JSON);
request.setEntity(stringEntity);
return client.execute(request);
}
}
//package org.gcube.portlets.widgets.ckandatapublisherwidget.server.threads;
//
//import java.io.IOException;
//import java.net.HttpURLConnection;
//import java.util.List;
//
//import org.apache.http.HttpEntity;
//import org.apache.http.HttpResponse;
//import org.apache.http.client.ClientProtocolException;
//import org.apache.http.client.methods.HttpPost;
//import org.apache.http.entity.StringEntity;
//import org.apache.http.impl.client.CloseableHttpClient;
//import org.apache.http.impl.client.HttpClientBuilder;
//import org.apache.http.util.EntityUtils;
//import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
//import org.gcube.common.scope.api.ScopeProvider;
//import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.GCoreEndPointReaderSocial;
//import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.GenericUtils;
//
//import com.google.gwt.json.client.JSONParser;
//import com.liferay.portal.kernel.log.Log;
//import com.liferay.portal.kernel.log.LogFactoryUtil;
//
//
///**
// * Let the Product Catalogue Manager write a post in a VRE and alert there is a new product
// * @author Costantino Perciante at ISTI-CNR
// * (costantino.perciante@isti.cnr.it)
// */
//public class WritePostCatalogueManagerThread extends Thread {
//
// public static final String APPLICATION_ID_CATALOGUE_MANAGER = "org.gcube.datacatalogue.ProductCatalogue";
// private static final String NOTIFICATION_MESSAGE = "Dear members,\n$USER_FULLNAME just published the item '$PRODUCT_TITLE'.\nYou can find it at: $PRODUCT_URL\n";
// private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "2/tokens/generate-application-token";
// private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "2/posts/write-post-app";
// private static final String MEDIATYPE_JSON = "application/json";
// private static final Log logger = LogFactoryUtil.getLog(WritePostCatalogueManagerThread.class);
// private String username;
// private String scope;
// private String productTitle;
// private String productUrl;
// private boolean enableNotification;
// private List<String> hashtags;
// private String userFullName;
// private String userCurrentUrl;
//
// /**
// * @param token
// * @param scope
// * @param productTitle
// * @param productUrl
// * @param enableNotification
// * @param hashtags
// * @param userFullName
// */
// public WritePostCatalogueManagerThread(
// String username, String scope,
// String productTitle, String productUrl, boolean enableNotification,
// List<String> hashtags, String userFullName, String userCurrentUrl) {
// super();
// this.username = username;
// this.scope = scope;
// this.productTitle = productTitle;
// this.productUrl = productUrl;
// this.enableNotification = enableNotification;
// this.hashtags = hashtags;
// this.userFullName = userFullName;
// this.userCurrentUrl = userCurrentUrl;
// }
//
// @Override
// public void run() {
//
// try{
// // evaluate user's token for this scope
// String token = GenericUtils.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 "
// + "token is " + token.substring(0, 10) + "****************");
//
// // set token and scope
// ScopeProvider.instance.set(scope);
// SecurityTokenProvider.instance.set(token);
//
// //see Feature #17577
// /*final String profilePageURL = GCubePortalConstants.PREFIX_GROUP_URL + extractOrgFriendlyURL(userCurrentUrl) + GCubePortalConstants.USER_PROFILE_FRIENDLY_URL;
//
// userFullName = "<a class=\"link\" href=\"" + profilePageURL + "?"+
// Base64.getEncoder().encodeToString(GCubeSocialNetworking.USER_PROFILE_OID.getBytes())+"="+
// Base64.getEncoder().encodeToString(username.getBytes())+"\">"+userFullName+
// "</a> ";
// */
//
// userFullName = "@"+username;
//
// // write
// writeProductPost(
// productTitle,
// productUrl,
// userFullName,
// hashtags,
// enableNotification
// );
//
// }catch(Exception e){
// logger.error("Failed to write the post because of the following error ", e);
// }finally{
// SecurityTokenProvider.instance.reset();
// ScopeProvider.instance.reset();
// }
// }
//
// public static String extractOrgFriendlyURL(String portalURL) {
// String groupRegEx = "/group/";
// if (portalURL.contains(groupRegEx)) {
// String[] splits = portalURL.split(groupRegEx);
// String friendlyURL = splits[1];
// if (friendlyURL.contains("/")) {
// friendlyURL = friendlyURL.split("/")[0];
// } else {
// friendlyURL = friendlyURL.split("\\?")[0].split("\\#")[0];
// }
// return "/"+friendlyURL;
// }
// return null;
// }
//
// /**
// * Send notification to vre members about the created product by writing a post.
// * @param productName the title of the product
// * @param productUrl the url of the product
// * @param hashtags a list of product's hashtags
// */
// private static void writeProductPost(String productName, String productUrl, String userFullname, List<String> hashtags, boolean enablePostNotification){
//
// // discover service endpoint for the social networking library
// String currentScope = ScopeProvider.instance.get();
// String tokenUser = SecurityTokenProvider.instance.get();
//
// logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
// String basePath = new GCoreEndPointReaderSocial(currentScope).getBasePath();
//
// if(basePath == null){
//
// logger.error("Unable to write a post because there is no social networking service available");
//
// }else{
//
// // check base path form
// basePath = basePath.endsWith("/") ? basePath : basePath + "/";
//
// try(CloseableHttpClient client = HttpClientBuilder.create().build();){
//
// String pathTokenApp = basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser;
// String tokenApp = requireAppToken(client, pathTokenApp);
// if(tokenApp != null){
// String pathWritePost = basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + tokenApp;
// writePost(client, pathWritePost, productName, productUrl, userFullname, hashtags, enablePostNotification);
// }
//
// }catch(Exception e){
// logger.error("Failed to create a post", e);
// }
// }
// }
//
// /**
// * Require the application token
// * @param tokenUser
// * @param basePath
// * @param client
// * @return
// */
// private static String requireAppToken(CloseableHttpClient client, String path){
//
// String token = null;
// try{
//
// JSONObject request = new JSONObject();
// request.put("app_id", APPLICATION_ID_CATALOGUE_MANAGER);
// HttpResponse response = performRequest(client, path, request.toJSONString());
//
// int statusTokenGenerate = response.getStatusLine().getStatusCode();
//
// if(statusTokenGenerate == HttpURLConnection.HTTP_CREATED){
//
// // extract token
// JSONObject obj = getJSONObject(response);
// if(((Boolean) obj.get("success")))
// token = (String)obj.get("result");
// else
// return null;
//
// }else if(statusTokenGenerate == HttpURLConnection.HTTP_MOVED_TEMP
// || statusTokenGenerate == HttpURLConnection.HTTP_MOVED_PERM
// || statusTokenGenerate == HttpURLConnection.HTTP_SEE_OTHER){
//
// // re-execute
// Header[] locations = response.getHeaders("Location");
// Header lastLocation = locations[locations.length - 1];
// String realLocation = lastLocation.getValue();
// logger.debug("New location is " + realLocation);
// token = requireAppToken(client, realLocation);
//
// }else
// return null;
//
// }catch(Exception e){
// logger.error("Failed to retrieve application token", e);
// }
//
// logger.info("Returning app token " + (token != null ? token.substring(0, 10) + "*************************" : null));
// return token;
// }
//
// /**
// * Write post request
// * @param client
// * @param applicationToken
// * @param productName
// * @param productUrl
// * @param userFullname
// * @param hashtags
// */
// private static void writePost(CloseableHttpClient client, String path, String productName, String productUrl, String userFullname, List<String> hashtags,
// boolean enablePostNotification) {
//
// try{
//
// // replace
// String message = NOTIFICATION_MESSAGE.replace("$PRODUCT_TITLE", productName).replace("$PRODUCT_URL", productUrl).replace("$USER_FULLNAME", userFullname);
//
// if(hashtags != null && !hashtags.isEmpty())
// for (String hashtag : hashtags) {
// String modifiedHashtag = hashtag.replaceAll(" ", "_").replace("_+", "_");
// if(modifiedHashtag.endsWith("_"))
// modifiedHashtag = modifiedHashtag.substring(0, modifiedHashtag.length() - 1);
// message += " #" + modifiedHashtag; // ckan accepts tag with empty spaces, we don't
// }
//
// JSONObject request = new JSONObject();
// request.put("text", message);
// request.put("enable_notification", enablePostNotification);
// logger.info("The post that is going to be written is ->\n" + request.toJSONString());
// HttpResponse response = performRequest(client, path, request.toJSONString());
// int statusWritePost = response.getStatusLine().getStatusCode();
//
// if(statusWritePost == HttpURLConnection.HTTP_CREATED){
//
// // extract token
// JSONObject obj = getJSONObject(response);
// if(((Boolean) obj.get("success")))
// logger.info("Post written");
// else
// logger.info("Failed to write the post " + obj.get("message"));
//
// }else if(statusWritePost == HttpURLConnection.HTTP_MOVED_TEMP
// || statusWritePost == HttpURLConnection.HTTP_MOVED_PERM
// || statusWritePost == HttpURLConnection.HTTP_SEE_OTHER){
//
// // re-execute
// Header[] locations = response.getHeaders("Location");
// Header lastLocation = locations[locations.length - 1];
// String realLocation = lastLocation.getValue();
// logger.debug("New location is " + realLocation);
// writePost(client, realLocation, productName, productUrl, userFullname, hashtags, enablePostNotification);
//
// }else
// throw new RuntimeException("Failed to write the post ");
//
// }catch(Exception e){
// logger.error("Failed to write the post ", e);
// }
//
// }
//
// /**
// * Convert the json response to a map
// * @param response
// * @return
// */
// private static JSONObject getJSONObject(HttpResponse response){
//
// JSONObject toReturn = null;
// HttpEntity entity = response.getEntity();
//
// if (entity != null) {
// try {
// String jsonString = EntityUtils.toString(response.getEntity());
// JSONParser parser = new JSONParser();
// toReturn = (JSONObject)parser.parse(jsonString);
// }catch(Exception e){
// logger.error("Failed to read json object", e);
// }
// }
//
// logger.debug("Returning " + toReturn.toJSONString());
// return toReturn;
// }
//
// /**
// * Perform an http request post request with json entity
// * @throws IOException
// * @throws ClientProtocolException
// */
// private static HttpResponse performRequest(CloseableHttpClient client, String path, String entity) throws ClientProtocolException, IOException{
//
// HttpPost request = new HttpPost(path);
// StringEntity stringEntity = new StringEntity(entity);
// stringEntity.setContentType(MEDIATYPE_JSON);
// request.setEntity(stringEntity);
// return client.execute(request);
//
// }
//
//}

@ -4,8 +4,9 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg;
import org.gcube.datacatalogue.utillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanOrganization;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.CKANPublisherServicesImpl;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
import org.gcube.vomanagement.usermanagement.GroupManager;
@ -19,18 +20,17 @@ import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeGroup;
import org.gcube.vomanagement.usermanagement.model.GCubeRole;
import org.gcube.vomanagement.usermanagement.model.GatewayRolesNames;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import eu.trentorise.opendata.jackan.model.CkanOrganization;
/**
* Facilities to check roles into the catalogue.
*/
public class CatalogueRoleManager {
private static final Log logger = LogFactoryUtil.getLog(CatalogueRoleManager.class);
private static final Logger logger = LoggerFactory.getLogger(CatalogueRoleManager.class);
/**
* Retrieve the highest ckan role the user has and also retrieve the list of organizations (scopes) in which the user has the ckan-admin or ckan-editor role

@ -10,24 +10,23 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.gcube.common.resources.gcore.utils.XPathHelper;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.shared.ex.ApplicationProfileNotFoundException;
import org.gcube.datacatalogue.utillibrary.shared.ex.ApplicationProfileNotFoundException;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.CKANPublisherServicesImpl;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.Query;
import org.gcube.resources.discovery.client.queries.impl.QueryBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
/**
* Discover in a given context if there is a Generic Resource containing the list of tags to be used within the widget.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class DiscoverTagsList {
private static final Log logger = LogFactoryUtil.getLog(CKANPublisherServicesImpl.class);
private static final Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class);
private final static String APPLICATION_PROFILE_NAME = "Tags";
private final static String QUERY = "for $profile in collection('/db/Profiles/GenericResource')//Resource " +

@ -9,9 +9,8 @@ import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Retrieves the base url of the social-networking service in the scope provided
@ -20,7 +19,7 @@ import com.liferay.portal.kernel.log.LogFactoryUtil;
public class GCoreEndPointReaderSocial {
private String basePath = null;
private static final Log logger = LogFactoryUtil.getLog(GCoreEndPointReaderSocial.class);
private static final Logger logger = LoggerFactory.getLogger(GCoreEndPointReaderSocial.class);
private static final String resource = "jersey-servlet";
private static final String serviceName = "SocialNetworking";
private static final String serviceClass = "Portal";

@ -15,16 +15,15 @@ import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.ApplicationProfileScopePerUrlReader;
import org.gcube.datacatalogue.utillibrary.server.ApplicationProfileScopePerUrlReader;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager;
import org.gcube.vomanagement.usermanagement.model.GCubeGroup;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Util class with static methods.
@ -35,7 +34,7 @@ public class GenericUtils {
// Logger
//private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Utils.class);
private static final Log logger = LogFactoryUtil.getLog(GenericUtils.class);
private static final Logger logger = LoggerFactory.getLogger(GenericUtils.class);
public static final String GCUBE_REQUEST_URL = "gcube-request-url";
/**
@ -52,13 +51,18 @@ public class GenericUtils {
GroupManager gm = new LiferayGroupManager();
List<GCubeGroup> groups = gm.listGroups();
for (GCubeGroup gCubeGroup : groups) {
if(gCubeGroup.getGroupName().equalsIgnoreCase(organizationName))
return gm.getInfrastructureScope(gCubeGroup.getGroupId());
if(gCubeGroup.getGroupName().equalsIgnoreCase(organizationName)) {
String theScope = gm.getInfrastructureScope(gCubeGroup.getGroupId());
logger.info("For organizationName: " + organizationName+" by using "+LiferayGroupManager.class.getSimpleName()+ " got the scope: "+theScope +", returning it");
return theScope;
}
}
logger.info("No scope detected for organizationName: " + organizationName +" by using "+LiferayGroupManager.class.getSimpleName());
return null;
}
/**
* First check to retrieve the token, else create it.
*

@ -10,8 +10,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.SessionCatalogueAttributes;
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataField;
@ -21,6 +19,8 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataTagging;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataValidator;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataVocabulary;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory;
import org.gcube.datacatalogue.utillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.datacatalogue.utillibrary.server.utils.SessionCatalogueAttributes;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.CategoryWrapper;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.DataTypeWrapper;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.FieldAsGroup;
@ -28,9 +28,8 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.FieldA
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.MetaDataProfileBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.MetadataFieldWrapper;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.metadata.TaggingGroupingValue;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Metadatadiscovery facility.
@ -38,7 +37,7 @@ import com.liferay.portal.kernel.log.LogFactoryUtil;
*/
public class MetadataDiscovery {
private static final Log logger = LogFactoryUtil.getLog(MetadataDiscovery.class);
private static final Logger logger = LoggerFactory.getLogger(MetadataDiscovery.class);
/**
* Returns the names of the metadata profiles in a given context

@ -1,5 +1,6 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -8,90 +9,186 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.gcube.common.homelibary.model.items.type.FolderItemType;
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.WorkspaceFolder;
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
import org.gcube.common.homelibrary.home.workspace.catalogue.WorkspaceCatalogue;
import org.gcube.common.homelibrary.home.workspace.folder.FolderItem;
import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalUrl;
import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.datacatalogue.ckanutillibrary.shared.ResourceBean;
import javax.servlet.http.HttpServletRequest;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.storagehubwrapper.server.StorageHubWrapper;
import org.gcube.common.storagehubwrapper.server.tohl.Workspace;
import org.gcube.common.storagehubwrapper.shared.tohl.WorkspaceItem;
import org.gcube.common.storagehubwrapper.shared.tohl.impl.URLFile;
import org.gcube.common.storagehubwrapper.shared.tohl.items.FileItem;
import org.gcube.common.storagehubwrapper.shared.tohl.items.GCubeItem;
import org.gcube.common.storagehubwrapper.shared.tohl.items.PropertyMap;
import org.gcube.datacatalogue.utillibrary.shared.ResourceBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
/**
* The Class WorkspaceUtils.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Feb 18, 2021
*/
public class WorkspaceUtils {
//private static final org.slf4j.Logger logger = LoggerFactory.getLogger(WorkspaceUtils.class);
private static final Log logger = LogFactoryUtil.getLog(WorkspaceUtils.class);
private static final Logger logger = LoggerFactory.getLogger(WorkspaceUtils.class);
private static final String RESOURCES_NAME_SEPARATOR = "_";
private static final String STRIP_NOT_ALPHANUMERIC = "[^A-Za-z0-9.-_]";
/**
* This method receives a folder id within the user's workspace and set the list of resources in the dataset bean to be returned
* @param folderId
* @param owner
* @param bean
* @param userName
* Checks if is within portal.
*
* @return true if you're running into the portal, false if in development
*/
public static boolean isWithinPortal() {
try {
UserLocalServiceUtil.getService();
return true;
} catch (Exception ex) {
logger.trace("Development Mode ON");
return false;
}
}
/**
* Gets the storage hub wrapper.
*
* @param request
* the request
* @param scopeGroupId
* the scope group id. If scopeGroupId is null the scope is read
* by using the request else by using the scopeGroupId
* @param user
* the user
* @return the storage hub wrapper
* @throws Exception
* the exception
*/
public static void handleWorkspaceResources(String folderId, String userName,
DatasetBean bean) throws Exception {
// get workspace
Workspace ws = HomeLibrary
.getHomeManagerFactory()
.getHomeManager()
.getHome().getWorkspace();
public static StorageHubWrapper getStorageHubWrapper(final HttpServletRequest request, String scopeGroupId,
GCubeUser user) throws Exception {
if (user == null || user.getUsername().isEmpty())
throw new Exception("Session expired");
try {
String scope;
PortalContext pContext = PortalContext.getConfiguration();
if (isWithinPortal() && scopeGroupId != null) {
scope = pContext.getCurrentScope(scopeGroupId);
logger.debug(scope + " has retrieved by using the scopeGroupId=" + scopeGroupId);
} else
scope = pContext.getCurrentScope(request);
logger.debug("Getting " + StorageHubWrapper.class.getSimpleName() + " for user: " + user.getUsername()
+ " by using the scope: " + scope);
String token = pContext.getCurrentUserToken(scope, user.getUsername());
return new StorageHubWrapper(scope, token, false, false, true);
} catch (Exception e) {
logger.error("Error during getting storageHub wrapper", e);
throw new Exception("Error on gettig the StorageHub wrapper for userId: " + user);
}
}
/**
* This method receives an item-id within the user's workspace and setit in the dataset bean to be returned.
* revisited by Francesco
*
* @param wsItemId the ws item id
* @param userName the user name
* @param bean the bean
* @param workspace the workspace
* @throws Exception the exception
*/
public static void toWorkspaceResource(String wsItemId, String userName,
DatasetBean bean, Workspace workspace) throws Exception {
WorkspaceItem originalFolderOrFile = ws.getItem(folderId);
WorkspaceItem originalFolderOrFile = workspace.getItem(wsItemId);
logger.debug("Item retrieved is " + originalFolderOrFile);
if(!originalFolderOrFile.isFolder()){
ResourceElementBean resource = new ResourceElementBean();
resource.setDescription(originalFolderOrFile.getDescription());
resource.setFolder(false);
resource.setEditableName(originalFolderOrFile.getName());
resource.setName(originalFolderOrFile.getName());
resource.setOriginalIdInWorkspace(folderId);
bean.setResourceRoot(resource);
bean.setTitle(originalFolderOrFile.getName().replaceAll(STRIP_NOT_ALPHANUMERIC, " "));
bean.setDescription(originalFolderOrFile.getDescription());
}else{
String onlyAlphanumericTitle = originalFolderOrFile.getName().replaceAll(STRIP_NOT_ALPHANUMERIC, " ");
bean.setTitle(onlyAlphanumericTitle);
bean.setDescription(originalFolderOrFile.getDescription());
// Create the folder in the catalogue
String title = originalFolderOrFile.getTitle() != null && !originalFolderOrFile.getTitle().isEmpty()
? originalFolderOrFile.getTitle()
: originalFolderOrFile.getName();
title = title.replaceAll(STRIP_NOT_ALPHANUMERIC, " ");
bean.setTitle(title);
ResourceElementBean resourceEB = new ResourceElementBean();
resourceEB.setOriginalIdInWorkspace(wsItemId);
resourceEB.setName(originalFolderOrFile.getName());
resourceEB.setDescription(originalFolderOrFile.getDescription());
resourceEB.setFolder(originalFolderOrFile.isFolder());
resourceEB.setEditableName(originalFolderOrFile.getName());
resourceEB.setRootIdInWorkspace(workspace.getRoot().getId());
//in case of folder
if(originalFolderOrFile.isFolder()) {
// loading gcube properties
Map<String, String> folderItems = getGcubeItemProperties(originalFolderOrFile);
if(folderItems != null){
if(folderItems != null && folderItems.size()>0){
// transform this properties
Map<String, List<String>> tempItems = new HashMap<String, List<String>>(folderItems.size());
Iterator<Entry<String, String>> iterator = folderItems.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<java.lang.String, java.lang.String> entry = (Map.Entry<java.lang.String, java.lang.String>) iterator
.next();
Map.Entry<java.lang.String, java.lang.String> entry = (Map.Entry<java.lang.String, java.lang.String>) iterator.next();
tempItems.put(entry.getKey(), Arrays.asList(entry.getValue()));
}
//setting properties as custom fields
bean.setCustomFields(tempItems);
}
// set them into the bean
bean.setResourceRoot(WorkspaceUtils.getTreeFromFolder(folderId, ws));
resourceEB.setChildrenSize(workspace.getChildren(originalFolderOrFile.getId()).size());
}else {
//it is a file, removing extension
int indexOfDot = title.lastIndexOf(".");
if(indexOfDot>0) {
String suffix = title.substring(indexOfDot, title.length());
if(suffix.length()>=1 && suffix.length()<=4) {
//I'm considering last .suffix as an file extension so removing it.
title = title.substring(0,indexOfDot);
bean.setTitle(title);
}
}
}
//Replacing /Home/user.name with ""
String fullPathBase = originalFolderOrFile.getPath();
logger.debug("Path is: "+fullPathBase);
String prefixNodeWorkspace = String.format("/%s/%s", "Home",userName);
logger.debug("Searching: "+prefixNodeWorkspace);
if(fullPathBase.startsWith(prefixNodeWorkspace)){
logger.info("Removing from path the prefix: "+prefixNodeWorkspace);
fullPathBase = fullPathBase.replaceFirst(prefixNodeWorkspace, "");
}
resourceEB.setFullPath(fullPathBase);
//setting parent id
ResourceElementBean theParent = new ResourceElementBean();
if(originalFolderOrFile.getParentId()!=null) {
try {
WorkspaceItem parentItem = workspace.getItem(originalFolderOrFile.getParentId());
theParent.setOriginalIdInWorkspace(parentItem.getId());
theParent.setName(parentItem.getName());
}catch (Exception e) {
logger.warn("Error on loading the parent item with id: "+originalFolderOrFile.getParentId()+" skipping it");
}
}
resourceEB.setParent(theParent);
bean.setResourceRoot(resourceEB);
}
/** Gets the gcube item properties.
@ -104,143 +201,180 @@ public class WorkspaceUtils {
if(item instanceof GCubeItem){
GCubeItem gItem = (GCubeItem) item;
try {
if(gItem.getProperties()!=null){
Map<String, String> map = gItem.getProperties().getProperties();
HashMap<String, String> properties = new HashMap<String, String>(map.size()); //TO PREVENT GWT SERIALIZATION ERROR
for (String key : map.keySet())
properties.put(key, map.get(key));
Map<String, String> properties = null;
if(gItem.getPropertyMap()!=null){
Map<String, String> map = toSimpleMap(gItem.getPropertyMap());
if(map!=null) {
properties = new HashMap<String, String>(map.size()); //TO PREVENT GWT SERIALIZATION ERROR
for (String key : map.keySet())
properties.put(key, map.get(key));
}
return properties;
}
} catch (InternalErrorException e) {
} catch (Exception e) {
logger.error("Error in server getItemProperties: ", e);
}
}
return null;
}
/**
* Returns a tree object
* @param workspaceFolderId
* @param ws
* @return ResourceElementBean a tree object
* @throws Exception
*/
public static ResourceElementBean getTreeFromFolder(String workspaceFolderId, Workspace ws) throws Exception{
ResourceElementBean rootElem = new ResourceElementBean();
String pathSeparator = ws.getPathSeparator();
WorkspaceItem initialItem = ws.getItem(workspaceFolderId);
String fullPathBase = initialItem.getPath();
fullPathBase = fullPathBase.endsWith(ws.getPathSeparator()) ? fullPathBase : fullPathBase + ws.getPathSeparator();
rootElem.setFolder(initialItem.isFolder());
rootElem.setFullPath(initialItem.getPath().replace(fullPathBase, ""));
rootElem.setName(initialItem.getName());
rootElem.setOriginalIdInWorkspace(initialItem.getId());
rootElem.setDescription(initialItem.getDescription());
extractEditableNameFromPath(rootElem, pathSeparator);
// recursive visiting
if(initialItem.isFolder())
visit(rootElem, initialItem, fullPathBase, pathSeparator);
logger.debug("Tree that is going to be returned is " + rootElem);
return rootElem;
}
/**
* Recursive visit of a workspace item
* @param rootElem
* @param initialItemWS
* @throws InternalErrorException
* To simple map.
*
* @param propertyMap the property map
* @return the map
*/
private static void visit(ResourceElementBean parent, WorkspaceItem initialItemWS, String fullPathBase, String pathSeparator) throws InternalErrorException {
List<? extends WorkspaceItem> children = initialItemWS.getChildren();
ArrayList<ResourceElementBean> childrenInTree = new ArrayList<ResourceElementBean>(children.size());
for (WorkspaceItem item : children) {
// logger.debug("Path BEFORE REPLACE is " + item.getPath());
// logger.debug("Path AFTER REPLACE is " + item.getPath().replace(fullPathBase, ""));
// logger.debug("Name is " + item.getName());
// logger.debug("id is " + item.getId());
ResourceElementBean elem = new ResourceElementBean();
elem.setFolder(item.isFolder());
elem.setOriginalIdInWorkspace(item.getId());
elem.setFullPath(item.getPath().replace(fullPathBase, ""));
elem.setParent(parent);
elem.setName(item.getName());
elem.setDescription(item.getDescription());
extractEditableNameFromPath(elem, pathSeparator);
childrenInTree.add(elem);
logger.trace("Elem is " + elem);
if(item.isFolder())
visit(elem, item, fullPathBase, pathSeparator);
public static Map<String, String> toSimpleMap(PropertyMap propertyMap) {
if (propertyMap == null)
return null;
try {
Map<String, String> properties = null;
Map<String, Object> map = propertyMap.getValues();
if (map != null) {
properties = new HashMap<String, String>(map.size());
for (String key : map.keySet()) {
Object theValue = map.get(key);
properties.put(key, (String) theValue);
}
}
if(properties!=null)
logger.error("Converted: "+properties.size()+" property/properties");
return properties;
} catch (Exception e) {
logger.error("Error on converting a PropertyMap to simple Map<String,String>: ", e);
return null;
}
// add these list as child of the rootElem
parent.setChildren(childrenInTree);
}
/**
* Replaces the "/" char with a custom one and return an editable name for the user
* @param rootElem
* @param pathSeparatorInWs
*/
private static void extractEditableNameFromPath(ResourceElementBean rootElem, String pathSeparatorInWs) {
if(rootElem == null)
return;
String elemName = rootElem.getName();
String fullPath = rootElem.getFullPath();
logger.info("Element original is " + rootElem);
int lastIndex = rootElem.getFullPath().lastIndexOf(elemName);
fullPath = rootElem.getFullPath().substring(0, lastIndex);
fullPath = fullPath.replaceAll(pathSeparatorInWs, RESOURCES_NAME_SEPARATOR) + elemName;
rootElem.setEditableName(fullPath);
}
// /**
// * Returns ResourceElementBean corresponding to workspaceFolderId
// *
// * @param workspaceFolderId the workspace folder id
// * @param workspace the workspace
// * @return ResourceElementBean a tree object
// * @throws Exception the exception
// */
// public static ResourceElementBean toResourceEBFromFolder(String workspaceFolderId, Workspace workspace) throws Exception{
//
// ResourceElementBean rootElem = new ResourceElementBean();
// String pathSeparator = "/";
//
// //String pathSeparator = ws.getPathSeparator();
//
// WorkspaceItem initialItem = workspace.getItem(workspaceFolderId);
// String fullPathBase = initialItem.getPath();
// fullPathBase = fullPathBase.endsWith(pathSeparator) ? fullPathBase : fullPathBase + pathSeparator;
// rootElem.setFolder(initialItem.isFolder());
// rootElem.setFullPath(initialItem.getPath().replace(fullPathBase, ""));
// rootElem.setName(initialItem.getName());
// rootElem.setOriginalIdInWorkspace(initialItem.getId());
// rootElem.setDescription(initialItem.getDescription());
// extractEditableNameFromPath(rootElem, pathSeparator);
//
// // recursive visiting
//// if(initialItem.isFolder())
//// visit(rootElem, initialItem, workspace, fullPathBase, pathSeparator);
//
// logger.debug("Tree that is going to be returned is " + rootElem);
// return rootElem;
// }
// /**
// * Recursive visit of a workspace item.
// *
// * @param parent the parent
// * @param initialItemWS the initial item WS
// * @param workspace the ws
// * @param fullPathBase the full path base
// * @param pathSeparator the path separator
// * @throws Exception the exception
// */
// private static void visit(ResourceElementBean parent, WorkspaceItem initialItemWS, Workspace workspace, String fullPathBase, String pathSeparator) throws Exception {
// //List<? extends WorkspaceItem> children = initialItemWS.getChildren();
//
// List<? extends WorkspaceItem> children = workspace.getChildren(initialItemWS.getId());
//
// ArrayList<ResourceElementBean> childrenInTree = new ArrayList<ResourceElementBean>(children.size());
// for (WorkspaceItem item : children) {
// // logger.debug("Path BEFORE REPLACE is " + item.getPath());
// // logger.debug("Path AFTER REPLACE is " + item.getPath().replace(fullPathBase, ""));
// // logger.debug("Name is " + item.getName());
// // logger.debug("id is " + item.getId());
// ResourceElementBean elem = new ResourceElementBean();
// elem.setFolder(item.isFolder());
// elem.setOriginalIdInWorkspace(item.getId());
// elem.setFullPath(item.getPath().replace(fullPathBase, ""));
// elem.setParent(parent);
// elem.setName(item.getName());
// elem.setDescription(item.getDescription());
// extractEditableNameFromPath(elem, pathSeparator);
// childrenInTree.add(elem);
// logger.trace("Elem is " + elem);
// if(item.isFolder())
// visit(elem, item, workspace, fullPathBase, pathSeparator);
// }
// // add these list as child of the rootElem
// parent.setChildren(childrenInTree);
// }
// /**
// * Replaces the "/" char with a custom one and return an editable name for the user.
// *
// * @param rootElem the root elem
// * @param pathSeparatorInWs the path separator in ws
// */
// public static void extractEditableNameFromPath(ResourceElementBean rootElem, String pathSeparatorInWs) {
//
// if(rootElem == null)
// return;
//
// String elemName = rootElem.getName();
// String fullPath = rootElem.getFullPath();
// logger.info("Element original is " + rootElem);
//
// int lastIndex = rootElem.getFullPath().lastIndexOf(elemName);
// fullPath = rootElem.getFullPath().substring(0, lastIndex);
// fullPath = fullPath.replaceAll(pathSeparatorInWs, RESOURCES_NAME_SEPARATOR) + elemName;
// rootElem.setEditableName(fullPath);
// logger.info("Editable name for resource name: "+rootElem.getName()+", is: " + rootElem.getEditableName());
// }
/**
* Copy into the .catalogue area folder the checked resources.
* There is no difference among a single-file-publish and a folder-publish.
* @param folderId
* @param userName
* @param bean
* @return
*
* @param bean the bean
* @param workspace the workspace
* @param username the username
* @return the list
* @throws Exception the exception
*/
public static List<ResourceBean> copyResourcesToUserCatalogueArea(String folderOrFileId, String userName, DatasetBean bean) throws Exception{
logger.debug("Request to copy onto catalogue area....");
public static List<ResourceBean> toResources(DatasetBean bean, Workspace workspace, String username) throws Exception{
logger.debug("Called to Resources...: ");
List<ResourceBean> resources = new ArrayList<ResourceBean>();
WorkspaceItem copiedFolder = null;
WorkspaceCatalogue userCatalogue = null;
ResourceElementBean rootResource = bean.getResourceRoot();
// into the .catalogue area of the user's workspace
Workspace ws = HomeLibrary
.getHomeManagerFactory()
.getHomeManager()
.getHome()
.getWorkspace();
// Retrieve the catalogue of the user
userCatalogue = ws.getCatalogue();
// get workspace item (it could be a file or a folder)
WorkspaceItem originalItem = ws.getItem(folderOrFileId);
// copy the folder in the catalogue if it is a folder, or create a new folder
long referenceTime = System.currentTimeMillis();
if(originalItem.isFolder()){
copiedFolder = userCatalogue.addWorkspaceItem(folderOrFileId, userCatalogue.getId()); // add to .catalogue root area
copiedFolder.setDescription(bean.getDescription());
((WorkspaceFolder)copiedFolder).rename(CatalogueUtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime);
}
else{
copiedFolder = userCatalogue.createFolder(CatalogueUtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime, bean.getDescription());
if(rootResource==null) {
logger.info("No resource root, returning empty list of resources");
return resources;
}
// retrieve the children
List<ResourceElementBean> resourcesToAdd = rootResource.getChildren();
List<ResourceElementBean> resourcesToAdd = rootResource.getToPublish();
if(resourcesToAdd==null) {
logger.info("No resource to add, returning empty list of resources");
return resources;
}
// copy only the selected ones
for(ResourceElementBean resource : resourcesToAdd){
@ -250,35 +384,130 @@ public class WorkspaceUtils {
logger.debug("Resource to add is " + resource);
// ok it is a file, so copy it into the copiedFolder
WorkspaceItem copiedFile = userCatalogue.addWorkspaceItem(resource.getOriginalIdInWorkspace(), copiedFolder.getId());
// name and description could have been edited
copiedFile.setDescription(resource.getDescription());
WorkspaceItem wsItem = workspace.getItem(resource.getOriginalIdInWorkspace());
String mimeType = null;
if(wsItem instanceof FileItem) {
mimeType = ((FileItem)wsItem).getMimeType();
}
// check if it is an external url
// check if it is an URLFile
String externalUrl = null;
try{
boolean isExternalUrl = ((FolderItem)copiedFile).getFolderItemType().equals(FolderItemType.EXTERNAL_URL);
externalUrl = isExternalUrl ? ((ExternalUrl)copiedFile).getUrl() : null;
if(wsItem instanceof URLFile) {
URLFile urlFile = (URLFile) wsItem;
externalUrl = urlFile.getValue()!=null?urlFile.getValue().toString():null;
}
}catch(Exception e){
logger.warn("Unable to check if it is an external url file ", e);
}
String resourceURL = externalUrl;
//it is not a URLFile
if(resourceURL==null) {
//getting public link of file
URL publicLink = workspace.getPublicLinkForFile(resource.getOriginalIdInWorkspace());
if(publicLink!=null)
resourceURL = publicLink.toString();
}
resources.add(new ResourceBean(
externalUrl != null ? externalUrl : copiedFile.getPublicLink(true),
resources.add(new ResourceBean(resourceURL,
resource.getEditableName(),
copiedFile.getDescription(),
copiedFile.getId(),
userName,
resource.getDescription(),
wsItem.getId(),
username,
null, // dataset id, to be set
((FolderItem)copiedFile).getMimeType()));
// postpone rename operation
copiedFile.rename(resource.getEditableName());
mimeType));
}
}
return resources;
}
// //MOVED TO GCAT
// /**
// * Copy into the .catalogue area folder the checked resources.
// * There is no difference among a single-file-publish and a folder-publish.
// * @param folderId
// * @param userName
// * @param bean
// * @return
// */
// public static List<ResourceBean> copyResourcesToUserCatalogueArea(String folderOrFileId, String userName, DatasetBean bean) throws Exception{
//
// logger.debug("Request to copy onto catalogue area....");
// List<ResourceBean> resources = new ArrayList<ResourceBean>();
// WorkspaceItem copiedFolder = null;
// WorkspaceCatalogue userCatalogue = null;
// ResourceElementBean rootResource = bean.getResourceRoot();
//
// // into the .catalogue area of the user's workspace
// Workspace ws = HomeLibrary
// .getHomeManagerFactory()
// .getHomeManager()
// .getHome()
// .getWorkspace();
//
// // Retrieve the catalogue of the user
// userCatalogue = ws.getCatalogue();
//
// // get workspace item (it could be a file or a folder)
// WorkspaceItem originalItem = ws.getItem(folderOrFileId);
//
// // copy the folder in the catalogue if it is a folder, or create a new folder
// long referenceTime = System.currentTimeMillis();
// if(originalItem.isFolder()){
// copiedFolder = userCatalogue.addWorkspaceItem(folderOrFileId, userCatalogue.getId()); // add to .catalogue root area
// copiedFolder.setDescription(bean.getDescription());
// ((WorkspaceFolder)copiedFolder).rename(CatalogueUtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime);
// }
// else{
// copiedFolder = userCatalogue.createFolder(CatalogueUtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime, bean.getDescription());
// }
//
// // retrieve the children
// List<ResourceElementBean> resourcesToAdd = rootResource.getChildren();
//
// // copy only the selected ones
// for(ResourceElementBean resource : resourcesToAdd){
//
// if (resource.isToBeAdded()) {
//
// logger.debug("Resource to add is " + resource);
//
// // ok it is a file, so copy it into the copiedFolder
// WorkspaceItem copiedFile = userCatalogue.addWorkspaceItem(resource.getOriginalIdInWorkspace(), copiedFolder.getId());
//
// // name and description could have been edited
// copiedFile.setDescription(resource.getDescription());
//
// // check if it is an external url
// String externalUrl = null;
// try{
// boolean isExternalUrl = ((FolderItem)copiedFile).getFolderItemType().equals(FolderItemType.EXTERNAL_URL);
// externalUrl = isExternalUrl ? ((ExternalUrl)copiedFile).getUrl() : null;
// }catch(Exception e){
// logger.warn("Unable to check if it is an external url file ", e);
// }
//
// resources.add(new ResourceBean(
// externalUrl != null ? externalUrl : copiedFile.getPublicLink(true),
// resource.getEditableName(),
// copiedFile.getDescription(),
// copiedFile.getId(),
// userName,
// null, // dataset id, to be set
// ((FolderItem)copiedFile).getMimeType()));
//
// // postpone rename operation
// copiedFile.rename(resource.getEditableName());
// }
//
// }
// return resources;
// }
}

@ -6,29 +6,64 @@ import java.util.List;
import com.google.gwt.view.client.ProvidesKey;
// TODO: Auto-generated Javadoc
/**
* A resource element bean. Contains part of the logic used into the TwinColumn widget
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*
* @author revisited by Francesco Mangiacrapa
*/
public class ResourceElementBean implements Comparable<ResourceElementBean>, Serializable{
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -1230871392599580669L;
/** The name. */
private String name;
/** The editable name. */
private String editableName;
/** The to be added. */
private boolean toBeAdded;
/** The is folder. */
private boolean isFolder;
/** The full path. */
private String fullPath;
/** The original id in workspace. */
private String originalIdInWorkspace;
private String rootIdInWorkspace;
/** The mime type. */
private String mimeType;
/** The url. */
private String url;
/** The description. */
private String description;
/** The organization name dataset parent. */
private String organizationNameDatasetParent; // the organization name in which the parent dataset was created
/** The parent. */
private ResourceElementBean parent;
private List<ResourceElementBean> children;
/** The children size. */
private Integer childrenSize;
// /** The to publish. */
private List<ResourceElementBean> toPublish; //Resources that must be published
/** The next id. */
// to generate the GWT identifiers
private static int nextId = 0;
/** The identifier GWT. */
// identifier of this instance
private int identifierGWT;
@ -43,8 +78,9 @@ public class ResourceElementBean implements Comparable<ResourceElementBean>, Ser
};
/**
* Copy constructor
* @param another
* Copy constructor.
*
* @param another the another
*/
public ResourceElementBean(ResourceElementBean another) {
this.name = another.name;
@ -59,7 +95,7 @@ public class ResourceElementBean implements Comparable<ResourceElementBean>, Ser
}
/**
* Default constructor
* Default constructor.
*/
public ResourceElementBean(){
super();
@ -68,43 +104,47 @@ public class ResourceElementBean implements Comparable<ResourceElementBean>, Ser
}
/**
* @param identifier
* @param parentFolder
* @param name
* @param movedToRight
* @param isFolder
* Instantiates a new resource element bean.
*
* @param parent the parent
* @param name the name
* @param isFolder the is folder
* @param childrenSize the children size
* @param fullPath the full path
*/
public ResourceElementBean(
ResourceElementBean parent,
String name,
boolean isFolder,
List<ResourceElementBean> children,
Integer childrenSize,
String fullPath) {
this.identifierGWT = nextId;
nextId++;
this.parent = parent;
this.name = name;
this.isFolder = isFolder;
this.children = children;
this.childrenSize = childrenSize;
this.fullPath = fullPath;
}
/**
* @param name
* @param toBeAdded
* @param isFolder
* @param parent
* @param children
* @param fullPath
* @param originalIdInWorkspace
* @param mimeType
* @param url
* @param description
* @param organizationNameDatasetParent
* Instantiates a new resource element bean.
*
* @param name the name
* @param toBeAdded the to be added
* @param isFolder the is folder
* @param parent the parent
* @param childrenSize the children size
* @param fullPath the full path
* @param originalIdInWorkspace the original id in workspace
* @param mimeType the mime type
* @param url the url
* @param description the description
* @param organizationNameDatasetParent the organization name dataset parent
*/
public ResourceElementBean(String name, boolean toBeAdded,
boolean isFolder, ResourceElementBean parent,
List<ResourceElementBean> children, String fullPath,
Integer childrenSize, String fullPath,
String originalIdInWorkspace, String mimeType, String url,
String description, String organizationNameDatasetParent) {
super();
@ -114,7 +154,7 @@ public class ResourceElementBean implements Comparable<ResourceElementBean>, Ser
this.toBeAdded = toBeAdded;
this.isFolder = isFolder;
this.parent = parent;
this.children = children;
this.childrenSize = childrenSize;
this.fullPath = fullPath;
this.originalIdInWorkspace = originalIdInWorkspace;
this.mimeType = mimeType;
@ -123,103 +163,247 @@ public class ResourceElementBean implements Comparable<ResourceElementBean>, Ser
this.organizationNameDatasetParent = organizationNameDatasetParent;
}
/**
* Gets the parent.
*
* @return the parent
*/
public ResourceElementBean getParent() {
return parent;
}
/**
* Sets the parent.
*
* @param parent the new parent
*/
public void setParent(ResourceElementBean parent) {
this.parent = parent;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Sets the name.
*
* @param name the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Checks if is to be added.
*
* @return true, if is to be added
*/
public boolean isToBeAdded() {
return toBeAdded;
}
/**
* Sets the to be added.
*
* @param toBeAdded the new to be added
*/
public void setToBeAdded(boolean toBeAdded) {
this.toBeAdded = toBeAdded;
}
/**
* Gets the mime type.
*
* @return the mime type
*/
public String getMimeType() {
return mimeType;
}
/**
* Sets the mime type.
*
* @param mimeType the new mime type
*/
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
/**
* Gets the url.
*
* @return the url
*/
public String getUrl() {
return url;
}
/**
* Sets the url.
*
* @param url the new url
*/
public void setUrl(String url) {
this.url = url;
}
/**
* Gets the description.
*
* @return the description
*/
public String getDescription() {
return description;
}
/**
* Sets the description.
*
* @param description the new description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Gets the organization name dataset parent.
*
* @return the organization name dataset parent
*/
public String getOrganizationNameDatasetParent() {
return organizationNameDatasetParent;
}
/**
* Sets the organization name dataset parent.
*
* @param organizationNameDatasetParent the new organization name dataset parent
*/
public void setOrganizationNameDatasetParent(
String organizationNameDatasetParent) {
this.organizationNameDatasetParent = organizationNameDatasetParent;
}
/**
* Checks if is folder.
*
* @return true, if is folder
*/
public boolean isFolder() {
return isFolder;
}
/**
* Sets the folder.
*
* @param isFolder the new folder
*/
public void setFolder(boolean isFolder) {
this.isFolder = isFolder;
}
public List<ResourceElementBean> getChildren() {
return children;
/**
* Gets the children size.
*
* @return the children size
*/
public Integer getChildrenSize() {
return childrenSize;
}
public void setChildren(List<ResourceElementBean> children) {
this.children = children;
/**
* Sets the children size.
*
* @param size the new children size
*/
public void setChildrenSize(Integer size) {
this.childrenSize = size;
}
/**
* Gets the full path.
*
* @return the full path
*/
public String getFullPath() {
return fullPath;
}
/**
* Sets the full path.
*
* @param fullPath the new full path
*/
public void setFullPath(String fullPath) {
this.fullPath = fullPath;
}
/**
* Gets the original id in workspace.
*
* @return the original id in workspace
*/
public String getOriginalIdInWorkspace() {
return originalIdInWorkspace;
}
/**
* Sets the original id in workspace.
*
* @param originalIdInWorkspace the new original id in workspace
*/
public void setOriginalIdInWorkspace(String originalIdInWorkspace) {
this.originalIdInWorkspace = originalIdInWorkspace;
}
/**
* Gets the editable name.
*
* @return the editable name
*/
public String getEditableName() {
return editableName;
}
/**
* Sets the editable name.
*
* @param newName the new editable name
*/
public void setEditableName(String newName) {
this.editableName = newName;
}
/**
* Gets the to publish.
*
* @return the to publish
*/
public List<ResourceElementBean> getToPublish() {
return toPublish;
}
/**
* Sets the to publish.
*
* @param toPublish the new to publish
*/
public void setToPublish(List<ResourceElementBean> toPublish) {
this.toPublish = toPublish;
}
/**
* Equals.
*
* @param o the o
* @return true, if successful
*/
@Override
public boolean equals(Object o) {
boolean toReturn = false;
@ -230,23 +414,62 @@ public class ResourceElementBean implements Comparable<ResourceElementBean>, Ser
return toReturn;
}
/**
* Compare to.
*
* @param o the o
* @return the int
*/
@Override
public int compareTo(ResourceElementBean o) {
int toReturn = (o == null || o.fullPath == null) ? -1 : -o.fullPath.compareTo(fullPath);
return toReturn;
}
public String getRootIdInWorkspace() {
return rootIdInWorkspace;
}
public void setRootIdInWorkspace(String rootIdInWorkspace) {
this.rootIdInWorkspace = rootIdInWorkspace;
}
@Override
public String toString() {
return "ResourceElementBean [identifierGWT=" + identifierGWT
+ ", name=" + name + ", editableName=" + editableName
+ ", toBeAdded=" + toBeAdded + ", isFolder=" + isFolder
+ ", fullPath=" + fullPath + ", originalIdInWorkspace="
+ originalIdInWorkspace + ", mimeType=" + mimeType + ", url="
+ url + ", description=" + description
+ ", organizationNameDatasetParent="
+ organizationNameDatasetParent + ", parent=" + parent
+ ", children number=" + (children == null ? 0 : children.size()) + "]";
StringBuilder builder = new StringBuilder();
builder.append("ResourceElementBean [name=");
builder.append(name);
builder.append(", editableName=");
builder.append(editableName);
builder.append(", toBeAdded=");
builder.append(toBeAdded);
builder.append(", isFolder=");
builder.append(isFolder);
builder.append(", fullPath=");
builder.append(fullPath);
builder.append(", originalIdInWorkspace=");
builder.append(originalIdInWorkspace);
builder.append(", rootIdInWorkspace=");
builder.append(rootIdInWorkspace);
builder.append(", mimeType=");
builder.append(mimeType);
builder.append(", url=");
builder.append(url);
builder.append(", description=");
builder.append(description);
builder.append(", organizationNameDatasetParent=");
builder.append(organizationNameDatasetParent);
builder.append(", childrenSize=");
builder.append(childrenSize);
builder.append(", toPublish=");
builder.append(toPublish);
builder.append("]");
return builder.toString();
}
}

@ -9,13 +9,14 @@
<set-property name="bootstrap.responsiveDesign" value="true" />
<inherits name='com.github.gwtbootstrap.datetimepicker.Datetimepicker' />
<inherits name='com.github.gwtbootstrap.datepicker.Datepicker' />
<inherits name='org.gcube.datacatalogue.ckanutillibrary.CkanUtilLibrary' />
<inherits name='org.gcube.datacatalogue.utillibrary.CkanUtilLibrary' />
<inherits name='org.gcube.portlets.user.gcubewidgets.WidgetFactory' />
<inherits name='com.google.gwt.json.JSON'/>
<inherits
name='org.gcube.portlets.widgets.openlayerbasicwidgets.olbasicwidgets' />
<inherits name='org.gcube.portlets.widgets.openlayerbasicwidgets.olbasicwidgets' />
<inherits name='org.gcube.portlets.widgets.wsexplorer.WorkspaceExplorer' />
<!-- Specify the app entry point class. -->
<entry-point

@ -11,11 +11,21 @@
<servlet-class>org.gcube.portlets.widgets.ckandatapublisherwidget.server.CKANPublisherServicesImpl</servlet-class>
</servlet>
<servlet>
<servlet-name>workspaceExplorer</servlet-name>
<servlet-class>org.gcube.portlets.widgets.wsexplorer.server.WorkspaceExplorerServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ckanpublisherservices</servlet-name>
<url-pattern>/CKanMetadataPublisher/ckanservices</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>workspaceExplorer</servlet-name>
<url-pattern>/CKanMetadataPublisher/WorkspaceExplorerService</url-pattern>
</servlet-mapping>
<!-- Default page to serve -->
<welcome-file-list>

@ -0,0 +1,107 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget;
import java.util.Arrays;
import java.util.Calendar;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.storagehubwrapper.server.StorageHubWrapper;
import org.gcube.datacatalogue.utillibrary.server.DataCatalogueFactory;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.WorkspaceUtils;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
import org.junit.Test;
import org.slf4j.LoggerFactory;
/**
* The Class TestDataCatalogueLib.
*
* @author Francesco Mangiacrapa at ISTI-CNR Pisa (Italy)
* Jun 1, 2020
*/
public class TestPublishingWidget {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestPublishingWidget.class);
private String scope = "/gcube";
//private String testUser = "costantino_perciante";
private String testUser = "francesco.mangiacrapa";
private String authorizationToken = "";
/**
* Before.
*
* @throws Exception the exception
*/
//@Before
public void before() throws Exception{
}
/**
* Factory test.
*
* @throws Exception the exception
*/
//@Test
public void factoryTest() throws Exception{
DataCatalogueFactory factory = DataCatalogueFactory.getFactory();
while(true){
factory.getUtilsPerScope(scope);
Thread.sleep(60* 1000 * 3);
factory.getUtilsPerScope(scope);
break;
}
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
factory.getUtilsPerScope(scope);
}
}
//@Test
public void getDatasetBeanTest() throws Exception{
ScopeProvider.instance.set(scope);
String userName = testUser;
String token = authorizationToken;
String folderId = "6399daa7-2173-4314-b4f7-2afa24eae8f8";
DatasetBean bean;
try{
bean = new DatasetBean();
bean.setId(folderId);
bean.setDescription("This is a fantastic description");
bean.setVersion(1);
String onlyAlphanumeric = "test-creation-blablabla".replaceAll("[^A-Za-z0-9]", "");
bean.setTitle(onlyAlphanumeric + Calendar.getInstance().getTimeInMillis());
bean.setAuthorName("Francesco");
bean.setAuthorSurname("Mangiacrapa");
bean.setAuthorEmail("francesco.mangiacrapa@isti.cnr.it");
bean.setMaintainer("Francesco Mangiacrapa");
bean.setMaintainerEmail("francesco.mangiacrapa@isti.cnr.it");
//UPDATED By Francesco
String vreName = scope.substring(scope.lastIndexOf("/")+1,scope.length());
LOG.debug("In dev mode using the scope: "+scope+" and VRE name: "+vreName);
bean.setOrganizationList(Arrays.asList(new OrganizationBean(vreName, vreName.toLowerCase(), true)));
bean.setOwnerIdentifier(userName);
if(folderId != null && !folderId.isEmpty()){
StorageHubWrapper storageHubWrapper = new StorageHubWrapper(scope, token, false, false, true);
WorkspaceUtils.toWorkspaceResource(folderId, userName, bean, storageHubWrapper.getWorkspace());
}
}catch(Exception e){
LOG.error("Error while building bean into dev mode", e);
throw new Exception("Error while retrieving basic information " + e.getMessage());
}
LOG.info("Got dataset: "+bean);
}
}

@ -0,0 +1,3 @@
/devsec.gcubekey
/gcube.gcubekey
/log4j.properties
Loading…
Cancel
Save