Added code to create a post when a new product is added to the catalogue. Searchable field is set to true when the created dataset is private
git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/widgets/ckan-metadata-publisher-widget@133744 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
173933bc5c
commit
efaa3669fe
|
@ -88,7 +88,7 @@ public class TagsPanel extends Composite{
|
|||
}
|
||||
|
||||
// ckan accepts only alphanumeric values
|
||||
String[] subTags = itemBox.getValue().split(" ");
|
||||
String[] subTags = itemBox.getValue().trim().split(" ");
|
||||
if(subTags.length == 1){
|
||||
if(!subTags[0].matches(REGEX_TAG))
|
||||
return;
|
||||
|
@ -102,7 +102,7 @@ public class TagsPanel extends Composite{
|
|||
}
|
||||
}
|
||||
|
||||
final String value = itemBox.getValue();
|
||||
final String value = itemBox.getValue().trim();
|
||||
final ListItem displayItem = new ListItem();
|
||||
displayItem.setStyleName("tag-style");
|
||||
Span tagText = new Span(itemBox.getValue());
|
||||
|
@ -134,7 +134,7 @@ public class TagsPanel extends Composite{
|
|||
return;
|
||||
|
||||
// ckan accepts only alphanumeric values
|
||||
String[] subTags = tag.split(" ");
|
||||
String[] subTags = tag.trim().split(" ");
|
||||
if(subTags.length == 1){
|
||||
if(!subTags[0].matches(REGEX_TAG))
|
||||
return;
|
||||
|
@ -173,7 +173,7 @@ public class TagsPanel extends Composite{
|
|||
*/
|
||||
private void removeTag(ListItem displayItem, String value) {
|
||||
|
||||
tagsList.remove(value);
|
||||
tagsList.remove(value.trim());
|
||||
tagsPanel.remove(displayItem);
|
||||
|
||||
}
|
||||
|
|
|
@ -389,10 +389,33 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
|
|||
// start a thread that will associate this dataset with the group
|
||||
if(toCreate.getChosenProfile() != null){
|
||||
|
||||
AssociationToGroupThread thread = new AssociationToGroupThread(toCreate.getChosenProfile(), datasetId, userName, utils, organizationNameOrId);
|
||||
thread.start();
|
||||
AssociationToGroupThread threadAssociationToGroup =
|
||||
new AssociationToGroupThread(
|
||||
toCreate.getChosenProfile(),
|
||||
datasetId,
|
||||
userName,
|
||||
utils,
|
||||
organizationNameOrId
|
||||
);
|
||||
threadAssociationToGroup.start();
|
||||
|
||||
}
|
||||
|
||||
// ask token for this context
|
||||
|
||||
|
||||
// launch notification thread
|
||||
WritePostCatalogueManagerThread threadWritePost =
|
||||
new WritePostCatalogueManagerThread(
|
||||
userName,
|
||||
scope,
|
||||
toCreate.getTitle(),
|
||||
datasetUrl,
|
||||
false,
|
||||
toCreate.getTags(),
|
||||
toCreate.getAuthorFullName()
|
||||
);
|
||||
threadWritePost.start();
|
||||
|
||||
return toCreate;
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
|
||||
|
||||
import static org.gcube.common.authorization.client.Constants.authorizationService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||
import org.gcube.common.authorization.library.provider.UserInfo;
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Write a post in a VRe
|
||||
* @author Costantino Perciante at ISTI-CNR
|
||||
* (costantino.perciante@isti.cnr.it)
|
||||
*/
|
||||
public class WritePostCatalogueManagerThread extends Thread {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WritePostCatalogueManagerThread.class);
|
||||
|
||||
private String username;
|
||||
private String scope;
|
||||
private String productTitle;
|
||||
private String productUrl;
|
||||
private boolean enableNotification;
|
||||
private List<String> hashtags;
|
||||
String userFullName;
|
||||
|
||||
/**
|
||||
* @param token
|
||||
* @param scope
|
||||
* @param productTitle
|
||||
* @param productUrl
|
||||
* @param enableNotification
|
||||
* @param hashtags
|
||||
* @param userFullName
|
||||
*/
|
||||
public WritePostCatalogueManagerThread(
|
||||
String username, String scope,
|
||||
String productTitle, String productUrl, boolean enableNotification,
|
||||
List<String> hashtags, String userFullName) {
|
||||
super();
|
||||
this.username = username;
|
||||
this.scope = scope;
|
||||
this.productTitle = productTitle;
|
||||
this.productUrl = productUrl;
|
||||
this.enableNotification = enableNotification;
|
||||
this.hashtags = hashtags;
|
||||
this.userFullName = userFullName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try{
|
||||
// evaluate user's token for this scope
|
||||
String token = authorizationService().generateUserToken(new UserInfo(username, new ArrayList<String>()), scope);
|
||||
|
||||
logger.info("Started request to write application post "
|
||||
+ "for new product created. Scope is " + scope + " and "
|
||||
+ "token is " + token.substring(0, 10) + "****************");
|
||||
|
||||
// set token and scope
|
||||
ScopeProvider.instance.set(scope);
|
||||
SecurityTokenProvider.instance.set(token);
|
||||
|
||||
// write
|
||||
Utils.writeProductPost(
|
||||
productTitle,
|
||||
productUrl,
|
||||
userFullName,
|
||||
hashtags,
|
||||
enableNotification
|
||||
);
|
||||
|
||||
}catch(Exception e){
|
||||
logger.error("Failed to write the post because of the following error ", e);
|
||||
}finally{
|
||||
// remove token and scope
|
||||
SecurityTokenProvider.instance.reset();
|
||||
ScopeProvider.instance.reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils;
|
||||
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
||||
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
||||
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Retrieves the base url of the social-networking service in the scope provided
|
||||
* @author Costantino Perciante at ISTI-CNR
|
||||
* (costantino.perciante@isti.cnr.it)
|
||||
*/
|
||||
public class ServiceEndPointReaderSocial {
|
||||
|
||||
private String basePath = null;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ServiceEndPointReaderSocial.class);
|
||||
private final static String RUNTIME_RESOURCE_NAME = "SocialNetworking";
|
||||
private final static String CATEGORY = "Portal";
|
||||
|
||||
public ServiceEndPointReaderSocial(String context){
|
||||
|
||||
if(context == null || context.isEmpty())
|
||||
throw new IllegalArgumentException("A valid context is needed to discover the service");
|
||||
|
||||
|
||||
String oldContext = ScopeProvider.instance.get();
|
||||
ScopeProvider.instance.set(context);
|
||||
|
||||
try{
|
||||
|
||||
List<ServiceEndpoint> resources = getConfigurationFromIS();
|
||||
if (resources.size() == 0){
|
||||
logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope.");
|
||||
throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope.");
|
||||
}
|
||||
else {
|
||||
|
||||
for (ServiceEndpoint res : resources) {
|
||||
|
||||
Iterator<AccessPoint> accessPointIterator = res.profile().accessPoints().iterator();
|
||||
|
||||
while (accessPointIterator.hasNext()) {
|
||||
ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator
|
||||
.next();
|
||||
|
||||
// get base path
|
||||
basePath = accessPoint.address();
|
||||
|
||||
// break
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
|
||||
logger.error("Unable to retrieve such service endpoint information!", e);
|
||||
|
||||
}finally{
|
||||
|
||||
if(oldContext != null && !oldContext.equals(context))
|
||||
ScopeProvider.instance.set(oldContext);
|
||||
|
||||
}
|
||||
|
||||
logger.info("Found base path " + basePath + " for the service");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve endpoints information from IS for the Service endpoint
|
||||
* @return list of endpoints
|
||||
* @throws Exception
|
||||
*/
|
||||
private List<ServiceEndpoint> getConfigurationFromIS() throws Exception{
|
||||
|
||||
SimpleQuery query = queryFor(ServiceEndpoint.class);
|
||||
query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'");
|
||||
query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'");
|
||||
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
|
||||
List<ServiceEndpoint> toReturn = client.submit(query);
|
||||
return toReturn;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base path of the social networking service
|
||||
* @return
|
||||
*/
|
||||
public String getBasePath() {
|
||||
return basePath;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -7,7 +10,14 @@ import java.util.Map;
|
|||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.gcube.application.framework.core.session.ASLSession;
|
||||
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
|
||||
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
|
||||
import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem;
|
||||
|
@ -41,6 +51,8 @@ import org.gcube.vomanagement.usermanagement.model.GCubeRole;
|
|||
import org.gcube.vomanagement.usermanagement.model.GatewayRolesNames;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import eu.trentorise.opendata.jackan.model.CkanOrganization;
|
||||
|
||||
/**
|
||||
|
@ -51,6 +63,11 @@ public class Utils {
|
|||
|
||||
// Logger
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Utils.class);
|
||||
private static final String APPLICATION_ID_CATALOGUE_MANAGER = "org.gcube.datacatalogue.DataCatalogueManager";
|
||||
private static final String NOTIFICATION_MESSAGE = "Dear members,<br>The product <b></em>PRODUCT_TITLE</em></b> has been just published by <b>USER_FULLNAME</b>.<br>You can find it here: PRODUCT_URL <br>";
|
||||
private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "2/tokens/generate-application-token/";
|
||||
private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "2/posts/write-post-app/";
|
||||
private static final String MEDIATYPE_JSON = "application/json";
|
||||
|
||||
/** Gets the gcube item properties.
|
||||
*
|
||||
|
@ -342,4 +359,121 @@ public class Utils {
|
|||
|
||||
return beans;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification to vre members about the created product by writing a post.
|
||||
* @param productName the title of the product
|
||||
* @param productUrl the url of the product
|
||||
* @param hashtags a list of product's hashtags
|
||||
*/
|
||||
public static void writeProductPost(String productName, String productUrl, String userFullname, List<String> hashtags, boolean enablePostNotification){
|
||||
|
||||
// discover service endpoint for the social networking library
|
||||
String currentScope = ScopeProvider.instance.get();
|
||||
String tokenUser = SecurityTokenProvider.instance.get();
|
||||
|
||||
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
|
||||
String basePath = new ServiceEndPointReaderSocial(currentScope).getBasePath();
|
||||
|
||||
if(basePath == null){
|
||||
|
||||
logger.error("Unable to write a post because there is no social networking service available");
|
||||
|
||||
}else{
|
||||
|
||||
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
|
||||
|
||||
// ask token application
|
||||
HttpPost postRequest = new HttpPost(basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser);
|
||||
StringEntity input = new StringEntity("{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}");
|
||||
input.setContentType(MEDIATYPE_JSON);
|
||||
postRequest.setEntity(input);
|
||||
HttpResponse response = client.execute(postRequest);
|
||||
|
||||
logger.debug("Url is " + basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser);
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != 201) {
|
||||
throw new RuntimeException("Failed to retrieve application token : HTTP error code : "
|
||||
+ response.getStatusLine().getStatusCode());
|
||||
}else{
|
||||
|
||||
Map<String, Object> mapResponseGeneratedToken = getResponseEntityAsJSON(response);
|
||||
boolean successGeneratedToken = (boolean)mapResponseGeneratedToken.get("success");
|
||||
if(!successGeneratedToken){
|
||||
|
||||
throw new RuntimeException("Failed to generate the token for the application!"
|
||||
+ " Error message is " + mapResponseGeneratedToken.get("message"));
|
||||
|
||||
}else{
|
||||
|
||||
String applicationToken = (String)mapResponseGeneratedToken.get("result");
|
||||
|
||||
// replace
|
||||
String message = NOTIFICATION_MESSAGE.replace("PRODUCT_TITLE", productName).replace("PRODUCT_URL", productUrl).replace("USER_FULLNAME", userFullname);
|
||||
|
||||
if(hashtags != null && !hashtags.isEmpty())
|
||||
for (String hashtag : hashtags) {
|
||||
String modifiedHashtag = hashtag.replaceAll(" ", "_").replace("_+", "_");
|
||||
if(modifiedHashtag.endsWith("_"))
|
||||
modifiedHashtag = modifiedHashtag.substring(0, modifiedHashtag.length() - 1);
|
||||
message += " #" + modifiedHashtag; // ckan accepts tag with empty spaces, we don't
|
||||
}
|
||||
|
||||
logger.info("The post that is going to be written is -> " + message);
|
||||
postRequest = new HttpPost(basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + applicationToken);
|
||||
input = new StringEntity("{\"text\":\"" + message + "\", \"enable_notification\" : "+ enablePostNotification+ "}");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the json response to a map
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> getResponseEntityAsJSON(HttpResponse response){
|
||||
|
||||
Map<String, Object> toReturn = null;
|
||||
HttpEntity entity = response.getEntity();
|
||||
|
||||
if (entity != null) {
|
||||
try {
|
||||
toReturn = new HashMap<String, Object>();
|
||||
InputStream is = entity.getContent();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String line = null;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line + "\n");
|
||||
}
|
||||
|
||||
logger.debug("Response as string is " + sb.toString());
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
toReturn = objectMapper.readValue(sb.toString(), HashMap.class);
|
||||
logger.debug("Map is " + toReturn);
|
||||
|
||||
}catch(Exception e){
|
||||
logger.error("Failed to read json object", e);
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||
import org.gcube.common.homelibrary.home.HomeLibrary;
|
||||
import org.gcube.common.homelibrary.home.exceptions.HomeNotFoundException;
|
||||
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
|
||||
|
@ -21,6 +23,7 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat;
|
|||
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataValidator;
|
||||
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataVocabulary;
|
||||
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.CKANPublisherServicesImpl;
|
||||
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.Utils;
|
||||
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DataType;
|
||||
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetaDataTypeWrapper;
|
||||
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetadataFieldWrapper;
|
||||
|
@ -163,4 +166,18 @@ public class TestClass {
|
|||
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testDataCatalogueManagerApplication(){
|
||||
|
||||
String token = "d423aed7-e9e2-424a-b9e7-2bbbd151d9c4-98187548";
|
||||
String scope = "/gcube/devNext/NextNext";
|
||||
|
||||
ScopeProvider.instance.set(scope);
|
||||
SecurityTokenProvider.instance.set(token);
|
||||
|
||||
Utils.writeProductPost("a great test product",
|
||||
"https://next.d4science.org/group/nextnext/data-catalogue?path=/dataset/test_for_visibility",
|
||||
"Costantino Perciante", Arrays.asList("tag1", "tag2", "tag33"), false);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue