Support added for datasets' relationships (added methods for creating, deleting and retrieving relationships between datasets). Some problems are reported here https://support.d4science.org/issues/4455

Test methods added too. The above methods all use the REST APIs since I wasn't able to make things properly work through jackan

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/ckan-util-library@130975 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-08-04 16:24:39 +00:00
parent 7c662a0c93
commit 41c8b09ee7
7 changed files with 518 additions and 29 deletions

View File

@ -1,5 +1,13 @@
<ReleaseNotes>
<Changeset component="org.gcube.data-catalogue.ckan-util-library.1-0-0" date="2016-06-01">
<Changeset component="org.gcube.data-catalogue.ckan-util-library.1-1-0"
date="2016-11-01">
<Change>Added support for datasets's relationships (create, delete,
retrieve methods)</Change>
<Change>Added Factory in order to reduce the number of created
instances of the utils class(cache)</Change>
</Changeset>
<Changeset component="org.gcube.data-catalogue.ckan-util-library.1-0-0"
date="2016-06-01">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

12
pom.xml
View File

@ -10,7 +10,7 @@
</parent>
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>ckan-util-library</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>CKan utility library</name>
@ -114,6 +114,16 @@
<version>3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>

View File

@ -4,6 +4,8 @@ import java.util.List;
import java.util.Map;
import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper;
import org.gcube.datacatalogue.ckanutillibrary.models.CkanDatasetRelationship;
import org.gcube.datacatalogue.ckanutillibrary.models.DatasetRelationships;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesIntoOrganization;
@ -64,13 +66,13 @@ public interface CKanUtils {
* @return the list of licenses' titles
*/
List<String> getLicenseTitles();
/**
* Retrieve ckan licenses
* @return
*/
List<CkanLicense> getLicenses();
/**
* Retrieve the list of organizations ids
* @return
@ -175,8 +177,66 @@ public interface CKanUtils {
boolean createOrganization(String orgName, String token) throws Exception;
/**
* Return the catalogue portlet for this url
* Return the catalogue portlet for this context(i.e. scope)
* @return
*/
String getPortletUrl();
/**
* Sets a relationship between a "subject" dataset and an "object" dataset
* Please note that according to ckan apis the following must be valid:
* <blockquote>To create a relationship between two datasets (packages),
* You must be authorized to edit both the subject and the object datasets.</blockquote>
* The relationship can be on of the following:
* <ul>
* <li> depends_on
* <li> dependency_of
* <li> derives_from
* <li> has_derivation
* <li> child_of
* <li> parent_of
* <li> links_to
* <li> linked_from
* </ul>
* @param datasetIdSubject
* @param datasetIdObject
* @param relation
* @param relationComment a comment about the relation
* @param apiKey the user api key
* @return <b>true</b> on success, <b>false</b> otherwise.
*/
boolean createDatasetRelationship(String datasetIdSubject, String datasetIdObject, DatasetRelationships relation, String relationComment, String apiKey);
/**
* Deletes a relationship between a "subject" dataset and an "object" dataset
* Please note that according to ckan apis the following must be valid:
* <blockquote>You must be authorised to delete dataset relationships, and to edit both the subject and the object datasets.</blockquote>
* The relationship can be on of the following:
* <ul>
* <li> depends_on
* <li> dependency_of
* <li> derives_from
* <li> has_derivation
* <li> child_of
* <li> parent_of
* <li> links_to
* <li> linked_from
* </ul>
* @param datasetIdSubject
* @param datasetIdObject
* @param relation
* @param apiKey the user api key
* @return <b>true</b> on success, <b>false</b> otherwise.
*/
boolean deleteDatasetRelationship(String datasetIdSubject, String datasetIdObject, DatasetRelationships relation, String apiKey);
/**
* Returns the list of relationships between dataset datasetIdSubject and dataset datasetIdObject.
* @param datasetIdSubject
* @param datasetIdObject
* @param relation
* @param apiKey
* @return list of CkanDatasetRelationship objects or null if an error occurs
*/
List<CkanDatasetRelationship> getRelationshipDatasets(String datasetIdSubject, String datasetIdObject, String apiKey);
}

View File

