From b13f1eafc9747405eb41e264a90bc94aecdd90f2 Mon Sep 17 00:00:00 2001 From: Costantino Perciante Date: Wed, 31 Jan 2018 17:28:47 +0000 Subject: [PATCH] added methods for creating revert operation urls. Started working on notification methods. git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/widgets/grsf-manage-widget@162826 82a268e6-3cf1-43bd-a215-b396298e98cf --- .settings/org.eclipse.wst.common.component | 3 + pom.xml | 18 +- .../client/GRSFManageWidget.java | 8 +- .../manage/GRSFNotificationService.java | 36 +- .../server/manage/Utils.java | 322 ++++++++++++++---- .../shared/ConnectedBean.java | 44 +-- .../shared/ManageProductBean.java | 15 +- .../shared/RevertOperationUrl.java | 245 +++++++++++++ .../shared/SimilarGRSFRecord.java | 21 -- 9 files changed, 568 insertions(+), 144 deletions(-) create mode 100644 src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/RevertOperationUrl.java diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 38e18cb..d0ac04b 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -4,6 +4,9 @@ + + uses + diff --git a/pom.xml b/pom.xml index dd1a102..58d5b44 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,15 @@ portal-manager provided + + org.gcube.portal + notifications-common-library + + + org.gcube.portlets.user + gcube-url-shortener + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + javax.portlet portlet-api @@ -112,18 +121,18 @@ org.gcube.core common-scope-maps - provided + compile org.gcube.core common-encryption - provided + compile org.gcube.common authorization-client - provided + compile junit @@ -131,7 +140,7 @@ 4.11 test - + org.slf4j slf4j-log4j12 provided @@ -234,4 +243,5 @@ + war diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/client/GRSFManageWidget.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/client/GRSFManageWidget.java index 634a71f..2d1728f 100644 --- a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/client/GRSFManageWidget.java +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/client/GRSFManageWidget.java @@ -1,6 +1,10 @@ package org.gcube.datacatalogue.grsf_manage_widget.client; +import org.gcube.datacatalogue.grsf_manage_widget.client.view.ManageProductWidget; + import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.client.ui.RootPanel; /** * Entry point classes define onModuleLoad(). @@ -11,7 +15,7 @@ public class GRSFManageWidget implements EntryPoint { * This is the entry point method. */ public void onModuleLoad(){ - //HandlerManager eventBus = new HandlerManager(null); - //RootPanel.get("manageDiv").add(new ManageProductWidget("fffb6167-b570-42a8-92b9-5be28549c3b8", eventBus)); + HandlerManager eventBus = new HandlerManager(null); + RootPanel.get("manageDiv").add(new ManageProductWidget("fffb6167-b570-42a8-92b9-5be28549c3b8", eventBus)); } } diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/GRSFNotificationService.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/GRSFNotificationService.java index c48ef54..9d2ebde 100644 --- a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/GRSFNotificationService.java +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/GRSFNotificationService.java @@ -21,9 +21,7 @@ import org.gcube.datacatalogue.grsf_manage_widget.shared.SourceRecord; import org.gcube.datacatalogue.grsf_manage_widget.shared.ex.NoGRSFRecordException; import org.gcube.vomanagement.usermanagement.RoleManager; import org.gcube.vomanagement.usermanagement.impl.LiferayRoleManager; -import org.gcube.vomanagement.usermanagement.model.GCubeRole; import org.gcube.vomanagement.usermanagement.model.GCubeTeam; -import org.gcube.vomanagement.usermanagement.model.GatewayRolesNames; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -162,7 +160,7 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS for (String similarGRSFRecord : similarGrsfRecordsAsStrings) { if(similarGRSFRecord.equals(Constants.NO_SIMILAR_GRSF_RECORDS)) // stop here if there is a single element with this information break; - + similarRecords.add(Utils.similarGRSFRecordFromJson(similarGRSFRecord)); } } @@ -194,7 +192,7 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS // set the values toReturn = new ManageProductBean(semanticId, catalogueIdentifier, uuidKB, grsfType, grsfDomain, grsfName, shortName, traceabilityFlag, Status.fromString(status), null, - null, null, sources, similarRecords, connectedBeans); + null, null, sources, similarRecords, connectedBeans, false); } } @@ -223,32 +221,31 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS String username = pContext.getCurrentUser(getThreadLocalRequest()).getUsername(); long userId = pContext.getCurrentUser(getThreadLocalRequest()).getUserId(); long groupId = pContext.getCurrentGroupId(getThreadLocalRequest()); - List vreRoles = roleManager.listRolesByUserAndGroup(userId, groupId); - List teamRoles = new LiferayRoleManager().listTeamsByUserAndGroup(userId, groupId); + // List vreRoles = roleManager.listRolesByUserAndGroup(userId, groupId); + List teamRoles = roleManager.listTeamsByUserAndGroup(userId, groupId); boolean toSetInSession = false; for (GCubeTeam team : teamRoles) { - if(team.getTeamName().equals(Constants.GRSF_CATALOGUE_MANAGER_ROLE)){ - logger.info("User " + username + " is " + Constants.GRSF_CATALOGUE_MANAGER_ROLE); + if(team.getTeamName().equals(Constants.GRSF_CATALOGUE_EDITOR_ROLE) || team.getTeamName().equals(Constants.GRSF_CATALOGUE_REVIEWER_ROLE)){ + logger.info("User " + username + " is allowed to modify GRSF records"); toSetInSession = true; break; } } - if(!toSetInSession) - for (GCubeRole gCubeTeam : vreRoles) { - if(gCubeTeam.getRoleName().equals(GatewayRolesNames.VRE_MANAGER.getRoleName())){ - logger.info("User " + username + " is " + GatewayRolesNames.VRE_MANAGER.getRoleName()); - toSetInSession = true; - break; - } - } + // if(!toSetInSession) + // for (GCubeRole gCubeTeam : vreRoles) { + // if(gCubeTeam.getRoleName().equals(GatewayRolesNames.VRE_MANAGER.getRoleName())){ + // logger.info("User " + username + " is " + GatewayRolesNames.VRE_MANAGER.getRoleName()); + // toSetInSession = true; + // break; + // } + // } getThreadLocalRequest().getSession().setAttribute(Constants.GRSF_ADMIN_SESSION_KEY, toSetInSession); return toSetInSession; } }catch(Exception e){ - logger.error("Failed to check if the user has team " + Constants.GRSF_CATALOGUE_MANAGER_ROLE - + " or " + GatewayRolesNames.VRE_MANAGER.getRoleName() +"!", e); + logger.error("Failed to check if the user belongs to team " + Constants.GRSF_CATALOGUE_EDITOR_ROLE + " or " + Constants.GRSF_CATALOGUE_REVIEWER_ROLE +"!", e); } return false; } @@ -342,7 +339,8 @@ public class GRSFNotificationService extends RemoteServiceServlet implements GRS baseUrl = Utils.discoverEndPoint(context); getThreadLocalRequest().getSession().setAttribute(keyPerContext, baseUrl); } - return Utils.updateRecord(baseUrl, bean, catalogue, username, administratorFullName); + return Utils.updateRecord(baseUrl, bean, catalogue, username, administratorFullName, getThreadLocalRequest(), + PortalContext.getConfiguration().getCurrentGroupId(getThreadLocalRequest())); }catch(Exception e){ logger.error("Unable to update the product.." + e.getMessage()); diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/Utils.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/Utils.java index bf6f5c8..a5c388d 100644 --- a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/Utils.java +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/server/manage/Utils.java @@ -5,7 +5,9 @@ import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; import java.io.StringReader; +import java.net.URLEncoder; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -20,6 +22,7 @@ import javax.servlet.http.HttpSession; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import org.gcube.common.encryption.StringEncrypter; import org.gcube.common.portal.PortalContext; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; @@ -27,15 +30,25 @@ import org.gcube.common.resources.gcore.utils.XPathHelper; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datacatalogue.ckanutillibrary.server.ApplicationProfileScopePerUrlReader; import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue; +import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster; import org.gcube.datacatalogue.ckanutillibrary.shared.ex.ApplicationProfileNotFoundException; import org.gcube.datacatalogue.common.Constants; +import org.gcube.datacatalogue.common.enums.Status; 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.RevertOperationUrl; +import org.gcube.datacatalogue.grsf_manage_widget.shared.RevertOperationUrl.Operation; import org.gcube.datacatalogue.grsf_manage_widget.shared.SimilarGRSFRecord; +import org.gcube.portlets.user.urlshortener.UrlShortener; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.Query; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.gcube.resources.discovery.client.queries.impl.QueryBox; +import org.gcube.vomanagement.usermanagement.RoleManager; +import org.gcube.vomanagement.usermanagement.UserManager; +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.GCubeUser; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -203,6 +216,32 @@ public class Utils { return toReturn; } + /** + * Get the extras of this dataset as hashmap + * @param extrasAsPairs + * @return + */ + public static Map> getExtras(List extrasAsPairs){ + + Map> toReturn = new HashMap>(); + + for (CkanPair ckanPair : extrasAsPairs) { + String pairKey = ckanPair.getKey(); + String pairValue = ckanPair.getValue(); + + List values = null; + if(toReturn.containsKey(pairKey)) + values = toReturn.get(pairKey); + else + values = new ArrayList(1); + + values.add(pairValue); + + toReturn.put(pairKey, values); + } + return toReturn; + } + /** * Discover the service endpoint and return its url * @param context @@ -257,9 +296,8 @@ public class Utils { * @param catalogue * @return true on success, false otherwise */ - @SuppressWarnings("unchecked") public static String updateRecord(String serviceUrl, ManageProductBean bean, DataCatalogue catalogue, String username, - String fullName) throws Exception{ + String fullName, HttpServletRequest httpServletRequest, long groupId) throws Exception{ if(serviceUrl == null) throw new IllegalArgumentException("GRSF Updater service url cannot be null"); @@ -269,82 +307,218 @@ public class Utils { try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){ - JSONObject obj = new JSONObject(); - obj.put(Constants.ADMINISTRATOR_FULLNAME, fullName); - obj.put(Constants.CATALOGUE_ID, bean.getCatalogueIdentifier()); - obj.put(Constants.KB_ID, bean.getKnowledgeBaseIdentifier()); - obj.put(Constants.NEW_STATUS, bean.getNewStatus().toString().toLowerCase()); - obj.put(Constants.OLD_STATUS, bean.getCurrentStatus().toString().toLowerCase()); - obj.put(Constants.TRACEABILITY_FLAG, bean.isTraceabilityFlag()); + // if there are merges, update the status of the involved records immediately + if(bean.isMergesInvolved()) + updateStatusInvolvedRecords(bean, catalogue); - String annotation = bean.getAnnotation(); - if(annotation != null) - obj.put(Constants.ANNOTATION, annotation.replaceAll("\"", "")); + // send update to the knowledge base + updateKB(httpClient, serviceUrl, bean, catalogue, username, fullName); - obj.put(Constants.SHORT_NAME_OLD, bean.getShortName()); + // send email to Editors and Reviewers if merges are involved or the record was rejected (but the record was the result of a merge) TODO + if(bean.isMergesInvolved() || bean.getNewStatus().equals(Status.Rejected)) + sendEmailAdministrators(bean, catalogue, username, fullName, groupId, httpServletRequest); - if(bean.getShortNameUpdated() == null || bean.getShortNameUpdated().isEmpty()) - bean.setShortNameUpdated(bean.getShortName()); - - obj.put(Constants.SHORT_NAME_NEW, bean.getShortNameUpdated()); - obj.put(Constants.OLD_STATUS, bean.getCurrentStatus().toString().toLowerCase()); - - // prepare connections - List connections = bean.getConnectTo(); - JSONArray connectionsJson = new JSONArray(); - - for(ConnectedBean c: connections){ - JSONObject cc = new JSONObject(); - cc.put(Constants.SOURCE_KNOWLEDGE_BASE_ID, c.getSourceKnowledgeBaseId()); - cc.put(Constants.DEST_KNOWLEDGE_BASE_ID, c.getDestKnowledgeBaseId()); - cc.put(Constants.SOURCE_DOMAIN, c.getSourceDomain()); - // cc.put(Constants.SUGGESTED, c.isExtra()); - // cc.put(Constants.TO_BE_KEPT, c.isToBeKept()); - connectionsJson.add(cc); - } - obj.put(Constants.CONNECTIONS, connectionsJson); - - // prepare similar grsf records - List similarRecords = bean.getSimilarGrsfRecords(); - JSONArray similarRecordsJson = new JSONArray(); - for(SimilarGRSFRecord s: similarRecords){ - JSONObject ss = new JSONObject(); - ss.put(Constants.KB_ID, s.getKnowledgeBaseId()); - ss.put(Constants.MERGE, s.isSuggestedMerge()); - similarRecordsJson.add(ss); - } - obj.put(Constants.SIMILAR_GRSF_RECORDS, similarRecordsJson); - - logger.info("Update request looks like " + obj.toJSONString()); - - HttpPost request = new HttpPost(serviceUrl + Constants.SERVICE_POST_METHOD); - request.setHeader("Accept", "application/json"); - request.setHeader("Content-type", "application/json"); - StringEntity params = new StringEntity(obj.toJSONString()); - request.setEntity(params); - HttpResponse response = httpClient.execute(request); - - logger.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase()); - - String result = EntityUtils.toString(response.getEntity()); - JSONParser parser = new JSONParser(); - JSONObject parsedJSON = (JSONObject)parser.parse(result); - - if(response.getStatusLine().getStatusCode() != Constants.STATUS_SUCCESS){ - throw new Exception("Update failed at knowledge base side!"); - }else if(!(boolean) parsedJSON.get(Constants.UPDATE_RESULT)) - throw new IllegalArgumentException( - "Update failed for the following reason " + parsedJSON.get(Constants.ERROR_MESSAGE)); - - // send email to VRE administrators and the user as well TODO + // create a post about the operation + createSocialPost(bean, catalogue, username, fullName); }catch(Exception e){ - logger.error("Unable to update this Item " + e); + logger.error("Unable to update this Item ", e); throw e; } return null; } + /** + * Update the status of the involved records to "to be merged" + * @param bean + * @param catalogue + * @param username + * @param fullName + * @throws Exception + */ + private static void updateStatusInvolvedRecords(ManageProductBean bean, DataCatalogue catalogue) throws Exception { + + String context = ScopeProvider.instance.get(); + String sysApi = fetchSysAPI(context); + for(SimilarGRSFRecord s: bean.getSimilarGrsfRecords()){ + if(s.isSuggestedMerge()){ + String productId = s.getKnowledgeBaseId(); + Map> extrasMap = getExtras(catalogue.getDataset(productId, sysApi).getExtras()); + extrasMap.put(Constants.STATUS_OF_THE_GRSF_RECORD_CUSTOM_KEY, Arrays.asList(Status.To_be_Merged.getOrigName())); + catalogue.patchProductCustomFields(productId, sysApi, extrasMap); + } + } + + // update the current status record + String productId = bean.getKnowledgeBaseIdentifier(); + Map> extrasMap = getExtras(catalogue.getDataset(productId, sysApi).getExtras()); + extrasMap.put(Constants.STATUS_OF_THE_GRSF_RECORD_CUSTOM_KEY, Arrays.asList(Status.To_be_Merged.getOrigName())); + catalogue.patchProductCustomFields(productId, sysApi, extrasMap); + + } + + /** + * Create a post with proper hashtags of the action taken by who and on which record + * @param bean + * @param catalogue + * @param username + * @param fullName + */ + private static void createSocialPost(ManageProductBean bean, + DataCatalogue catalogue, String username, String fullName) { + List hashtags = getHashTagsFromActions(bean); + // TODO + + } + + /** + * Send an email to the administrator as well as the + * @param bean + * @param catalogue + * @param username + * @param fullName + * @param httpSession + * @throws Exceptio + */ + private static void sendEmailAdministrators(ManageProductBean bean, + DataCatalogue catalogue, String username, String fullName, long groupId, HttpServletRequest httpServletRequest) throws Exception { + + // get the list of GRSF Reviewers to alert as well + RoleManager roleManager = new LiferayRoleManager(); + List teamRoles = roleManager.listTeamsByGroup(groupId); + List reviewers = new ArrayList<>(); + UserManager um = new LiferayUserManager(); + + for(GCubeTeam tr: teamRoles){ + if(tr.getTeamName().equals(Constants.GRSF_CATALOGUE_REVIEWER_ROLE)) + reviewers.add(um.getUserById(tr.getUserId())); + } + + logger.info("List of " + Constants.GRSF_CATALOGUE_REVIEWER_ROLE + " is " + reviewers); + + // build the url that allows to revert the operation TODO + Operation operation = bean.isMergesInvolved() ? Operation.MERGE : Operation.DISSECT; + getEncodedUrlManage(operation, username, System.currentTimeMillis(), bean.getKnowledgeBaseIdentifier(), httpServletRequest); + + String object = "A GRSF Record has been modified"; + + // send the emails reviewers + String messageReviewer = ""; + + // send email to the editor + String messageEditor = ""; + + // TODO + } + + /** + * Create the url to be send for reverting the operation + * @param httpSession + * @return + * @throws Exception + */ + public static String getEncodedUrlManage(Operation operation, String administrator, long timestamp, String uuid, HttpServletRequest httpServletRequest) throws Exception{ + + String clientUrl = getCurrentClientUrl(httpServletRequest).split("\\?")[0]; // ignore other parameters + RevertOperationUrl operationUrl = new RevertOperationUrl(clientUrl, administrator, timestamp, uuid, operation, operation); + String shortUrl = operationUrl.getShortUrl(); + logger.info("Encrypted and shortened url " + shortUrl); + return shortUrl; + } + + /** + * Get the list of hashtags from the actions taken onto the record + * @param bean + * @return + */ + private static List getHashTagsFromActions(ManageProductBean bean) { + // TODO Auto-generated method stub + return null; + } + + /** + * Send updates to the knowledge base + * @param httpClient + * @param serviceUrl + * @param bean + * @param catalogue + * @param username + * @param fullName + */ + @SuppressWarnings("unchecked") + private static void updateKB(CloseableHttpClient httpClient, String serviceUrl, ManageProductBean bean, + DataCatalogue catalogue, String username, String fullName) throws Exception{ + + JSONObject obj = new JSONObject(); + obj.put(Constants.ADMINISTRATOR_FULLNAME, fullName); + obj.put(Constants.CATALOGUE_ID, bean.getCatalogueIdentifier()); + obj.put(Constants.KB_ID, bean.getKnowledgeBaseIdentifier()); + obj.put(Constants.NEW_STATUS, bean.getNewStatus().toString().toLowerCase()); + obj.put(Constants.OLD_STATUS, bean.getCurrentStatus().toString().toLowerCase()); + obj.put(Constants.TRACEABILITY_FLAG, bean.isTraceabilityFlag()); + + String annotation = bean.getAnnotation(); + if(annotation != null) + obj.put(Constants.ANNOTATION, annotation.replaceAll("\"", "")); + + obj.put(Constants.SHORT_NAME_OLD, bean.getShortName()); + + if(bean.getShortNameUpdated() == null || bean.getShortNameUpdated().isEmpty()) + bean.setShortNameUpdated(bean.getShortName()); + + obj.put(Constants.SHORT_NAME_NEW, bean.getShortNameUpdated()); + obj.put(Constants.OLD_STATUS, bean.getCurrentStatus().toString().toLowerCase()); + + // prepare connections + List connections = bean.getConnectTo(); + JSONArray connectionsJson = new JSONArray(); + + for(ConnectedBean c: connections){ + JSONObject cc = new JSONObject(); + 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, c.getSourceKnowledgeBaseId()); + cc.put(Constants.DEST_KNOWLEDGE_BASE_ID, c.getDestKnowledgeBaseId()); + cc.put(Constants.SOURCE_DOMAIN, c.getSourceDomain()); + cc.put(Constants.CONNECTION_TO_REMOVE, c.isRemove()); + } + connectionsJson.add(cc); + } + obj.put(Constants.CONNECTIONS, connectionsJson); + + // prepare similar grsf records + List similarRecords = bean.getSimilarGrsfRecords(); + JSONArray similarRecordsJson = new JSONArray(); + for(SimilarGRSFRecord s: similarRecords){ + JSONObject ss = new JSONObject(); + ss.put(Constants.KB_ID, s.getKnowledgeBaseId()); + ss.put(Constants.MERGE, s.isSuggestedMerge()); + similarRecordsJson.add(ss); + } + obj.put(Constants.SIMILAR_GRSF_RECORDS, similarRecordsJson); + + logger.info("Update request looks like " + obj.toJSONString()); + + HttpPost request = new HttpPost(serviceUrl + Constants.SERVICE_POST_METHOD); + request.setHeader("Accept", "application/json"); + request.setHeader("Content-type", "application/json"); + StringEntity params = new StringEntity(obj.toJSONString()); + request.setEntity(params); + HttpResponse response = httpClient.execute(request); + + logger.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase()); + + String result = EntityUtils.toString(response.getEntity()); + JSONParser parser = new JSONParser(); + JSONObject parsedJSON = (JSONObject)parser.parse(result); + + if(response.getStatusLine().getStatusCode() != Constants.STATUS_SUCCESS){ + throw new Exception("Update failed at knowledge base side!"); + }else if(!(boolean) parsedJSON.get(Constants.UPDATE_RESULT)) + throw new IllegalArgumentException( + "Update failed for the following reason " + parsedJSON.get(Constants.ERROR_MESSAGE)); + + } + /** * Get the scope in which ckan information needs to be discovered from the url * @param httpServletRequest @@ -619,4 +793,16 @@ public class Utils { } + /** + * Fetch the sysadmin key from the IS + * @return + * @throws Exception + */ + public static String fetchSysAPI(String context) throws Exception{ + + DataCatalogueRunningCluster catalogueRunningInstance = new DataCatalogueRunningCluster(context); + return catalogueRunningInstance.getSysAdminToken(); + + } + } diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ConnectedBean.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ConnectedBean.java index f0e5eeb..586f5a3 100644 --- a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ConnectedBean.java +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ConnectedBean.java @@ -16,8 +16,8 @@ public class ConnectedBean implements Serializable{ private String destSemanticIdentifier; private String destKnowledgeBaseId; // the dest indentifier of a Fishery or Stock (the link is from a Stock to a Fishery and viceversa) private String url; - // private boolean isExtra; - private boolean toBeKept = true; + private boolean remove; + private boolean connect; public ConnectedBean() { super(); @@ -45,6 +45,14 @@ public class ConnectedBean implements Serializable{ } + public boolean isConnect() { + return connect; + } + + public void setConnect(boolean connect) { + this.connect = connect; + } + public String getDestShortName() { return destShortName; } @@ -83,21 +91,13 @@ public class ConnectedBean implements Serializable{ this.sourceDomain = sourceDomain; } - public boolean isToBeKept() { - return toBeKept; + public boolean isRemove() { + return remove; } - public void setToBeKept(boolean toBeKept) { - this.toBeKept = toBeKept; + public void setRemove(boolean remove) { + this.remove = remove; } - // - // public boolean isExtra() { - // return isExtra; - // } - // - // public void setExtra(boolean isExtra) { - // this.isExtra = isExtra; - // } public String getUrl() { return url; @@ -105,15 +105,6 @@ public class ConnectedBean implements Serializable{ public void setUrl(String url) { this.url = url; } - // @Override - // public String toString() { - // return "ConnectedBean [sourceKnowledgeBaseId=" + sourceKnowledgeBaseId - // + ", sourceDomain=" + sourceDomain + ", destShortName=" - // + destShortName + ", destSemanticIdentifier=" - // + destSemanticIdentifier + ", destKnowledgeBaseId=" - // + destKnowledgeBaseId + ", url=" + url + ", isExtra=" + isExtra - // + ", toBeKept=" + toBeKept + "]"; - // } @Override public String toString() { @@ -121,11 +112,8 @@ public class ConnectedBean implements Serializable{ + ", sourceDomain=" + sourceDomain + ", destShortName=" + destShortName + ", destSemanticIdentifier=" + destSemanticIdentifier + ", destKnowledgeBaseId=" - + destKnowledgeBaseId + ", url=" + url + ", toBeKept=" - + toBeKept + "]"; + + destKnowledgeBaseId + ", url=" + url + ", remove=" + remove + + ", connect=" + connect + "]"; } - - - } diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ManageProductBean.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ManageProductBean.java index 05cf97e..14741bd 100644 --- a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ManageProductBean.java +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/ManageProductBean.java @@ -29,6 +29,7 @@ public class ManageProductBean implements Serializable{ private List sources; // sources for this record private List similarGrsfRecords; private List connectTo; + private boolean mergesInvolved; public ManageProductBean() { super(); @@ -40,7 +41,7 @@ public class ManageProductBean implements Serializable{ String shortName, boolean traceabilityFlag, Status currentStatus, Status newStatus, String annotation, Map extrasIfAvailable, List sources, - List similarGrsfRecords, List connectedBeans) { + List similarGrsfRecords, List connectedBeans, boolean mergesInvolved) { super(); this.semanticIdentifier = semanticIdentifier; this.catalogueIdentifier = catalogueIdentifier; @@ -58,6 +59,7 @@ public class ManageProductBean implements Serializable{ this.sources = sources; this.similarGrsfRecords = similarGrsfRecords; this.connectTo = connectedBeans; + this.mergesInvolved = mergesInvolved; } public String getSemanticIdentifier() { @@ -190,6 +192,14 @@ public class ManageProductBean implements Serializable{ this.connectTo = connectTo; } + public boolean isMergesInvolved() { + return mergesInvolved; + } + + public void setMergesInvolved(boolean mergesInvolved) { + this.mergesInvolved = mergesInvolved; + } + @Override public String toString() { return "ManageProductBean [semanticIdentifier=" + semanticIdentifier @@ -202,6 +212,7 @@ public class ManageProductBean implements Serializable{ + currentStatus + ", newStatus=" + newStatus + ", annotation=" + annotation + ", extrasIfAvailable=" + extrasIfAvailable + ", sources=" + sources + ", similarGrsfRecords=" - + similarGrsfRecords + ", connectTo=" + connectTo + "]"; + + similarGrsfRecords + ", connectTo=" + connectTo + + ", mergesInvolved=" + mergesInvolved + "]"; } } diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/RevertOperationUrl.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/RevertOperationUrl.java new file mode 100644 index 0000000..b16fb6e --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/RevertOperationUrl.java @@ -0,0 +1,245 @@ +package org.gcube.datacatalogue.grsf_manage_widget.shared; + +import java.net.URLDecoder; +import java.net.URLEncoder; + +import org.gcube.common.encryption.StringEncrypter; +import org.gcube.portlets.user.urlshortener.UrlShortener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Encode and decode the url for reverting operations + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class RevertOperationUrl { + + private static final Logger logger = LoggerFactory.getLogger(RevertOperationUrl.class); + + // parameters for reverting operations + public static final String MANAGE_QUERY_PARAM = "manage=true&"; + public static final String ADMIN_QUERY_PARAM = "admin"; + public static final String TIMESTAMP_QUERY_PARAM = "t"; + public static final String UUID_QUERY_PARAM = "uuid"; + public static final String OPERATION_REVERT_QUERY_PARAM = "operation_revert"; + + public enum Operation { + + MERGE("merge"), + DISSECT("dissect"); + private String name; + + private Operation(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + } + + private String baseUrl; + private String admin; + private long timestamp; + private String uuid; + private Operation operation; + private Operation op; + + /** + * @param admin + * @param timestamp + * @param uuid + * @param operation + * @param op + */ + public RevertOperationUrl(String baseUrl, String admin, long timestamp, String uuid, + Operation operation, Operation op) { + super(); + this.baseUrl = baseUrl; + this.admin = admin; + this.timestamp = timestamp; + this.uuid = uuid; + this.operation = operation; + this.op = op; + } + + + public String getShortUrl() throws Exception{ + + String query = ADMIN_QUERY_PARAM + "=" + admin + "&" + TIMESTAMP_QUERY_PARAM + "=" + timestamp +"&" + UUID_QUERY_PARAM + "=" + uuid + "&" + OPERATION_REVERT_QUERY_PARAM + "=" + operation; + logger.info("Query is " + query); + String encryptedQuery = StringEncrypter.getEncrypter().encrypt(query); + encryptedQuery = URLEncoder.encode(encryptedQuery, "UTF-8"); + String encryptedUrl = + baseUrl + + MANAGE_QUERY_PARAM + "&" + + encryptedQuery; + UrlShortener shortener = new UrlShortener(); + String shortUrl = null; + try{ + if(shortener!=null && shortener.isAvailable()) + shortUrl = shortener.shorten(encryptedUrl); + }catch (Exception e) { + logger.warn("Unable to get short url", e); + shortUrl = encryptedUrl; + } + + logger.debug("Encrypted and shortened url " + shortUrl); + return shortUrl; + + } + + public RevertOperationUrl(String encryptedUrl) throws Exception{ + + if(encryptedUrl == null) + throw new IllegalArgumentException("encryptedUrl is null"); + + String params = encryptedUrl.split("\\?")[1]; + logger.debug("Params encrypted are " + params); + + // remove MANAGE_QUERY_PARAM + params = params.replace(MANAGE_QUERY_PARAM + "&", ""); + + String decoded = URLDecoder.decode(params, "UTF-8"); + String decrypted = StringEncrypter.getEncrypter().decrypt(decoded); + + logger.info("Decrypted is " + decrypted); + + try{ + String[] splittedQuery = decrypted.split("&"); + for (int i = 0; i < splittedQuery.length; i++) { + String subParam = splittedQuery[i]; + String[] queryAndValue = subParam.split("="); + String query = queryAndValue[0]; + String value = queryAndValue[1]; + + switch (query) { + case ADMIN_QUERY_PARAM: + this.admin = value; + break; + case TIMESTAMP_QUERY_PARAM: + this.timestamp = Long.valueOf(value); + break; + case UUID_QUERY_PARAM: + this.uuid = value; + break; + case OPERATION_REVERT_QUERY_PARAM: + this.operation = Operation.valueOf(value); + break; + default: + break; + } + + } + }catch(Exception e){ + logger.error("Failed to parse url", e); + } + + } + + public String getBaseUrl() { + return baseUrl; + } + + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + + public String getAdmin() { + return admin; + } + + + public void setAdmin(String admin) { + this.admin = admin; + } + + + public long getTimestamp() { + return timestamp; + } + + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + + public String getUuid() { + return uuid; + } + + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + + public Operation getOperation() { + return operation; + } + + + public void setOperation(Operation operation) { + this.operation = operation; + } + + + public Operation getOp() { + return op; + } + + + public void setOp(Operation op) { + this.op = op; + } + + + @Override + public String toString() { + return "RevertOperationUrl [baseUrl=" + baseUrl + ", admin=" + admin + + ", timestamp=" + timestamp + ", uuid=" + uuid + + ", operation=" + operation + ", op=" + op + "]"; + } + + // public static void main(String[] args) throws Exception { + // + // ScopeProvider.instance.set("/gcube/devNext/NextNext"); + // String url = "https://bluebridge.d4science.org/group/grsf_admin/data-catalogue?"; + // + // // try encrypt + encode + // String query = "admin=costantino.perciante&t="+ System.currentTimeMillis() +"&uuid=" + UUID.randomUUID().toString() + "&operation_revert=merge"; + // String encrypted = StringEncrypter.getEncrypter().encrypt(query); + // encrypted = URLEncoder.encode(encrypted, "UTF-8"); + // + // + // String encryptedUrl = url + encrypted; + // System.out.println("Encrypted is " + encryptedUrl); + // + // UrlShortener shortener = new UrlShortener(); + // String shortUrl = null; + // try{ + // if(shortener!=null && shortener.isAvailable()) + // shortUrl = shortener.shorten(encryptedUrl); + // }catch (Exception e) { + // e.printStackTrace(); + // shortUrl = encryptedUrl; + // } + // + // System.out.println("Encrypted is " + shortUrl); + // + // + // // try decode + decrypt + // String params = encryptedUrl.split("\\?")[1]; + // System.out.println("Params encrypted are " + params); + // String decoded = URLDecoder.decode(encrypted, "UTF-8"); + // String decrypted = StringEncrypter.getEncrypter().decrypt(decoded); + // + // System.out.println("Decrypted is " + decrypted); + //} + +} diff --git a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/SimilarGRSFRecord.java b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/SimilarGRSFRecord.java index 11704c0..ba522c8 100644 --- a/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/SimilarGRSFRecord.java +++ b/src/main/java/org/gcube/datacatalogue/grsf_manage_widget/shared/SimilarGRSFRecord.java @@ -16,8 +16,6 @@ public class SimilarGRSFRecord implements Serializable{ private String shortName; private String url; private boolean suggestedMerge; - // private boolean isExtra; - // private boolean toBeKept = true; public SimilarGRSFRecord() { super(); @@ -108,23 +106,4 @@ public class SimilarGRSFRecord implements Serializable{ + suggestedMerge + "]"; } - // public boolean isExtra() { - // return isExtra; - // } - // - // public void setExtra(boolean isExtra) { - // this.isExtra = isExtra; - // } - // @Override - // public String toString() { - // return "SimilarGRSFRecord [description=" + description - // + ", knowledgeBaseId=" + knowledgeBaseId - // + ", semanticIdentifier=" + semanticIdentifier + ", shortName=" - // + shortName + ", url=" + url + ", suggestedMerge=" - // + suggestedMerge + ", isExtra=" + isExtra + ", toBeKept=" - // + toBeKept + "]"; - // } - - - }