ckan-metadata-publisher-widget/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/utils/WorkspaceUtils.java

473 lines
16 KiB
Java

package org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.storagehubwrapper.server.StorageHubWrapper;
import org.gcube.common.storagehubwrapper.server.tohl.Workspace;
import org.gcube.common.storagehubwrapper.shared.tohl.WorkspaceItem;
import org.gcube.common.storagehubwrapper.shared.tohl.impl.URLFile;
import org.gcube.common.storagehubwrapper.shared.tohl.items.FileItem;
import org.gcube.common.storagehubwrapper.shared.tohl.items.GCubeItem;
import org.gcube.common.storagehubwrapper.shared.tohl.items.PropertyMap;
import org.gcube.datacatalogue.utillibrary.shared.ResourceBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
/**
* The Class WorkspaceUtils.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
*
* Feb 18, 2021
*/
public class WorkspaceUtils {
//private static final org.slf4j.Logger logger = LoggerFactory.getLogger(WorkspaceUtils.class);
private static final Log logger = LogFactoryUtil.getLog(WorkspaceUtils.class);
private static final String RESOURCES_NAME_SEPARATOR = "_";
private static final String STRIP_NOT_ALPHANUMERIC = "[^A-Za-z0-9.-_]";
/**
* Checks if is within portal.
*
* @return true if you're running into the portal, false if in development
*/
public static boolean isWithinPortal() {
try {
UserLocalServiceUtil.getService();
return true;
} catch (Exception ex) {
logger.trace("Development Mode ON");
return false;
}
}
/**
* Gets the storage hub wrapper.
*
* @param request
* the request
* @param scopeGroupId
* the scope group id. If scopeGroupId is null the scope is read
* by using the request else by using the scopeGroupId
* @param user
* the user
* @return the storage hub wrapper
* @throws Exception
* the exception
*/
public static StorageHubWrapper getStorageHubWrapper(final HttpServletRequest request, String scopeGroupId,
GCubeUser user) throws Exception {
if (user == null || user.getUsername().isEmpty())
throw new Exception("Session expired");
try {
String scope;
PortalContext pContext = PortalContext.getConfiguration();
if (isWithinPortal() && scopeGroupId != null) {
scope = pContext.getCurrentScope(scopeGroupId);
logger.debug(scope + " has retrieved by using the scopeGroupId=" + scopeGroupId);
} else
scope = pContext.getCurrentScope(request);
logger.debug("Getting " + StorageHubWrapper.class.getSimpleName() + " for user: " + user.getUsername()
+ " by using the scope: " + scope);
String token = pContext.getCurrentUserToken(scope, user.getUsername());
return new StorageHubWrapper(scope, token, false, false, true);
} catch (Exception e) {
logger.error("Error during getting storageHub wrapper", e);
throw new Exception("Error on gettig the StorageHub wrapper for userId: " + user);
}
}
/**
* This method receives a folder id within the user's workspace and set the list of resources in the dataset bean to be returned.
*
* @param folderId the folder id
* @param userName the user name
* @param bean the bean
* @param workspace the workspace
* @throws Exception the exception
*/
public static void handleWorkspaceResources(String folderId, String userName,
DatasetBean bean, Workspace workspace) throws Exception {
WorkspaceItem originalFolderOrFile = workspace.getItem(folderId);
logger.debug("Item retrieved is " + originalFolderOrFile);
String title = originalFolderOrFile.getTitle() != null && !originalFolderOrFile.getTitle().isEmpty()
? originalFolderOrFile.getTitle()
: originalFolderOrFile.getName();
title = title.replaceAll(STRIP_NOT_ALPHANUMERIC, " ");
if(!originalFolderOrFile.isFolder()){
ResourceElementBean resource = new ResourceElementBean();
resource.setDescription(originalFolderOrFile.getDescription());
resource.setFolder(false);
resource.setEditableName(originalFolderOrFile.getName());
resource.setName(originalFolderOrFile.getName());
resource.setOriginalIdInWorkspace(folderId);
bean.setResourceRoot(resource);
bean.setTitle(title);
bean.setDescription(originalFolderOrFile.getDescription());
}else{
String onlyAlphanumericTitle = title;
bean.setTitle(onlyAlphanumericTitle);
bean.setDescription(originalFolderOrFile.getDescription());
// Create the folder in the catalogue
Map<String, String> folderItems = getGcubeItemProperties(originalFolderOrFile);
if(folderItems != null){
// transform this properties
Map<String, List<String>> tempItems = new HashMap<String, List<String>>(folderItems.size());
Iterator<Entry<String, String>> iterator = folderItems.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<java.lang.String, java.lang.String> entry = (Map.Entry<java.lang.String, java.lang.String>) iterator
.next();
tempItems.put(entry.getKey(), Arrays.asList(entry.getValue()));
}
bean.setCustomFields(tempItems);
}
// set them into the bean
bean.setResourceRoot(WorkspaceUtils.getTreeFromFolder(folderId, workspace));
}
}
/** Gets the gcube item properties.
*
* @param item the item
* @return the gcube item properties
*/
public static Map<String, String> getGcubeItemProperties(WorkspaceItem item) {
if(item instanceof GCubeItem){
GCubeItem gItem = (GCubeItem) item;
try {
Map<String, String> properties = null;
if(gItem.getPropertyMap()!=null){
Map<String, String> map = toSimpleMap(gItem.getPropertyMap());
if(map!=null) {
properties = new HashMap<String, String>(map.size()); //TO PREVENT GWT SERIALIZATION ERROR
for (String key : map.keySet())
properties.put(key, map.get(key));
}
return properties;
}
} catch (Exception e) {
logger.error("Error in server getItemProperties: ", e);
}
}
return null;
}
/**
* To simple map.
*
* @param propertyMap the property map
* @return the map
*/
public static Map<String, String> toSimpleMap(PropertyMap propertyMap) {
if (propertyMap == null)
return null;
try {
Map<String, String> properties = null;
Map<String, Object> map = propertyMap.getValues();
if (map != null) {
properties = new HashMap<String, String>(map.size());
for (String key : map.keySet()) {
Object theValue = map.get(key);
properties.put(key, (String) theValue);
}
}
if(properties!=null)
logger.error("Converted: "+properties.size()+" property/properties");
return properties;
} catch (Exception e) {
logger.error("Error on converting a PropertyMap to simple Map<String,String>: ", e);
return null;
}
}
/**
* Returns a tree object.
*
* @param workspaceFolderId the workspace folder id
* @param workspace the workspace
* @return ResourceElementBean a tree object
* @throws Exception the exception
*/
public static ResourceElementBean getTreeFromFolder(String workspaceFolderId, Workspace workspace) throws Exception{
ResourceElementBean rootElem = new ResourceElementBean();
String pathSeparator = "/";
//String pathSeparator = ws.getPathSeparator();
WorkspaceItem initialItem = workspace.getItem(workspaceFolderId);
String fullPathBase = initialItem.getPath();
fullPathBase = fullPathBase.endsWith(pathSeparator) ? fullPathBase : fullPathBase + pathSeparator;
rootElem.setFolder(initialItem.isFolder());
rootElem.setFullPath(initialItem.getPath().replace(fullPathBase, ""));
rootElem.setName(initialItem.getName());
rootElem.setOriginalIdInWorkspace(initialItem.getId());
rootElem.setDescription(initialItem.getDescription());
extractEditableNameFromPath(rootElem, pathSeparator);
// recursive visiting
if(initialItem.isFolder())
visit(rootElem, initialItem, workspace, fullPathBase, pathSeparator);
logger.debug("Tree that is going to be returned is " + rootElem);
return rootElem;
}
/**
* Recursive visit of a workspace item.
*
* @param parent the parent
* @param initialItemWS the initial item WS
* @param workspace the ws
* @param fullPathBase the full path base
* @param pathSeparator the path separator
* @throws Exception the exception
*/
private static void visit(ResourceElementBean parent, WorkspaceItem initialItemWS, Workspace workspace, String fullPathBase, String pathSeparator) throws Exception {
//List<? extends WorkspaceItem> children = initialItemWS.getChildren();
List<? extends WorkspaceItem> children = workspace.getChildren(initialItemWS.getId());
ArrayList<ResourceElementBean> childrenInTree = new ArrayList<ResourceElementBean>(children.size());
for (WorkspaceItem item : children) {
// logger.debug("Path BEFORE REPLACE is " + item.getPath());
// logger.debug("Path AFTER REPLACE is " + item.getPath().replace(fullPathBase, ""));
// logger.debug("Name is " + item.getName());
// logger.debug("id is " + item.getId());
ResourceElementBean elem = new ResourceElementBean();
elem.setFolder(item.isFolder());
elem.setOriginalIdInWorkspace(item.getId());
elem.setFullPath(item.getPath().replace(fullPathBase, ""));
elem.setParent(parent);
elem.setName(item.getName());
elem.setDescription(item.getDescription());
extractEditableNameFromPath(elem, pathSeparator);
childrenInTree.add(elem);
logger.trace("Elem is " + elem);
if(item.isFolder())
visit(elem, item, workspace, fullPathBase, pathSeparator);
}
// add these list as child of the rootElem
parent.setChildren(childrenInTree);
}
/**
* Replaces the "/" char with a custom one and return an editable name for the user.
*
* @param rootElem the root elem
* @param pathSeparatorInWs the path separator in ws
*/
private static void extractEditableNameFromPath(ResourceElementBean rootElem, String pathSeparatorInWs) {
if(rootElem == null)
return;
String elemName = rootElem.getName();
String fullPath = rootElem.getFullPath();
logger.info("Element original is " + rootElem);
int lastIndex = rootElem.getFullPath().lastIndexOf(elemName);
fullPath = rootElem.getFullPath().substring(0, lastIndex);
fullPath = fullPath.replaceAll(pathSeparatorInWs, RESOURCES_NAME_SEPARATOR) + elemName;
rootElem.setEditableName(fullPath);
logger.info("Editable name for resource name: "+rootElem.getName()+", is: " + rootElem.getEditableName());
}
/**
* Copy into the .catalogue area folder the checked resources.
* There is no difference among a single-file-publish and a folder-publish.
*
* @param bean the bean
* @param workspace the workspace
* @param username the username
* @return the list
* @throws Exception the exception
*/
public static List<ResourceBean> toResources(DatasetBean bean, Workspace workspace, String username) throws Exception{
logger.debug("Request to copy onto catalogue area....");
List<ResourceBean> resources = new ArrayList<ResourceBean>();
ResourceElementBean rootResource = bean.getResourceRoot();
// retrieve the children
List<ResourceElementBean> resourcesToAdd = rootResource.getChildren();
// copy only the selected ones
for(ResourceElementBean resource : resourcesToAdd){
if (resource.isToBeAdded()) {
logger.debug("Resource to add is " + resource);
// ok it is a file, so copy it into the copiedFolder
WorkspaceItem wsItem = workspace.getItem(resource.getOriginalIdInWorkspace());
String mimeType = null;
if(wsItem instanceof FileItem) {
mimeType = ((FileItem)wsItem).getMimeType();
}
// check if it is an URLFile
String externalUrl = null;
try{
if(wsItem instanceof URLFile) {
URLFile urlFile = (URLFile) wsItem;
externalUrl = urlFile.getValue()!=null?urlFile.getValue().toString():null;
}
}catch(Exception e){
logger.warn("Unable to check if it is an external url file ", e);
}
String resourceURL = externalUrl;
//it is not a URLFile
if(resourceURL==null) {
//getting public link of file
URL publicLink = workspace.getPublicLinkForFile(resource.getOriginalIdInWorkspace());
if(publicLink!=null)
resourceURL = publicLink.toString();
}
resources.add(new ResourceBean(resourceURL,
resource.getEditableName(),
resource.getDescription(),
wsItem.getId(),
username,
null, // dataset id, to be set
mimeType));
}
}
return resources;
}
// //MOVED TO GCAT
// /**
// * Copy into the .catalogue area folder the checked resources.
// * There is no difference among a single-file-publish and a folder-publish.
// * @param folderId
// * @param userName
// * @param bean
// * @return
// */
// public static List<ResourceBean> copyResourcesToUserCatalogueArea(String folderOrFileId, String userName, DatasetBean bean) throws Exception{
//
// logger.debug("Request to copy onto catalogue area....");
// List<ResourceBean> resources = new ArrayList<ResourceBean>();
// WorkspaceItem copiedFolder = null;
// WorkspaceCatalogue userCatalogue = null;
// ResourceElementBean rootResource = bean.getResourceRoot();
//
// // into the .catalogue area of the user's workspace
// Workspace ws = HomeLibrary
// .getHomeManagerFactory()
// .getHomeManager()
// .getHome()
// .getWorkspace();
//
// // Retrieve the catalogue of the user
// userCatalogue = ws.getCatalogue();
//
// // get workspace item (it could be a file or a folder)
// WorkspaceItem originalItem = ws.getItem(folderOrFileId);
//
// // copy the folder in the catalogue if it is a folder, or create a new folder
// long referenceTime = System.currentTimeMillis();
// if(originalItem.isFolder()){
// copiedFolder = userCatalogue.addWorkspaceItem(folderOrFileId, userCatalogue.getId()); // add to .catalogue root area
// copiedFolder.setDescription(bean.getDescription());
// ((WorkspaceFolder)copiedFolder).rename(CatalogueUtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime);
// }
// else{
// copiedFolder = userCatalogue.createFolder(CatalogueUtilMethods.fromProductTitleToName(bean.getTitle()) + "_" + referenceTime, bean.getDescription());
// }
//
// // retrieve the children
// List<ResourceElementBean> resourcesToAdd = rootResource.getChildren();
//
// // copy only the selected ones
// for(ResourceElementBean resource : resourcesToAdd){
//
// if (resource.isToBeAdded()) {
//
// logger.debug("Resource to add is " + resource);
//
// // ok it is a file, so copy it into the copiedFolder
// WorkspaceItem copiedFile = userCatalogue.addWorkspaceItem(resource.getOriginalIdInWorkspace(), copiedFolder.getId());
//
// // name and description could have been edited
// copiedFile.setDescription(resource.getDescription());
//
// // check if it is an external url
// String externalUrl = null;
// try{
// boolean isExternalUrl = ((FolderItem)copiedFile).getFolderItemType().equals(FolderItemType.EXTERNAL_URL);
// externalUrl = isExternalUrl ? ((ExternalUrl)copiedFile).getUrl() : null;
// }catch(Exception e){
// logger.warn("Unable to check if it is an external url file ", e);
// }
//
// resources.add(new ResourceBean(
// externalUrl != null ? externalUrl : copiedFile.getPublicLink(true),
// resource.getEditableName(),
// copiedFile.getDescription(),
// copiedFile.getId(),
// userName,
// null, // dataset id, to be set
// ((FolderItem)copiedFile).getMimeType()));
//
// // postpone rename operation
// copiedFile.rename(resource.getEditableName());
// }
//
// }
// return resources;
// }
}