added report and hastags evaluation. Partially revised the SocialCommunication class

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/widgets/grsf-manage-widget@162944 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2018-02-05 16:16:14 +00:00
parent 1d388e0c57
commit 2aa9b3dd42
23 changed files with 735 additions and 597 deletions

View File

@ -20,7 +20,6 @@
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry excluding="**" kind="src" output="${webappDirectory}/WEB-INF/classes" path="src/main/resources"> <classpathentry excluding="**" kind="src" output="${webappDirectory}/WEB-INF/classes" path="src/main/resources">
@ -28,7 +27,7 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes> <attributes>
<attribute name="owner.project.facets" value="java"/> <attribute name="owner.project.facets" value="java"/>
</attributes> </attributes>

View File

@ -1,13 +1,13 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.compiler.source=1.7

View File

@ -4,10 +4,6 @@
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/> <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
<dependent-module archiveName="ckan-util-library-2.4.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/ckan-util-library/ckan-util-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="context-root" value="grsf-manage-widget"/> <property name="context-root" value="grsf-manage-widget"/>
<property name="java-output-path" value="/grsf-manage-widget/target/grsf-manage-widget-1.0.0-SNAPSHOT/WEB-INF/classes"/> <property name="java-output-path" value="/grsf-manage-widget/target/grsf-manage-widget-1.0.0-SNAPSHOT/WEB-INF/classes"/>
</wb-module> </wb-module>

View File

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

View File

@ -117,18 +117,18 @@
<dependency> <dependency>
<groupId>org.gcube.core</groupId> <groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId> <artifactId>common-scope-maps</artifactId>
<scope>compile</scope> <scope>provided</scope>
<!-- put at provided for deploying --> <!-- put at provided for deploying -->
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.gcube.core</groupId> <groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId> <artifactId>common-encryption</artifactId>
<scope>compile</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.gcube.common</groupId> <groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId> <artifactId>authorization-client</artifactId>
<scope>compile</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>

View File

@ -12,8 +12,7 @@ public class GRSFManageWidget implements EntryPoint {
*/ */
public void onModuleLoad(){ public void onModuleLoad(){
// HandlerManager eventBus = new HandlerManager(null); // HandlerManager eventBus = new HandlerManager(null);
//RootPanel.get("manageDiv").add(new ManageProductWidget("fffb6167-b570-42a8-92b9-5be28549c3b8", eventBus)); // RootPanel.get("manageDiv").add(new ManageProductWidget("fffb6167-b570-42a8-92b9-5be28549c3b8", eventBus));
// RootPanel.get("manageDiv").add(new ManageRevertOperationWidget( // RootPanel.get("manageDiv").add(new ManageRevertOperationWidget("random-url-here", eventBus));
// "random-url-here", eventBus));
} }
} }

View File

@ -26,7 +26,7 @@ public interface GRSFManageWidgetService extends RemoteService {
/** /**
* Notify product update * Notify product update
*/ */
String notifyProductUpdate(ManageProductBean bean) throws Exception; void notifyProductUpdate(ManageProductBean bean) throws Exception;
/** /**
* Identifier of the record (UUID) * Identifier of the record (UUID)

View File

@ -15,7 +15,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
public interface GRSFManageWidgetServiceAsync { public interface GRSFManageWidgetServiceAsync {
void notifyProductUpdate(ManageProductBean bean, void notifyProductUpdate(ManageProductBean bean,
AsyncCallback<String> callback); AsyncCallback<Void> callback);
void getProductBeanById(String identifier, void getProductBeanById(String identifier,
AsyncCallback<ManageProductBean> callback); AsyncCallback<ManageProductBean> callback);

View File

@ -2,7 +2,9 @@ package org.gcube.datacatalogue.grsf_manage_widget.client.view;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.gcube.datacatalogue.common.enums.Status; import org.gcube.datacatalogue.common.enums.Status;
import org.gcube.datacatalogue.grsf_manage_widget.client.GRSFManageWidgetService; import org.gcube.datacatalogue.grsf_manage_widget.client.GRSFManageWidgetService;
@ -12,6 +14,8 @@ import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.Connect
import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.SimilarGRSFRecordWidget; import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.SimilarGRSFRecordWidget;
import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.SourceWidget; import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.SourceWidget;
import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.SuggestMerges; import org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets.SuggestMerges;
import org.gcube.datacatalogue.grsf_manage_widget.shared.ConnectedBean;
import org.gcube.datacatalogue.grsf_manage_widget.shared.HashTagsOnUpdate;
import org.gcube.datacatalogue.grsf_manage_widget.shared.ManageProductBean; import org.gcube.datacatalogue.grsf_manage_widget.shared.ManageProductBean;
import org.gcube.datacatalogue.grsf_manage_widget.shared.SimilarGRSFRecord; import org.gcube.datacatalogue.grsf_manage_widget.shared.SimilarGRSFRecord;
import org.gcube.datacatalogue.grsf_manage_widget.shared.SourceRecord; import org.gcube.datacatalogue.grsf_manage_widget.shared.SourceRecord;
@ -31,7 +35,6 @@ import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.AlertType; import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SelectElement; import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiBinder;
@ -173,7 +176,7 @@ public class ManageProductWidget extends Composite{
// show modal // show modal
manageProductModal.addStyleName("management-metadata-modal-style"); manageProductModal.addStyleName("management-metadata-modal-style");
manageProductModal.getElement().getStyle().setWidth(60, Unit.PCT); // manageProductModal.getElement().getStyle().setWidth(60, Unit.PCT);
manageProductModal.show(); manageProductModal.show();
// async request to fetch the product // async request to fetch the product
@ -222,7 +225,7 @@ public class ManageProductWidget extends Composite{
infoBlock.setVisible(false); infoBlock.setVisible(false);
// top: more or less fixed information // top: more or less fixed information
GRSFNameTexBox.setText(bean.getGrsfName()); GRSFNameTexBox.setText(bean.getTitle());
shortNameTextBox.setText(bean.getShortName()); shortNameTextBox.setText(bean.getShortName());
semanticIdentifierTextBox.setText(bean.getSemanticIdentifier()); semanticIdentifierTextBox.setText(bean.getSemanticIdentifier());
productGrsfType.setText(bean.getGrsfType()); productGrsfType.setText(bean.getGrsfType());
@ -244,7 +247,7 @@ public class ManageProductWidget extends Composite{
similarGRSFRecordGroup.setVisible(false); similarGRSFRecordGroup.setVisible(false);
// further suggested merges // further suggested merges
suggestedMergesPanel = new SuggestMerges(service); suggestedMergesPanel = new SuggestMerges(service, bean.getDomain());
panelForFurtherMerges.add(suggestedMergesPanel); panelForFurtherMerges.add(suggestedMergesPanel);
// prepare "connect" panel // prepare "connect" panel
@ -309,11 +312,19 @@ public class ManageProductWidget extends Composite{
@UiHandler("confirmButton") @UiHandler("confirmButton")
void onSaveButton(ClickEvent ce){ void onSaveButton(ClickEvent ce){
String report = "";
Set<String> hashtags = new HashSet<>();
// if the status has not be changed ... // if the status has not be changed ...
if(listBoxStatus.getSelectedIndex() <= 0) if(listBoxStatus.getSelectedIndex() <= 0){
bean.setNewStatus(bean.getCurrentStatus()); bean.setNewStatus(bean.getCurrentStatus());
else report = "-The Status is unchanged";
}
else{
bean.setNewStatus(Status.fromString(listBoxStatus.getSelectedItemText())); bean.setNewStatus(Status.fromString(listBoxStatus.getSelectedItemText()));
report = "-The Status has been changed to " + bean.getNewStatus().getOrigName();
hashtags.add(bean.getNewStatus().getOrigName());
}
manageProductModal.setCloseVisible(false); manageProductModal.setCloseVisible(false);
cancelButton.setEnabled(false); cancelButton.setEnabled(false);
@ -323,9 +334,26 @@ public class ManageProductWidget extends Composite{
// get short name // get short name
bean.setShortNameUpdated(shortNameTextBox.getText()); bean.setShortNameUpdated(shortNameTextBox.getText());
if(bean.getShortName() != bean.getShortNameUpdated()){
report += "\n- The GRSF Short Name has been changed to '" + bean.getShortNameUpdated() + "'";
hashtags.add(HashTagsOnUpdate.SHORTNAME_UPDATED.getString());
}
// evaluate the connections and the actions on them // evaluate the connections and the actions on them
bean.setConnections(connectWidget.getConnectList()); bean.setConnections(connectWidget.getConnectList());
// add the connections for the report
if(!bean.getConnections().isEmpty()){
report += "\n- Suggested connections:";
hashtags.add(HashTagsOnUpdate.CONNECT.getString());
for(ConnectedBean cb: bean.getConnections()){
if(cb.isRemove())
report += "\n\t - remove connection with record " + cb.getKnowledgeBaseId() + ";";
else if(cb.isConnect())
report += "\n\t - add connection with record " + cb.getKnowledgeBaseId() + ";";
}
}
// update similar records and to connect // update similar records and to connect
if(similarRecordPanel != null) if(similarRecordPanel != null)
bean.setSimilarGrsfRecords(similarRecordPanel.getSimilarRecords()); bean.setSimilarGrsfRecords(similarRecordPanel.getSimilarRecords());
@ -337,33 +365,51 @@ public class ManageProductWidget extends Composite{
// set the merge operator on the bean if there is at least one merge to be done // set the merge operator on the bean if there is at least one merge to be done
for(SimilarGRSFRecord sR: bean.getSimilarGrsfRecords()){ for(SimilarGRSFRecord sR: bean.getSimilarGrsfRecords()){
report += "\n- Suggested merges:";
if(sR.isSuggestedMerge()){ if(sR.isSuggestedMerge()){
bean.setMergesInvolved(true); bean.setMergesInvolved(true);
break; report += "\n\t - merge the current record with record " + sR.getKnowledgeBaseId() + ";";
}
if(bean.isMergesInvolved()){
report += "\n- The update involves a merge operation.";
hashtags.add(HashTagsOnUpdate.MERGE.getString());
} }
} }
// set new values // set new values
bean.setAnnotation(new HTML(annotationArea.getText().trim()).getText()); bean.setAnnotation(new HTML(annotationArea.getText().trim()).getText());
// traceability flag if(bean.getAnnotation() != null && !bean.getAnnotation().isEmpty())
bean.setTraceabilityFlag(traceabilityFlag.getValue()); report += "\n- Annotation message is: " + bean.getAnnotation();
service.notifyProductUpdate(bean, new AsyncCallback<String>() { // traceability flag
Boolean traceabilityNewValue = traceabilityFlag.getValue();
boolean currentTraceabilitFlag = bean.isTraceabilityFlag();
if(!traceabilityNewValue.equals(currentTraceabilitFlag)){
report += "\n- Traceability flag has been changed to: " + traceabilityNewValue;
if(traceabilityNewValue)
hashtags.add(HashTagsOnUpdate.TRACEABILITY_FLAG_SET.getString());
else
hashtags.add(HashTagsOnUpdate.TRACEABILITY_FLAG_UNSET.getString());
}
bean.setTraceabilityFlag(traceabilityNewValue);
// set the report
bean.setReport(report);
GWT.log("Report is:\n" + report);
service.notifyProductUpdate(bean, new AsyncCallback<Void>() {
@Override @Override
public void onSuccess(String result) { public void onSuccess(Void v) {
if(result == null){
showInfo(STATUS_UPDATE_SUCCESS, AlertType.SUCCESS);
confirmButton.removeFromParent();
formUpdate.setVisible(false);
}else{
showInfo(STATUS_UPDATE_ERROR + "(" + result + ")", AlertType.ERROR);
confirmButton.setEnabled(true);
}
showInfo(STATUS_UPDATE_SUCCESS, AlertType.SUCCESS);
confirmButton.removeFromParent();
formUpdate.setVisible(false);
manageProductModal.setCloseVisible(true); manageProductModal.setCloseVisible(true);
cancelButton.setEnabled(true); cancelButton.setEnabled(true);
loaderIcon.setVisible(false); loaderIcon.setVisible(false);

View File

@ -17,7 +17,6 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.FontWeight; import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiField;
@ -76,15 +75,12 @@ public class ManageRevertOperationWidget extends Composite {
private static GRSFManageWidgetServiceAsync service = GWT.create(GRSFManageWidgetService.class); private static GRSFManageWidgetServiceAsync service = GWT.create(GRSFManageWidgetService.class);
private HandlerManager eventBus;
public static final String LOADING_IMAGE_URL = GWT.getModuleBaseURL() + "../images/loader.gif"; public static final String LOADING_IMAGE_URL = GWT.getModuleBaseURL() + "../images/loader.gif";
private RevertableOperationInfo revertableOperation = null; private RevertableOperationInfo revertableOperation = null;
public ManageRevertOperationWidget(String encryptedUrlOperation, HandlerManager eventBus) { public ManageRevertOperationWidget(String encryptedUrlOperation) {
initWidget(uiBinder.createAndBindUi(this)); initWidget(uiBinder.createAndBindUi(this));
this.eventBus = eventBus;
GWT.log("Encrypted url is " + encryptedUrlOperation); GWT.log("Encrypted url is " + encryptedUrlOperation);
if(encryptedUrlOperation == null || encryptedUrlOperation.isEmpty()) if(encryptedUrlOperation == null || encryptedUrlOperation.isEmpty())
@ -99,6 +95,8 @@ public class ManageRevertOperationWidget extends Composite {
// revertOperationModal.getElement().getStyle().setWidth(60, Unit.PCT); // revertOperationModal.getElement().getStyle().setWidth(60, Unit.PCT);
revertOperationModal.show(); revertOperationModal.show();
moreInfoAboutOperation.getElement().getStyle().setMarginBottom(50, Unit.PX);
// async request to fetch the product // async request to fetch the product
loadModalContent(encryptedUrlOperation); loadModalContent(encryptedUrlOperation);
@ -106,7 +104,6 @@ public class ManageRevertOperationWidget extends Composite {
/** /**
* Validate the parameters of the url and ask the editor/reviewer what he/she wants to do. * Validate the parameters of the url and ask the editor/reviewer what he/she wants to do.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @param encryptedUrlOperation * @param encryptedUrlOperation
*/ */
private void loadModalContent(String encryptedUrlOperation) { private void loadModalContent(String encryptedUrlOperation) {
@ -123,7 +120,7 @@ public class ManageRevertOperationWidget extends Composite {
if(result != null){ if(result != null){
revertableOperation = result; revertableOperation = result;
String dateString = DateTimeFormat.getFormat("MM/dd/yyyy HH:mm:ss").format(new Date(revertableOperation.getTimestamp())); String dateString = DateTimeFormat.getFormat("MM/dd/yyyy HH:mm:ss").format(new Date(revertableOperation.getTimestamp()));
requestAuthor.setText(revertableOperation.getAdmin()); requestAuthor.setText(revertableOperation.getFullNameOriginalAdmin() + "(" + revertableOperation.getUserNameOriginalAdmin() + ")");
requestTypeBox.setText(revertableOperation.getOperation().toString().toUpperCase()); requestTypeBox.setText(revertableOperation.getOperation().toString().toUpperCase());
requestRecordUUID.setText(revertableOperation.getUuid()); requestRecordUUID.setText(revertableOperation.getUuid());
requestTimestamp.setText(dateString); requestTimestamp.setText(dateString);
@ -133,7 +130,7 @@ public class ManageRevertOperationWidget extends Composite {
viewRecord.getElement().getStyle().setFontWeight(FontWeight.BOLD); viewRecord.getElement().getStyle().setFontWeight(FontWeight.BOLD);
viewRecord.setHref(revertableOperation.getRecordUrl()); viewRecord.setHref(revertableOperation.getRecordUrl());
viewRecord.setTarget("_blank"); viewRecord.setTarget("_blank");
viewRecord.getElement().getStyle().setMarginBottom(20, Unit.PX);
moreInfoAboutOperation.add(viewRecord); moreInfoAboutOperation.add(viewRecord);
moreInfoAboutOperation.setVisible(true); moreInfoAboutOperation.setVisible(true);
revertButton.setEnabled(true); revertButton.setEnabled(true);

View File

@ -16,10 +16,6 @@
<b:Image ui:field="loadingImage" styleName="{style.loader-image}" <b:Image ui:field="loadingImage" styleName="{style.loader-image}"
visible="true"></b:Image> visible="true"></b:Image>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="infoBlock"></b:AlertBlock>
<g:VerticalPanel ui:field="moreInfoAboutOperation" <g:VerticalPanel ui:field="moreInfoAboutOperation"
visible="false" width="100%"> visible="false" width="100%">
@ -75,6 +71,10 @@
</b:Form> </b:Form>
</g:VerticalPanel> </g:VerticalPanel>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="infoBlock"></b:AlertBlock>
</g:VerticalPanel> </g:VerticalPanel>
<b:ModalFooter> <b:ModalFooter>
<b:Icon type="GEAR" spin="true" ui:field="loaderIcon" <b:Icon type="GEAR" spin="true" ui:field="loaderIcon"

View File

@ -9,25 +9,18 @@ import org.gcube.datacatalogue.grsf_manage_widget.client.GRSFManageWidgetService
import org.gcube.datacatalogue.grsf_manage_widget.shared.ConnectedBean; import org.gcube.datacatalogue.grsf_manage_widget.shared.ConnectedBean;
import org.gcube.datacatalogue.grsf_manage_widget.shared.ManageProductBean; import org.gcube.datacatalogue.grsf_manage_widget.shared.ManageProductBean;
import com.github.gwtbootstrap.client.ui.AppendButton;
import com.github.gwtbootstrap.client.ui.Button; import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.CheckBox; import com.github.gwtbootstrap.client.ui.CheckBox;
import com.github.gwtbootstrap.client.ui.Icon;
import com.github.gwtbootstrap.client.ui.Paragraph; import com.github.gwtbootstrap.client.ui.Paragraph;
import com.github.gwtbootstrap.client.ui.TextBox; import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.ButtonType;
import com.github.gwtbootstrap.client.ui.constants.IconType;
import com.google.gwt.core.client.GWT; 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.dom.client.Style.Float; import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.FontWeight; import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.AsyncCallback;
@ -47,8 +40,6 @@ public class ConnectToWidget extends Composite{
private static ConnectToWidgetUiBinder uiBinder = GWT private static ConnectToWidgetUiBinder uiBinder = GWT
.create(ConnectToWidgetUiBinder.class); .create(ConnectToWidgetUiBinder.class);
private static final String REGEX_UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
interface ConnectToWidgetUiBinder extends UiBinder<Widget, ConnectToWidget> { interface ConnectToWidgetUiBinder extends UiBinder<Widget, ConnectToWidget> {
} }
@ -92,9 +83,9 @@ public class ConnectToWidget extends Composite{
} }
// manage the button for manual suggestion // manage the button for manual suggestion
final String acceptedDomain = bean.getGrsfDomain().equalsIgnoreCase(Product_Type.STOCK.getOrigName()) ? final String acceptedDomain = bean.getDomain().equalsIgnoreCase(Product_Type.STOCK.getOrigName()) ?
Product_Type.FISHERY.getOrigName() : Product_Type.STOCK.getOrigName(); Product_Type.FISHERY.getOrigName() : Product_Type.STOCK.getOrigName();
suggestRecord.setTitle("Connect this " + bean.getGrsfDomain() + " record to a " + acceptedDomain + " record "); suggestRecord.setTitle("Connect this " + bean.getDomain() + " record to a " + acceptedDomain + " record ");
suggestRecord.setText("Add Connection"); suggestRecord.setText("Add Connection");
suggestRecord.setType(ButtonType.LINK); suggestRecord.setType(ButtonType.LINK);
suggestRecord.getElement().getStyle().setFontWeight(FontWeight.BOLD); suggestRecord.getElement().getStyle().setFontWeight(FontWeight.BOLD);
@ -190,54 +181,44 @@ public class ConnectToWidget extends Composite{
private Tuple buildWidgetConnect(final ConnectedBean cb, final String acceptedDomain){ private Tuple buildWidgetConnect(final ConnectedBean cb, final String acceptedDomain){
VerticalPanel main = new VerticalPanel(); VerticalPanel main = new VerticalPanel();
main.setWidth("100%");
HorizontalPanel hp = new HorizontalPanel(); HorizontalPanel hp = new HorizontalPanel();
main.setWidth("100%");
hp.setWidth("100%"); hp.setWidth("100%");
VerticalPanel vpLeft = new VerticalPanel(); VerticalPanel vpLeft = new VerticalPanel();
vpLeft.getElement().getStyle().setMarginLeft(15, Unit.PX); vpLeft.getElement().getStyle().setMarginLeft(15, Unit.PX);
vpLeft.setWidth("80%"); vpLeft.setWidth("80%");
Paragraph semanticIdentifier = new Paragraph("UUID:"); Paragraph identifier = new Paragraph("Record UUID:");
final TextBox box = new TextBox();
final Icon icon = new Icon(IconType.OK_SIGN); // view link
icon.setVisible(false);
icon.getElement().getStyle().setMarginLeft(10, Unit.PX);
icon.getElement().getStyle().setMarginTop(5, Unit.PX);
final Anchor view = new Anchor(); final Anchor view = new Anchor();
view.setText("View"); view.setText("View");
view.setTitle("Click to inspect the record"); view.setTitle("Click to inspect the record");
view.setTarget("_blank"); view.setTarget("_blank");
view.getElement().getStyle().setFontWeight(FontWeight.BOLD); view.getElement().getStyle().setFontWeight(FontWeight.BOLD);
view.setVisible(false); view.setVisible(false);
// add a couple of handlers // a textbox with a validate button on the right side
box.addKeyPressHandler(new KeyPressHandler() { AppendButton uuidAndValidateButton = new AppendButton();
final Button validateUUIDButton = new Button("Validate");
@Override validateUUIDButton.setEnabled(false);
public void onKeyPress(KeyPressEvent event) { final PasteAwareTextBox box = new PasteAwareTextBox(validateUUIDButton);
GWT.log("onKeyPress " + event.getNativeEvent().getKeyCode());
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
box.setFocus(false);
}
});
}
});
box.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
GWT.log("onChange");
validateUUID(box, cb, icon, view, acceptedDomain);
}
});
box.setWidth("512px"); box.setWidth("512px");
box.setPlaceholder("Copy and Paste the Identifier (UUID) of the record to connect here"); box.setPlaceholder("Copy and Paste the Identifier (UUID) of the record to connect here, then validate");
validateUUIDButton.addClickHandler(new ClickHandler() {
vpLeft.add(semanticIdentifier);
vpLeft.add(box); @Override
public void onClick(ClickEvent event) {
validateUUID(box, cb, view, validateUUIDButton, acceptedDomain);
}
});
uuidAndValidateButton.add(box);
uuidAndValidateButton.add(validateUUIDButton);
vpLeft.add(identifier);
vpLeft.add(uuidAndValidateButton);
vpLeft.add(view);
VerticalPanel vpRight = new VerticalPanel(); VerticalPanel vpRight = new VerticalPanel();
vpRight.setWidth("20%"); vpRight.setWidth("20%");
@ -274,66 +255,53 @@ public class ConnectToWidget extends Composite{
return new Tuple(cb, main, box); return new Tuple(cb, main, box);
} }
protected void validateUUID(final TextBox box, final ConnectedBean c, final Icon icon, final Anchor view, final String acceptedDomain) { protected void validateUUID(final TextBox box, final ConnectedBean c, final Anchor view, final Button validateUUIDButton, final String acceptedDomain) {
if(!box.isEnabled())
return;
validateUUIDButton.setText("Validating...");
validateUUIDButton.setEnabled(false);
box.setEnabled(false);
view.setVisible(false);
final String currentText = box.getText().trim(); final String currentText = box.getText().trim();
c.setKnowledgeBaseId(null); c.setKnowledgeBaseId(null);
c.setConnect(false); c.setConnect(false);
icon.setVisible(false);
view.setVisible(false);
icon.setSpin(false);
if(currentText == null || currentText.isEmpty())
return;
if(!currentText.matches(REGEX_UUID)){
icon.setType(IconType.BAN_CIRCLE);
icon.setTitle("Not a valid UUID");
icon.setVisible(true);
view.setVisible(false);
return;
}
// else check at server side if it exists // else check at server side if it exists
GWT.log("Text changed to " + currentText);
box.setEnabled(false);
icon.setIcon(IconType.ROTATE_RIGHT);
icon.setSpin(true);
service.checkIdentifierExistsInDomain(currentText, acceptedDomain, new AsyncCallback<String>() { service.checkIdentifierExistsInDomain(currentText, acceptedDomain, new AsyncCallback<String>() {
@Override @Override
public void onSuccess(String result) { public void onSuccess(String result) {
icon.setSpin(false);
if(result != null){ if(result != null){
c.setKnowledgeBaseId(currentText); c.setKnowledgeBaseId(currentText);
c.setConnect(true); c.setConnect(true);
icon.setType(IconType.OK_CIRCLE);
icon.setTitle("Accepted");
view.setHref(result); view.setHref(result);
view.setVisible(true); view.setVisible(true);
box.setEnabled(false); box.setEnabled(false);
validateUUIDButton.setText("Accepted");
validateUUIDButton.setType(ButtonType.SUCCESS);
validateUUIDButton.setEnabled(false);
} }
else{ else{
icon.setType(IconType.BAN_CIRCLE);
icon.setTitle("Not a valid UUID");
view.setVisible(false); view.setVisible(false);
box.setEnabled(true); box.setEnabled(true);
validateUUIDButton.setText("Invalid");
validateUUIDButton.setType(ButtonType.DANGER);
validateUUIDButton.setEnabled(true);
} }
icon.setVisible(true);
} }
@Override @Override
public void onFailure(Throwable caught) { public void onFailure(Throwable caught) {
box.setEnabled(true); box.setEnabled(true);
icon.setSpin(false);
view.setVisible(false); view.setVisible(false);
icon.setType(IconType.BAN_CIRCLE); validateUUIDButton.setText("Invalid");
icon.setTitle(caught.getMessage()); validateUUIDButton.setTitle("Error is " + caught);
validateUUIDButton.setType(ButtonType.DANGER);
view.setVisible(false);
box.setEnabled(true);
} }
}); });

View File

@ -0,0 +1,62 @@
package org.gcube.datacatalogue.grsf_manage_widget.client.view.subwidgets;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.Event;
/**
* A paste aware textbox widget.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class PasteAwareTextBox extends TextBox {
private Button toBeEnabled;
private static final String REGEX_UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
public PasteAwareTextBox(Button b) {
super();
toBeEnabled = b;
sinkEvents(Event.ONPASTE);
sinkEvents(Event.ONCHANGE);
sinkEvents(Event.ONKEYPRESS);
}
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE:
onEvent(getClipboardData(event));
break;
case Event.ONCHANGE:
case Event.ONKEYPRESS:
onEvent(this.getText());
break;
}
}
private void onEvent(String clipboardData) {
GWT.log("Current text is:" + clipboardData);
toBeEnabled.setEnabled(false);
if(clipboardData != null && !clipboardData.isEmpty()){
final String currentText = clipboardData.trim();
if(!currentText.matches(REGEX_UUID))
return;
else
toBeEnabled.setEnabled(true);
}
}
/**
* In case of PASTE event
* @param event
* @return
*/
private static native String getClipboardData(Event event) /*-{
return event.clipboardData.getData('text/plain');
}-*/;
}

View File

@ -7,22 +7,17 @@ import java.util.List;
import org.gcube.datacatalogue.grsf_manage_widget.client.GRSFManageWidgetServiceAsync; import org.gcube.datacatalogue.grsf_manage_widget.client.GRSFManageWidgetServiceAsync;
import org.gcube.datacatalogue.grsf_manage_widget.shared.SimilarGRSFRecord; import org.gcube.datacatalogue.grsf_manage_widget.shared.SimilarGRSFRecord;
import com.github.gwtbootstrap.client.ui.AppendButton;
import com.github.gwtbootstrap.client.ui.Button; import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.Icon;
import com.github.gwtbootstrap.client.ui.Paragraph; import com.github.gwtbootstrap.client.ui.Paragraph;
import com.github.gwtbootstrap.client.ui.TextBox; import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.ButtonType;
import com.github.gwtbootstrap.client.ui.constants.IconType;
import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Float; import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.FontWeight; import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.AsyncCallback;
@ -46,14 +41,12 @@ public class SuggestMerges extends Composite {
private List<Tuple> extraSimilarRecordsList = new ArrayList<Tuple>(0); private List<Tuple> extraSimilarRecordsList = new ArrayList<Tuple>(0);
private static final String REGEX_UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
interface SuggestMergesUiBinder extends UiBinder<Widget, SuggestMerges> { interface SuggestMergesUiBinder extends UiBinder<Widget, SuggestMerges> {
} }
private GRSFManageWidgetServiceAsync service; private GRSFManageWidgetServiceAsync service;
public SuggestMerges(GRSFManageWidgetServiceAsync service) { public SuggestMerges(GRSFManageWidgetServiceAsync service, final String acceptedDomain) {
initWidget(uiBinder.createAndBindUi(this)); initWidget(uiBinder.createAndBindUi(this));
this.service = service; this.service = service;
@ -69,7 +62,7 @@ public class SuggestMerges extends Composite {
@Override @Override
public void onClick(ClickEvent arg0) { public void onClick(ClickEvent arg0) {
SimilarGRSFRecord s = new SimilarGRSFRecord(); SimilarGRSFRecord s = new SimilarGRSFRecord();
Widget w = buildWidgetForExtraSimilarRecord(s); Widget w = buildWidgetForExtraSimilarRecord(s, acceptedDomain);
extraSimilarRecordsList.add(new Tuple(s, w, null)); extraSimilarRecordsList.add(new Tuple(s, w, null));
similarGrsfRecordsSuggestedPanel.add(w); similarGrsfRecordsSuggestedPanel.add(w);
} }
@ -81,7 +74,7 @@ public class SuggestMerges extends Composite {
* @param w the widget * @param w the widget
* @param s the similar record. * @param s the similar record.
*/ */
private Widget buildWidgetForExtraSimilarRecord(final SimilarGRSFRecord s){ private Widget buildWidgetForExtraSimilarRecord(final SimilarGRSFRecord s, final String acceptedDomain){
VerticalPanel main = new VerticalPanel(); VerticalPanel main = new VerticalPanel();
main.getElement().getStyle().setMarginTop(10, Unit.PX); main.getElement().getStyle().setMarginTop(10, Unit.PX);
@ -95,12 +88,9 @@ public class SuggestMerges extends Composite {
HorizontalPanel textBoxIconContainer = new HorizontalPanel(); HorizontalPanel textBoxIconContainer = new HorizontalPanel();
textBoxIconContainer.setWidth("100%"); textBoxIconContainer.setWidth("100%");
Paragraph identifier = new Paragraph("UUID:"); Paragraph identifier = new Paragraph("Record UUID:");
final TextBox box = new TextBox();
final Icon icon = new Icon(IconType.OK_SIGN); // view link
icon.setVisible(false);
icon.getElement().getStyle().setMarginLeft(10, Unit.PX);
icon.getElement().getStyle().setMarginTop(5, Unit.PX);
final Anchor view = new Anchor(); final Anchor view = new Anchor();
view.setText("View"); view.setText("View");
view.setTitle("Click to inspect the record"); view.setTitle("Click to inspect the record");
@ -108,28 +98,26 @@ public class SuggestMerges extends Composite {
view.getElement().getStyle().setFontWeight(FontWeight.BOLD); view.getElement().getStyle().setFontWeight(FontWeight.BOLD);
view.setVisible(false); view.setVisible(false);
// add a couple of handlers // a textbox with a validate button on the right side
box.addKeyPressHandler(new KeyPressHandler() { AppendButton uuidAndValidateButton = new AppendButton();
final Button validateUUIDButton = new Button("Validate");
validateUUIDButton.setEnabled(false);
final PasteAwareTextBox box = new PasteAwareTextBox(validateUUIDButton);
box.setWidth("512px");
box.setPlaceholder("Copy and Paste the Identifier (UUID) of the record to merge, then validate");
validateUUIDButton.addClickHandler(new ClickHandler() {
@Override @Override
public void onKeyPress(KeyPressEvent event) { public void onClick(ClickEvent event) {
validateUUID(box, s, icon, view);
validateUUID(box, s, view, validateUUIDButton, acceptedDomain);
} }
}); });
box.addChangeHandler(new ChangeHandler() { uuidAndValidateButton.add(box);
@Override uuidAndValidateButton.add(validateUUIDButton);
public void onChange(ChangeEvent event) {
GWT.log("onChange");
validateUUID(box, s, icon, view);
}
});
box.setWidth("511px");
box.setPlaceholder("Insert the Identifier (UUID) of the record to be merged");
vpLeft.add(identifier); vpLeft.add(identifier);
textBoxIconContainer.add(box); vpLeft.add(uuidAndValidateButton);
textBoxIconContainer.add(icon);
vpLeft.add(textBoxIconContainer);
vpLeft.add(view); vpLeft.add(view);
// the right side // the right side
@ -179,68 +167,53 @@ public class SuggestMerges extends Composite {
* @param icon * @param icon
* @param view * @param view
*/ */
protected void validateUUID(final TextBox box, final SimilarGRSFRecord s, final Icon icon, final Anchor view) { protected void validateUUID(final TextBox box, final SimilarGRSFRecord s, final Anchor view, final Button validateUUIDButton, final String acceptedDomain) {
if(!box.isEnabled()) validateUUIDButton.setText("Validating...");
return; validateUUIDButton.setEnabled(false);
box.setEnabled(false);
view.setVisible(false);
final String currentText = box.getText().trim(); final String currentText = box.getText().trim();
s.setKnowledgeBaseId(null); s.setKnowledgeBaseId(null);
s.setSuggestedMerge(false); s.setSuggestedMerge(false);
icon.setVisible(false);
view.setVisible(false);
icon.setSpin(false);
if(currentText == null || currentText.isEmpty())
return;
if(!currentText.matches(REGEX_UUID)){
icon.setType(IconType.BAN_CIRCLE);
icon.setTitle("Not a valid UUID");
icon.setVisible(true);
return;
}
// else check at server side if it exists // else check at server side if it exists
GWT.log("Text changed to " + currentText); service.checkIdentifierExistsInDomain(currentText, acceptedDomain, new AsyncCallback<String>() {
box.setEnabled(false);
icon.setVisible(true);
icon.setIcon(IconType.ROTATE_RIGHT);
icon.setTitle("Checking...");
icon.setSpin(true);
service.checkIdentifierExistsInDomain(currentText, s.getDomain(), new AsyncCallback<String>() {
@Override @Override
public void onSuccess(String result) { public void onSuccess(String result) {
icon.setSpin(false);
if(result != null){ if(result != null){
s.setKnowledgeBaseId(currentText); s.setKnowledgeBaseId(currentText);
s.setSuggestedMerge(true); s.setSuggestedMerge(true);
icon.setType(IconType.OK_CIRCLE);
icon.setTitle("Accepted");
view.setHref(result); view.setHref(result);
view.setVisible(true); view.setVisible(true);
box.setEnabled(false); box.setEnabled(false);
validateUUIDButton.setText("Accepted");
validateUUIDButton.setType(ButtonType.SUCCESS);
validateUUIDButton.setEnabled(false);
} }
else{ else{
icon.setType(IconType.BAN_CIRCLE);
icon.setTitle("Not a valid UUID");
view.setVisible(false); view.setVisible(false);
box.setEnabled(true); box.setEnabled(true);
validateUUIDButton.setText("Invalid");
validateUUIDButton.setType(ButtonType.DANGER);
validateUUIDButton.setEnabled(true);
} }
icon.setVisible(true);
} }
@Override @Override
public void onFailure(Throwable caught) { public void onFailure(Throwable caught) {
box.setEnabled(true); box.setEnabled(true);
icon.setSpin(false);
icon.setType(IconType.BAN_CIRCLE);
icon.setVisible(true);
view.setVisible(false); view.setVisible(false);
icon.setTitle(caught.getMessage()); validateUUIDButton.setText("Invalid");
validateUUIDButton.setTitle("Error is " + caught);
validateUUIDButton.setType(ButtonType.DANGER);
view.setVisible(false);
box.setEnabled(true);
} }
}); });
@ -257,7 +230,8 @@ public class SuggestMerges extends Composite {
SimilarGRSFRecord similarRecord = ((SimilarGRSFRecord)p.getO()); SimilarGRSFRecord similarRecord = ((SimilarGRSFRecord)p.getO());
if(similarRecord.getKnowledgeBaseId() == null || similarRecord.getKnowledgeBaseId().isEmpty()) if(similarRecord.getKnowledgeBaseId() == null || similarRecord.getKnowledgeBaseId().isEmpty())
continue; continue;
toReturn.add((SimilarGRSFRecord) p.getO()); similarRecord.setSuggestedMerge(true);
toReturn.add(similarRecord);
} }
return toReturn; return toReturn;

View File

@ -28,6 +28,7 @@ import org.gcube.datacatalogue.grsf_manage_widget.shared.SourceRecord;
import org.gcube.datacatalogue.grsf_manage_widget.shared.ex.NoGRSFRecordException; import org.gcube.datacatalogue.grsf_manage_widget.shared.ex.NoGRSFRecordException;
import org.gcube.vomanagement.usermanagement.RoleManager; import org.gcube.vomanagement.usermanagement.RoleManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayRoleManager; import org.gcube.vomanagement.usermanagement.impl.LiferayRoleManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeTeam; import org.gcube.vomanagement.usermanagement.model.GCubeTeam;
import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.gcube.vomanagement.usermanagement.model.GCubeUser;
@ -85,6 +86,8 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
if(!Utils.isIntoPortal()){ if(!Utils.isIntoPortal()){
Thread.sleep(2000);
toReturn = new ManageProductBean(); toReturn = new ManageProductBean();
toReturn.setCatalogueIdentifier(UUID.randomUUID().toString()); toReturn.setCatalogueIdentifier(UUID.randomUUID().toString());
List<ConnectedBean> connectTo = new ArrayList<>(); List<ConnectedBean> connectTo = new ArrayList<>();
@ -112,12 +115,12 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
"Fishery" "Fishery"
)); ));
toReturn.setSuggestedByKnowledgeBaseConnections(suggestionsForConnections); toReturn.setSuggestedByKnowledgeBaseConnections(suggestionsForConnections);
toReturn.setGrsfDomain("Stock"); toReturn.setDomain("Stock");
toReturn.setGrsfType("Assessment Unit"); toReturn.setGrsfType("Assessment Unit");
toReturn.setKnowledgeBaseIdentifier("91f1e413-dc9f-3b4e-b1c5-0e8560177253"); toReturn.setKnowledgeBaseId("91f1e413-dc9f-3b4e-b1c5-0e8560177253");
toReturn.setShortName("Widow rockfish - US West Coast"); toReturn.setShortName("Widow rockfish - US West Coast");
toReturn.setShortNameUpdated("Widow rockfish - US West Coast"); toReturn.setShortNameUpdated("Widow rockfish - US West Coast");
toReturn.setGrsfName("sebastes entomelas FAO 77 FAO 67"); toReturn.setTitle("sebastes entomelas FAO 77 FAO 67");
toReturn.setTraceabilityFlag(true); toReturn.setTraceabilityFlag(true);
toReturn.setCurrentStatus(Status.Pending); toReturn.setCurrentStatus(Status.Pending);
toReturn.setSemanticIdentifier("asfis:WRO+fao:67;FAO"); toReturn.setSemanticIdentifier("asfis:WRO+fao:67;FAO");
@ -217,6 +220,7 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
Map<String, List<String>> extrasWithoutNamespaces = Utils.replaceFieldsKey(extrasAsPairs, fieldsNamespacesMap); Map<String, List<String>> extrasWithoutNamespaces = Utils.replaceFieldsKey(extrasAsPairs, fieldsNamespacesMap);
String catalogueIdentifier = record.getId(); String catalogueIdentifier = record.getId();
String description = record.getNotes();
Status status = Status.fromString(extrasWithoutNamespaces.get(Constants.STATUS_OF_THE_GRSF_RECORD_CUSTOM_KEY).get(0)); Status status = Status.fromString(extrasWithoutNamespaces.get(Constants.STATUS_OF_THE_GRSF_RECORD_CUSTOM_KEY).get(0));
String uuidKB = extrasWithoutNamespaces.get(Constants.UUID_KB_CUSTOM_KEY).get(0); String uuidKB = extrasWithoutNamespaces.get(Constants.UUID_KB_CUSTOM_KEY).get(0);
String grsfDomain = extrasWithoutNamespaces.get(Constants.DOMAIN_CUSTOM_KEY).get(0); String grsfDomain = extrasWithoutNamespaces.get(Constants.DOMAIN_CUSTOM_KEY).get(0);
@ -295,7 +299,7 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
// set the values // set the values
toReturn = new ManageProductBean( toReturn = new ManageProductBean(
semanticId, catalogueIdentifier, uuidKB, grsfType, semanticId, catalogueIdentifier, uuidKB, grsfType,
grsfDomain, grsfName, shortName, traceabilityFlag, grsfDomain, shortName, description, grsfName,traceabilityFlag,
status, recordUrl, sources, similarRecords, status, recordUrl, sources, similarRecords,
connectedBeans, suggestedConnectionsByKnowledgeBase); connectedBeans, suggestedConnectionsByKnowledgeBase);
@ -340,9 +344,13 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
} }
@Override @Override
public String notifyProductUpdate(ManageProductBean bean) throws Exception{ public void notifyProductUpdate(ManageProductBean bean) throws Exception{
logger.info("Creating notification for the bean " + bean + " to send to the knowledge base"); logger.info("Creating notification for the bean " + bean + " to send to the knowledge base");
if(!Utils.isIntoPortal()){
Thread.sleep(2500);
return;
}
try{ try{
String context = Utils.getScopeFromClientUrl(getThreadLocalRequest()); String context = Utils.getScopeFromClientUrl(getThreadLocalRequest());
@ -364,8 +372,8 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
String sessionProductKey = ScopeProvider.instance.get() + bean.getCatalogueIdentifier(); String sessionProductKey = ScopeProvider.instance.get() + bean.getCatalogueIdentifier();
threadRequest.getSession().removeAttribute(sessionProductKey); threadRequest.getSession().removeAttribute(sessionProductKey);
return Utils.updateRecord(baseUrl, bean, catalogue, username, administratorFullName, threadRequest, Utils.updateRecord(baseUrl, bean, catalogue, username, administratorFullName, threadRequest,
PortalContext.getConfiguration().getCurrentGroupId(threadRequest), context, token, bean.getReport()); PortalContext.getConfiguration().getCurrentGroupId(threadRequest), context, token);
}catch(Exception e){ }catch(Exception e){
logger.error("Unable to update the product", e); logger.error("Unable to update the product", e);
@ -377,12 +385,22 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
public RevertableOperationInfo validateRevertOperation(String encryptedUrl) throws Exception { public RevertableOperationInfo validateRevertOperation(String encryptedUrl) throws Exception {
if(!Utils.isIntoPortal()){ if(!Utils.isIntoPortal()){
Thread.sleep(2000);
// random result
boolean throwException = Math.random() > 0.5;
if(throwException)
throw new Exception("Unable to parse the inserted url");
String baseUrl = "url of the record here"; String baseUrl = "url of the record here";
String fullName = "Andrea Rossi"; String fullName = "Andrea Rossi";
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
String adminInUrl = "costantino.perciante"; String adminInUrl = "costantino.perciante";
String adminInUrlFullName = "Costantino Perciante";
long timestamp = System.currentTimeMillis() - 1000 * ((long)(Math.random() * 10 * 60 * 60)); long timestamp = System.currentTimeMillis() - 1000 * ((long)(Math.random() * 10 * 60 * 60));
return new RevertableOperationInfo(baseUrl, fullName, uuid, adminInUrl, timestamp, RevertableOperations.MERGE); return new RevertableOperationInfo(
baseUrl, fullName, uuid, adminInUrlFullName, adminInUrl, timestamp, RevertableOperations.MERGE);
} }
PortalContext pContext = PortalContext.getConfiguration(); PortalContext pContext = PortalContext.getConfiguration();
@ -403,31 +421,32 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
// decrypt the url // decrypt the url
RevertOperationUrl decryptedUrl = new RevertOperationUrl(encryptedUrl); RevertOperationUrl decryptedUrl = new RevertOperationUrl(encryptedUrl);
String adminInUrl = decryptedUrl.getAdmin(); String userNameadminInUrl = decryptedUrl.getAdmin(); // this is the username
String fullNameadminInUrl = new LiferayUserManager().getUserByUsername(userNameadminInUrl).getFullname(); // this is the fullname
String uuid = decryptedUrl.getUuid(); String uuid = decryptedUrl.getUuid();
logger.info("User " + username + " has requested to invert an operation on record with id " + uuid + " and admin in url is " + adminInUrl); logger.info("User " + username + " has requested to invert an operation on record with id " + uuid + " and admin in url is " + userNameadminInUrl);
// we need to check the timestamp (it has 24h validity) // we need to check the timestamp (it has 24h validity)
boolean isValidTimestamp = decryptedUrl.isTimestampValid(); boolean isValidTimestamp = decryptedUrl.isTimestampValid();
if(!isValidTimestamp) if(!isValidTimestamp)
throw new Exception("This operation can no longer be reverted (link expired)!"); throw new Exception("This operation can no longer be reverted (link expired)!");
DataCatalogue catalogue = getCatalogue(context); DataCatalogue catalogue = getCatalogue(context);
String recordUrl = catalogue.getDataset(uuid, catalogue.getApiKeyFromUsername(username)).getExtrasAsHashMap().get(Constants.ITEM_URL_FIELD); String recordUrl = catalogue.getDataset(uuid, catalogue.getApiKeyFromUsername(username)).getExtrasAsHashMap().get(Constants.ITEM_URL_FIELD);
// check if it is a reviewer, than he can do what he wants (no matter the admin) // check if it is a reviewer, than he can do what he wants (no matter the admin)
if(isReviewer){ if(isReviewer){
return new RevertableOperationInfo(recordUrl, return new RevertableOperationInfo(recordUrl,
fullName, uuid, adminInUrl, decryptedUrl.getTimestamp(), decryptedUrl.getOperation()); fullName, uuid, fullNameadminInUrl, userNameadminInUrl, decryptedUrl.getTimestamp(), decryptedUrl.getOperation());
}else{ }else{
if(!username.equals(adminInUrl)) if(!username.equals(userNameadminInUrl))
throw new Exception("You are not the editor allowed to perform this operation!"); throw new Exception("You are not the editor allowed to perform this operation!");
else else
return new RevertableOperationInfo(recordUrl, return new RevertableOperationInfo(recordUrl,
fullName, uuid, adminInUrl, decryptedUrl.getTimestamp(), decryptedUrl.getOperation()); fullName, uuid, fullNameadminInUrl, userNameadminInUrl, decryptedUrl.getTimestamp(), decryptedUrl.getOperation());
} }
} }
@ -435,25 +454,25 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
@Override @Override
public Boolean performRevertOperation(RevertableOperationInfo rInfo) public Boolean performRevertOperation(RevertableOperationInfo rInfo)
throws Exception { throws Exception {
if(!Utils.isIntoPortal()){ if(!Utils.isIntoPortal()){
// random result // random result
boolean toReturn = Math.random() > 0.5; boolean toReturn = Math.random() > 0.5;
if(toReturn){ if(toReturn){
boolean throwException = Math.random() > 0.5; boolean throwException = Math.random() > 0.5;
if(throwException) if(throwException)
throw new Exception("Unable to execute request for XYZ"); throw new Exception("Unable to execute request for XYZ");
} }
return toReturn; return toReturn;
} }
HttpServletRequest threadRequest = getThreadLocalRequest(); HttpServletRequest threadRequest = getThreadLocalRequest();
String context = Utils.getScopeFromClientUrl(threadRequest); String context = Utils.getScopeFromClientUrl(threadRequest);
String token = SecurityTokenProvider.instance.get(); String token = SecurityTokenProvider.instance.get();
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){ try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){
String keyPerContext = UtilMethods.concatenateSessionKeyScope(Constants.GRSF_UPDATER_SERVICE, context); String keyPerContext = UtilMethods.concatenateSessionKeyScope(Constants.GRSF_UPDATER_SERVICE, context);
@ -465,9 +484,10 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS
if(baseUrl == null || baseUrl.isEmpty()) if(baseUrl == null || baseUrl.isEmpty())
throw new Exception("Unable to discover grsf-updater service!"); throw new Exception("Unable to discover grsf-updater service!");
Utils.revertOperation(httpClient, baseUrl, rInfo, token, context, PortalContext.getConfiguration().getCurrentGroupId(threadRequest)); Utils.revertOperation(httpClient, baseUrl, threadRequest, rInfo, token, context,
PortalContext.getConfiguration().getCurrentGroupId(threadRequest));
} }
catch(Exception e){ catch(Exception e){
logger.error("Unable to revert operation ", e); logger.error("Unable to revert operation ", e);

View File

@ -98,7 +98,7 @@ public class GRSFUpdaterServiceClient {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put(Constants.ADMINISTRATOR_FULLNAME, fullName); obj.put(Constants.ADMINISTRATOR_FULLNAME, fullName);
obj.put(Constants.CATALOGUE_ID, bean.getCatalogueIdentifier()); obj.put(Constants.CATALOGUE_ID, bean.getCatalogueIdentifier());
obj.put(Constants.KB_ID, bean.getKnowledgeBaseIdentifier()); obj.put(Constants.KB_ID, bean.getKnowledgeBaseId());
obj.put(Constants.NEW_STATUS, bean.getNewStatus().toString().toLowerCase()); obj.put(Constants.NEW_STATUS, bean.getNewStatus().toString().toLowerCase());
obj.put(Constants.OLD_STATUS, bean.getCurrentStatus().toString().toLowerCase()); obj.put(Constants.OLD_STATUS, bean.getCurrentStatus().toString().toLowerCase());
obj.put(Constants.TRACEABILITY_FLAG, bean.isTraceabilityFlag()); obj.put(Constants.TRACEABILITY_FLAG, bean.isTraceabilityFlag());
@ -122,9 +122,9 @@ public class GRSFUpdaterServiceClient {
for(ConnectedBean c: connections){ for(ConnectedBean c: connections){
JSONObject cc = new JSONObject(); JSONObject cc = new JSONObject();
if(c.isRemove() || (c.isConnect() && !c.isRemove())){ // do not send it if it needs to be unconnected but not removed if(c.isRemove() || (c.isConnect() && !c.isRemove())){ // do not send it if it needs to be unconnected but not removed
cc.put(Constants.SOURCE_KNOWLEDGE_BASE_ID, bean.getKnowledgeBaseIdentifier()); cc.put(Constants.SOURCE_KNOWLEDGE_BASE_ID, bean.getKnowledgeBaseId());
cc.put(Constants.DEST_KNOWLEDGE_BASE_ID, c.getKnowledgeBaseId()); cc.put(Constants.DEST_KNOWLEDGE_BASE_ID, c.getKnowledgeBaseId());
cc.put(Constants.SOURCE_DOMAIN, bean.getGrsfDomain()); cc.put(Constants.SOURCE_DOMAIN, bean.getDomain());
cc.put(Constants.CONNECTION_TO_REMOVE, c.isRemove()); cc.put(Constants.CONNECTION_TO_REMOVE, c.isRemove());
} }
connectionsJson.add(cc); connectionsJson.add(cc);

View File

@ -7,6 +7,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -15,6 +16,7 @@ import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.common.Constants; import org.gcube.datacatalogue.common.Constants;
import org.gcube.datacatalogue.grsf_manage_widget.shared.HashTagsOnUpdate;
import org.gcube.datacatalogue.grsf_manage_widget.shared.ManageProductBean; import org.gcube.datacatalogue.grsf_manage_widget.shared.ManageProductBean;
import org.gcube.datacatalogue.grsf_manage_widget.shared.RevertableOperationInfo; import org.gcube.datacatalogue.grsf_manage_widget.shared.RevertableOperationInfo;
import org.gcube.datacatalogue.grsf_manage_widget.shared.RevertableOperations; import org.gcube.datacatalogue.grsf_manage_widget.shared.RevertableOperations;
@ -34,6 +36,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpEntity; 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.HttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.CloseableHttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpPost; 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.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.CloseableHttpClient;
@ -77,76 +80,79 @@ public class SocialCommunications {
+ "<br>your request for the record 'PRODUCT_TITLE' has been accepted." + "<br>your request for the record 'PRODUCT_TITLE' has been accepted."
+ "<br>It is available here LINK_RECORD."; + "<br>It is available here LINK_RECORD.";
private static final String ADD_REPORT = "<br>This is a summary of the actions proposed:<br>REPORT_UPDATE<br>";
// revert link
private static final String REVERT_LINK_PIECE = "<br>The request involves a merge operation. You can reject the merge by exploiting this link LINK in the following 24 hours."; private static final String REVERT_LINK_PIECE = "<br>The request involves a merge operation. You can reject the merge by exploiting this link LINK in the following 24 hours.";
// on revert operation // on revert operation
private static final String EMAIL_REVIEWER_REVERT = "Dear GRSF Reviewer," private static final String EMAIL_REVIEWER_REVERT = "Dear GRSF Reviewer,"
+ "<br>a revert operation (undo merge) has been requested on record RECORD_URL, by USERNAME."; + "<br>a revert operation (undo merge) has been requested on record RECORD_URL, by ADMIN_WHO_CHANGED.";
private static final String EMAIL_EDITOR_REVERT = "Dear USER_FULLNAME," private static final String EMAIL_EDITOR_REVERT = "Dear ORIGINAL_USER,"
+"<br> a revert operation (undo merge) has been requested on this RECORD_URL you managed."; +"<br> a revert operation (undo merge) has been requested on this RECORD_URL you managed by ADMIN_WHO_CHANGED.";
// post on revert
private static final String POST_ON_REVERT = "Dear members,"
+ "<br>a merge operation has been reverted on this record RECORD_URL by ADMIN_WHO_CHANGED. The merge was originally proposed by ORIGINAL_USER.";
private static final String SOCIAL_NETWORKING_BASE_URL_SESSION_KEY = "SOCIAL_NETWORKING_SESSION_KEY";
/** /**
* *
* @param httpServletRequest
* @param context * @param context
* @return * @return
*/ */
private static String getBaseUrlSocialService(String context){ public static String getBaseUrlSocialService(HttpServletRequest httpServletRequest){
if(context == null || context.isEmpty()) String context = ScopeProvider.instance.get();
throw new IllegalArgumentException("A valid context is needed to discover the service");
String oldContext = ScopeProvider.instance.get(); String keyPerContext = SOCIAL_NETWORKING_BASE_URL_SESSION_KEY + context;
ScopeProvider.instance.set(context); String basePath = (String) httpServletRequest.getSession().getAttribute(keyPerContext);
String basePath = null; if(basePath == null){
try{ try{
SimpleQuery query = queryFor(GCoreEndpoint.class); SimpleQuery query = queryFor(GCoreEndpoint.class);
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'",serviceClass)); query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'",serviceClass));
query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'"); query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'");
query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'",serviceName)); query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'",serviceName));
query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+resource+"\"]/text()"); query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+resource+"\"]/text()");
DiscoveryClient<String> client = client(); DiscoveryClient<String> client = client();
List<String> endpoints = client.submit(query); List<String> endpoints = client.submit(query);
if (endpoints == null || endpoints.isEmpty()) if (endpoints == null || endpoints.isEmpty())
throw new Exception("Cannot retrieve the GCoreEndpoint serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+context); throw new Exception("Cannot retrieve the GCoreEndpoint serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+context);
basePath = endpoints.get(0); basePath = endpoints.get(0);
if(basePath==null) if(basePath==null)
throw new Exception("Endpoint:"+resource+", is null for serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+context); throw new Exception("Endpoint:"+resource+", is null for serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+context);
}catch(Exception e){ httpServletRequest.getSession().setAttribute(keyPerContext, basePath);
logger.error("Unable to retrieve such service endpoint information!", e);
}finally{ }catch(Exception e){
if(oldContext != null && !oldContext.equals(context)) logger.error("Unable to retrieve such service endpoint information!", e);
ScopeProvider.instance.set(oldContext); }
} }
logger.info("Found base path " + basePath + " for the service"); logger.info("Found base path " + basePath + " for the service");
return basePath; return basePath;
} }
/** /**
* Notify the users about the required changes. * Require a proper application token for writing a post and send messages.
* @param bean * @return
* @param url * @throws Exception
* @param username
* @param fullName
* @param hashtags
* @param enablePostNotification
* @throws Exception
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void writeProductPost(ManageProductBean bean, String username, String fullName, String report, boolean enablePostNotification) throws Exception{ private static String requireApplicationToken(String serviceUrl) throws Exception{
// discover service endpoint for the social networking library
String currentScope = ScopeProvider.instance.get(); String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get(); String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************"); logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
String basePath = getBaseUrlSocialService(currentScope); String basePath = serviceUrl;
if(basePath == null){ if(basePath == null){
@ -161,7 +167,9 @@ public class SocialCommunications {
// ask token application // ask token application
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser); HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser);
StringEntity input = new StringEntity("{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}"); JSONObject requestToken = new JSONObject();
requestToken.put("app_id", APPLICATION_ID_CATALOGUE_MANAGER);
StringEntity input = new StringEntity(requestToken.toJSONString());
input.setContentType(MEDIATYPE_JSON); input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input); postRequest.setEntity(input);
HttpResponse response = client.execute(postRequest); HttpResponse response = client.execute(postRequest);
@ -182,39 +190,144 @@ public class SocialCommunications {
}else{ }else{
String applicationToken = (String)mapResponseGeneratedToken.get("result"); return (String)mapResponseGeneratedToken.get("result");
// replace
String message = POST_MESSAGE.replace("PRODUCT_TITLE", bean.getGrsfName()).replace("PRODUCT_URL", bean.getRecordUrl()).replace("USER_FULLNAME", fullName);
// evaluate hashtags from the report ... TODO
// if(hashtags != null && !hashtags.isEmpty())
// for (String hashtag : hashtags) {
// String modifiedHashtag = hashtag.replaceAll(" ", "_").replace("_+", "_"); // no empty spaces allowed
// if(modifiedHashtag.endsWith("_"))
// modifiedHashtag = modifiedHashtag.substring(0, modifiedHashtag.length() - 1);
// message += " #" + modifiedHashtag;
// }
logger.info("The post that is going to be written is -> " + message);
postRequest = new HttpPost(basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + applicationToken);
JSONObject object = new JSONObject();
object.put("text", message);
object.put("enable_notification", enablePostNotification);
input = new StringEntity(object.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
response = client.execute(postRequest);
Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201)
throw new RuntimeException("Failed to write application post : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
} }
} }
}catch(Exception e){
logger.error("Failed to create a post", e);
throw e;
}
}
}
/**
* Notify the users about the required changes.
* @param bean
* @param url
* @param username
* @param fullName
* @param hashtags
* @param enablePostNotification
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static void writePostOnRevert(String serviceUrl, RevertableOperationInfo rInfo, boolean enablePostNotification) throws Exception{
// 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 = serviceUrl;
if(basePath == null){
logger.error("Unable to write a post because there is no social networking service available");
throw new Exception("Unable to discover the social networking service");
}else{
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
try(CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();){
// require url
String applicationToken = requireApplicationToken(serviceUrl);
// replace
String message = POST_ON_REVERT.replace("RECORD_URL", rInfo.getRecordUrl()).replace("ADMIN_WHO_CHANGED", rInfo.getFullNameCurrentAdmin()).replace("ORIGINAL_USER", rInfo.getFullNameOriginalAdmin());
// add hashtag
message +="<br><br>";
message += " #" + HashTagsOnUpdate.REVERTED_MERGE.getString();
logger.info("The post that is going to be written is -> " + message);
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + applicationToken);
JSONObject object = new JSONObject();
object.put("text", message);
object.put("enable_notification", enablePostNotification);
StringEntity input = new StringEntity(object.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
CloseableHttpResponse response = client.execute(postRequest);
Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201)
throw new RuntimeException("Failed to write application post : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}catch(Exception e){
logger.error("Failed to create a post", e);
}
}
}
/**
* Notify the users about the required changes.
* @param bean
* @param url
* @param username
* @param fullName
* @param hashtags
* @param enablePostNotification
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static void writeProductPost(String serviceUrl, ManageProductBean bean, String username, String fullName, boolean enablePostNotification) throws Exception{
// 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 = serviceUrl;
if(basePath == null){
logger.error("Unable to write a post because there is no social networking service available");
throw new Exception("Unable to discover the social networking service");
}else{
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
try(CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();){
// require url
String applicationToken = requireApplicationToken(serviceUrl);
// replace
String message = POST_MESSAGE.replace("PRODUCT_TITLE", bean.getTitle()).replace("PRODUCT_URL", bean.getUrl()).
replace("USER_FULLNAME", fullName);
if(bean.getReport() != null)
message += ADD_REPORT.replace("REPORT_UPDATE", bean.getReport());
Set<String> hashtags = bean.getHashtags();
if(hashtags != null && !hashtags.isEmpty()){
message +="<br><br>";
for (String hashtag : hashtags) {
message += " #" + hashtag;
}
}
logger.info("The post that is going to be written is -> " + message);
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + applicationToken);
JSONObject object = new JSONObject();
object.put("text", message);
object.put("enable_notification", enablePostNotification);
StringEntity input = new StringEntity(object.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
CloseableHttpResponse response = client.execute(postRequest);
Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201)
throw new RuntimeException("Failed to write application post : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}catch(Exception e){ }catch(Exception e){
logger.error("Failed to create a post", e); logger.error("Failed to create a post", e);
} }
@ -233,6 +346,7 @@ public class SocialCommunications {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void sendEmailAdministratorsOnMerge( public static void sendEmailAdministratorsOnMerge(
String serviceUrl,
ManageProductBean bean, ManageProductBean bean,
DataCatalogue catalogue, DataCatalogue catalogue,
String username, String username,
@ -265,7 +379,7 @@ public class SocialCommunications {
String tokenUser = SecurityTokenProvider.instance.get(); String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************"); logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
String basePath = getBaseUrlSocialService(currentScope); String basePath = serviceUrl;
if(basePath == null){ if(basePath == null){
@ -278,88 +392,69 @@ public class SocialCommunications {
try(CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();){ try(CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();){
// ask token application /// require url
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser); String applicationToken = requireApplicationToken(serviceUrl);
StringEntity input = new StringEntity("{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}"); String revertUrl = getEncodedUrlManage(operation, username, System.currentTimeMillis(), bean.getKnowledgeBaseId(), httpServletRequest);
String messageToEditor = (EMAIL_MESSAGE_EDITOR +
(isMergeInvolved? REVERT_LINK_PIECE : "")).replace("USER_FULLNAME", fullName).replace("PRODUCT_TITLE", bean.getTitle()).
replace("LINK_RECORD", bean.getUrl()).replace("LINK", revertUrl);
String messageToReviewer = (EMAIL_MESSAGE_REVIEWER+
(isMergeInvolved? REVERT_LINK_PIECE : "")).replace("USER_FULLNAME", fullName).replace("PRODUCT_TITLE", bean.getTitle()).
replace("LINK_RECORD", bean.getUrl()).replace("LINK", revertUrl);
String subject = "Update request on GRSF Record";
// append report
if(bean.getReport() != null){
messageToEditor += ADD_REPORT.replace("REPORT_UPDATE", bean.getReport());
messageToReviewer += ADD_REPORT.replace("REPORT_UPDATE", bean.getReport());
}
// send email to the editor
logger.info("The message that is going to be send to the editor is\n" + messageToEditor);
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
JSONObject reqMessage = new JSONObject();
reqMessage.put("subject", subject);
reqMessage.put("body", messageToEditor);
JSONArray recipients = new JSONArray();
JSONObject recipient = new JSONObject();
recipient.put("id", username);
recipients.add(recipient);
reqMessage.put("recipients", recipients);
StringEntity input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON); input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input); postRequest.setEntity(input);
HttpResponse response = client.execute(postRequest); CloseableHttpResponse response = client.execute(postRequest);
logger.debug("Url is " + basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser); Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201) { if (response.getStatusLine().getStatusCode() != 201){
throw new RuntimeException("Failed to retrieve application token : HTTP error code : " logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode()); + response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}else{ }
Map<String, Object> mapResponseGeneratedToken = getResponseEntityAsJSON(response); // send email to the reviewers
boolean successGeneratedToken = (boolean)mapResponseGeneratedToken.get("success"); logger.info("The message that is going to be send to the reviewers is\n" + messageToReviewer);
if(!successGeneratedToken){ postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
reqMessage = new JSONObject();
throw new RuntimeException("Failed to generate the token for the application!" reqMessage.put("subject", subject);
+ " Error message is " + mapResponseGeneratedToken.get("message")); reqMessage.put("body", messageToReviewer);
recipients = new JSONArray();
}else{ for(String reviewer: reviewers){
JSONObject recip = new JSONObject();
String applicationToken = (String)mapResponseGeneratedToken.get("result"); recip.put("id", reviewer);
recipients.add(recip);
String revertUrl = getEncodedUrlManage(operation, username, System.currentTimeMillis(), bean.getKnowledgeBaseIdentifier(), httpServletRequest); }
reqMessage.put("recipients", recipients);
String messageToEditor = (EMAIL_MESSAGE_EDITOR + input = new StringEntity(reqMessage.toJSONString());
(isMergeInvolved? REVERT_LINK_PIECE : "")).replace("USER_FULLNAME", fullName).replace("PRODUCT_TITLE", bean.getGrsfName()).replace("LINK_RECORD", bean.getRecordUrl()).replace("LINK", revertUrl); input.setContentType(MEDIATYPE_JSON);
String messageToReviewer = (EMAIL_MESSAGE_REVIEWER+ postRequest.setEntity(input);
(isMergeInvolved? REVERT_LINK_PIECE : "")).replace("USER_FULLNAME", fullName).replace("PRODUCT_TITLE", bean.getGrsfName()).replace("LINK_RECORD", bean.getRecordUrl()).replace("LINK", revertUrl); response = client.execute(postRequest);
String subject = "Update request on GRSF Record"; mapResponseWritePost = getResponseEntityAsJSON(response);
// send email to the editor
logger.info("The message that is going to be send to the editor is\n" + messageToEditor);
postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
JSONObject reqMessage = new JSONObject();
reqMessage.put("subject", subject);
reqMessage.put("body", messageToEditor);
JSONArray recipients = new JSONArray();
JSONObject recipient = new JSONObject();
recipient.put("id", username);
recipients.add(recipient);
reqMessage.put("recipients", recipients);
input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
response = client.execute(postRequest);
Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}
// send email to the reviewers
logger.info("The message that is going to be send to the reviewers is\n" + messageToReviewer);
postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
reqMessage = new JSONObject();
reqMessage.put("subject", subject);
reqMessage.put("body", messageToReviewer);
recipients = new JSONArray();
for(String reviewer: reviewers){
JSONObject recip = new JSONObject();
recip.put("id", reviewer);
recipients.add(recip);
}
reqMessage.put("recipients", recipients);
input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
response = client.execute(postRequest);
mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}
}
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
} }
}catch(Exception e){ }catch(Exception e){
@ -369,7 +464,9 @@ public class SocialCommunications {
} }
@SuppressWarnings("unchecked")
public static void sendEmailAdministratorsOnOperationReverted( public static void sendEmailAdministratorsOnOperationReverted(
String serviceUrl,
RevertableOperationInfo rInfo, RevertableOperationInfo rInfo,
long groupId long groupId
) throws Exception { ) throws Exception {
@ -386,19 +483,16 @@ public class SocialCommunications {
} }
// if the user is a reviewer, then send the email just once // if the user is a reviewer, then send the email just once
reviewers.remove(rInfo.getAdmin()); reviewers.remove(rInfo.getUserNameOriginalAdmin());
logger.info("List of " + Constants.GRSF_CATALOGUE_REVIEWER_ROLE + " is " + reviewers); logger.info("List of " + Constants.GRSF_CATALOGUE_REVIEWER_ROLE + " is " + reviewers);
// build the url that allows to revert the operation
RevertableOperations operation = RevertableOperations.MERGE;
// discover service endpoint for the social networking library // discover service endpoint for the social networking library
String currentScope = ScopeProvider.instance.get(); String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get(); String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************"); logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
String basePath = getBaseUrlSocialService(currentScope); String basePath = serviceUrl;
if(basePath == null){ if(basePath == null){
@ -411,84 +505,59 @@ public class SocialCommunications {
try(CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();){ try(CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();){
// ask token application String applicationToken = requireApplicationToken(serviceUrl);
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser);
StringEntity input = new StringEntity("{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}"); String messageToEditor = EMAIL_EDITOR_REVERT.replace("RECORD_URL", rInfo.getRecordUrl()).replace("ORIGINAL_USER", rInfo.getFullNameOriginalAdmin()).
replace("ADMIN_WHO_CHANGED", rInfo.getFullNameCurrentAdmin());
String messageToReviewer = EMAIL_REVIEWER_REVERT.replace("ADMIN_WHO_CHANGED", rInfo.getFullNameCurrentAdmin()).replace("RECORD_URL", rInfo.getRecordUrl()).
replace("ORIGINAL_USER", rInfo.getFullNameOriginalAdmin());
String subject = "Revert merge request on GRSF Record";
// send email to the editor
logger.info("The message that is going to be send to the editor is\n" + messageToEditor);
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
JSONObject reqMessage = new JSONObject();
reqMessage.put("subject", subject);
reqMessage.put("body", messageToEditor);
JSONArray recipients = new JSONArray();
JSONObject recipient = new JSONObject();
recipient.put("id", rInfo.getUserNameOriginalAdmin());
recipients.add(recipient);
reqMessage.put("recipients", recipients);
StringEntity input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON); input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input); postRequest.setEntity(input);
HttpResponse response = client.execute(postRequest); CloseableHttpResponse response = client.execute(postRequest);
logger.debug("Url is " + basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser); Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201) { if (response.getStatusLine().getStatusCode() != 201){
throw new RuntimeException("Failed to retrieve application token : HTTP error code : " logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode()); + response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}else{ }
Map<String, Object> mapResponseGeneratedToken = getResponseEntityAsJSON(response); // send email to the reviewers
boolean successGeneratedToken = (boolean)mapResponseGeneratedToken.get("success"); logger.info("The message that is going to be send to the reviewers is\n" + messageToReviewer);
if(!successGeneratedToken){ postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
reqMessage = new JSONObject();
throw new RuntimeException("Failed to generate the token for the application!" reqMessage.put("subject", subject);
+ " Error message is " + mapResponseGeneratedToken.get("message")); reqMessage.put("body", messageToReviewer);
recipients = new JSONArray();
}else{ for(String reviewer: reviewers){
JSONObject recip = new JSONObject();
String applicationToken = (String)mapResponseGeneratedToken.get("result"); recip.put("id", reviewer);
recipients.add(recip);
String messageToEditor = EMAIL_EDITOR_REVERT.replace("RECORD_URL", rInfo.getRecordUrl()).replace("USER_FULLNAME", rInfo.getFullName()); }
String messageToReviewer = EMAIL_REVIEWER_REVERT.replace("USER_FULLNAME", rInfo.getFullName()).replace("RECORD_URL", rInfo.getRecordUrl()); reqMessage.put("recipients", recipients);
String subject = "Revert merge request on GRSF Record"; input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
// send email to the editor postRequest.setEntity(input);
logger.info("The message that is going to be send to the editor is\n" + messageToEditor); response = client.execute(postRequest);
postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken); mapResponseWritePost = getResponseEntityAsJSON(response);
JSONObject reqMessage = new JSONObject();
reqMessage.put("subject", subject);
reqMessage.put("body", messageToEditor);
JSONArray recipients = new JSONArray();
JSONObject recipient = new JSONObject();
recipient.put("id", rInfo.getAdmin());
recipients.add(recipient);
reqMessage.put("recipients", recipients);
input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
response = client.execute(postRequest);
Map<String, Object> mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}
// send email to the reviewers
logger.info("The message that is going to be send to the reviewers is\n" + messageToReviewer);
postRequest = new HttpPost(basePath + SOCIAL_SEND_EMAIL + "?gcube-token=" + applicationToken);
reqMessage = new JSONObject();
reqMessage.put("subject", subject);
reqMessage.put("body", messageToReviewer);
recipients = new JSONArray();
for(String reviewer: reviewers){
JSONObject recip = new JSONObject();
recip.put("id", reviewer);
recipients.add(recip);
}
reqMessage.put("recipients", recipients);
input = new StringEntity(reqMessage.toJSONString());
input.setContentType(MEDIATYPE_JSON);
postRequest.setEntity(input);
response = client.execute(postRequest);
mapResponseWritePost = getResponseEntityAsJSON(response);
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
}
}
if (response.getStatusLine().getStatusCode() != 201){
logger.error("Failed to send message to editor : HTTP error code : "
+ response.getStatusLine().getStatusCode() + mapResponseWritePost.get("message"));
} }
}catch(Exception e){ }catch(Exception e){

View File

@ -178,17 +178,16 @@ public class Utils {
* @param catalogue * @param catalogue
* @return true on success, false otherwise * @return true on success, false otherwise
*/ */
public static String updateRecord( public static void updateRecord(
String serviceUrl, String serviceUrl,
ManageProductBean bean, final ManageProductBean bean,
DataCatalogue catalogue, final DataCatalogue catalogue,
String username, final String username,
String fullName, final String fullName,
HttpServletRequest httpServletRequest, final HttpServletRequest httpServletRequest,
long groupId, final long groupId,
String context, final String context,
String token, final String token) throws Exception{
String report) throws Exception{
if(serviceUrl == null) if(serviceUrl == null)
throw new IllegalArgumentException("GRSF Updater service url cannot be null"); throw new IllegalArgumentException("GRSF Updater service url cannot be null");
@ -205,35 +204,41 @@ public class Utils {
// send update to the knowledge base // send update to the knowledge base
GRSFUpdaterServiceClient.updateKB(httpClient, serviceUrl, bean, catalogue, username, fullName); GRSFUpdaterServiceClient.updateKB(httpClient, serviceUrl, bean, catalogue, username, fullName);
// require social networking url
final String baseUrlSocial = SocialCommunications.getBaseUrlSocialService(httpServletRequest);
// manage interactions through a separated thread but set there security token and context (and then reset them) // manage interactions through a separated thread but set there security token and context (and then reset them)
new Thread(()->{ Thread t = new Thread(new Runnable() {
ScopeProvider.instance.set(context); @Override
SecurityTokenProvider.instance.set(token); public void run() {
try{ ScopeProvider.instance.set(context);
SecurityTokenProvider.instance.set(token);
try{
// send email to Editors and Reviewers // send email to Editors and Reviewers
SocialCommunications.sendEmailAdministratorsOnMerge(bean, catalogue, username, fullName, groupId, httpServletRequest, bean.isMergesInvolved()); SocialCommunications.sendEmailAdministratorsOnMerge(baseUrlSocial, bean, catalogue, username, fullName,
groupId, httpServletRequest, bean.isMergesInvolved());
// create a post about the operation // create a post about the operation
SocialCommunications.writeProductPost(bean, username, fullName, report, true); SocialCommunications.writeProductPost(baseUrlSocial, bean, username, fullName, false);
}catch(Exception e){ }catch(Exception e){
logger.error("Something failed while alerting editors/reviewers", e); logger.error("Something failed while alerting editors/reviewers", e);
}finally{ }finally{
ScopeProvider.instance.reset(); ScopeProvider.instance.reset();
SecurityTokenProvider.instance.reset(); SecurityTokenProvider.instance.reset();
}
} }
});
}).start(); t.start();
}catch(Exception e){ }catch(Exception e){
logger.error("Unable to update this Item ", e); logger.error("Unable to update this Item ", e);
throw e; throw e;
} }
return null;
} }
/** /**
* Revert operation and alert admins/vre users * Revert operation and alert admins/vre users
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
@ -242,30 +247,40 @@ public class Utils {
* @param fullName * @param fullName
* @param uuid * @param uuid
*/ */
public static void revertOperation(CloseableHttpClient httpClient, String baseUrl, public static void revertOperation(CloseableHttpClient httpClient, String baseUrl, HttpServletRequest httpServletRequest,
RevertableOperationInfo rInfo, String token, String context, long groupId) throws Exception{ final RevertableOperationInfo rInfo, final String token, final String context, final long groupId) throws Exception{
GRSFUpdaterServiceClient.revertOperation(httpClient, baseUrl, rInfo.getFullName(), rInfo.getUuid()); GRSFUpdaterServiceClient.revertOperation(httpClient, baseUrl, rInfo.getFullNameCurrentAdmin(), rInfo.getUuid());
// require social networking url
final String baseUrlSocial = SocialCommunications.getBaseUrlSocialService(httpServletRequest);
// manage interactions through a separated thread but set there security token and context (and then reset them) // manage interactions through a separated thread but set there security token and context (and then reset them)
new Thread(()->{ Thread t = new Thread(new Runnable() {
ScopeProvider.instance.set(context); @Override
SecurityTokenProvider.instance.set(token); public void run() {
try{ ScopeProvider.instance.set(context);
SecurityTokenProvider.instance.set(token);
try{
// create a post about the operation // write post about this
SocialCommunications.sendEmailAdministratorsOnOperationReverted(rInfo, groupId); SocialCommunications.writePostOnRevert(baseUrlSocial, rInfo, true);
}catch(Exception e){ // alert who's involved
logger.error("Something failed while alerting editors/reviewers", e); SocialCommunications.sendEmailAdministratorsOnOperationReverted(baseUrlSocial, rInfo, groupId);
}finally{
ScopeProvider.instance.reset(); }catch(Exception e){
SecurityTokenProvider.instance.reset(); logger.error("Something failed while alerting editors/reviewers", e);
}finally{
ScopeProvider.instance.reset();
SecurityTokenProvider.instance.reset();
}
} }
});
t.start();
}).start();
} }
/** /**
@ -290,7 +305,7 @@ public class Utils {
} }
// update the current status record // update the current status record
String productId = bean.getKnowledgeBaseIdentifier(); String productId = bean.getKnowledgeBaseId();
Map<String, List<String>> extrasMap = getExtrasAsHashMap(catalogue.getDataset(productId, sysApi).getExtras()); Map<String, List<String>> extrasMap = getExtrasAsHashMap(catalogue.getDataset(productId, sysApi).getExtras());
extrasMap.put(Constants.STATUS_OF_THE_GRSF_RECORD_CUSTOM_KEY, Arrays.asList(Status.To_be_Merged.getOrigName())); extrasMap.put(Constants.STATUS_OF_THE_GRSF_RECORD_CUSTOM_KEY, Arrays.asList(Status.To_be_Merged.getOrigName()));
catalogue.patchProductCustomFields(productId, sysApi, extrasMap); catalogue.patchProductCustomFields(productId, sysApi, extrasMap);
@ -445,10 +460,10 @@ public class Utils {
JSONParser parser = new JSONParser(); JSONParser parser = new JSONParser();
JSONObject object = (JSONObject)parser.parse(json); JSONObject object = (JSONObject)parser.parse(json);
String uuid = getDatasetKnowledgeBaseIdFromUrl((String)object.get(Constants.SIMILAR_RECORDS_BEAN_FIELD_URL)); String uuid = getDatasetKnowledgeBaseIdFromUrl((String)object.get(Constants.SIMILAR_RECORDS_BEAN_FIELD_URL));
CkanDataset dataset = ctl.getDataset(uuid, apiKey); CkanDataset dataset = ctl.getDataset(uuid, apiKey);
return new SimilarGRSFRecord( return new SimilarGRSFRecord(
uuid, uuid,
(String)object.get(Constants.SIMILAR_RECORDS_BEAN_FIELD_DESCRIPTION), (String)object.get(Constants.SIMILAR_RECORDS_BEAN_FIELD_DESCRIPTION),
@ -507,7 +522,7 @@ public class Utils {
String destDomain = extrasWithoutNamespaces.get(Constants.DOMAIN_CUSTOM_KEY).get(0); String destDomain = extrasWithoutNamespaces.get(Constants.DOMAIN_CUSTOM_KEY).get(0);
String shortName = extrasWithoutNamespaces.get(Constants.SHORT_NAME_CUSTOM_KEY).get(0); String shortName = extrasWithoutNamespaces.get(Constants.SHORT_NAME_CUSTOM_KEY).get(0);
String description = destDataset.getNotes(); String description = destDataset.getNotes();
return new ConnectedBean( return new ConnectedBean(
connectedBeanUuid, connectedBeanUuid,
description, description,

View File

@ -0,0 +1,26 @@
package org.gcube.datacatalogue.grsf_manage_widget.shared;
/**
* A list of hastags to send along the update
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public enum HashTagsOnUpdate {
MERGE("merge"),
REVERTED_MERGE("reverted_merge"),
CONNECT("connect"),
SHORTNAME_UPDATED("shortname_updated"),
TRACEABILITY_FLAG_SET("traceability_flag_set"),
TRACEABILITY_FLAG_UNSET("traceability_flag_unset");
private String string;
HashTagsOnUpdate(String asString){
this.string = asString;
}
public String getString() {
return string;
}
}

View File

@ -1,8 +1,8 @@
package org.gcube.datacatalogue.grsf_manage_widget.shared; package org.gcube.datacatalogue.grsf_manage_widget.shared;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import org.gcube.datacatalogue.common.enums.Status; import org.gcube.datacatalogue.common.enums.Status;
@ -10,16 +10,11 @@ import org.gcube.datacatalogue.common.enums.Status;
* The bean to be managed by GRSF Editors and Reviewers. * The bean to be managed by GRSF Editors and Reviewers.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/ */
public class ManageProductBean implements Serializable{ public class ManageProductBean extends GenericRecord{
private static final long serialVersionUID = -4882608487467259326L; private static final long serialVersionUID = -4882608487467259326L;
private String semanticIdentifier; // Stock id or Fishery id
private String catalogueIdentifier; // Catalogue id private String catalogueIdentifier; // Catalogue id
private String knowledgeBaseIdentifier; // GRSF UUID
private String grsfType; // Fishery or Stock type (e.g., Assessment_Unit, Marine Resource and so on) private String grsfType; // Fishery or Stock type (e.g., Assessment_Unit, Marine Resource and so on)
private String grsfDomain; // fishery/stock
private String grsfName; // Fishery name or Stock name
private String shortName; // it is editable ...
private String shortNameUpdated; // the updated one, if any private String shortNameUpdated; // the updated one, if any
private boolean traceabilityFlag; //from false to true etc private boolean traceabilityFlag; //from false to true etc
private Status currentStatus; private Status currentStatus;
@ -32,8 +27,8 @@ public class ManageProductBean implements Serializable{
private List<ConnectedBean> currentConnections; private List<ConnectedBean> currentConnections;
private List<ConnectedBean> connections; // the one to used eventually private List<ConnectedBean> connections; // the one to used eventually
private boolean mergesInvolved; // important: in this case an email must be sent to the editors/reviewers private boolean mergesInvolved; // important: in this case an email must be sent to the editors/reviewers
private String recordUrl; // this record url
private String report; // the report that keeps track of the changes private String report; // the report that keeps track of the changes
private Set<String> hashtags;
public ManageProductBean() { public ManageProductBean() {
super(); super();
@ -44,9 +39,10 @@ public class ManageProductBean implements Serializable{
String catalogueIdentifier, String catalogueIdentifier,
String knowledgeBaseIdentifier, String knowledgeBaseIdentifier,
String grsfType, String grsfType,
String grsfDomain, String grsfDomain,
String grsfName,
String shortName, String shortName,
String description,
String title,
boolean traceabilityFlag, boolean traceabilityFlag,
Status currentStatus, Status currentStatus,
String recordUrl, String recordUrl,
@ -55,14 +51,9 @@ public class ManageProductBean implements Serializable{
List<ConnectedBean> currentConnections, List<ConnectedBean> currentConnections,
List<ConnectedBean> suggestedByKnowledgeBaseConnections List<ConnectedBean> suggestedByKnowledgeBaseConnections
) { ) {
super(); super(knowledgeBaseIdentifier, description, shortName, title, recordUrl, semanticIdentifier, grsfDomain);
this.semanticIdentifier = semanticIdentifier;
this.catalogueIdentifier = catalogueIdentifier; this.catalogueIdentifier = catalogueIdentifier;
this.knowledgeBaseIdentifier = knowledgeBaseIdentifier;
this.grsfType = grsfType; this.grsfType = grsfType;
this.grsfDomain = grsfDomain;
this.grsfName = grsfName;
this.shortName = shortName;
this.shortNameUpdated = shortName; this.shortNameUpdated = shortName;
this.traceabilityFlag = traceabilityFlag; this.traceabilityFlag = traceabilityFlag;
this.currentStatus = currentStatus; this.currentStatus = currentStatus;
@ -70,15 +61,6 @@ public class ManageProductBean implements Serializable{
this.similarGrsfRecords = similarGrsfRecords; this.similarGrsfRecords = similarGrsfRecords;
this.currentConnections = currentConnections; this.currentConnections = currentConnections;
this.suggestedByKnowledgeBaseConnections = suggestedByKnowledgeBaseConnections; this.suggestedByKnowledgeBaseConnections = suggestedByKnowledgeBaseConnections;
this.recordUrl = recordUrl;
}
public String getSemanticIdentifier() {
return semanticIdentifier;
}
public void setSemanticIdentifier(String semanticIdentifier) {
this.semanticIdentifier = semanticIdentifier;
} }
public List<SourceRecord> getSources() { public List<SourceRecord> getSources() {
@ -105,14 +87,6 @@ public class ManageProductBean implements Serializable{
this.catalogueIdentifier = catalogueIdentifier; this.catalogueIdentifier = catalogueIdentifier;
} }
public String getKnowledgeBaseIdentifier() {
return knowledgeBaseIdentifier;
}
public void setKnowledgeBaseIdentifier(String knowledgeBaseIdentifier) {
this.knowledgeBaseIdentifier = knowledgeBaseIdentifier;
}
public String getGrsfType() { public String getGrsfType() {
return grsfType; return grsfType;
} }
@ -121,22 +95,6 @@ public class ManageProductBean implements Serializable{
this.grsfType = grsfType; this.grsfType = grsfType;
} }
public String getGrsfDomain() {
return grsfDomain;
}
public void setGrsfDomain(String grsfDomain) {
this.grsfDomain = grsfDomain;
}
public String getGrsfName() {
return grsfName;
}
public void setGrsfName(String grsfName) {
this.grsfName = grsfName;
}
public Status getCurrentStatus() { public Status getCurrentStatus() {
return currentStatus; return currentStatus;
} }
@ -169,14 +127,6 @@ public class ManageProductBean implements Serializable{
this.traceabilityFlag = traceabilityFlag; this.traceabilityFlag = traceabilityFlag;
} }
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getShortNameUpdated() { public String getShortNameUpdated() {
return shortNameUpdated; return shortNameUpdated;
} }
@ -219,14 +169,6 @@ public class ManageProductBean implements Serializable{
this.mergesInvolved = mergesInvolved; this.mergesInvolved = mergesInvolved;
} }
public String getRecordUrl() {
return recordUrl;
}
public void setRecordUrl(String recordUrl) {
this.recordUrl = recordUrl;
}
public List<ConnectedBean> getConnections() { public List<ConnectedBean> getConnections() {
return connections; return connections;
} }
@ -243,23 +185,30 @@ public class ManageProductBean implements Serializable{
this.report = report; this.report = report;
} }
public Set<String> getHashtags() {
return hashtags;
}
public void setHashtags(Set<String> hashtags) {
this.hashtags = hashtags;
}
@Override @Override
public String toString() { public String toString() {
return "ManageProductBean [semanticIdentifier=" + semanticIdentifier return "ManageProductBean [catalogueIdentifier=" + catalogueIdentifier
+ ", catalogueIdentifier=" + catalogueIdentifier + ", grsfType=" + grsfType + ", shortNameUpdated="
+ ", knowledgeBaseIdentifier=" + knowledgeBaseIdentifier + shortNameUpdated + ", traceabilityFlag=" + traceabilityFlag
+ ", grsfType=" + grsfType + ", grsfDomain=" + grsfDomain + ", currentStatus=" + currentStatus + ", newStatus="
+ ", grsfName=" + grsfName + ", shortName=" + shortName + newStatus + ", annotation=" + annotation + ", sources="
+ ", shortNameUpdated=" + shortNameUpdated + sources + ", similarGrsfRecords=" + similarGrsfRecords
+ ", traceabilityFlag=" + traceabilityFlag + ", currentStatus=" + ", suggestedByKnowledgeBaseConnections="
+ currentStatus + ", newStatus=" + newStatus + ", annotation=" + suggestedByKnowledgeBaseConnections
+ annotation + ", sources=" + sources + ", similarGrsfRecords=" + ", suggestdByAdministratorConnections="
+ similarGrsfRecords + ", suggestedByKnowledgeBaseConnections="
+ suggestedByKnowledgeBaseConnections + ", suggestdByAdministratorConnections="
+ suggestdByAdministratorConnections + ", currentConnections=" + suggestdByAdministratorConnections + ", currentConnections="
+ currentConnections + ", connections=" + connections + currentConnections + ", connections=" + connections
+ ", mergesInvolved=" + mergesInvolved + ", recordUrl=" + ", mergesInvolved=" + mergesInvolved + ", report=" + report
+ recordUrl + ", report=" + report + "]"; + ", hashtags=" + hashtags + ", GenericRecord=" + super.toString()
+ "]";
} }
} }

View File

@ -6,35 +6,33 @@ public class RevertableOperationInfo implements Serializable{
private static final long serialVersionUID = 5274434342849474800L; private static final long serialVersionUID = 5274434342849474800L;
private String recordUrl; private String recordUrl;
private String fullName; private String fullNameCurrentAdmin; // the one who is thinking to revert it
private String uuid; private String uuid;
private String admin; private String fullNameOriginalAdmin; // the original admin in the link (his/her Full Name)
private String userNameOriginalAdmin; // the original admin's username
private long timestamp; private long timestamp;
private RevertableOperations operation; private RevertableOperations operation;
public RevertableOperationInfo() { public RevertableOperationInfo() {
super(); super();
} }
public RevertableOperationInfo(
public RevertableOperationInfo(String recordUrl, String fullName, String recordUrl,
String uuid, String admin, long timestamp, RevertableOperations operation) { String fullNameCurrentAdmin,
String uuid,
String fullNameOriginalAdmin,
String userNameOriginalAdmin,
long timestamp,
RevertableOperations operation) {
super(); super();
this.recordUrl = recordUrl; this.recordUrl = recordUrl;
this.fullName = fullName; this.fullNameCurrentAdmin = fullNameCurrentAdmin;
this.uuid = uuid; this.uuid = uuid;
this.admin = admin; this.fullNameOriginalAdmin = fullNameOriginalAdmin;
this.timestamp = timestamp; this.timestamp = timestamp;
this.operation = operation; this.operation = operation;
} }
public String getAdmin() {
return admin;
}
public void setAdmin(String admin) {
this.admin = admin;
}
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
@ -57,23 +55,43 @@ public class RevertableOperationInfo implements Serializable{
public void setRecordUrl(String recordUrl) { public void setRecordUrl(String recordUrl) {
this.recordUrl = recordUrl; this.recordUrl = recordUrl;
} }
public String getFullName() {
return fullName; public String getFullNameCurrentAdmin() {
return fullNameCurrentAdmin;
} }
public void setFullName(String fullName) {
this.fullName = fullName; public void setFullNameCurrentAdmin(String fullNameCurrentAdmin) {
this.fullNameCurrentAdmin = fullNameCurrentAdmin;
} }
public String getFullNameOriginalAdmin() {
return fullNameOriginalAdmin;
}
public void setFullNameOriginalAdmin(String fullNameOriginalAdmin) {
this.fullNameOriginalAdmin = fullNameOriginalAdmin;
}
public String getUserNameOriginalAdmin() {
return userNameOriginalAdmin;
}
public void setUserNameOriginalAdmin(String userNameOriginalAdmin) {
this.userNameOriginalAdmin = userNameOriginalAdmin;
}
public String getUuid() { public String getUuid() {
return uuid; return uuid;
} }
public void setUuid(String uuid) { public void setUuid(String uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
@Override @Override
public String toString() { public String toString() {
return "RevertableOperationInfo [recordUrl=" + recordUrl + ", fullName=" return "RevertableOperationInfo [recordUrl=" + recordUrl
+ fullName + ", uuid=" + uuid + ", admin=" + admin + ", fullNameCurrentAdmin=" + fullNameCurrentAdmin + ", uuid="
+ uuid + ", fullNameOriginalAdmin=" + fullNameOriginalAdmin
+ ", userNameOriginalAdmin=" + userNameOriginalAdmin
+ ", timestamp=" + timestamp + ", operation=" + operation + "]"; + ", timestamp=" + timestamp + ", operation=" + operation + "]";
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

Before

Width:  |  Height:  |  Size: 554 B

After

Width:  |  Height:  |  Size: 554 B