@ -1,5 +1,10 @@
package org.gcube.datacatalogue.ckanutillibrary;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
@ -21,10 +26,15 @@ import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;
import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper;
import org.gcube.datacatalogue.ckanutillibrary.models.CkanDatasetRelationship;
import org.gcube.datacatalogue.ckanutillibrary.models.DatasetRelationships;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesIntoOrganization;
import org.gcube.datacatalogue.ckanutillibrary.models.State;
import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -135,6 +145,10 @@ public class CKanUtilsImpl implements CKanUtils{
logger.debug("Request api key for user = " + username);
// checks
checkNotNull(username);
checkArgument(!username.isEmpty());
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
@ -173,6 +187,11 @@ public class CKanUtilsImpl implements CKanUtils{
@Override
public CKanUserWrapper getUserFromApiKey(String apiKey) {
logger.debug("Request user whose api key is = " + apiKey);
// checks
checkNotNull(apiKey);
checkArgument(!apiKey.isEmpty());
CKanUserWrapper user = new CKanUserWrapper();
// the connection
@ -217,6 +236,9 @@ public class CKanUtilsImpl implements CKanUtils{
logger.debug("Requested organizations for user " + username);
// checks
checkNotNull(username);
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
@ -256,6 +278,10 @@ public class CKanUtilsImpl implements CKanUtils{
public Map<String, List<RolesIntoOrganization>> getGroupsAndRolesByUser(
String username, List<RolesIntoOrganization> rolesToMatch) {
// checks
checkNotNull(username);
checkArgument(!rolesToMatch.isEmpty());
logger.debug("Requested roles that the user " + username + " has into his organizations");
logger.debug("Roles to check are " + rolesToMatch);
@ -357,6 +383,9 @@ public class CKanUtilsImpl implements CKanUtils{
logger.debug("Requested organizations for user " + username);
// checks
checkNotNull(username);
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
@ -377,6 +406,9 @@ public class CKanUtilsImpl implements CKanUtils{
public String findLicenseIdByLicense(String chosenLicense) {
logger.debug("Requested license id");
// checks
checkNotNull(chosenLicense);
//retrieve the list of available licenses
List<CkanLicense> licenses = client.getLicenseList();
@ -423,6 +455,14 @@ public class CKanUtilsImpl implements CKanUtils{
public boolean setDatasetPrivate(boolean priv, String organizationId,
String datasetId, String apiKey) {
// checks
checkNotNull(organizationId);
checkNotNull(apiKey);
checkNotNull(datasetId);
checkArgument(!apiKey.isEmpty());
checkArgument(!datasetId.isEmpty());
checkArgument(!organizationId.isEmpty());
String pathSetPrivate = "/api/3/action/bulk_update_private";
String pathSetPublic = "/api/3/action/bulk_update_public";
@ -486,6 +526,11 @@ public class CKanUtilsImpl implements CKanUtils{
logger.debug("Request to add a resource described by this bean " + resourceBean);
// checks
checkNotNull(resourceBean);
checkNotNull(apiKey);
checkArgument(!apiKey.isEmpty());
try{
if(UtilMethods.resourceExists(resourceBean.getUrl())){
@ -528,6 +573,12 @@ public class CKanUtilsImpl implements CKanUtils{
logger.error("Request to delete a resource with id " + resourceId + " coming by user with key " + apiKey);
// checks
checkNotNull(apiKey);
checkNotNull(resourceId);
checkArgument(!apiKey.isEmpty());
checkArgument(!resourceId.isEmpty());
try{
CheckedCkanClient client = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
@ -550,6 +601,14 @@ public class CKanUtilsImpl implements CKanUtils{
List<String> tags, Map<String, String> customFields,
List<ResourceBean> resources, boolean setPublic) {
// checks (minimum)
checkNotNull(apiKey);
checkNotNull(title);
checkNotNull(organizationNameOrId);
checkArgument(!apiKey.isEmpty());
checkArgument(!title.isEmpty());
checkArgument(!organizationNameOrId.isEmpty());
logger.debug("Request for dataset creation");
CheckedCkanClient client = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
@ -679,6 +738,12 @@ public class CKanUtilsImpl implements CKanUtils{
logger.debug("Request coming for dataset url of dataset with name/id " + datasetIdOrName);
// checks
checkNotNull(apiKey);
checkNotNull(datasetIdOrName);
checkArgument(!apiKey.isEmpty());
checkArgument(!datasetIdOrName.isEmpty());
// the url of the dataset looks like "getCatalogueUrl() + /dataset/ + dataset name"
try{
@ -705,6 +770,13 @@ public class CKanUtilsImpl implements CKanUtils{
logger.debug("Request for checking if " + username + " into " + organizationName + " has role " + correspondentRoleToCheck);
// checks
checkNotNull(username);
checkNotNull(organizationName);
checkNotNull(correspondentRoleToCheck);
checkArgument(!username.isEmpty());
checkArgument(!organizationName.isEmpty());
// convert ckan username
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
@ -786,6 +858,12 @@ public class CKanUtilsImpl implements CKanUtils{
@Override
public boolean isSysAdmin(String username, String apiKey) {
// checks
checkNotNull(username);
checkNotNull(apiKey);
checkArgument(!username.isEmpty());
checkArgument(!apiKey.isEmpty());
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
try{
@ -804,13 +882,11 @@ public class CKanUtilsImpl implements CKanUtils{
// we invoke the ckan connector to create this organization
boolean result = false;
if(token == null || token.trim().isEmpty()){
throw new IllegalArgumentException("Gcube Token is missing here!");
}
if(orgName == null || orgName.trim().isEmpty()){
throw new IllegalArgumentException("Organization name is missing here!");
}
// checks
checkNotNull(orgName);
checkNotNull(token);
checkArgument(!token.isEmpty());
checkArgument(!orgName.isEmpty());
try{
String callUrl = CKAN_CATALOGUE_URL + "/ckan-connector/gcube/service/organization/" + orgName + "?gcube-token=" + token;
@ -834,4 +910,181 @@ public class CKanUtilsImpl implements CKanUtils{
return result;
}
@Override
public boolean createDatasetRelationship(String datasetIdSubject,
String datasetIdObject, DatasetRelationships relation, String relationComment, String apiKey) {
// checks
checkNotNull(datasetIdSubject);
checkNotNull(datasetIdObject);
checkNotNull(relation);
checkNotNull(apiKey);
checkArgument(!datasetIdSubject.isEmpty());
checkArgument(!datasetIdObject.isEmpty());
checkArgument(!apiKey.isEmpty());
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){
// we need to use the apis to make it
String path = "/api/3/action/package_relationship_create";
// Request parameters to be replaced
String parameter = "{"
+ "\"subject\":\"SUBJECT\","
+ "\"object\":\"OBJECT\","
+ "\"type\":\"RELATIONSHIP\","
+ "\"comment\" : \"COMMENT\""
+ "}";
// replace those values
parameter = parameter.replace("SUBJECT", datasetIdSubject);
parameter = parameter.replace("OBJECT", datasetIdObject);
parameter = parameter.replace("RELATIONSHIP", relation.toString());
if(relationComment != null && !relationComment.isEmpty())
parameter = parameter.replace("COMMENT", relationComment);
logger.debug("API request for relationship create is going to be " + parameter);
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
request.addHeader("Authorization", apiKey);
StringEntity params = new StringEntity(parameter);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
return (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK);
}catch(Exception e){
logger.error("Failed to create the relationship between dataset subject = " + datasetIdSubject
+ " and " + " dataset subject " + datasetIdObject, e);
}
return false;
}
@Override
public boolean deleteDatasetRelationship(String datasetIdSubject,
String datasetIdObject, DatasetRelationships relation, String apiKey) {
// checks
checkNotNull(datasetIdSubject);
checkNotNull(datasetIdObject);
checkNotNull(relation);
checkNotNull(apiKey);
checkArgument(!datasetIdSubject.isEmpty());
checkArgument(!datasetIdObject.isEmpty());
checkArgument(!apiKey.isEmpty());
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){
// we need to use the apis to make it
String path = "/api/3/action/package_relationship_delete";
// Request parameters to be replaced
String parameter = "{"
+ "\"subject\":\"SUBJECT\","
+ "\"object\":\"OBJECT\","
+ "\"type\":\"RELATIONSHIP\""
+ "}";
// replace those values
parameter = parameter.replace("SUBJECT", datasetIdSubject);
parameter = parameter.replace("OBJECT", datasetIdObject);
parameter = parameter.replace("RELATIONSHIP", relation.toString());
logger.debug("API request for delete relationship is going to be " + parameter);
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
request.addHeader("Authorization", apiKey);
StringEntity params = new StringEntity(parameter);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
return (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK);
}catch(Exception e){
logger.error("Failed to delete the relationship between dataset subject = " + datasetIdSubject
+ " and " + " dataset subject " + datasetIdObject, e);
}
return false;
}
@Override
public List<CkanDatasetRelationship> getRelationshipDatasets(
String datasetIdSubject, String datasetIdObject, String apiKey) {
// checks
checkNotNull(datasetIdSubject);
checkNotNull(datasetIdObject);
checkNotNull(apiKey);
checkArgument(!datasetIdSubject.isEmpty());
checkArgument(!datasetIdObject.isEmpty());
checkArgument(!apiKey.isEmpty());
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){
List<CkanDatasetRelationship> toReturn = new ArrayList<CkanDatasetRelationship>();
// we need to use the apis to make it
String path = "/api/3/action/package_relationships_list";
// Request parameters to be replaced
String parameter = "{"
+ "\"id\":\"SUBJECT\","
+ "\"id2\":\"OBJECT\""
+ "}";
// replace those values
parameter = parameter.replace("SUBJECT", datasetIdSubject);
parameter = parameter.replace("OBJECT", datasetIdObject);
logger.debug("API request for delete relationship is going to be " + parameter);
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
request.addHeader("Authorization", apiKey);
StringEntity params = new StringEntity(parameter);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
// parse the json and convert to java beans
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
String res = "";
while ((output = br.readLine()) != null) {
res += output;
}
if(res == "")
return toReturn;
// parse the json object returned
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(res);
JSONArray resultJson = (JSONArray) json.get("result");
Iterator<JSONObject> it = resultJson.iterator();
while (it.hasNext()) {
JSONObject object = (JSONObject) it.next();
try{
CkanDatasetRelationship relation = new CkanDatasetRelationship(object);
toReturn.add(relation);
}catch(Exception e){
logger.error("Error while building CkanRelationship bean from object " + object, e);
}
}
}
return toReturn;
}catch(Exception e){
logger.error("Failed to delete the relationship between dataset subject = " + datasetIdSubject
+ " and " + " dataset subject " + datasetIdObject, e);
}
return null;
}
}

View File

@ -0,0 +1,96 @@
package org.gcube.datacatalogue.ckanutillibrary.models;
import static com.google.common.base.Preconditions.checkNotNull;
import org.json.simple.JSONObject;
/**
* A ckan dataset relationship. It is represented by the following fields
* <ul>
* <li> subject dataset id
* <li> object dataset id
* <li> type of the relationship
* <li> comment an optional comment
* </ul>
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class CkanDatasetRelationship {
private String subject;
private String object;
private String comment;
private String type;
public CkanDatasetRelationship(){
super();
}
/**
* @param subject
* @param object
* @param comment
* @param type
*/
public CkanDatasetRelationship(String subject, String object,
String comment, String type) {
super();
this.subject = subject;
this.object = object;
this.comment = comment;
this.type = type;
}
/**
* From a json object that must have the properties listed in the class header (comment is optional)
* @param object
*/
public CkanDatasetRelationship(JSONObject object) {
this.comment = (String) object.get("comment");
this.object = (String) object.get("object");
this.subject = (String) object.get("subject");
this.type = (String) object.get("type"); // TODO convert to one of enums DatasetRelationships
checkNotNull(object);
checkNotNull(subject);
checkNotNull(type);
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getObject() {
return object;
}
public void setObject(String object) {
this.object = object;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "CkanDatasetRelationship [subject=" + subject + ", object="
+ object + ", comment=" + comment + ", type=" + type
+ "]";
}
}

View File

@ -0,0 +1,28 @@
package org.gcube.datacatalogue.ckanutillibrary.models;
/**
* Allowed relationships between packages(datasets). Some of them are not supported yet due to the problem
* reported here https://support.d4science.org/issues/4455
* <ul>
* <li> depends_on
* <li> dependency_of
* <li> derives_from
* <li> has_derivation
* <li> child_of
* <li> parent_of
* <li> links_to
* <li> linked_from
* </ul>
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public enum DatasetRelationships {
depends_on,
// dependency_of,
derives_from,
// has_derivation,
child_of,
// parent_of,
links_to
// linked_from
}

View File

@ -7,6 +7,8 @@ import java.util.Map;
import java.util.Map.Entry;
import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper;
import org.gcube.datacatalogue.ckanutillibrary.models.CkanDatasetRelationship;
import org.gcube.datacatalogue.ckanutillibrary.models.DatasetRelationships;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesIntoOrganization;
import org.slf4j.LoggerFactory;
@ -16,7 +18,47 @@ public class TestCKanLib {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestCKanLib.class);
CKanUtilsImpl instance;
private CkanUtilsFactory factory;
private String scope = "/gcube/devsec/devVRE";
private String testUser = "costantino_perciante";
//@Before
public void before(){
factory = CkanUtilsFactory.getFactory();
}
//@Test
public void datasetsRelationshipCreateDelete() throws Exception{
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
String subjectId = "lucio_organization";
String objectId = "test_for_visibility";
DatasetRelationships relation = DatasetRelationships.depends_on;
boolean resC = instance.createDatasetRelationship(subjectId, objectId, relation, "Comment for this relationship", instance.getApiKeyFromUsername(testUser));
Thread.sleep(500);
boolean resD = instance.deleteDatasetRelationship(subjectId, objectId, relation, instance.getApiKeyFromUsername(testUser));
logger.debug("ResC is " + resC);
logger.debug("ResD is " + resD);
}
//@Test
public void datasetRelationshipRetrieve() throws Exception{
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
String subjectId = "lucio_organization";
String objectId = "test_for_visibility";
List<CkanDatasetRelationship> res = instance.getRelationshipDatasets(subjectId, objectId, instance.getApiKeyFromUsername(testUser));
logger.debug("Relationships " + res);
}
//@Test
public void factoryTest() throws Exception{
@ -38,20 +80,10 @@ public class TestCKanLib {
}
//@Test
public void before() throws Exception{
instance = new CKanUtilsImpl("/gcube");
List<String> orgs = instance.getOrganizationsNamesByUser("costantino.perciante");
for (String string : orgs) {
System.out.println("org is " + string);
}
}
//@Test
public void testgetApiKeyFromUser() {
public void testgetApiKeyFromUser() throws Exception {
logger.debug("Testing getApiKeyFromUser");
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
String username = "francescomangiacrapa";
String key = instance.getApiKeyFromUsername(username);
@ -60,9 +92,10 @@ public class TestCKanLib {
}
//@Test
public void testgetUserFromApiKey() {
public void testgetUserFromApiKey() throws Exception {
logger.debug("Testing getApiKeyFromUser");
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
String key = "put-your-key-here";
CKanUserWrapper user = instance.getUserFromApiKey(key);
@ -71,9 +104,10 @@ public class TestCKanLib {
}
//@Test
public void getOrganizationsByUser() {
public void getOrganizationsByUser() throws Exception {
System.out.println("Testing getOrganizationsByUser");
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
String username = "francescomangiacrapa";
List<CkanOrganization> organizations = instance.getOrganizationsByUser(username);
@ -89,6 +123,7 @@ public class TestCKanLib {
public void getGroupsAndRolesByUser() throws Exception {
logger.debug("Testing getGroupsAndRolesByUser");
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
String username = "andrea.rossi";
instance = new CKanUtilsImpl("/gcube");
@ -103,8 +138,7 @@ public class TestCKanLib {
//@Test
public void getUsers() throws Exception{
instance = new CKanUtilsImpl("/gcube");
CKanUtilsImpl instance = factory.getUtilsPerScope(scope);
List<RolesIntoOrganization> rolesToMatch = new ArrayList<RolesIntoOrganization>();
rolesToMatch.add(RolesIntoOrganization.ADMIN);