1343 lines
50 KiB
Java
1343 lines
50 KiB
Java
package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Calendar;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.function.Function;
|
|
import java.util.stream.Collectors;
|
|
|
|
import javax.servlet.http.HttpSession;
|
|
|
|
import org.gcube.common.portal.PortalContext;
|
|
import org.gcube.common.storagehubwrapper.server.StorageHubWrapper;
|
|
import org.gcube.common.storagehubwrapper.server.tohl.Workspace;
|
|
import org.gcube.datacatalogue.utillibrary.server.DataCatalogue;
|
|
import org.gcube.datacatalogue.utillibrary.server.DataCatalogueFactory;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.CatalogueUtilMethods;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.SessionCatalogueAttributes;
|
|
import org.gcube.datacatalogue.utillibrary.shared.ResourceBean;
|
|
import org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanGroup;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanLicense;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanOrganization;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanResource;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanTag;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.CatalogueRoleManager;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.DiscoverTagsList;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.GenericUtils;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.MetadataDiscovery;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.WorkspaceUtils;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetBean;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetadataProfileBeanForUpdate;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
|
|
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
|
|
import org.gcube.portlets.widgets.mpformbuilder.shared.license.LicenseBean;
|
|
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.MetaDataProfileBean;
|
|
import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.MetadataFieldWrapper;
|
|
import org.gcube.vomanagement.usermanagement.GroupManager;
|
|
import org.gcube.vomanagement.usermanagement.UserManager;
|
|
import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault;
|
|
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
|
|
import org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager;
|
|
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
|
|
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
|
|
import org.geojson.GeoJsonObject;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
|
|
import com.liferay.portal.service.UserLocalServiceUtil;
|
|
|
|
/**
|
|
* Server side of the data publisher.
|
|
*
|
|
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
|
|
*/
|
|
public class CKANPublisherServicesImpl extends RemoteServiceServlet implements CKanPublisherService {
|
|
|
|
private static final long serialVersionUID = 7252248774050361697L;
|
|
|
|
// Logger
|
|
// private static final org.slf4j.Logger logger =
|
|
// LoggerFactory.getLogger(CKANPublisherServicesImpl.class);
|
|
private static final Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class);
|
|
public static final String ITEM_URL_FIELD = "Item URL";
|
|
public static final String SYSTEM_KEY_PREFIX = "system:";
|
|
public static final String SYS_TYPE = SYSTEM_KEY_PREFIX + "type";
|
|
public static final String TAGS_VOCABULARY_KEY = "TAGS_VOCABULARY";
|
|
|
|
public static final List<String> SYSTEM_CUSTOM_FIELDS_PREFIXES = Arrays.asList(ITEM_URL_FIELD, SYSTEM_KEY_PREFIX);
|
|
|
|
// map <orgName, scope>
|
|
private ConcurrentHashMap<String, String> mapOrganizationScope = new ConcurrentHashMap<String, String>();
|
|
|
|
/**
|
|
* Dev mode set contexts.
|
|
*/
|
|
private void devModeSetContexts() {
|
|
if (!isWithinPortal()) {
|
|
logger.info("DETECTED DEV MODE");
|
|
GenericUtils.getCurrentContext(getThreadLocalRequest(), true);
|
|
GenericUtils.getCurrentToken(getThreadLocalRequest(), true);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Retrieve an instance of the library for the scope.
|
|
*
|
|
* @param scope if it is null it is evaluated from the session
|
|
* @return the catalogue
|
|
*/
|
|
public DataCatalogue getCatalogue(String scope) {
|
|
|
|
DataCatalogue instance = null;
|
|
String scopeInWhichDiscover = null;
|
|
try {
|
|
scopeInWhichDiscover = scope != null && !scope.isEmpty() ? scope
|
|
: GenericUtils.getCurrentContext(getThreadLocalRequest(), false);
|
|
logger.debug("Discovering ckan instance into scope " + scopeInWhichDiscover);
|
|
instance = DataCatalogueFactory.getFactory().getUtilsPerScope(scopeInWhichDiscover);
|
|
} catch (Exception e) {
|
|
logger.warn("Unable to retrieve ckan utils in scope " + scopeInWhichDiscover + ". Error is "
|
|
+ e.getLocalizedMessage());
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the list of organizations in which the user can publish (roles
|
|
* ADMIN/EDITOR).
|
|
*
|
|
* @param username the username
|
|
* @param scope the scope
|
|
* @return the list of organizations
|
|
* @throws UserManagementSystemException the user management system exception
|
|
* @throws GroupRetrievalFault the group retrieval fault
|
|
*/
|
|
private List<OrganizationBean> getUserOrganizationsListAdmin(String username, String scope)
|
|
throws UserManagementSystemException, GroupRetrievalFault {
|
|
|
|
logger.debug("Request for user " + username + " organizations list");
|
|
List<OrganizationBean> orgsName = new ArrayList<OrganizationBean>();
|
|
|
|
HttpSession httpSession = getThreadLocalRequest().getSession();
|
|
String keyPerScope = CatalogueUtilMethods
|
|
.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_ORGANIZATIONS_PUBLISH_KEY, scope);
|
|
|
|
if (httpSession.getAttribute(keyPerScope) != null) {
|
|
orgsName = (List<OrganizationBean>) httpSession.getAttribute(keyPerScope);
|
|
logger.info("List of organizations was into session " + orgsName);
|
|
} else {
|
|
String gatewayURL = GenericUtils.getGatewayClientHostname(getThreadLocalRequest());
|
|
logger.info("The Gateway URL is: " + gatewayURL);
|
|
CatalogueRoleManager.getHighestRole(scope, username, GenericUtils.getGroupFromScope(scope).getGroupName(),
|
|
this, orgsName, gatewayURL);
|
|
httpSession.setAttribute(keyPerScope, orgsName);
|
|
logger.info("Organizations name for user " + username + " has been saved into session " + orgsName);
|
|
}
|
|
|
|
return orgsName;
|
|
}
|
|
|
|
/**
|
|
* Online or in development mode?.
|
|
*
|
|
* @return true if you're running into the portal, false if in development
|
|
*/
|
|
private boolean isWithinPortal() {
|
|
try {
|
|
UserLocalServiceUtil.getService();
|
|
return true;
|
|
} catch (com.liferay.portal.kernel.bean.BeanLocatorException ex) {
|
|
logger.trace("Development Mode ON");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the workspace from storage hub.
|
|
*
|
|
* @return the workspace from storage hub
|
|
* @throws Exception the exception
|
|
*/
|
|
protected Workspace getWorkspaceFromStorageHub() throws Exception {
|
|
GCubeUser user = PortalContext.getConfiguration().getCurrentUser(this.getThreadLocalRequest());
|
|
StorageHubWrapper storageHubWrapper = WorkspaceUtils.getStorageHubWrapper(this.getThreadLocalRequest(), null,
|
|
user);
|
|
return storageHubWrapper.getWorkspace();
|
|
}
|
|
|
|
/**
|
|
* Find a license id given the license text.
|
|
*
|
|
* @param chosenLicense the chosen license
|
|
* @return the string
|
|
*/
|
|
private String findLicenseIdByLicense(String chosenLicense) {
|
|
|
|
// get scope from client url
|
|
String scope = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
return getCatalogue(scope).findLicenseIdByLicenseTitle(chosenLicense);
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the licenses.
|
|
*
|
|
* @return the licenses
|
|
*/
|
|
@Override
|
|
public List<LicenseBean> getLicenses() {
|
|
|
|
// get http session
|
|
HttpSession httpSession = getThreadLocalRequest().getSession();
|
|
String scope = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
logger.info("Request for CKAN licenses for scope " + scope);
|
|
String keyPerScope = CatalogueUtilMethods
|
|
.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_LICENSES_KEY, scope);
|
|
|
|
// if(!isWithinPortal()){
|
|
// logger.info("DEV MODE returning funny licenses...");
|
|
// List<LicenseBean> licenses = new ArrayList<LicenseBean>();
|
|
// licenses.add(new LicenseBean("AFL-3.0", "https://opensource.org/licenses/AFL-3.0"));
|
|
// return licenses;
|
|
// }
|
|
|
|
List<LicenseBean> licensesBean = null;
|
|
if (httpSession.getAttribute(keyPerScope) != null) {
|
|
licensesBean = (List<LicenseBean>) httpSession.getAttribute(keyPerScope);
|
|
logger.info("List of licenses was into session");
|
|
} else {
|
|
List<CkanLicense> licenses = getCatalogue(scope).getLicenses();
|
|
licensesBean = new ArrayList<LicenseBean>();
|
|
for (CkanLicense license : licenses) {
|
|
licensesBean.add(new LicenseBean(license.getTitle(), license.getUrl()));
|
|
}
|
|
|
|
// sort the list
|
|
Collections.sort(licensesBean, new Comparator<LicenseBean>() {
|
|
public int compare(LicenseBean l1, LicenseBean l2) {
|
|
return l1.getTitle().compareTo(l2.getTitle());
|
|
}
|
|
});
|
|
|
|
httpSession.setAttribute(keyPerScope, licensesBean);
|
|
logger.info("List of licenses has been saved into session");
|
|
}
|
|
|
|
return licensesBean;
|
|
}
|
|
|
|
/**
|
|
* Gets the dataset bean.
|
|
*
|
|
* @param folderId the folder id
|
|
* @return the dataset bean
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public DatasetBean getDatasetBean(String folderId) throws Exception {
|
|
|
|
DatasetBean bean = null;
|
|
String userName = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
|
|
logger.info("DatasetBean request for folderId " + folderId + " and " + userName);
|
|
|
|
if (isWithinPortal()) {
|
|
try {
|
|
|
|
String scope = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
|
|
logger.debug("Scope recovered from session is " + scope);
|
|
logger.debug(
|
|
"Request dataset metadata bean for folder with id " + folderId + " whose owner is " + userName);
|
|
|
|
UserManager liferUserManager = new LiferayUserManager();
|
|
GCubeUser userOwner = liferUserManager.getUserByUsername(userName);
|
|
|
|
// build bean
|
|
logger.debug("Building bean");
|
|
bean = new DatasetBean();
|
|
|
|
bean.setId(folderId);
|
|
bean.setOwnerIdentifier(userName);
|
|
bean.setVersion(1);
|
|
bean.setAuthorName(userOwner.getFirstName());
|
|
bean.setAuthorSurname(userOwner.getLastName());
|
|
bean.setAuthorEmail(userOwner.getEmail());
|
|
bean.setMaintainer(userOwner.getFullname());
|
|
bean.setMaintainerEmail(userOwner.getEmail());
|
|
bean.setOrganizationList(getUserOrganizationsListAdmin(userName, scope));
|
|
bean.setTagsVocabulary(discoverTagsVocabulary(scope));
|
|
|
|
// if the request comes from the workspace
|
|
if (folderId != null && !folderId.isEmpty()) {
|
|
Workspace workspace = getWorkspaceFromStorageHub();
|
|
WorkspaceUtils.toWorkspaceResource(folderId, userName, bean, workspace);
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Error while retrieving bean information", e);
|
|
throw new Exception("Error while retrieving basic information " + e.getMessage());
|
|
}
|
|
} else {
|
|
|
|
logger.info("DEV MODE DETECTED");
|
|
GenericUtils.getCurrentToken(getThreadLocalRequest(), true);
|
|
|
|
try {
|
|
bean = new DatasetBean();
|
|
bean.setId(folderId);
|
|
bean.setDescription("This is a fantastic description");
|
|
bean.setVersion(1);
|
|
String onlyAlphanumeric = "test-creation-blablabla".replaceAll("[^A-Za-z0-9]", "");
|
|
bean.setTitle(onlyAlphanumeric + Calendar.getInstance().getTimeInMillis());
|
|
bean.setAuthorName("Francesco");
|
|
bean.setAuthorSurname("Mangiacrapa");
|
|
bean.setAuthorEmail("francesco.mangiacrapa@isti.cnr.it");
|
|
bean.setMaintainer("Francesco Mangiacrapa");
|
|
bean.setMaintainerEmail("francesco.mangiacrapa@isti.cnr.it");
|
|
|
|
// UPDATED By Francesco
|
|
String scope = GenericUtils.getCurrentContext(this.getThreadLocalRequest(), false);
|
|
String vreName = scope.substring(scope.lastIndexOf("/") + 1, scope.length());
|
|
logger.debug("In dev mode using the scope: " + scope + " and VRE name: " + vreName);
|
|
bean.setOrganizationList(Arrays.asList(new OrganizationBean(vreName, vreName.toLowerCase(), true)));
|
|
|
|
bean.setOwnerIdentifier(userName);
|
|
|
|
if (folderId != null && !folderId.isEmpty()) {
|
|
Workspace workspace = getWorkspaceFromStorageHub();
|
|
WorkspaceUtils.toWorkspaceResource(folderId, userName, bean, workspace);
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Error while building bean into dev mode", e);
|
|
throw new Exception("Error while retrieving basic information " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
logger.debug("Returning bean " + bean);
|
|
return bean;
|
|
}
|
|
|
|
/**
|
|
* Gets the dataset bean for update.
|
|
*
|
|
* @param datasetIdOrName the dataset id or name
|
|
* @return the dataset bean for update
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public DatasetBean getDatasetBeanForUpdate(String datasetIdOrName) throws Exception {
|
|
|
|
DatasetBean bean = null;
|
|
String userName = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
|
|
logger.info("DatasetBeanForUpdate request for " + datasetIdOrName + " and " + userName);
|
|
|
|
String scopePerCurrentUrl = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
|
|
DataCatalogue utils = getCatalogue(scopePerCurrentUrl);
|
|
|
|
CkanDataset dataset = utils.getDataset(datasetIdOrName, userName);
|
|
|
|
if (dataset == null) {
|
|
// the user cannot read the item, so he/she is not the owner nor the admin
|
|
throw new Exception("Dataset with id " + datasetIdOrName + " not found for user " + userName);
|
|
}
|
|
|
|
logger.debug("Building bean");
|
|
bean = new DatasetBean();
|
|
|
|
bean.setId(datasetIdOrName);
|
|
bean.setCkanName(dataset.getName());
|
|
bean.setTitle(dataset.getTitle());
|
|
bean.setDescription(dataset.getNotes());
|
|
bean.setLicense(dataset.getLicenseTitle());
|
|
bean.setVisibile(dataset.isPriv());
|
|
|
|
long version = 1;
|
|
try {
|
|
version = Long.parseLong(dataset.getVersion());
|
|
} catch (Exception e) {
|
|
// TODO: handle exception
|
|
}
|
|
bean.setVersion(version);
|
|
|
|
bean.setOwnerIdentifier(dataset.getCreatorUserId());
|
|
|
|
bean.setAuthorFullName(dataset.getAuthor());
|
|
bean.setAuthorEmail(dataset.getAuthorEmail());
|
|
|
|
bean.setMaintainer(dataset.getMaintainer());
|
|
bean.setMaintainerEmail(dataset.getMaintainerEmail());
|
|
|
|
CkanOrganization ckanOrganization = dataset.getOrganization();
|
|
|
|
// UPDATED By Francesco
|
|
// String vreName = scope.substring(scope.lastIndexOf("/") + 1, scope.length());
|
|
// logger.debug("In dev mode using the scope: " + scope + " and VRE name: " + vreName);
|
|
final OrganizationBean ckanOrganizationBean = new OrganizationBean(ckanOrganization.getTitle(),
|
|
ckanOrganization.getName(), true);
|
|
bean.setOrganizationList(Arrays.asList(ckanOrganizationBean));
|
|
|
|
List<CkanTag> listDatasetTags = dataset.getTags();
|
|
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug("List tags from CKAN are: ");
|
|
for (CkanTag ckanTag : listDatasetTags) {
|
|
// logger.debug("ckanTag: " + ckanTag.getDisplayName());
|
|
logger.debug("ckanTag: " + ckanTag.getName());
|
|
}
|
|
}
|
|
|
|
// selected tags into Dataset
|
|
if (listDatasetTags != null) {
|
|
List<String> listTags = dataset.getTags().stream().map(t -> t.getName()).collect(Collectors.toList());
|
|
logger.info("setTags: {}", listTags);
|
|
bean.setTags(listTags);
|
|
}
|
|
|
|
// Vocabulary Tags from Generi Resources
|
|
bean.setTagsVocabulary(discoverTagsVocabulary(scopePerCurrentUrl));
|
|
|
|
// By default setting the root folder ID for updating the Resources on the
|
|
// client-side
|
|
// TODO LOAD THE WORKSPACE ROOT
|
|
/*
|
|
* Workspace workspace = getWorkspaceFromStorageHub();
|
|
* WorkspaceUtils.toWorkspaceResource(workspace.getRoot().getId(), userName,
|
|
* bean, workspace);
|
|
*/
|
|
|
|
// Settings the CKAN resources
|
|
List<CkanResource> resources = dataset.getResources();
|
|
if (resources != null) {
|
|
List<ResourceElementBean> list = new ArrayList<ResourceElementBean>(resources.size());
|
|
for (CkanResource ckanResource : resources) {
|
|
ResourceElementBean reb = PublisherCatalogueConveter.toResourceElementBean(ckanResource,
|
|
ckanOrganizationBean.getName());
|
|
list.add(reb);
|
|
}
|
|
bean.setResources(list);
|
|
}
|
|
|
|
// Settings the dataset type
|
|
Map<String, List<String>> extras = dataset.getListExtrasAsHashMap();
|
|
if (extras != null) {
|
|
List<String> theDatasetType = extras.get(SYS_TYPE);
|
|
if (theDatasetType != null && theDatasetType.size() > 0) {
|
|
bean.setChosenType(theDatasetType.get(0));
|
|
}
|
|
}
|
|
|
|
logger.debug("Returning bean " + bean);
|
|
logger.info("Returning the bean for dataset title {} and type {}" + bean.getTitle(), bean.getChosenType());
|
|
return bean;
|
|
}
|
|
|
|
/**
|
|
* Discover from the IS the vocabulary of tags for this scope, if present.
|
|
*
|
|
* @param context the context
|
|
* @return a list of tags vocabulary
|
|
*/
|
|
private List<String> discoverTagsVocabulary(String context) {
|
|
|
|
logger.debug("Looking for vocabulary of tags in this context " + context);
|
|
String keyPerVocabulary = CatalogueUtilMethods.concatenateSessionKeyScope(TAGS_VOCABULARY_KEY, context);
|
|
|
|
List<String> vocabulary = (List<String>) getThreadLocalRequest().getSession().getAttribute(keyPerVocabulary);
|
|
if (vocabulary == null) {
|
|
vocabulary = DiscoverTagsList.discoverTagsList(context);
|
|
if (vocabulary != null)
|
|
getThreadLocalRequest().getSession().setAttribute(keyPerVocabulary, vocabulary);
|
|
}
|
|
|
|
logger.debug("Vocabulary for tags is " + vocabulary);
|
|
|
|
return vocabulary;
|
|
}
|
|
|
|
/**
|
|
* Gets the tags for organization.
|
|
*
|
|
* @param orgName the org name
|
|
* @return the tags for organization
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public List<String> getTagsForOrganization(String orgName) throws Exception {
|
|
return discoverTagsVocabulary(getScopeFromOrgName(orgName));
|
|
}
|
|
|
|
/**
|
|
* Creates the C kan dataset.
|
|
*
|
|
* @param toCreate the to create
|
|
* @return the dataset bean
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public DatasetBean createCKanDataset(DatasetBean toCreate) throws Exception {
|
|
|
|
try {
|
|
devModeSetContexts();
|
|
logger.info("Request for creating a dataset with title: {} " + toCreate.getTitle());
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug("Dataset is: {} " + toCreate);
|
|
}
|
|
String userName = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
String title = toCreate.getTitle();
|
|
String organizationNameOrId = toCreate.getSelectedOrganization();
|
|
String author = toCreate.getAuthorFullName();
|
|
String authorMail = toCreate.getAuthorEmail();
|
|
String maintainer = toCreate.getMaintainer();
|
|
String maintainerMail = toCreate.getMaintainerEmail();
|
|
long version = toCreate.getVersion();
|
|
String description = toCreate.getDescription();
|
|
String chosenLicense = toCreate.getLicense();
|
|
String licenseId = findLicenseIdByLicense(chosenLicense);
|
|
List<String> listOfTags = toCreate.getTags();
|
|
Map<String, List<String>> customFields = toCreate.getCustomFields();
|
|
|
|
// add Type for custom fields
|
|
if (toCreate.getChosenType() != null)
|
|
customFields.put(SYS_TYPE, Arrays.asList(toCreate.getChosenType()));
|
|
|
|
boolean setPublic = toCreate.getVisibility();
|
|
|
|
// get the list of resources and convert to ResourceBean
|
|
List<ResourceBean> resources = null;
|
|
ResourceElementBean resourcesToAdd = toCreate.getResourceRoot();
|
|
|
|
// converting to resources to be added
|
|
if (resourcesToAdd != null) {
|
|
Workspace workspace = getWorkspaceFromStorageHub();
|
|
resources = WorkspaceUtils.toResources(toCreate, workspace, userName);
|
|
}
|
|
|
|
logger.debug("The user wants to publish in organization with name " + organizationNameOrId);
|
|
String scope = getScopeFromOrgName(organizationNameOrId);
|
|
DataCatalogue utils = getCatalogue(scope);
|
|
|
|
if (!isWithinPortal()) {
|
|
logger.debug("Should be added:");
|
|
for (String key : customFields.keySet()) {
|
|
logger.debug("Custom field with key: " + key + ", value: " + customFields.get(key));
|
|
}
|
|
}
|
|
|
|
String datasetId = utils.createCkanDatasetMultipleCustomFields(userName, title, null, organizationNameOrId,
|
|
author, authorMail, maintainer, maintainerMail, version, description, licenseId, listOfTags,
|
|
customFields, resources, setPublic, true, true);
|
|
|
|
if (datasetId != null) {
|
|
|
|
logger.info("Dataset created!");
|
|
toCreate.setId(datasetId);
|
|
|
|
// #23491 Building the go to the item to "Catalogue Portlet URL" (instead of URI
|
|
// Resolver URL)
|
|
String catalogueURL = utils.getPortletUrl();
|
|
// logger.debug("Returning catalogueURL: "+catalogueURL);
|
|
// logger.debug("Returning datasetId: "+datasetId);
|
|
toCreate.setSource(String.format("%s?path=/dataset/%s", catalogueURL, datasetId));
|
|
logger.debug("Returning getSource(): " + toCreate.getSource());
|
|
logger.debug("Returning dataset: " + toCreate);
|
|
|
|
// #24744 Returning lazy object
|
|
toCreate.setGroups(null);
|
|
toCreate.setCustomFields(null);
|
|
toCreate.setGroupsForceCreation(null);
|
|
toCreate.setMetadataList(null);
|
|
toCreate.setOrganizationList(null);
|
|
|
|
logger.info("Returning lazy dataset: " + toCreate);
|
|
|
|
// createdDatasetBean.getSource();
|
|
// createdDatasetBean.getTitle();
|
|
// resourceForm = new AddResourceToDataset(eventBus, createdDatasetBean.getId(),
|
|
// createdDatasetBean.getTitle(),
|
|
// createdDatasetBean.getSelectedOrganization(), owner, datasetUrl);
|
|
return toCreate;
|
|
} else {
|
|
logger.error("Failed to create the dataset");
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Error while creating item ", e);
|
|
throw new Exception(e.getMessage());
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
/**
|
|
* Update CKAN dataset.
|
|
*
|
|
* @param toUpdate the to create
|
|
* @return the dataset bean
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public DatasetBean updateCKANDataset(DatasetBean toUpdate) throws Exception {
|
|
|
|
try {
|
|
devModeSetContexts();
|
|
logger.info("Request for updating a dataset with title: {} " + toUpdate.getTitle());
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug("Dataset is: {} " + toUpdate);
|
|
}
|
|
|
|
if (toUpdate.getCkanName() == null)
|
|
throw new Exception("Error on updating: the input parameter 'name' is null");
|
|
|
|
String userName = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
String title = toUpdate.getTitle();
|
|
String organizationNameOrId = toUpdate.getSelectedOrganization();
|
|
String author = toUpdate.getAuthorFullName();
|
|
String authorMail = toUpdate.getAuthorEmail();
|
|
String maintainer = toUpdate.getMaintainer();
|
|
String maintainerMail = toUpdate.getMaintainerEmail();
|
|
long version = toUpdate.getVersion();
|
|
String description = toUpdate.getDescription();
|
|
String chosenLicense = toUpdate.getLicense();
|
|
String licenseId = findLicenseIdByLicense(chosenLicense);
|
|
List<String> listOfTags = toUpdate.getTags();
|
|
Map<String, List<String>> customFields = toUpdate.getCustomFields();
|
|
|
|
// add Type for custom fields
|
|
// if (toUpdate.getChosenType() != null) {
|
|
// customFields.put(SYS_TYPE, Arrays.asList(toUpdate.getChosenType()));
|
|
// }
|
|
|
|
// Reading the CKAN Dataset with extras in order to set the reserver system into
|
|
// update request
|
|
String scopePerCurrentUrl = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
DataCatalogue utils = getCatalogue(scopePerCurrentUrl);
|
|
CkanDataset currentDataset = utils.getDataset(toUpdate.getId(), userName);
|
|
|
|
Map<String, List<String>> ckanExtras = currentDataset.getListExtrasAsHashMap();
|
|
Map<String, List<String>> ckanReserverSystemExtras = getReserverdSystemFields(ckanExtras);
|
|
// putting all reserved system fields into customFields to update
|
|
customFields.putAll(ckanReserverSystemExtras);
|
|
|
|
// Settings the CKAN resources
|
|
List<CkanResource> listCurrentResources = currentDataset.getResources();
|
|
List<ResourceBean> resources = null;
|
|
if (listCurrentResources != null) {
|
|
resources = new ArrayList<ResourceBean>(listCurrentResources.size());
|
|
for (CkanResource ckanResource : listCurrentResources) {
|
|
String orgName = null; // not required here
|
|
ResourceBean reb = PublisherCatalogueConveter.toResourceBean(ckanResource, orgName);
|
|
resources.add(reb);
|
|
}
|
|
}
|
|
|
|
boolean setPublic = toUpdate.getVisibility();
|
|
|
|
// get the list of resources and convert to ResourceBean from the Workspace
|
|
ResourceElementBean resourcesToAdd = toUpdate.getResourceRoot();
|
|
// converting to resources to be added
|
|
if (resourcesToAdd != null) {
|
|
Workspace workspace = getWorkspaceFromStorageHub();
|
|
resources.addAll(WorkspaceUtils.toResources(toUpdate, workspace, userName));
|
|
}
|
|
|
|
logger.debug("The user wants to publish in organization with name " + organizationNameOrId);
|
|
// String scope = getScopeFromOrgName(organizationNameOrId);
|
|
|
|
if (!isWithinPortal()) {
|
|
logger.debug("Should be added:");
|
|
for (String key : customFields.keySet()) {
|
|
logger.debug("Custom field with key: " + key + ", value: " + customFields.get(key));
|
|
}
|
|
}
|
|
|
|
String datasetId = utils.updateCkanDatasetMultipleCustomFields(userName, title, toUpdate.getCkanName(),
|
|
organizationNameOrId, author, authorMail, maintainer, maintainerMail, version, description,
|
|
licenseId, listOfTags, customFields, resources, setPublic, true, true);
|
|
|
|
if (datasetId != null) {
|
|
|
|
logger.info("Dataset updated!");
|
|
toUpdate.setId(datasetId);
|
|
|
|
// #23491 Building the go to the item to "Catalogue Portlet URL" (instead of URI
|
|
// Resolver URL)
|
|
String catalogueURL = utils.getPortletUrl();
|
|
// logger.debug("Returning catalogueURL: "+catalogueURL);
|
|
// logger.debug("Returning datasetId: "+datasetId);
|
|
toUpdate.setSource(String.format("%s?path=/dataset/%s", catalogueURL, datasetId));
|
|
logger.debug("Returning getSource(): " + toUpdate.getSource());
|
|
logger.debug("Returning dataset: " + toUpdate);
|
|
|
|
// #24744 Returning lazy object
|
|
toUpdate.setGroups(null);
|
|
toUpdate.setCustomFields(null);
|
|
toUpdate.setGroupsForceCreation(null);
|
|
toUpdate.setMetadataList(null);
|
|
toUpdate.setOrganizationList(null);
|
|
|
|
logger.info("Returning lazy dataset: " + toUpdate);
|
|
|
|
// createdDatasetBean.getSource();
|
|
// createdDatasetBean.getTitle();
|
|
// resourceForm = new AddResourceToDataset(eventBus, createdDatasetBean.getId(),
|
|
// createdDatasetBean.getTitle(),
|
|
// createdDatasetBean.getSelectedOrganization(), owner, datasetUrl);
|
|
return toUpdate;
|
|
} else {
|
|
logger.error("Failed to update the dataset");
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Error while updating item ", e);
|
|
throw new Exception(e.getMessage());
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
/**
|
|
* Adds the resource to dataset.
|
|
*
|
|
* @param resource the resource
|
|
* @param organizationName the organization name
|
|
* @param datasetId the dataset id
|
|
* @return the resource element bean
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public ResourceElementBean addResourceToDataset(ResourceElementBean resource, String organizationName,
|
|
String datasetId) throws Exception {
|
|
logger.info("called addResourceToDataset");
|
|
devModeSetContexts();
|
|
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
logger.debug("Incoming request for creating new resource for dataset with id " + datasetId
|
|
+ " and organization name of the dataset is " + resource.getOrganizationNameDatasetParent());
|
|
logger.debug("Owner is " + username + " and resource is " + resource);
|
|
|
|
ResourceBean resourceBean = new ResourceBean(resource.getUrl(), resource.getName(), resource.getDescription(),
|
|
null, username, datasetId, null);
|
|
|
|
// get the scope in which we should discover the ckan instance given the
|
|
// organization name in which the dataset was created
|
|
String scope = getScopeFromOrgName(resource.getOrganizationNameDatasetParent());
|
|
DataCatalogue catalogue = getCatalogue(scope);
|
|
CkanResource theCreatedResource = catalogue.addResource(resourceBean, datasetId,
|
|
resource.getOrganizationNameDatasetParent(), username);
|
|
|
|
if (theCreatedResource != null) {
|
|
logger.info("Resource " + resource.getName() + " is now available");
|
|
|
|
ResourceElementBean reb = PublisherCatalogueConveter.toResourceElementBean(theCreatedResource,
|
|
organizationName);
|
|
|
|
return reb;
|
|
}
|
|
|
|
logger.debug("No resource created");
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Delete resource from dataset.
|
|
*
|
|
* @param resource the resource
|
|
* @return true, if successful
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public boolean deleteResourceFromDataset(ResourceElementBean resource) throws Exception {
|
|
logger.debug("Request for deleting resource " + resource);
|
|
boolean deleted = false;
|
|
devModeSetContexts();
|
|
try {
|
|
// get the scope in which we should discover the ckan instance given the
|
|
// organization name in which the dataset was created
|
|
String scope = getScopeFromOrgName(resource.getOrganizationNameDatasetParent());
|
|
DataCatalogue catalogue = getCatalogue(scope);
|
|
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
deleted = catalogue.deleteResourceFromDataset(resource.getCkanResourceID(), username);
|
|
if (deleted) {
|
|
logger.info("Resource described by " + resource + " deleted");
|
|
} else
|
|
logger.error("Resource described by " + resource + " NOT deleted");
|
|
} catch (Exception e) {
|
|
String error = "Sorry, an error occurred while trying to delete resource described by "
|
|
+ resource.getName();
|
|
logger.error(error, e);
|
|
throw new Exception(error + ". Error is: " + e.getMessage());
|
|
}
|
|
return deleted;
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the profiles.
|
|
*
|
|
* @param orgName the org name
|
|
* @return the profiles
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public List<MetaDataProfileBean> getProfiles(String orgName) throws Exception {
|
|
|
|
logger.debug("Requested profiles for products into orgName " + orgName);
|
|
List<MetaDataProfileBean> toReturn = new ArrayList<MetaDataProfileBean>();
|
|
try {
|
|
String evaluatedScope = getScopeFromOrgName(orgName);
|
|
logger.debug("Evaluated scope is " + evaluatedScope);
|
|
toReturn = MetadataDiscovery.getMetadataProfilesList(evaluatedScope, getThreadLocalRequest());
|
|
} catch (Exception e) {
|
|
logger.error("Failed to retrieve profiles for scope coming from organization name " + orgName, e);
|
|
throw e;
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
/**
|
|
* Gets the profile for update.
|
|
*
|
|
* @param orgName the org name
|
|
* @param datasetType the dataset type
|
|
* @param datasedIdOrName the datased id or name
|
|
* @return the profile for update
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public MetadataProfileBeanForUpdate getProfileForUpdate(String orgName, String datasetType, String datasedIdOrName)
|
|
throws Exception {
|
|
logger.info("Called getProfileForUpdate for orgName {} and dataset type {} ", orgName, datasetType);
|
|
logger.debug("Requested profiles for products into orgName " + orgName);
|
|
List<MetaDataProfileBean> toRead = new ArrayList<MetaDataProfileBean>();
|
|
|
|
List<MetaDataProfileBean> toReturn = new ArrayList<MetaDataProfileBean>();
|
|
try {
|
|
String evaluatedScope = getScopeFromOrgName(orgName);
|
|
logger.debug("Evaluated scope is " + evaluatedScope);
|
|
toRead = MetadataDiscovery.getMetadataProfilesList(evaluatedScope, getThreadLocalRequest());
|
|
|
|
// Getting profile for datasetType, expecting only one
|
|
toReturn = toRead.stream().filter(tr -> tr.getType().compareTo(datasetType) == 0)
|
|
.collect(Collectors.toList());
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Failed to retrieve profiles for scope coming from organization name " + orgName, e);
|
|
throw e;
|
|
}
|
|
|
|
// retrieve scope per current Portlet url
|
|
String scopePerCurrentUrl = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
DataCatalogue utils = getCatalogue(scopePerCurrentUrl);
|
|
CkanDataset dataset = utils.getDataset(datasedIdOrName, username);
|
|
|
|
if (toReturn.isEmpty())
|
|
throw new Exception("No Profile found for dataset type: " + datasetType);
|
|
|
|
// Settings current values in the profile found
|
|
MetaDataProfileBean profileBean = toReturn.get(0);
|
|
if (logger.isTraceEnabled()) {
|
|
logger.trace("The source profile is: {}", profileBean);
|
|
logger.trace("The metadatafields into source profile are: {}", profileBean.getMetadataFields().size());
|
|
for (int i = 0; i < profileBean.getMetadataFields().size(); i++) {
|
|
MetadataFieldWrapper mw = profileBean.getMetadataFields().get(i);
|
|
logger.trace(i + " MetadataFieldWrapper : {}", mw);
|
|
}
|
|
}
|
|
Map<String, List<String>> extras = dataset.getListExtrasAsHashMap();
|
|
|
|
Map<String, List<String>> customFieldsMap = new HashMap<String, List<String>>(extras);
|
|
|
|
logger.trace("Current extras are {}", extras);
|
|
|
|
List<MetadataFieldWrapper> expandedListForMultipleOccurs = new ArrayList<MetadataFieldWrapper>();
|
|
|
|
// Operating on the source cloned list
|
|
List<MetadataFieldWrapper> clonedList = cloneList(profileBean.getMetadataFields());
|
|
|
|
// Creating bean to return
|
|
MetaDataProfileBean toReturnMetaDataProfileBean = new MetaDataProfileBean();
|
|
toReturnMetaDataProfileBean.setTitle(profileBean.getTitle());
|
|
toReturnMetaDataProfileBean.setType(profileBean.getType());
|
|
toReturnMetaDataProfileBean.setCategories(profileBean.getCategories());
|
|
|
|
for (MetadataFieldWrapper metadataFieldWrapper : clonedList) {
|
|
String fieldName = metadataFieldWrapper.getFieldNameFromCategory();
|
|
// removing profile key from the map
|
|
|
|
logger.trace("Searching field name '{}' in the profile", fieldName);
|
|
List<String> currValuesOfExtraField = extras.get(fieldName);
|
|
logger.trace("Current value found is '{}' for field name '{}'", currValuesOfExtraField, fieldName);
|
|
|
|
// the profile field is set as extra field (it is not null), so going to set the
|
|
// current values
|
|
if (currValuesOfExtraField != null && !currValuesOfExtraField.isEmpty()) {
|
|
|
|
customFieldsMap.remove(fieldName);
|
|
|
|
if (currValuesOfExtraField.size() == 1) {
|
|
metadataFieldWrapper.setCurrentValues(currValuesOfExtraField.stream().toArray(String[]::new));
|
|
} else {
|
|
// Duplicating the fields with multiple occurrences
|
|
int dataSize = currValuesOfExtraField.size();
|
|
for (int j = 0; j < dataSize; j++) {
|
|
List<MetadataFieldWrapper> cloned = cloneList(Arrays.asList(metadataFieldWrapper));
|
|
MetadataFieldWrapper mfw = cloned.get(0);
|
|
|
|
// Duplicating MetadataFieldWrapper for data list with isMultiSelection==false
|
|
if (!mfw.isMultiSelection()) {
|
|
mfw.setCurrentValues(currValuesOfExtraField.get(j) + "");
|
|
// In case of array, from the first to second-last one, repeated field is set to
|
|
// 'false'
|
|
// These properties are managed properly with the
|
|
// last one field
|
|
if (j < dataSize - 1) {
|
|
mfw.setMandatory(false);
|
|
mfw.setMaxOccurs(1);
|
|
}
|
|
expandedListForMultipleOccurs.add(mfw);
|
|
} else {
|
|
// Setting dataArray as list of current values when isMultiSelection is true
|
|
String[] toArray = (String[]) currValuesOfExtraField.toArray(new String[0]);
|
|
mfw.setCurrentValues(toArray);
|
|
expandedListForMultipleOccurs.add(mfw);
|
|
// Exit from for
|
|
break;
|
|
}
|
|
}
|
|
// returns to external for because the field with multiple occurrences has been
|
|
// added to list
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// add field to list
|
|
expandedListForMultipleOccurs.add(metadataFieldWrapper);
|
|
}
|
|
|
|
toReturnMetaDataProfileBean.setMetadataFields(expandedListForMultipleOccurs);
|
|
|
|
logger.trace("CustomFieldsMap (extras) not matching metadata profile are {}", customFieldsMap);
|
|
|
|
int customFieldsSize = customFieldsMap.size();
|
|
|
|
// There are the Custom Fields not belonging to profile
|
|
logger.info("Custom fields founds # {}", customFieldsSize);
|
|
|
|
if (customFieldsSize > 0) {
|
|
customFieldsMap = purgeSystemFields(customFieldsMap);
|
|
}
|
|
|
|
logger.info("custom fields to return {}", customFieldsMap.keySet());
|
|
|
|
MetadataProfileBeanForUpdate mpfu = new MetadataProfileBeanForUpdate();
|
|
mpfu.setListProfileBean(Arrays.asList(toReturnMetaDataProfileBean));
|
|
mpfu.setCustomFields(customFieldsMap);
|
|
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug("Returning filled profile {}", toReturnMetaDataProfileBean.getType());
|
|
logger.debug("with MetadataFields {}", toReturnMetaDataProfileBean.getMetadataFields());
|
|
logger.debug("Custom fields founds {}", customFieldsMap.keySet());
|
|
}
|
|
|
|
logger.info("returing the filled profile {}", profileBean.getType());
|
|
return mpfu;
|
|
}
|
|
|
|
/**
|
|
* Dataset id already exists.
|
|
*
|
|
* @param title the title
|
|
* @param orgName the org name
|
|
* @return true, if successful
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public boolean datasetIdAlreadyExists(String title, String orgName) throws Exception {
|
|
if (title == null || title.isEmpty())
|
|
return true; // it's an error somehow
|
|
try {
|
|
String scopeFromOrgName = getScopeFromOrgName(orgName);
|
|
String idFromTitle = CatalogueUtilMethods.fromProductTitleToName(title);
|
|
logger.debug(
|
|
"Evaluating if dataset with id " + title + " in context " + scopeFromOrgName + " already exists");
|
|
return getCatalogue(scopeFromOrgName).existProductWithNameOrId(idFromTitle);
|
|
} catch (Exception e) {
|
|
logger.error("Unable to check if such a dataset id already exists", e);
|
|
throw new Exception("Unable to check if such a dataset id already exists " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The method tries to retrieve the scope related to the organization using the
|
|
* map first, if no match is found, it retrieves such information by using
|
|
* liferay.
|
|
*
|
|
* @param orgName the org name
|
|
* @return the scope from org name
|
|
*/
|
|
private String getScopeFromOrgName(String orgName) {
|
|
|
|
logger.info("Request for scope related to orgName " + orgName + " [map that will be used is "
|
|
+ mapOrganizationScope.toString() + "]");
|
|
if (orgName == null || orgName.isEmpty())
|
|
throw new IllegalArgumentException("orgName cannot be empty or null!");
|
|
|
|
String toReturn = null;
|
|
|
|
if (isWithinPortal()) {
|
|
if (mapOrganizationScope.containsKey(orgName)) {
|
|
toReturn = mapOrganizationScope.get(orgName);
|
|
} else {
|
|
try {
|
|
String evaluatedScope = GenericUtils.retrieveScopeFromOrganizationName(orgName);
|
|
// see #20801
|
|
if (evaluatedScope == null || evaluatedScope.isEmpty()) {
|
|
logger.warn("Scope detected for OrganizationName: " + orgName
|
|
+ " is null or empty, skipping filling 'mapOrganizationScope' and returning null");
|
|
return toReturn;
|
|
}
|
|
mapOrganizationScope.put(orgName, evaluatedScope);
|
|
toReturn = evaluatedScope;
|
|
} catch (Exception e) {
|
|
logger.error("Failed to retrieve scope from OrgName for organization " + orgName, e);
|
|
}
|
|
}
|
|
} else {
|
|
// UPDATED By FRANCESCO
|
|
toReturn = GenericUtils.getCurrentContext(this.getThreadLocalRequest(), false);
|
|
mapOrganizationScope.put(orgName, toReturn);
|
|
}
|
|
logger.info("Returning scope " + toReturn);
|
|
return toReturn;
|
|
}
|
|
|
|
/**
|
|
* Gets the user groups.
|
|
*
|
|
* @param orgName the org name
|
|
* @return the user groups
|
|
*/
|
|
@Override
|
|
public List<OrganizationBean> getUserGroups(String orgName) {
|
|
|
|
List<OrganizationBean> toReturn = new ArrayList<OrganizationBean>();
|
|
|
|
if (isWithinPortal()) {
|
|
GCubeUser user = GenericUtils.getCurrentUser(getThreadLocalRequest());
|
|
String username = null;
|
|
if (user != null)
|
|
username = user.getUsername();
|
|
|
|
logger.debug("Request for user " + username + " groups. Organization name is " + orgName);
|
|
|
|
// get http session
|
|
HttpSession httpSession = getThreadLocalRequest().getSession();
|
|
String scope = orgName != null ? getScopeFromOrgName(orgName)
|
|
: GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
|
|
// check if they are in session
|
|
String keyPerScopeGroups = CatalogueUtilMethods
|
|
.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_GROUPS_MEMBER, scope);
|
|
|
|
if (httpSession.getAttribute(keyPerScopeGroups) != null) {
|
|
toReturn = (List<OrganizationBean>) httpSession.getAttribute(keyPerScopeGroups);
|
|
logger.info("Found user's groups in session " + toReturn);
|
|
} else {
|
|
|
|
// Fixing Incident #12563
|
|
try {
|
|
DataCatalogue catalogue = getCatalogue(scope);
|
|
// Fixing Incident #12563
|
|
if (username != null && !username.isEmpty()) {
|
|
Map<String, Map<CkanGroup, RolesCkanGroupOrOrg>> mapRoleGroup = catalogue
|
|
.getUserRoleByGroup(username);
|
|
Set<Entry<String, Map<CkanGroup, RolesCkanGroupOrOrg>>> set = mapRoleGroup.entrySet();
|
|
for (Entry<String, Map<CkanGroup, RolesCkanGroupOrOrg>> entry : set) {
|
|
Set<Entry<CkanGroup, RolesCkanGroupOrOrg>> subSet = entry.getValue().entrySet();
|
|
for (Entry<CkanGroup, RolesCkanGroupOrOrg> subEntry : subSet) {
|
|
toReturn.add(new OrganizationBean(subEntry.getKey().getTitle(),
|
|
subEntry.getKey().getName(), false));
|
|
}
|
|
}
|
|
httpSession.setAttribute(keyPerScopeGroups, toReturn);
|
|
} else
|
|
logger.warn("The API_KEY for " + username + " is null or empty in the catalogue: "
|
|
+ catalogue.getCatalogueUrl());
|
|
} catch (Exception e) {
|
|
logger.error("Error on recovery the user groups for " + username, e);
|
|
}
|
|
}
|
|
} else {
|
|
logger.warn("Dev mode detected");
|
|
toReturn = Arrays.asList();
|
|
}
|
|
|
|
logger.info("Returning user's groups: " + toReturn);
|
|
return toReturn;
|
|
}
|
|
|
|
/**
|
|
* Checks if is publisher user.
|
|
*
|
|
* @return true, if is publisher user
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public boolean isPublisherUser() throws Exception {
|
|
|
|
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
logger.info("Checking if the user " + username + " can publish or not on the catalogue");
|
|
|
|
if (!isWithinPortal()) {
|
|
logger.warn("OUT FROM PORTAL DETECTED RETURNING TRUE");
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
|
|
HttpSession httpSession = this.getThreadLocalRequest().getSession();
|
|
|
|
// retrieve scope per current portlet url
|
|
String scopePerCurrentUrl = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
|
|
// get key per scope
|
|
String keyPerScopeRole = CatalogueUtilMethods
|
|
.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_HIGHEST_ROLE, scopePerCurrentUrl);
|
|
String keyPerScopeOrganizations = CatalogueUtilMethods.concatenateSessionKeyScope(
|
|
SessionCatalogueAttributes.CKAN_ORGANIZATIONS_PUBLISH_KEY, scopePerCurrentUrl);
|
|
String keyPerScopeGroups = CatalogueUtilMethods
|
|
.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_GROUPS_MEMBER, scopePerCurrentUrl);
|
|
|
|
// check if this information was already into session(true means the user has at
|
|
// least in one org
|
|
// the role editor), false that he is just a member so he cannot publish
|
|
RolesCkanGroupOrOrg role = (RolesCkanGroupOrOrg) httpSession.getAttribute(keyPerScopeRole);
|
|
|
|
// if the attribute was already set..
|
|
if (role != null)
|
|
return !role.equals(RolesCkanGroupOrOrg.MEMBER);
|
|
else {
|
|
|
|
try {
|
|
|
|
GroupManager gm = new LiferayGroupManager();
|
|
String groupName = gm.getGroup(gm.getGroupIdFromInfrastructureScope(scopePerCurrentUrl))
|
|
.getGroupName();
|
|
|
|
// we build up also a list that keeps track of the scopes (orgs) in which the
|
|
// user has role ADMIN/EDITOR
|
|
List<OrganizationBean> orgsInWhichAtLeastEditorRole = new ArrayList<OrganizationBean>();
|
|
String gatewayURL = GenericUtils.getGatewayClientHostname(getThreadLocalRequest());
|
|
logger.info("The Gateway URL is: " + gatewayURL);
|
|
role = CatalogueRoleManager.getHighestRole(scopePerCurrentUrl, username, groupName, this,
|
|
orgsInWhichAtLeastEditorRole, gatewayURL);
|
|
|
|
// if he is an admin/editor preload:
|
|
// 1) organizations in which he can publish (the widget will find these info in
|
|
// session)
|
|
if (!role.equals(RolesCkanGroupOrOrg.MEMBER)) {
|
|
httpSession.setAttribute(keyPerScopeOrganizations, orgsInWhichAtLeastEditorRole);
|
|
String orgName = scopePerCurrentUrl.split("/")[scopePerCurrentUrl.split("/").length - 1];
|
|
httpSession.setAttribute(keyPerScopeGroups, getUserGroups(orgName));
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("Unable to retrieve the role information for this user. Returning FALSE", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// set role in session for this scope
|
|
httpSession.setAttribute(keyPerScopeRole, role);
|
|
|
|
logger.info("Does the user have the right to publish on the catalogue? " + role);
|
|
return !role.equals(RolesCkanGroupOrOrg.MEMBER);
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Failed to check the user's role", e);
|
|
throw new Exception("Failed to check if you are an Administrator or Editor " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if is publisher owner or admin user.
|
|
*
|
|
* @param datasetIdOrName the dataset id or name
|
|
* @return true, if is publisher owner or admin user
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public boolean isPublisherOwnerOrAdminUser(String datasetIdOrName) throws Exception {
|
|
|
|
String username = GenericUtils.getCurrentUser(getThreadLocalRequest()).getUsername();
|
|
logger.info("Checking if the user " + username + " can publish or not on the catalogue");
|
|
|
|
boolean isPublisher = isPublisherUser();
|
|
|
|
if (isPublisher) {
|
|
RolesCkanGroupOrOrg role = null;
|
|
String scopePerCurrentUrl = GenericUtils.getScopeFromClientUrl(getThreadLocalRequest());
|
|
|
|
if (!isWithinPortal()) {
|
|
role = RolesCkanGroupOrOrg.EDITOR;
|
|
logger.warn("OUT FROM PORTAL SETTING HARD-CODED ROLE " + role);
|
|
} else {
|
|
String keyPerScopeRole = CatalogueUtilMethods
|
|
.concatenateSessionKeyScope(SessionCatalogueAttributes.CKAN_HIGHEST_ROLE, scopePerCurrentUrl);
|
|
HttpSession httpSession = this.getThreadLocalRequest().getSession();
|
|
role = (RolesCkanGroupOrOrg) httpSession.getAttribute(keyPerScopeRole);
|
|
}
|
|
|
|
// if the user is an EDITOT he/she must be also the owner of the dataset
|
|
if (role.equals(RolesCkanGroupOrOrg.EDITOR)) {
|
|
logger.info("The user {} is an {}", username, RolesCkanGroupOrOrg.EDITOR);
|
|
String loggedUserEmail = GenericUtils.getCurrentUser(getThreadLocalRequest()).getEmail();
|
|
logger.debug("Logged user email: {} ", loggedUserEmail);
|
|
DataCatalogue utils = getCatalogue(scopePerCurrentUrl);
|
|
CkanDataset dataset = utils.getDataset(datasetIdOrName, username);
|
|
String datasetOwnerEmail = dataset.getAuthorEmail();
|
|
logger.debug("Dataset Owner email: {} ", datasetOwnerEmail);
|
|
|
|
if (loggedUserEmail != null && datasetOwnerEmail != null
|
|
&& datasetOwnerEmail.compareTo(loggedUserEmail) == 0) {
|
|
logger.info("The user {} is owner of the dataset id {}, returning isOwnerOrAdminUser true ",
|
|
username, dataset.getId());
|
|
return true;
|
|
}
|
|
} else if (role.equals(RolesCkanGroupOrOrg.ADMIN)) {
|
|
logger.info("The user {} is an {}", username, RolesCkanGroupOrOrg.ADMIN);
|
|
return true;
|
|
}
|
|
}
|
|
logger.info("The user {} does not have the rights to update the dataset with id {}", username, datasetIdOrName);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks if is geo JSON valid.
|
|
*
|
|
* @param geoJson the geo json
|
|
* @return true, if is geo JSON valid
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public boolean isGeoJSONValid(String geoJson) throws Exception {
|
|
try {
|
|
new ObjectMapper().readValue(geoJson, GeoJsonObject.class);
|
|
return true;
|
|
} catch (Exception e) {
|
|
throw new Exception("GeoJSON field with value '" + geoJson + "' seems not valid!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Purge system fields.
|
|
*
|
|
* @param extras the extras
|
|
* @return the map
|
|
*/
|
|
public static Map<String, List<String>> purgeSystemFields(Map<String, List<String>> extras) {
|
|
logger.info("Purging extras from reserved fields {} ", SYSTEM_CUSTOM_FIELDS_PREFIXES);
|
|
if (extras == null)
|
|
return null;
|
|
|
|
Map<String, List<String>> extrasPop = new HashMap<String, List<String>>(extras);
|
|
for (String key : extras.keySet()) {
|
|
List<String> list = SYSTEM_CUSTOM_FIELDS_PREFIXES.stream().filter(scf -> key.startsWith(scf))
|
|
.collect(Collectors.toList());
|
|
|
|
if (list.size() > 0)
|
|
extrasPop.remove(key);
|
|
}
|
|
|
|
logger.debug("returning purged extras {} ", extrasPop);
|
|
return extrasPop;
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the reserverd system fields.
|
|
*
|
|
* @param extras the extras
|
|
* @return the reserverd system fields
|
|
*/
|
|
public static Map<String, List<String>> getReserverdSystemFields(Map<String, List<String>> extras) {
|
|
logger.info("Reading reserved fields from extras...");
|
|
if (extras == null)
|
|
return null;
|
|
|
|
Map<String, List<String>> reserverSystemExtras = new HashMap<String, List<String>>();
|
|
for (String key : extras.keySet()) {
|
|
List<String> list = SYSTEM_CUSTOM_FIELDS_PREFIXES.stream().filter(scf -> key.startsWith(scf))
|
|
.collect(Collectors.toList());
|
|
|
|
if (list.size() > 0)
|
|
reserverSystemExtras.put(key, extras.get(key));
|
|
}
|
|
logger.debug("returning reserverd extras {} ", reserverSystemExtras);
|
|
return reserverSystemExtras;
|
|
|
|
}
|
|
|
|
/**
|
|
* Clone list.
|
|
*
|
|
* @param list the list
|
|
* @return the list
|
|
*/
|
|
public static List<MetadataFieldWrapper> cloneList(List<MetadataFieldWrapper> list) {
|
|
List<MetadataFieldWrapper> listCloned = new ArrayList<MetadataFieldWrapper>(list.size());
|
|
|
|
Function<MetadataFieldWrapper, MetadataFieldWrapper> cloneWrapper = (mfw) -> {
|
|
|
|
MetadataFieldWrapper newMfw = new MetadataFieldWrapper();
|
|
newMfw.setAsGroup(mfw.getAsGroup());
|
|
newMfw.setAsTag(mfw.getAsTag());
|
|
List<String> listValues = mfw.getCurrentValues();
|
|
if (listValues != null) {
|
|
newMfw.setCurrentValues(listValues.stream().toArray(String[]::new));
|
|
}
|
|
newMfw.setDefaultValue(mfw.getDefaultValue());
|
|
newMfw.setFieldId(mfw.getFieldId());
|
|
newMfw.setFieldName(mfw.getFieldName());
|
|
newMfw.setFieldNameFromCategory(mfw.getFieldNameFromCategory());
|
|
newMfw.setMandatory(mfw.getMandatory());
|
|
newMfw.setMaxOccurs(mfw.getMaxOccurs());
|
|
newMfw.setMultiSelection(mfw.isMultiSelection());
|
|
newMfw.setNote(mfw.getNote());
|
|
newMfw.setOwnerCategory(mfw.getOwnerCategory());
|
|
newMfw.setType(mfw.getType());
|
|
newMfw.setValidator(mfw.getValidator());
|
|
newMfw.setVocabulary(mfw.getVocabulary());
|
|
|
|
return newMfw;
|
|
|
|
};
|
|
|
|
for (MetadataFieldWrapper item : list) {
|
|
MetadataFieldWrapper cloned = cloneWrapper.apply(item);
|
|
listCloned.add(cloned);
|
|
}
|
|
return listCloned;
|
|
}
|
|
|
|
} |