package org.gcube.data_catalogue.grsf_publish_ws.utils; import java.beans.PropertyDescriptor; import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag; import org.gcube.data_catalogue.grsf_publish_ws.json.input.Common; import org.gcube.data_catalogue.grsf_publish_ws.json.input.DatabaseSource; import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueFactory; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueImpl; import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean; import org.slf4j.LoggerFactory; import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse; import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpGet; import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient; import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder; import eu.trentorise.opendata.jackan.model.CkanLicense; /** * Helper methods * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) */ public abstract class HelperMethods { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(HelperMethods.class); // to be retrieved from the web.xml private static final String PENDING_CONTEX_KEY = "PendingContext"; private static final String CONFIRMED_CONTEX_KEY = "ConfirmedContext"; public static final String PRODUCT_TYPE = "Product type"; /** * Convert a group name to its id on ckan * @param origName * @return */ public static String getGroupNameOnCkan(String origName){ if(origName == null) throw new IllegalArgumentException("origName cannot be null"); String modified = origName.trim().toLowerCase().replaceAll("[^A-Za-z0-9-]", "-"); if(modified.startsWith("-")) modified = modified.substring(1); if(modified.endsWith("-")) modified = modified.substring(0, modified.length() -1); return modified; } /** * Retrieve the running instance of the data catalogue for this scope * @return * @throws Exception */ public static DataCatalogue getDataCatalogueRunningInstance(String scope) throws Exception{ try{ DataCatalogueImpl instance = DataCatalogueFactory.getFactory().getUtilsPerScope(scope); return instance; }catch(Exception e){ logger.error("Failed to instanciate data catalogue lib", e); } return null; } /** * Retrieve the list of tags for this object */ public static void getTags(List tags, Common record){ Class current = record.getClass(); do{ Field[] fields = current.getDeclaredFields(); for (Field field : fields) { if(field.isAnnotationPresent(Tag.class)){ try{ Object f = new PropertyDescriptor(field.getName(), current).getReadMethod().invoke(record); if(f != null){ tags.add(f.toString().trim()); } }catch(Exception e){ logger.error("Failed ot read value for field " + field.getName() + " skipping", e); } } } } while((current = current.getSuperclass())!=null); // now parse also the Database Sources field List sources = record.getDatabaseSources(); for (DatabaseSource databaseSource : sources) { logger.debug("Database source is " + databaseSource); String nameAsTag = databaseSource.getName().toString(); if(!tags.contains(nameAsTag)) tags.add(nameAsTag); } } /** * Retrieve the list of groups' names for this object */ public static void getGroups(List groups, Common record){ Class current = record.getClass(); do{ Field[] fields = current.getDeclaredFields(); for (Field field : fields) { if(field.isAnnotationPresent(Group.class)){ try{ Object f = new PropertyDescriptor(field.getName(), current).getReadMethod().invoke(record); if(f != null){ // also convert to the group name that should be on ckan String groupName = getGroupNameOnCkan(f.toString().trim()); if(!groups.contains(groupName)) groups.add(groupName); } }catch(Exception e){ logger.error("Failed ot read value for field " + field.getName() + " skipping", e); } } } } while((current = current.getSuperclass())!=null); logger.debug("Groups is " + groups); // now parse also the Database Sources field List sources = record.getDatabaseSources(); for (DatabaseSource databaseSource : sources) { logger.debug("Database source is " + databaseSource); Source name = databaseSource.getName(); String groupName = getGroupNameOnCkan(name.toString().trim()); if(!groups.contains(groupName)) groups.add(groupName); } } /** * Retrieve the list of extras for this object */ public static void getExtras(Map extras, Common record){ Class current = record.getClass(); do{ Field[] fields = current.getDeclaredFields(); for (Field field : fields) { if(field.isAnnotationPresent(CustomField.class)){ try{ Object f = new PropertyDescriptor(field.getName(), current).getReadMethod().invoke(record); if(f != null){ // get the key to put into the map first extras.put(field.getAnnotation(CustomField.class).key(), f.toString().trim()); } }catch(Exception e){ logger.error("Failed ot read value for field " + field.getName() + " skipping", e); } } } } while((current = current.getSuperclass())!=null); } /** * Retrieve the organization name in which the user wants to publish starting from the scope * @param contextInWhichPublish * @return */ public static String retrieveOrgNameFromScope(String scope) { String[] splittedScope = scope.split("/"); return splittedScope[splittedScope.length - 1].toLowerCase(); } /** * Return the context in which the user wants to publish by the status information * @param status * @param contextServlet * @return */ public static String getContextFromStatus(Status status, ServletContext contextServlet) { String toReturn = null; switch(status){ case Confirmed : toReturn = (String)contextServlet.getInitParameter(CONFIRMED_CONTEX_KEY); break; case Pending: toReturn = (String)contextServlet.getInitParameter(PENDING_CONTEX_KEY); break; default: break; } logger.debug("Context evaluated is " + toReturn); return toReturn; } /** * Validate the name the product will have * @param futureName * @return */ public static boolean isValid(String futureName) { if(futureName == null || futureName.isEmpty()) return false; else{ return futureName.matches("[\\sA-Za-z0-9_.-]+"); } } /** * Retrieve the user's email given his/her username * @param context * @param token * @return * @throws Exception */ public static String getUserEmail(String context, String token){ try(CloseableHttpClient client = HttpClientBuilder.create().build();){ String baseUrl = new ServiceEndPointReaderSocial(context).getBasePath(); String url = baseUrl.replace("http", "https") + "/users/getUserEmail?gcube-token=" + token; logger.debug("Request url is " + baseUrl); HttpGet getRequest = new HttpGet(url); HttpResponse response = client.execute(getRequest); if (response.getStatusLine().getStatusCode() != 200) { throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode()); } BufferedReader br = new BufferedReader( new InputStreamReader((response.getEntity().getContent()))); String email = ""; String temp = null; while ((temp = br.readLine()) != null) { email+= temp; } return email; }catch(Exception e){ logger.error("error while performing post method " + e.toString()); } return null; } /** * Retrieve the user's fullname given his/her username * @param context * @param token * @return * @throws Exception */ public static String getUserFullname(String context, String token){ try(CloseableHttpClient client = HttpClientBuilder.create().build();){ String baseUrl = new ServiceEndPointReaderSocial(context).getBasePath(); String url = baseUrl.replace("http", "https") + "/users/getUserEmail?gcube-token=" + token; logger.debug("Request url is " + url); HttpGet getRequest = new HttpGet(url); HttpResponse response = client.execute(getRequest); if (response.getStatusLine().getStatusCode() != 200) { throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode()); } BufferedReader br = new BufferedReader( new InputStreamReader((response.getEntity().getContent()))); String fullName = ""; String temp = null; while ((temp = br.readLine()) != null) { fullName+= temp; } return fullName; }catch(Exception e){ logger.error("error while performing post method " + e.toString()); } return null; } /** * Retrieve the list of ckan licenses and build up a map * @return * @throws Exception */ public static Map getLicenses() throws Exception { Map toReturn = new HashMap(); String scope = ScopeProvider.instance.get(); DataCatalogue catalogue = getDataCatalogueRunningInstance(scope); List licenses = catalogue.getLicenses(); for (CkanLicense ckanLicense : licenses) { toReturn.put(ckanLicense.getId(), ckanLicense.getTitle()); } return toReturn; } /** * Check that the given license id is in CKAN * @param license id to check * @return * @throws Exception */ public static boolean existsLicenseId(String license) throws Exception { Map licenses = getLicenses(); return licenses.containsKey(license); } // /** // * Validate a record along the database_sources and the source_of_information // * @param record // * @return // */ // public static Response validateBeanAndResources(Common record){ // // ResponseCreationBean responseBean = new ResponseCreationBean(); // javax.ws.rs.core.Response.Status status = javax.ws.rs.core.Response.Status.BAD_REQUEST; // // ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); // Validator validator = factory.getValidator(); // // // Set> violations = validator.validate(record); // for (ConstraintViolation constraintViolation : violations) { // logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage()); // responseBean.setError(constraintViolation.getMessage()); // return Response.status(status).entity(responseBean).build(); // } // // // check database_sources and source_of_information (they are not null nor empty at this point) // List databaseSources = record.getDatabaseSources(); // for (DatabaseSource databaseSource : databaseSources) { // Set> violationsDatabaseSourcesBean = validator.validate(databaseSource); // for (ConstraintViolation constraintViolation : violationsDatabaseSourcesBean) { // logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage()); // responseBean.setError(constraintViolation.getMessage()); // return Response.status(status).entity(responseBean).build(); // } // } // // List sourcesOfInformation = record.getSourceOfInformation(); // for (Resource sourceOfinformation : sourcesOfInformation) { // Set> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation); // for (ConstraintViolation constraintViolation : violationsSourceOfinformationsBean) { // logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage()); // responseBean.setError(constraintViolation.getMessage()); // return Response.status(status).entity(responseBean).build(); // } // } // return null; // } /** * Retrieve the ResourceBean given the record (extract resources from Database Sources and Source of Information) * @param record * @return */ public static List getResourcesFromBean(Common record, String username) { List toReturn = new ArrayList(); List databaseSources = record.getDatabaseSources(); List databaseOfInformation = record.getSourceOfInformation(); // transform database sources for (DatabaseSource res : databaseSources) { logger.debug("Adding resource " + res); toReturn.add(new ResourceBean(res.getUrl(), res.getName().getOrigName(), res.getDescription(), null, username, null, null)); } // just add source of information for (Resource res : databaseOfInformation) { logger.debug("Adding resource " + res); toReturn.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null)); } logger.debug("Returning resources " + toReturn); return toReturn; } }