/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.core.storage.fedora.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import org.roda.core.data.exceptions.RequestNotValidException;
import org.roda.core.data.v2.ip.StoragePath;
import org.roda.core.storage.DefaultStoragePath;
import org.roda.core.storage.fedora.FedoraStorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Fedora related utility class
*
* @author Sébastien Leroux <sleroux@keep.pt>
* @author Hélder Silva <hsilva@keep.pt>
* @author Luis Faria <lfaria@keep.pt>
*/
public final class FedoraUtils {
private static final String FEDORA_PATH_DELIMITER = "/";
private static final Logger LOGGER = LoggerFactory.getLogger(FedoraUtils.class);
/**
* Private empty constructor
*/
private FedoraUtils() {
// do nothing
}
/**
* Creates a {@code String} version of a {@code StoragePath} for Fedora
*/
public static String storagePathToFedoraPath(StoragePath storagePath) {
return storagePath.asList().stream().map(t -> doubleURLEncode(t))
.collect(Collectors.joining(FEDORA_PATH_DELIMITER));
}
public static StoragePath fedoraPathToStoragePath(String fedoraPath) throws RequestNotValidException {
List<String> path = Arrays.asList(fedoraPath.split("/")).stream().map(t -> doubleURLDecode(t))
.collect(Collectors.toList());
return DefaultStoragePath.parse(path);
}
public static String doubleURLEncode(String origin) {
String encoded = origin;
String encoding = "UTF-8";
try {
encoded = URLEncoder.encode(encoded, encoding);
encoded = URLEncoder.encode(encoded, encoding);
} catch (UnsupportedEncodingException uee) {
LOGGER.error(uee.getMessage(), uee);
}
return encoded;
}
public static String doubleURLDecode(String origin) {
String decoded = origin;
String encoding = "UTF-8";
try {
decoded = URLDecoder.decode(decoded, encoding);
decoded = URLDecoder.decode(decoded, encoding);
} catch (UnsupportedEncodingException uee) {
LOGGER.error(uee.getMessage(), uee);
}
return decoded;
}
/**
* Method for creating a SPARQL update query using the prefix "roda:"
*
* @param action
* action to be performed
* @param subject
* subject to which the action is going to be applied
* @param predicate
* predicate without the prefix (added automatically)
* @param literal
* literal to be used
*/
public static String createSparqlUpdateQuery(String action, String subject, String predicate, String literal) {
return "PREFIX " + FedoraStorageService.RODA_PREFIX + ": <" + FedoraStorageService.RODA_NAMESPACE + "> " + action
+ " { " + subject + " " + FedoraStorageService.RODA_PREFIX + ":" + predicate + " '" + literal + "' . }";
}
/**
* Method for creating a SPARQL update query using the prefix "roda:". Query
* is built by doing the concatenation of RODA prefix/namespace declaration,
* <code>DELETE DATA</code> instruction using <code>metadataToDelete</code>
* data (if not null) and <code>INSERT DATA</code> instruction using
* <code>metadataToAdd</code> data (if not null).
*
* @param metadataToAdd
* the metadata to be added
* @param metadataToDelete
* the metadata to be deleted.
*/
public static String createSparqlUpdateQuery(Map<String, Set<String>> metadataToAdd,
Map<String, Set<String>> metadataToDelete) {
boolean hasMetadataToAdd = metadataToAdd != null && !metadataToAdd.isEmpty();
boolean hasMetadataToDelete = metadataToDelete != null && !metadataToDelete.isEmpty();
if (!hasMetadataToAdd && !hasMetadataToDelete) {
return null;
}
StringBuilder sb = new StringBuilder();
// PREFIX
sb.append("PREFIX ").append(FedoraStorageService.RODA_PREFIX).append(": <")
.append(FedoraStorageService.RODA_NAMESPACE).append(">\n");
// DELETE
if (hasMetadataToDelete) {
sb.append("DELETE { <> ");
addAllTriples(metadataToDelete, sb);
sb.append("}\n");
}
// INSERT
if (hasMetadataToAdd) {
sb.append("INSERT { <> ");
addAllTriples(metadataToAdd, sb);
sb.append("}\n");
sb.append(" WHERE {}");
}
return sb.toString();
}
private static void addAllTriples(Map<String, Set<String>> metadata, StringBuilder sb) {
Iterator<Entry<String, Set<String>>> entriesIt = metadata.entrySet().iterator();
// list of all predicate-object entries separated by a ';'
while (entriesIt.hasNext()) {
Entry<String, Set<String>> entry = entriesIt.next();
// predicate
sb.append(FedoraStorageService.RODA_PREFIX).append(":").append(entry.getKey());
// list of literals separated by ','
Iterator<String> literalsIt = entry.getValue().iterator();
while (literalsIt.hasNext()) {
String literal = literalsIt.next();
sb.append(" '").append(literal).append("'");
if (literalsIt.hasNext()) {
sb.append(" , ");
}
}
if (entriesIt.hasNext()) {
sb.append(" ; ");
}
}
}
public static StoragePath doubleURLDecode(StoragePath storagePath) {
try {
List<String> encodedPath = new ArrayList<>();
encodedPath.add(doubleURLDecode(storagePath.getContainerName()));
if (!storagePath.isFromAContainer()) {
for (String s : storagePath.getDirectoryPath()) {
encodedPath.add(doubleURLDecode(s));
}
encodedPath.add(doubleURLDecode(storagePath.getName()));
}
return DefaultStoragePath.parse(encodedPath);
} catch (RequestNotValidException rnve) {
return storagePath;
}
}
}