/**
* 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.index.utils;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.xpath.XPathExpressionException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrQuery.SortClause;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.util.DateUtil;
import org.apache.solr.handler.loader.XMLLoader;
import org.roda.core.common.MetadataFileUtils;
import org.roda.core.common.PremisV3Utils;
import org.roda.core.common.RodaUtils;
import org.roda.core.common.dips.DIPUtils;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.common.RodaConstants.DateGranularity;
import org.roda.core.data.exceptions.AuthorizationDeniedException;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.exceptions.NotFoundException;
import org.roda.core.data.exceptions.NotSupportedException;
import org.roda.core.data.exceptions.RequestNotValidException;
import org.roda.core.data.utils.JsonUtils;
import org.roda.core.data.v2.LiteRODAObject;
import org.roda.core.data.v2.common.OptionalWithCause;
import org.roda.core.data.v2.formats.Format;
import org.roda.core.data.v2.index.IndexResult;
import org.roda.core.data.v2.index.IndexRunnable;
import org.roda.core.data.v2.index.IsIndexed;
import org.roda.core.data.v2.index.facet.FacetFieldResult;
import org.roda.core.data.v2.index.facet.FacetParameter;
import org.roda.core.data.v2.index.facet.FacetParameter.SORT;
import org.roda.core.data.v2.index.facet.Facets;
import org.roda.core.data.v2.index.facet.SimpleFacetParameter;
import org.roda.core.data.v2.index.filter.AndFiltersParameters;
import org.roda.core.data.v2.index.filter.BasicSearchFilterParameter;
import org.roda.core.data.v2.index.filter.DateIntervalFilterParameter;
import org.roda.core.data.v2.index.filter.DateRangeFilterParameter;
import org.roda.core.data.v2.index.filter.EmptyKeyFilterParameter;
import org.roda.core.data.v2.index.filter.Filter;
import org.roda.core.data.v2.index.filter.FilterParameter;
import org.roda.core.data.v2.index.filter.FiltersParameters;
import org.roda.core.data.v2.index.filter.LongRangeFilterParameter;
import org.roda.core.data.v2.index.filter.NotSimpleFilterParameter;
import org.roda.core.data.v2.index.filter.OneOfManyFilterParameter;
import org.roda.core.data.v2.index.filter.OrFiltersParameters;
import org.roda.core.data.v2.index.filter.SimpleFilterParameter;
import org.roda.core.data.v2.index.select.SelectedItems;
import org.roda.core.data.v2.index.sort.SortParameter;
import org.roda.core.data.v2.index.sort.Sorter;
import org.roda.core.data.v2.index.sublist.Sublist;
import org.roda.core.data.v2.ip.AIP;
import org.roda.core.data.v2.ip.AIPLink;
import org.roda.core.data.v2.ip.AIPState;
import org.roda.core.data.v2.ip.DIP;
import org.roda.core.data.v2.ip.DIPFile;
import org.roda.core.data.v2.ip.File;
import org.roda.core.data.v2.ip.FileLink;
import org.roda.core.data.v2.ip.HasPermissionFilters;
import org.roda.core.data.v2.ip.IndexedAIP;
import org.roda.core.data.v2.ip.IndexedDIP;
import org.roda.core.data.v2.ip.IndexedFile;
import org.roda.core.data.v2.ip.IndexedRepresentation;
import org.roda.core.data.v2.ip.Permissions;
import org.roda.core.data.v2.ip.Permissions.PermissionType;
import org.roda.core.data.v2.ip.Representation;
import org.roda.core.data.v2.ip.RepresentationLink;
import org.roda.core.data.v2.ip.StoragePath;
import org.roda.core.data.v2.ip.TransferredResource;
import org.roda.core.data.v2.ip.metadata.DescriptiveMetadata;
import org.roda.core.data.v2.ip.metadata.FileFormat;
import org.roda.core.data.v2.ip.metadata.IndexedPreservationAgent;
import org.roda.core.data.v2.ip.metadata.IndexedPreservationEvent;
import org.roda.core.data.v2.ip.metadata.IndexedPreservationEvent.PreservationMetadataEventClass;
import org.roda.core.data.v2.ip.metadata.LinkingIdentifier;
import org.roda.core.data.v2.ip.metadata.OtherMetadata;
import org.roda.core.data.v2.ip.metadata.PreservationMetadata.PreservationMetadataType;
import org.roda.core.data.v2.jobs.IndexedReport;
import org.roda.core.data.v2.jobs.Job;
import org.roda.core.data.v2.jobs.Job.JOB_STATE;
import org.roda.core.data.v2.jobs.JobStats;
import org.roda.core.data.v2.jobs.PluginType;
import org.roda.core.data.v2.jobs.Report;
import org.roda.core.data.v2.jobs.Report.PluginState;
import org.roda.core.data.v2.log.LogEntry;
import org.roda.core.data.v2.log.LogEntry.LOG_ENTRY_STATE;
import org.roda.core.data.v2.log.LogEntryParameter;
import org.roda.core.data.v2.notifications.Notification;
import org.roda.core.data.v2.risks.IndexedRisk;
import org.roda.core.data.v2.risks.Risk;
import org.roda.core.data.v2.risks.RiskIncidence;
import org.roda.core.data.v2.user.Group;
import org.roda.core.data.v2.user.RODAMember;
import org.roda.core.data.v2.user.User;
import org.roda.core.model.ModelService;
import org.roda.core.model.utils.ModelUtils;
import org.roda.core.storage.Binary;
import org.roda.core.storage.Directory;
import org.roda.core.storage.StorageService;
import org.roda.core.storage.fs.FSUtils;
import org.roda.core.util.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* Utilities class related to Apache Solr
*
* @author Hélder Silva <hsilva@keep.pt>
* @author LuÃs Faria <lfaria@keep.pt>
* @author Sébastien Leroux <sleroux@keep.pt>
*/
public class SolrUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(SolrUtils.class);
private static final String DEFAULT_QUERY_PARSER_OPERATOR = "AND";
private static final Set<String> NON_REPEATABLE_FIELDS = new HashSet<>(Arrays.asList(RodaConstants.AIP_TITLE,
RodaConstants.AIP_LEVEL, RodaConstants.AIP_DATE_INITIAL, RodaConstants.AIP_DATE_FINAL));
private static Map<String, List<String>> liteFieldsForEachClass = new HashMap<>();
/** Private empty constructor */
private SolrUtils() {
// do nothing
}
/*
* Search & Retrieval
* ____________________________________________________________________________________________________________________
*/
public static <T extends IsIndexed> Long count(SolrClient index, Class<T> classToRetrieve, Filter filter)
throws GenericException, RequestNotValidException {
return find(index, classToRetrieve, filter, null, new Sublist(0, 0), new ArrayList<>()).getTotalCount();
}
public static <T extends IsIndexed> Long count(SolrClient index, Class<T> classToRetrieve, Filter filter, User user,
boolean justActive) throws GenericException, RequestNotValidException {
return find(index, classToRetrieve, filter, null, new Sublist(0, 0), null, user, justActive, new ArrayList<>())
.getTotalCount();
}
public static <T extends IsIndexed> T retrieve(SolrClient index, Class<T> classToRetrieve, String id,
List<String> fieldsToReturn) throws NotFoundException, GenericException {
if (id == null) {
throw new GenericException("Could not retrieve object from a null id");
}
T ret;
try {
SolrDocument doc = index.getById(getIndexName(classToRetrieve).get(0), id);
if (doc != null) {
ret = solrDocumentTo(classToRetrieve, doc, fieldsToReturn);
} else {
throw new NotFoundException("Could not find document " + id);
}
} catch (SolrServerException | IOException e) {
throw new GenericException("Could not retrieve object from index", e);
}
return ret;
}
public static <T extends IsIndexed> List<T> retrieve(SolrClient index, Class<T> classToRetrieve, List<String> id,
List<String> fieldsToReturn) throws NotFoundException, GenericException {
List<T> ret = new ArrayList<>();
try {
int block = RodaConstants.DEFAULT_PAGINATION_VALUE;
for (int i = 0; i < id.size(); i += block) {
List<String> subList = id.subList(i, (i + block <= id.size() ? i + block : id.size()));
SolrDocumentList docs = index.getById(getIndexName(classToRetrieve).get(0), subList);
for (SolrDocument doc : docs) {
ret.add(solrDocumentTo(classToRetrieve, doc, fieldsToReturn));
}
}
} catch (SolrServerException | IOException e) {
throw new GenericException("Could not retrieve object from index", e);
}
return ret;
}
public static <T extends IsIndexed> IndexResult<T> find(SolrClient index, Class<T> classToRetrieve, Filter filter,
Sorter sorter, Sublist sublist, List<String> fieldsToReturn) throws GenericException, RequestNotValidException {
return find(index, classToRetrieve, filter, sorter, sublist, null, fieldsToReturn);
}
public static <T extends IsIndexed> IndexResult<T> find(SolrClient index, Class<T> classToRetrieve, Filter filter,
Sorter sorter, Sublist sublist, Facets facets, List<String> fieldsToReturn)
throws GenericException, RequestNotValidException {
IndexResult<T> ret;
SolrQuery query = new SolrQuery();
query.setParam("q.op", DEFAULT_QUERY_PARSER_OPERATOR);
query.setQuery(parseFilter(filter));
query.setSorts(parseSorter(sorter));
query.setStart(sublist.getFirstElementIndex());
query.setRows(sublist.getMaximumElementCount());
if (!fieldsToReturn.isEmpty()) {
query.setFields(fieldsToReturn.toArray(new String[fieldsToReturn.size()]));
}
parseAndConfigureFacets(facets, query);
try {
QueryResponse response = index.query(getIndexName(classToRetrieve).get(0), query);
ret = queryResponseToIndexResult(response, classToRetrieve, facets, fieldsToReturn);
} catch (SolrServerException | IOException e) {
throw new GenericException("Could not query index", e);
} catch (SolrException e) {
throw new RequestNotValidException(e);
} catch (RuntimeException e) {
throw new GenericException("Unexpected exception while querying index", e);
}
return ret;
}
public static <T extends IsIndexed> List<String> getClassLiteFields(Class<T> classToRetrieve) {
List<String> ret;
if (liteFieldsForEachClass.containsKey(classToRetrieve.getName())) {
ret = liteFieldsForEachClass.get(classToRetrieve.getName());
} else {
try {
ret = classToRetrieve.newInstance().liteFields();
liteFieldsForEachClass.put(classToRetrieve.getName(), ret);
} catch (InstantiationException | IllegalAccessException e) {
LOGGER.error("Error instantiating object of type {}", classToRetrieve.getName(), e);
ret = new ArrayList<>();
}
}
return ret;
}
public static <T extends IsIndexed> IndexResult<T> find(SolrClient index, Class<T> classToRetrieve, Filter filter,
Sorter sorter, Sublist sublist, Facets facets, User user, boolean justActive, List<String> fieldsToReturn)
throws GenericException, RequestNotValidException {
IndexResult<T> ret;
SolrQuery query = new SolrQuery();
query.setParam("q.op", DEFAULT_QUERY_PARSER_OPERATOR);
query.setQuery(parseFilter(filter));
query.setSorts(parseSorter(sorter));
query.setStart(sublist.getFirstElementIndex());
query.setRows(sublist.getMaximumElementCount());
query.setFields(fieldsToReturn.toArray(new String[fieldsToReturn.size()]));
parseAndConfigureFacets(facets, query);
if (hasPermissionFilters(classToRetrieve)) {
query.addFilterQuery(getFilterQueries(user, justActive, classToRetrieve));
}
try {
QueryResponse response = index.query(getIndexName(classToRetrieve).get(0), query);
ret = queryResponseToIndexResult(response, classToRetrieve, facets, fieldsToReturn);
} catch (SolrServerException | IOException e) {
throw new GenericException("Could not query index", e);
} catch (SolrException e) {
throw new RequestNotValidException(e.getMessage());
} catch (RuntimeException e) {
throw new GenericException("Unexpected exception while querying index", e);
}
return ret;
}
/*
* "Internal" helper methods
* ____________________________________________________________________________________________________________________
*/
private static <T> T solrDocumentTo(Class<T> resultClass, SolrDocument doc, List<String> fieldsToReturn)
throws GenericException {
T ret;
if (resultClass.equals(IndexedAIP.class)) {
ret = resultClass.cast(solrDocumentToIndexedAIP(doc));
} else if (resultClass.equals(IndexedRepresentation.class) || resultClass.equals(Representation.class)) {
ret = resultClass.cast(solrDocumentToRepresentation(doc));
} else if (resultClass.equals(LogEntry.class)) {
ret = resultClass.cast(solrDocumentToLogEntry(doc, fieldsToReturn));
} else if (resultClass.equals(Report.class) || resultClass.equals(IndexedReport.class)) {
ret = resultClass.cast(solrDocumentToJobReport(doc, fieldsToReturn));
} else if (resultClass.equals(RODAMember.class) || resultClass.equals(User.class)
|| resultClass.equals(Group.class)) {
ret = resultClass.cast(solrDocumentToRodaMember(doc));
} else if (resultClass.equals(TransferredResource.class)) {
ret = resultClass.cast(solrDocumentToTransferredResource(doc));
} else if (resultClass.equals(Job.class)) {
ret = resultClass.cast(solrDocumentToJob(doc, fieldsToReturn));
} else if (resultClass.equals(Risk.class) || resultClass.equals(IndexedRisk.class)) {
ret = resultClass.cast(solrDocumentToRisk(doc));
} else if (resultClass.equals(Format.class)) {
ret = resultClass.cast(solrDocumentToFormat(doc));
} else if (resultClass.equals(Notification.class)) {
ret = resultClass.cast(solrDocumentToNotification(doc, fieldsToReturn));
} else if (resultClass.equals(RiskIncidence.class)) {
ret = resultClass.cast(solrDocumentToRiskIncidence(doc));
} else if (resultClass.equals(DIP.class) || resultClass.equals(IndexedDIP.class)) {
ret = resultClass.cast(solrDocumentToIndexedDIP(doc, fieldsToReturn));
} else if (resultClass.equals(DIPFile.class)) {
ret = resultClass.cast(solrDocumentToDIPFile(doc));
} else if (resultClass.equals(IndexedFile.class)) {
ret = resultClass.cast(solrDocumentToIndexedFile(doc));
} else if (resultClass.equals(IndexedPreservationEvent.class)) {
ret = resultClass.cast(solrDocumentToIndexedPreservationEvent(doc));
} else if (resultClass.equals(IndexedPreservationAgent.class)) {
ret = resultClass.cast(solrDocumentToIndexedPreservationAgent(doc));
} else {
throw new GenericException("Cannot find class index name: " + resultClass.getName());
}
return ret;
}
private static <T> SolrInputDocument toSolrDocument(Class<T> resultClass, T object)
throws GenericException, NotSupportedException {
SolrInputDocument ret;
if (resultClass.equals(IndexedAIP.class)) {
throw new NotSupportedException();
} else if (resultClass.equals(IndexedRepresentation.class) || resultClass.equals(Representation.class)) {
throw new NotSupportedException();
} else if (resultClass.equals(LogEntry.class)) {
ret = logEntryToSolrDocument((LogEntry) object);
} else if (resultClass.equals(Report.class) || resultClass.equals(IndexedReport.class)) {
throw new NotSupportedException();
} else if (resultClass.equals(RODAMember.class) || resultClass.equals(User.class)
|| resultClass.equals(Group.class)) {
ret = rodaMemberToSolrDocument((RODAMember) object);
} else if (resultClass.equals(TransferredResource.class)) {
ret = transferredResourceToSolrDocument((TransferredResource) object);
} else if (resultClass.equals(Job.class)) {
ret = jobToSolrDocument((Job) object);
} else if (resultClass.equals(Risk.class) || resultClass.equals(IndexedRisk.class)) {
ret = riskToSolrDocument((Risk) object, 0);
} else if (resultClass.equals(Format.class)) {
ret = formatToSolrDocument((Format) object);
} else if (resultClass.equals(Notification.class)) {
ret = notificationToSolrDocument((Notification) object);
} else if (resultClass.equals(RiskIncidence.class)) {
ret = riskIncidenceToSolrDocument((RiskIncidence) object);
} else if (resultClass.equals(DIP.class) || resultClass.equals(IndexedDIP.class)) {
ret = dipToSolrDocument((DIP) object);
} else if (resultClass.equals(IndexedFile.class) || resultClass.equals(DIPFile.class)) {
throw new NotSupportedException();
} else if (resultClass.equals(IndexedPreservationEvent.class)) {
throw new NotSupportedException();
} else if (resultClass.equals(IndexedPreservationAgent.class)) {
throw new NotSupportedException();
} else {
throw new GenericException("Cannot find class index name: " + resultClass.getName());
}
return ret;
}
public static <T extends Serializable> List<String> getIndexName(Class<T> resultClass) throws GenericException {
List<String> indexNames = new ArrayList<>();
// INFO 201608 nvieira: the first index name must be the "main" one
if (resultClass.equals(AIP.class) || resultClass.equals(IndexedAIP.class)) {
indexNames.add(RodaConstants.INDEX_AIP);
indexNames.add(RodaConstants.INDEX_REPRESENTATION);
indexNames.add(RodaConstants.INDEX_FILE);
// INFO nvieira 20170207 events should be cleared on specific plugin
} else if (resultClass.equals(Representation.class) || resultClass.equals(IndexedRepresentation.class)) {
indexNames.add(RodaConstants.INDEX_REPRESENTATION);
} else if (resultClass.equals(IndexedPreservationEvent.class)) {
indexNames.add(RodaConstants.INDEX_PRESERVATION_EVENTS);
} else if (resultClass.equals(IndexedPreservationAgent.class)) {
indexNames.add(RodaConstants.INDEX_PRESERVATION_AGENTS);
} else if (resultClass.equals(LogEntry.class)) {
indexNames.add(RodaConstants.INDEX_ACTION_LOG);
} else if (resultClass.equals(Report.class) || resultClass.equals(IndexedReport.class)) {
indexNames.add(RodaConstants.INDEX_JOB_REPORT);
} else if (resultClass.equals(User.class) || resultClass.equals(Group.class)
|| resultClass.equals(RODAMember.class)) {
indexNames.add(RodaConstants.INDEX_MEMBERS);
} else if (resultClass.equals(TransferredResource.class)) {
indexNames.add(RodaConstants.INDEX_TRANSFERRED_RESOURCE);
} else if (resultClass.equals(Job.class)) {
indexNames.add(RodaConstants.INDEX_JOB);
indexNames.add(RodaConstants.INDEX_JOB_REPORT);
} else if (resultClass.equals(IndexedFile.class) || resultClass.equals(File.class)) {
indexNames.add(RodaConstants.INDEX_FILE);
} else if (resultClass.equals(Risk.class) || resultClass.equals(IndexedRisk.class)) {
indexNames.add(RodaConstants.INDEX_RISK);
} else if (resultClass.equals(Format.class)) {
indexNames.add(RodaConstants.INDEX_FORMAT);
} else if (resultClass.equals(Notification.class)) {
indexNames.add(RodaConstants.INDEX_NOTIFICATION);
} else if (resultClass.equals(RiskIncidence.class)) {
indexNames.add(RodaConstants.INDEX_RISK_INCIDENCE);
} else if (resultClass.equals(DIP.class) || resultClass.equals(IndexedDIP.class)) {
indexNames.add(RodaConstants.INDEX_DIP);
indexNames.add(RodaConstants.INDEX_DIP_FILE);
} else if (resultClass.equals(DIPFile.class)) {
indexNames.add(RodaConstants.INDEX_DIP_FILE);
} else {
throw new GenericException("Cannot find class index name: " + resultClass.getName());
}
return indexNames;
}
private static <T> boolean hasPermissionFilters(Class<T> resultClass) throws GenericException {
return HasPermissionFilters.class.isAssignableFrom(resultClass);
}
/**
* Method that knows how to escape characters for Solr
* <p>
* <code>+ - && || ! ( ) { } [ ] ^ " ~ * ? : /</code>
* </p>
* <p>
* Note: chars <code>'*'</code> are not being escaped on purpose
* </p>
*
* @return a string with special characters escaped
*/
// FIXME perhaps && and || are not being properly escaped: see how to do it
public static String escapeSolrSpecialChars(String string) {
return string.replaceAll("([+&|!(){}\\[\\-\\]\\^\\\\~?:\"/])", "\\\\$1");
}
private static List<String> objectToListString(Object object) {
List<String> ret;
if (object == null) {
ret = new ArrayList<>();
} else if (object instanceof String) {
List<String> l = new ArrayList<>();
l.add((String) object);
return l;
} else if (object instanceof List<?>) {
List<?> l = (List<?>) object;
ret = new ArrayList<>();
for (Object o : l) {
ret.add(o.toString());
}
} else {
LOGGER.error("Could not convert Solr object to List<String> ({})", object.getClass().getName());
ret = new ArrayList<>();
}
return ret;
}
public static Integer objectToInteger(Object object, Integer defaultValue) {
Integer ret = defaultValue;
if (object != null) {
if (object instanceof Integer) {
ret = (Integer) object;
} else if (object instanceof String) {
try {
ret = Integer.parseInt((String) object);
} catch (NumberFormatException e) {
LOGGER.error("Could not convert Solr object to integer", e);
}
} else {
LOGGER.error("Could not convert Solr object to integer ({})", object.getClass().getName());
}
}
return ret;
}
public static Long objectToLong(Object object, Long defaultValue) {
Long ret = defaultValue;
if (object != null) {
if (object instanceof Long) {
ret = (Long) object;
} else if (object instanceof String) {
try {
ret = Long.parseLong((String) object);
} catch (NumberFormatException e) {
LOGGER.error("Could not convert Solr object to long", e);
}
} else {
LOGGER.error("Could not convert Solr object to long ({})", object.getClass().getName());
}
}
return ret;
}
@SuppressWarnings("unused")
private static Float objectToFloat(Object object) {
Float ret;
if (object instanceof Float) {
ret = (Float) object;
} else if (object instanceof String) {
try {
ret = Float.parseFloat((String) object);
} catch (NumberFormatException e) {
LOGGER.error("Could not convert Solr object to float", e);
ret = null;
}
} else {
LOGGER.error("Could not convert Solr object to float ({})", object.getClass().getName());
ret = null;
}
return ret;
}
private static Date objectToDate(Object object) {
Date ret;
if (object == null) {
ret = null;
} else if (object instanceof Date) {
ret = (Date) object;
} else if (object instanceof String) {
try {
LOGGER.trace("Parsing date ({}) from string", object);
ret = RodaUtils.parseDate((String) object);
} catch (ParseException e) {
LOGGER.error("Could not convert Solr object to date", e);
ret = null;
}
} else {
LOGGER.error("Could not convert Solr object to date, unsupported class: {}", object.getClass().getName());
ret = null;
}
return ret;
}
private static Boolean objectToBoolean(Object object, Boolean defaultValue) {
Boolean ret = defaultValue;
if (object != null) {
if (object instanceof Boolean) {
ret = (Boolean) object;
} else if (object instanceof String) {
ret = Boolean.parseBoolean((String) object);
} else {
LOGGER.error("Could not convert Solr object to Boolean ({})", object.getClass().getName());
}
}
return ret;
}
private static String objectToString(Object object, String defaultValue) {
String ret = defaultValue;
if (object != null) {
if (object instanceof String) {
ret = (String) object;
} else {
LOGGER.warn("Could not convert Solr object to string, unsupported class: {}", object.getClass().getName());
}
}
return ret;
}
private static <E extends Enum<E>> E objectToEnum(Object object, Class<E> enumeration, E defaultValue) {
E ret = defaultValue;
if (object != null) {
if (object instanceof String) {
String name = (String) object;
try {
ret = Enum.valueOf(enumeration, name);
} catch (IllegalArgumentException e) {
LOGGER.warn("Invalid name for enumeration: {}, name: {}", enumeration.getName(), name);
} catch (NullPointerException e) {
LOGGER.warn("Error parsing enumeration: {}, name: {}", enumeration.getName(), name);
}
} else {
LOGGER.warn("Could not convert Solr object to enumeration: {}, unsupported class: {}", enumeration.getName(),
object.getClass().getName());
}
}
return ret;
}
/**
* @deprecated use {@link #objectToString(Object, String)} instead
*/
@Deprecated
private static String objectToString(Object object) {
String ret;
if (object == null) {
ret = null;
} else if (object instanceof String) {
ret = (String) object;
} else {
LOGGER.warn("Could not convert Solr object to string, unsupported class: {}", object.getClass().getName());
ret = object.toString();
}
return ret;
}
private static <T extends Serializable> IndexResult<T> queryResponseToIndexResult(QueryResponse response,
Class<T> responseClass, Facets facets, List<String> liteFields) throws GenericException {
final SolrDocumentList docList = response.getResults();
final List<FacetFieldResult> facetResults = processFacetFields(facets, response.getFacetFields());
final long offset = docList.getStart();
final long limit = docList.size();
final long totalCount = docList.getNumFound();
final List<T> docs = new ArrayList<>();
for (SolrDocument doc : docList) {
T result = solrDocumentTo(responseClass, doc, liteFields);
docs.add(result);
}
return new IndexResult<>(offset, limit, totalCount, docs, facetResults);
}
private static List<FacetFieldResult> processFacetFields(Facets facets, List<FacetField> facetFields) {
List<FacetFieldResult> ret = new ArrayList<>();
FacetFieldResult facetResult;
if (facetFields != null) {
for (FacetField facet : facetFields) {
LOGGER.trace("facet:{} count:{}", facet.getName(), facet.getValueCount());
facetResult = new FacetFieldResult(facet.getName(), facet.getValueCount(),
facets.getParameters().get(facet.getName()).getValues());
for (Count count : facet.getValues()) {
LOGGER.trace(" value:{} value:{}", count.getName(), count.getCount());
facetResult.addFacetValue(count.getName(), count.getName(), count.getCount());
}
ret.add(facetResult);
}
}
return ret;
}
public static SolrInputDocument getDescriptiveMetadataFields(Binary binary, String metadataType,
String metadataVersion) throws GenericException {
SolrInputDocument doc;
Map<String, String> parameters = new HashMap<>();
parameters.put("prefix", RodaConstants.INDEX_OTHER_DESCRIPTIVE_DATA_PREFIX);
Reader transformationResult = RodaUtils.applyMetadataStylesheet(binary, RodaConstants.CORE_CROSSWALKS_INGEST,
metadataType, metadataVersion, parameters);
try {
XMLLoader loader = new XMLLoader();
XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(transformationResult);
boolean parsing = true;
doc = null;
while (parsing) {
int event = parser.next();
if (event == XMLStreamConstants.END_DOCUMENT) {
parser.close();
parsing = false;
} else if (event == XMLStreamConstants.START_ELEMENT) {
String currTag = parser.getLocalName();
if ("doc".equals(currTag)) {
doc = loader.readDoc(parser);
}
}
}
} catch (XMLStreamException | FactoryConfigurationError e) {
throw new GenericException("Could not process descriptive metadata binary " + binary.getStoragePath(), e);
} finally {
IOUtils.closeQuietly(transformationResult);
}
return doc == null ? new SolrInputDocument() : validateDescriptiveMetadataFields(doc);
}
private static SolrInputDocument validateDescriptiveMetadataFields(SolrInputDocument doc) {
if (doc.get(RodaConstants.AIP_DATE_INITIAL) != null) {
Object value = doc.get(RodaConstants.AIP_DATE_INITIAL).getValue();
if (value instanceof String) {
try {
Date d = DateUtil.parseDate((String) value);
doc.setField(RodaConstants.AIP_DATE_INITIAL, d);
} catch (ParseException pe) {
doc.remove(RodaConstants.AIP_DATE_INITIAL);
doc.setField(RodaConstants.AIP_DATE_INITIAL + "_txt", value);
}
}
}
if (doc.get(RodaConstants.AIP_DATE_FINAL) != null) {
Object value = doc.get(RodaConstants.AIP_DATE_FINAL).getValue();
if (value instanceof String) {
try {
Date d = DateUtil.parseDate((String) value);
doc.setField(RodaConstants.AIP_DATE_FINAL, d);
} catch (ParseException pe) {
doc.remove(RodaConstants.AIP_DATE_FINAL);
doc.setField(RodaConstants.AIP_DATE_FINAL + "_txt", value);
}
}
}
return doc;
}
/*
* Roda Filter > Apache Solr query
* ____________________________________________________________________________________________________________________
*/
public static String parseFilter(Filter filter) throws RequestNotValidException {
StringBuilder ret = new StringBuilder();
if (filter == null || filter.getParameters().isEmpty()) {
ret.append("*:*");
} else {
for (FilterParameter parameter : filter.getParameters()) {
parseFilterParameter(ret, parameter, true);
}
if (ret.length() == 0) {
ret.append("*:*");
}
}
LOGGER.trace("Converting filter {} to query {}", filter, ret);
return ret.toString();
}
private static void parseFilterParameter(StringBuilder ret, FilterParameter parameter,
boolean prefixWithANDOperatorIfBuilderNotEmpty) throws RequestNotValidException {
if (parameter instanceof SimpleFilterParameter) {
SimpleFilterParameter simplePar = (SimpleFilterParameter) parameter;
appendExactMatch(ret, simplePar.getName(), simplePar.getValue(), true, prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof OneOfManyFilterParameter) {
OneOfManyFilterParameter param = (OneOfManyFilterParameter) parameter;
appendValuesUsingOROperator(ret, param.getName(), param.getValues(), prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof BasicSearchFilterParameter) {
BasicSearchFilterParameter param = (BasicSearchFilterParameter) parameter;
appendBasicSearch(ret, param.getName(), param.getValue(), "AND", prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof EmptyKeyFilterParameter) {
EmptyKeyFilterParameter param = (EmptyKeyFilterParameter) parameter;
appendANDOperator(ret, true);
ret.append("(*:* NOT " + param.getName() + ":*)");
} else if (parameter instanceof DateRangeFilterParameter) {
DateRangeFilterParameter param = (DateRangeFilterParameter) parameter;
appendRange(ret, param.getName(), Date.class, param.getFromValue(), String.class,
processToDate(param.getToValue(), param.getGranularity(), false), prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof DateIntervalFilterParameter) {
DateIntervalFilterParameter param = (DateIntervalFilterParameter) parameter;
appendRangeInterval(ret, param.getFromName(), param.getToName(), param.getFromValue(), param.getToValue(),
param.getGranularity(), prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof LongRangeFilterParameter) {
LongRangeFilterParameter param = (LongRangeFilterParameter) parameter;
appendRange(ret, param.getName(), Long.class, param.getFromValue(), Long.class, param.getToValue(),
prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof NotSimpleFilterParameter) {
NotSimpleFilterParameter notSimplePar = (NotSimpleFilterParameter) parameter;
appendNotExactMatch(ret, notSimplePar.getName(), notSimplePar.getValue(), true,
prefixWithANDOperatorIfBuilderNotEmpty);
} else if (parameter instanceof OrFiltersParameters || parameter instanceof AndFiltersParameters) {
FiltersParameters filters = (FiltersParameters) parameter;
appendFiltersWithOperator(ret, parameter instanceof OrFiltersParameters ? "OR" : "AND", filters.getValues(),
prefixWithANDOperatorIfBuilderNotEmpty);
} else {
LOGGER.error("Unsupported filter parameter class: {}", parameter.getClass().getName());
throw new RequestNotValidException("Unsupported filter parameter class: " + parameter.getClass().getName());
}
}
private static void appendANDOperator(StringBuilder ret, boolean prefixWithANDOperatorIfBuilderNotEmpty) {
if (prefixWithANDOperatorIfBuilderNotEmpty && ret.length() > 0) {
ret.append(" AND ");
}
}
private static void appendOROperator(StringBuilder ret, boolean prefixWithOROperatorIfBuilderNotEmpty) {
if (prefixWithOROperatorIfBuilderNotEmpty && ret.length() > 0) {
ret.append(" OR ");
}
}
private static void appendExactMatch(StringBuilder ret, String key, String value, boolean appendDoubleQuotes,
boolean prefixWithANDOperatorIfBuilderNotEmpty) {
appendANDOperator(ret, prefixWithANDOperatorIfBuilderNotEmpty);
ret.append("(").append(key).append(": ");
if (appendDoubleQuotes) {
ret.append("\"");
}
ret.append(value.replaceAll("(\")", "\\\\$1"));
if (appendDoubleQuotes) {
ret.append("\"");
}
ret.append(")");
}
private static void appendValuesUsingOROperator(StringBuilder ret, String key, List<String> values,
boolean prefixWithANDOperatorIfBuilderNotEmpty) {
if (!values.isEmpty()) {
appendANDOperator(ret, prefixWithANDOperatorIfBuilderNotEmpty);
ret.append("(");
for (int i = 0; i < values.size(); i++) {
if (i != 0) {
ret.append(" OR ");
}
appendExactMatch(ret, key, values.get(i), true, false);
}
ret.append(")");
}
}
private static void appendBasicSearch(StringBuilder ret, String key, String value, String operator,
boolean prefixWithANDOperatorIfBuilderNotEmpty) {
if (StringUtils.isBlank(value)) {
appendExactMatch(ret, key, "*", false, prefixWithANDOperatorIfBuilderNotEmpty);
} else if (value.matches("^\".+\"$")) {
appendExactMatch(ret, key, value.substring(1, value.length() - 1), true, prefixWithANDOperatorIfBuilderNotEmpty);
} else {
appendWhiteSpaceTokenizedString(ret, key, value, operator, prefixWithANDOperatorIfBuilderNotEmpty);
}
}
private static void appendKeyValue(StringBuilder ret, String key, String value) {
ret.append(key).append(":").append("(").append(value).append(")");
}
private static void appendFiltersWithOperator(StringBuilder ret, String operator, List<FilterParameter> values,
boolean prefixWithANDOperatorIfBuilderNotEmpty) throws RequestNotValidException {
if (!values.isEmpty()) {
appendANDOperator(ret, prefixWithANDOperatorIfBuilderNotEmpty);
ret.append("(");
for (int i = 0; i < values.size(); i++) {
if (i != 0) {
ret.append(" ").append(operator).append(" ");
}
parseFilterParameter(ret, values.get(i), false);
}
ret.append(")");
}
}
private static void appendWhiteSpaceTokenizedString(StringBuilder ret, String key, String value, String operator,
boolean prefixWithANDOperatorIfBuilderNotEmpty) {
appendANDOperator(ret, prefixWithANDOperatorIfBuilderNotEmpty);
String[] split = value.trim().split("\\s+");
ret.append("(");
for (int i = 0; i < split.length; i++) {
if (i != 0 && operator != null) {
ret.append(" " + operator + " ");
}
if (split[i].matches("(AND|OR|NOT)")) {
ret.append(key).append(": \"").append(split[i]).append("\"");
} else {
ret.append(key).append(": (").append(escapeSolrSpecialChars(split[i])).append(")");
}
}
ret.append(")");
}
private static <T extends Serializable, T1 extends Serializable> void appendRange(StringBuilder ret, String key,
Class<T> fromClass, T fromValue, Class<T1> toClass, T1 toValue, boolean prefixWithANDOperatorIfBuilderNotEmpty) {
if (fromValue != null || toValue != null) {
appendANDOperator(ret, prefixWithANDOperatorIfBuilderNotEmpty);
ret.append("(").append(key).append(":[");
generateRangeValue(ret, fromClass, fromValue);
ret.append(" TO ");
generateRangeValue(ret, toClass, toValue);
ret.append("])");
}
}
private static <T extends Serializable> void generateRangeValue(StringBuilder ret, Class<T> valueClass, T value) {
if (value != null) {
if (valueClass.equals(Date.class)) {
String date = DateUtil.getThreadLocalDateFormat().format(Date.class.cast(value));
LOGGER.trace("Appending date value \"{}\" to range", date);
ret.append(date);
} else if (valueClass.equals(Long.class)) {
ret.append(Long.class.cast(value));
} else if (valueClass.equals(String.class)) {
ret.append(String.class.cast(value));
} else {
LOGGER.error("Cannot process range of the type {}", valueClass);
}
} else {
ret.append("*");
}
}
private static void appendRangeInterval(StringBuilder ret, String fromKey, String toKey, Date fromValue, Date toValue,
DateGranularity granularity, boolean prefixWithANDOperatorIfBuilderNotEmpty) {
if (fromValue != null || toValue != null) {
appendANDOperator(ret, prefixWithANDOperatorIfBuilderNotEmpty);
ret.append("(");
ret.append(fromKey).append(":[");
ret.append(processFromDate(fromValue));
ret.append(" TO ");
ret.append(processToDate(toValue, granularity));
ret.append("]").append(" OR ");
ret.append(toKey).append(":[");
ret.append(processFromDate(fromValue));
ret.append(" TO ");
ret.append(processToDate(toValue, granularity));
ret.append("]");
if (fromValue != null && toValue != null) {
ret.append(" OR ").append("(").append(fromKey).append(":[* TO ").append(processToDate(fromValue, granularity))
.append("]");
ret.append(" AND ").append(toKey).append(":[").append(processFromDate(toValue)).append(" TO *]").append(")");
}
ret.append(")");
}
}
private static String processFromDate(Date fromValue) {
final String ret;
if (fromValue != null) {
return DateUtil.getThreadLocalDateFormat().format(fromValue);
} else {
ret = "*";
}
return ret;
}
private static String processToDate(Date toValue, DateGranularity granularity) {
return processToDate(toValue, granularity, true);
}
private static String processToDate(Date toValue, DateGranularity granularity, boolean returnAsteriskOnNull) {
final String ret;
StringBuilder sb = new StringBuilder();
if (toValue != null) {
sb.append(DateUtil.getThreadLocalDateFormat().format(toValue));
switch (granularity) {
case YEAR:
sb.append("+1YEAR-1MILLISECOND");
break;
case MONTH:
sb.append("+1MONTH-1MILLISECOND");
break;
case DAY:
sb.append("+1DAY-1MILLISECOND");
break;
case HOUR:
sb.append("+1HOUR-1MILLISECOND");
break;
case MINUTE:
sb.append("+1MINUTE-1MILLISECOND");
break;
case SECOND:
sb.append("+1SECOND-1MILLISECOND");
break;
default:
// do nothing
break;
}
ret = sb.toString();
} else {
ret = returnAsteriskOnNull ? "*" : null;
}
return ret;
}
private static void appendNotExactMatch(StringBuilder ret, String key, String value, boolean appendDoubleQuotes,
boolean prefixWithANDOperatorIfBuilderNotEmpty) {
appendExactMatch(ret, "*:* -" + key, value, appendDoubleQuotes, prefixWithANDOperatorIfBuilderNotEmpty);
}
public static String getLastScanDate(Date scanDate) {
return DateUtil.getThreadLocalDateFormat().format(scanDate);
}
/*
* Roda Sorter > Apache Solr Sort clauses
* ____________________________________________________________________________________________________________________
*/
public static List<SortClause> parseSorter(Sorter sorter) {
List<SortClause> ret = new ArrayList<>();
if (sorter != null) {
for (SortParameter sortParameter : sorter.getParameters()) {
ret.add(new SortClause(sortParameter.getName(), sortParameter.isDescending() ? ORDER.desc : ORDER.asc));
}
}
return ret;
}
/*
* Roda Facets > Apache Solr Facets
* ____________________________________________________________________________________________________________________
*/
private static void parseAndConfigureFacets(Facets facets, SolrQuery query) {
if (facets != null) {
query.setFacetSort(getSolrFacetParameterSortValue(FacetParameter.DEFAULT_SORT));
if (!"".equals(facets.getQuery())) {
query.addFacetQuery(facets.getQuery());
}
StringBuilder filterQuery = new StringBuilder();
for (Entry<String, FacetParameter> parameter : facets.getParameters().entrySet()) {
FacetParameter facetParameter = parameter.getValue();
setSolrFacetParameterSort(query, facetParameter);
if (facetParameter instanceof SimpleFacetParameter) {
setQueryFacetParameter(query, (SimpleFacetParameter) facetParameter);
appendValuesUsingOROperator(filterQuery, facetParameter.getName(),
((SimpleFacetParameter) facetParameter).getValues(), true);
} else {
LOGGER.error("Unsupported facet parameter class: {}", facetParameter.getClass().getName());
}
}
if (filterQuery.length() > 0) {
query.addFilterQuery(filterQuery.toString());
LOGGER.trace("Query after defining facets: {}", query);
}
}
}
private static void setSolrFacetParameterSort(SolrQuery query, FacetParameter facetParameter) {
if (FacetParameter.DEFAULT_SORT != facetParameter.getSort()) {
query.add(String.format("f.%s.facet.sort", facetParameter.getName()),
getSolrFacetParameterSortValue(facetParameter.getSort()));
}
}
private static String getSolrFacetParameterSortValue(SORT facetSort) {
return facetSort == SORT.INDEX ? FacetParams.FACET_SORT_INDEX : FacetParams.FACET_SORT_COUNT;
}
private static void setQueryFacetParameter(SolrQuery query, SimpleFacetParameter facetParameter) {
query.addFacetField(facetParameter.getName());
query.add(String.format("f.%s.facet.mincount", facetParameter.getName()),
String.valueOf(facetParameter.getMinCount()));
query.add(String.format("f.%s.facet.limit", facetParameter.getName()), String.valueOf(facetParameter.getLimit()));
}
/*
* Roda user > Apache Solr filter query
* ____________________________________________________________________________________________________________________
*/
private static <T extends IsIndexed> String getFilterQueries(User user, boolean justActive,
Class<T> classToRetrieve) {
StringBuilder fq = new StringBuilder();
// TODO find a better way to define admin super powers
if (user != null && !RodaConstants.ADMIN.equals(user.getName())) {
fq.append("(");
String usersKey = RodaConstants.INDEX_PERMISSION_USERS_PREFIX + PermissionType.READ;
appendExactMatch(fq, usersKey, user.getId(), true, false);
String groupsKey = RodaConstants.INDEX_PERMISSION_GROUPS_PREFIX + PermissionType.READ;
appendValuesUsingOROperatorForQuery(fq, groupsKey, new ArrayList<>(user.getGroups()), true);
fq.append(")");
}
if (justActive && !IndexedDIP.class.equals(classToRetrieve) && !DIPFile.class.equals(classToRetrieve)) {
appendExactMatch(fq, RodaConstants.STATE, AIPState.ACTIVE.toString(), true, true);
}
return fq.toString();
}
private static void appendValuesUsingOROperatorForQuery(StringBuilder ret, String key, List<String> values,
boolean prependWithOrIfNeeded) {
if (!values.isEmpty()) {
if (prependWithOrIfNeeded) {
appendOROperator(ret, true);
} else {
appendANDOperator(ret, true);
}
ret.append("(");
for (int i = 0; i < values.size(); i++) {
if (i != 0) {
ret.append(" OR ");
}
appendExactMatch(ret, key, values.get(i), true, false);
}
ret.append(")");
}
}
/*
* Apache Solr helper methods
* ____________________________________________________________________________________________________________________
*/
private static void commit(SolrClient index, String... collections) {
boolean waitFlush = false;
boolean waitSearcher = true;
boolean softCommit = true;
for (String collection : collections) {
try {
index.commit(collection, waitFlush, waitSearcher, softCommit);
} catch (SolrServerException | IOException e) {
LOGGER.error("Error commiting into collection: {}", collection, e);
}
}
}
public static void commit(SolrClient index, List<Class<? extends IsIndexed>> resultClasses) throws GenericException {
List<String> collections = new ArrayList<>();
for (Class<? extends IsIndexed> resultClass : resultClasses) {
collections.add(getIndexName(resultClass).get(0));
}
commit(index, collections.toArray(new String[] {}));
}
@SafeVarargs
public static void commit(SolrClient index, Class<? extends IsIndexed>... resultClasses) throws GenericException {
commit(index, Arrays.asList(resultClasses));
}
public static <T extends IsIndexed> void create(SolrClient index, Class<T> classToCreate, T instance)
throws GenericException {
try {
index.add(getIndexName(classToCreate).get(0), toSolrDocument(classToCreate, instance));
} catch (SolrServerException | IOException | NotSupportedException e) {
throw new GenericException("Error adding instance to index", e);
}
}
/*
* Crosswalks: RODA Objects <-> Apache Solr documents
* ____________________________________________________________________________________________________________________
*/
public static IndexedAIP solrDocumentToIndexedAIP(SolrDocument doc) {
final String id = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
AIPState state = null;
if (doc.containsKey(RodaConstants.STATE)) {
state = AIPState.valueOf(objectToString(doc.get(RodaConstants.STATE), AIPState.getDefault().toString()));
}
final String parentId = objectToString(doc.get(RodaConstants.AIP_PARENT_ID), null);
final List<String> ingestSIPIds = objectToListString(doc.get(RodaConstants.INGEST_SIP_IDS));
final String ingestJobId = objectToString(doc.get(RodaConstants.INGEST_JOB_ID), "");
final List<String> ingestUpdateJobIds = objectToListString(doc.get(RodaConstants.INGEST_UPDATE_JOB_IDS));
final List<String> ancestors = objectToListString(doc.get(RodaConstants.AIP_ANCESTORS));
final List<String> levels = objectToListString(doc.get(RodaConstants.AIP_LEVEL));
final List<String> titles = objectToListString(doc.get(RodaConstants.AIP_TITLE));
final List<String> descriptions = objectToListString(doc.get(RodaConstants.AIP_DESCRIPTION));
final Date dateInitial = objectToDate(doc.get(RodaConstants.AIP_DATE_INITIAL));
final Date dateFinal = objectToDate(doc.get(RodaConstants.AIP_DATE_FINAL));
final Long numberOfSubmissionFiles = objectToLong(doc.get(RodaConstants.AIP_NUMBER_OF_SUBMISSION_FILES), 0L);
final Long numberOfDocumentationFiles = objectToLong(doc.get(RodaConstants.AIP_NUMBER_OF_DOCUMENTATION_FILES), 0L);
final Long numberOfSchemaFiles = objectToLong(doc.get(RodaConstants.AIP_NUMBER_OF_SCHEMA_FILES), 0L);
final Boolean hasRepresentations = objectToBoolean(doc.get(RodaConstants.AIP_HAS_REPRESENTATIONS), Boolean.FALSE);
final Boolean ghost = objectToBoolean(doc.get(RodaConstants.AIP_GHOST), Boolean.FALSE);
Permissions permissions = getPermissions(doc);
final String title = titles.isEmpty() ? null : titles.get(0);
final String description = descriptions.isEmpty() ? null : descriptions.get(0);
String level;
if (ghost) {
level = RodaConstants.AIP_GHOST;
} else {
level = levels.isEmpty() ? null : levels.get(0);
}
return new IndexedAIP(id, state, level, title, dateInitial, dateFinal, description, parentId, ancestors,
permissions, numberOfSubmissionFiles, numberOfDocumentationFiles, numberOfSchemaFiles, hasRepresentations, ghost)
.setIngestSIPIds(ingestSIPIds).setIngestJobId(ingestJobId).setIngestUpdateJobIds(ingestUpdateJobIds);
}
public static SolrInputDocument aipToSolrInputDocument(AIP aip, List<String> ancestors, ModelService model,
boolean safemode)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
SolrInputDocument ret = new SolrInputDocument();
ret.addField(RodaConstants.INDEX_UUID, aip.getId());
ret.addField(RodaConstants.AIP_ID, aip.getId());
ret.addField(RodaConstants.AIP_PARENT_ID, aip.getParentId());
ret.addField(RodaConstants.STATE, aip.getState().toString());
ret.addField(RodaConstants.INGEST_SIP_IDS, aip.getIngestSIPIds());
ret.addField(RodaConstants.INGEST_JOB_ID, aip.getIngestJobId());
ret.addField(RodaConstants.INGEST_UPDATE_JOB_IDS, aip.getIngestUpdateJobIds());
ret.addField(RodaConstants.AIP_ANCESTORS, ancestors);
List<String> descriptiveMetadataIds = aip.getDescriptiveMetadata().stream().map(dm -> dm.getId())
.collect(Collectors.toList());
ret.addField(RodaConstants.AIP_DESCRIPTIVE_METADATA_ID, descriptiveMetadataIds);
List<String> representationIds = aip.getRepresentations().stream().map(r -> r.getId()).collect(Collectors.toList());
ret.addField(RodaConstants.AIP_REPRESENTATION_ID, representationIds);
ret.addField(RodaConstants.AIP_HAS_REPRESENTATIONS, !representationIds.isEmpty());
setPermissions(aip.getPermissions(), ret);
ret.addField(RodaConstants.AIP_GHOST, aip.getGhost() != null ? aip.getGhost() : false);
if (!safemode) {
// guarding against repeated fields
Set<String> usedNonRepeatableFields = new HashSet<>();
for (DescriptiveMetadata metadata : aip.getDescriptiveMetadata()) {
StoragePath storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aip.getId(), metadata.getId());
Binary binary = model.getStorage().getBinary(storagePath);
try {
SolrInputDocument fields = getDescriptiveMetadataFields(binary, metadata.getType(), metadata.getVersion());
for (SolrInputField field : fields) {
if (NON_REPEATABLE_FIELDS.contains(field.getName())) {
boolean added = usedNonRepeatableFields.add(field.getName());
if (added) {
ret.addField(field.getName(), field.getValue(), field.getBoost());
}
} else {
ret.addField(field.getName(), field.getValue(), field.getBoost());
}
}
} catch (GenericException e) {
LOGGER.info("Problem processing descriptive metadata: {}", e.getMessage());
} catch (Exception e) {
LOGGER.error("Error processing descriptive metadata: {}", metadata, e);
}
}
}
// Calculate number of documentation and schema files
StorageService storage = model.getStorage();
Long numberOfSubmissionFiles;
try {
Directory submissionDirectory = model.getSubmissionDirectory(aip.getId());
numberOfSubmissionFiles = storage.countResourcesUnderDirectory(submissionDirectory.getStoragePath(), true);
} catch (NotFoundException e) {
numberOfSubmissionFiles = 0L;
}
Long numberOfDocumentationFiles;
try {
Directory documentationDirectory = model.getDocumentationDirectory(aip.getId());
numberOfDocumentationFiles = storage.countResourcesUnderDirectory(documentationDirectory.getStoragePath(), true);
} catch (NotFoundException e) {
numberOfDocumentationFiles = 0L;
}
Long numberOfSchemaFiles;
try {
Directory schemasDirectory = model.getSchemasDirectory(aip.getId());
numberOfSchemaFiles = storage.countResourcesUnderDirectory(schemasDirectory.getStoragePath(), true);
} catch (NotFoundException e) {
numberOfSchemaFiles = 0L;
}
ret.addField(RodaConstants.AIP_NUMBER_OF_SUBMISSION_FILES, numberOfSubmissionFiles);
ret.addField(RodaConstants.AIP_NUMBER_OF_DOCUMENTATION_FILES, numberOfDocumentationFiles);
ret.addField(RodaConstants.AIP_NUMBER_OF_SCHEMA_FILES, numberOfSchemaFiles);
return ret;
}
public static IndexedRepresentation solrDocumentToRepresentation(SolrDocument doc) {
final String uuid = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
final String id = objectToString(doc.get(RodaConstants.REPRESENTATION_ID), null);
final String aipId = objectToString(doc.get(RodaConstants.REPRESENTATION_AIP_ID), null);
final Boolean original = objectToBoolean(doc.get(RodaConstants.REPRESENTATION_ORIGINAL), Boolean.FALSE);
final String type = objectToString(doc.get(RodaConstants.REPRESENTATION_TYPE), null);
final Long sizeInBytes = objectToLong(doc.get(RodaConstants.REPRESENTATION_SIZE_IN_BYTES), 0L);
final Long totalNumberOfFiles = objectToLong(doc.get(RodaConstants.REPRESENTATION_NUMBER_OF_DATA_FILES), 0L);
final Long numberOfDocumentationFiles = objectToLong(
doc.get(RodaConstants.REPRESENTATION_NUMBER_OF_DOCUMENTATION_FILES), 0L);
final Long numberOfSchemaFiles = objectToLong(doc.get(RodaConstants.REPRESENTATION_NUMBER_OF_SCHEMA_FILES), 0L);
final List<String> ancestors = objectToListString(doc.get(RodaConstants.AIP_ANCESTORS));
return new IndexedRepresentation(uuid, id, aipId, Boolean.TRUE.equals(original), type, sizeInBytes,
totalNumberOfFiles, numberOfDocumentationFiles, numberOfSchemaFiles, ancestors);
}
public static SolrInputDocument representationToSolrDocument(AIP aip, Representation rep, Long sizeInBytes,
Long numberOfDataFiles, Long numberOfDocumentationFiles, Long numberOfSchemaFiles, List<String> ancestors) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, IdUtils.getRepresentationId(rep));
doc.addField(RodaConstants.REPRESENTATION_ID, rep.getId());
doc.addField(RodaConstants.REPRESENTATION_AIP_ID, rep.getAipId());
doc.addField(RodaConstants.REPRESENTATION_ORIGINAL, rep.isOriginal());
doc.addField(RodaConstants.REPRESENTATION_TYPE, rep.getType());
doc.addField(RodaConstants.REPRESENTATION_SIZE_IN_BYTES, sizeInBytes);
doc.addField(RodaConstants.REPRESENTATION_NUMBER_OF_DATA_FILES, numberOfDataFiles);
doc.addField(RodaConstants.REPRESENTATION_NUMBER_OF_DOCUMENTATION_FILES, numberOfDocumentationFiles);
doc.addField(RodaConstants.REPRESENTATION_NUMBER_OF_SCHEMA_FILES, numberOfSchemaFiles);
// indexing active state and permissions
doc.addField(RodaConstants.STATE, aip.getState().toString());
doc.addField(RodaConstants.INGEST_SIP_IDS, aip.getIngestSIPIds());
doc.addField(RodaConstants.INGEST_JOB_ID, aip.getIngestJobId());
doc.addField(RodaConstants.INGEST_UPDATE_JOB_IDS, aip.getIngestUpdateJobIds());
doc.addField(RodaConstants.REPRESENTATION_ANCESTORS, ancestors);
setPermissions(aip.getPermissions(), doc);
return doc;
}
public static SolrInputDocument fileToSolrDocument(AIP aip, File file, List<String> ancestors) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, IdUtils.getFileId(file));
List<String> path = file.getPath();
doc.addField(RodaConstants.FILE_PATH, path);
if (path != null && !path.isEmpty()) {
List<String> ancestorsPath = getFileAncestorsPath(file.getAipId(), file.getRepresentationId(), path);
if (!ancestorsPath.isEmpty()) {
doc.addField(RodaConstants.FILE_PARENT_UUID, ancestorsPath.get(ancestorsPath.size() - 1));
doc.addField(RodaConstants.FILE_ANCESTORS_PATH, ancestorsPath);
}
}
doc.addField(RodaConstants.FILE_AIP_ID, file.getAipId());
doc.addField(RodaConstants.FILE_FILE_ID, file.getId());
doc.addField(RodaConstants.FILE_REPRESENTATION_ID, file.getRepresentationId());
doc.addField(RodaConstants.FILE_REPRESENTATION_UUID,
IdUtils.getRepresentationId(file.getAipId(), file.getRepresentationId()));
doc.addField(RodaConstants.FILE_ISDIRECTORY, file.isDirectory());
// extra-fields
try {
StoragePath filePath = ModelUtils.getFileStoragePath(file);
doc.addField(RodaConstants.FILE_STORAGEPATH, FSUtils.getStoragePathAsString(filePath, false));
} catch (RequestNotValidException e) {
LOGGER.warn("Could not index file storage path", e);
}
String fileId = file.getId();
if (!file.isDirectory() && fileId.contains(".") && !fileId.startsWith(".")) {
String extension = fileId.substring(fileId.lastIndexOf('.') + 1);
doc.addField(RodaConstants.FILE_EXTENSION, extension);
}
// indexing AIP inherited info
doc.addField(RodaConstants.STATE, aip.getState().toString());
doc.addField(RodaConstants.INGEST_SIP_IDS, aip.getIngestSIPIds());
doc.addField(RodaConstants.INGEST_JOB_ID, aip.getIngestJobId());
doc.addField(RodaConstants.INGEST_UPDATE_JOB_IDS, aip.getIngestUpdateJobIds());
doc.addField(RodaConstants.FILE_ANCESTORS, ancestors);
setPermissions(aip.getPermissions(), doc);
return doc;
}
private static List<String> getFileAncestorsPath(String aipId, String representationId, List<String> path) {
List<String> parentFileDirectoryPath = new ArrayList<>();
List<String> ancestorsPath = new ArrayList<>();
parentFileDirectoryPath.addAll(path);
while (!parentFileDirectoryPath.isEmpty()) {
int lastElementIndex = parentFileDirectoryPath.size() - 1;
String parentFileId = parentFileDirectoryPath.get(lastElementIndex);
parentFileDirectoryPath.remove(lastElementIndex);
ancestorsPath.add(0, IdUtils.getFileId(aipId, representationId, parentFileDirectoryPath, parentFileId));
}
return ancestorsPath;
}
public static IndexedFile solrDocumentToIndexedFile(SolrDocument doc) {
String uuid = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
String aipId = objectToString(doc.get(RodaConstants.FILE_AIP_ID), null);
String representationId = objectToString(doc.get(RodaConstants.FILE_REPRESENTATION_ID), null);
String fileId = objectToString(doc.get(RodaConstants.FILE_FILE_ID), null);
List<String> path = objectToListString(doc.get(RodaConstants.FILE_PATH));
String representationUUID = objectToString(doc.get(RodaConstants.FILE_REPRESENTATION_UUID), null);
String parentUUID = objectToString(doc.get(RodaConstants.FILE_PARENT_UUID), null);
List<String> ancestorsPath = objectToListString(doc.get(RodaConstants.FILE_ANCESTORS_PATH));
String originalName = objectToString(doc.get(RodaConstants.FILE_ORIGINALNAME), null);
List<String> hash = objectToListString(doc.get(RodaConstants.FILE_HASH));
long size = objectToLong(doc.get(RodaConstants.FILE_SIZE), 0L);
boolean isDirectory = objectToBoolean(doc.get(RodaConstants.FILE_ISDIRECTORY), Boolean.FALSE);
String storagePath = objectToString(doc.get(RodaConstants.FILE_STORAGEPATH), null);
// format
String formatDesignationName = objectToString(doc.get(RodaConstants.FILE_FILEFORMAT), null);
String formatDesignationVersion = objectToString(doc.get(RodaConstants.FILE_FORMAT_VERSION), null);
String mimetype = objectToString(doc.get(RodaConstants.FILE_FORMAT_MIMETYPE), null);
String pronom = objectToString(doc.get(RodaConstants.FILE_PRONOM), null);
String extension = objectToString(doc.get(RodaConstants.FILE_EXTENSION), null);
// FIXME how to restore format registries
Map<String, String> formatRegistries = new HashMap<>();
// technical features
String creatingApplicationName = objectToString(doc.get(RodaConstants.FILE_CREATING_APPLICATION_NAME), null);
String creatingApplicationVersion = objectToString(doc.get(RodaConstants.FILE_CREATING_APPLICATION_VERSION), null);
String dateCreatedByApplication = objectToString(doc.get(RodaConstants.FILE_DATE_CREATED_BY_APPLICATION), null);
final List<String> ancestors = objectToListString(doc.get(RodaConstants.AIP_ANCESTORS));
// handle other properties
Map<String, List<String>> otherProperties = new HashMap<>();
for (String fieldName : doc.getFieldNames()) {
if (fieldName.endsWith("_txt")) {
List<String> otherProperty = objectToListString(doc.get(fieldName));
otherProperties.put(fieldName, otherProperty);
}
}
FileFormat fileFormat = new FileFormat(formatDesignationName, formatDesignationVersion, mimetype, pronom, extension,
formatRegistries);
return new IndexedFile(uuid, parentUUID, aipId, representationId, representationUUID, path, ancestorsPath, fileId,
fileFormat, originalName, size, isDirectory, creatingApplicationName, creatingApplicationVersion,
dateCreatedByApplication, hash, storagePath, ancestors, otherProperties);
}
public static SolrInputDocument addOtherPropertiesToIndexedFile(String prefix, OtherMetadata otherMetadataBinary,
ModelService model, SolrClient index)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException,
ParserConfigurationException, SAXException, IOException, XPathExpressionException, SolrServerException {
SolrDocument solrDocument = index.getById(RodaConstants.INDEX_FILE,
IdUtils.getFileId(otherMetadataBinary.getAipId(), otherMetadataBinary.getRepresentationId(),
otherMetadataBinary.getFileDirectoryPath(), otherMetadataBinary.getFileId()));
Binary binary = model.retrieveOtherMetadataBinary(otherMetadataBinary);
Map<String, List<String>> otherProperties = MetadataFileUtils.parseBinary(binary);
for (Map.Entry<String, List<String>> entry : otherProperties.entrySet()) {
solrDocument.setField(prefix + entry.getKey(), entry.getValue());
}
return solrDocumentToSolrInputDocument(solrDocument);
}
private static LogEntry solrDocumentToLogEntry(SolrDocument doc, List<String> fieldsToReturn) {
final String id = objectToString(doc.get(RodaConstants.LOG_ID), null);
final String actionComponent = objectToString(doc.get(RodaConstants.LOG_ACTION_COMPONENT), null);
final String actionMethod = objectToString(doc.get(RodaConstants.LOG_ACTION_METHOD), null);
final String address = objectToString(doc.get(RodaConstants.LOG_ADDRESS), null);
final Date datetime = objectToDate(doc.get(RodaConstants.LOG_DATETIME));
final long duration = objectToLong(doc.get(RodaConstants.LOG_DURATION), 0L);
final String parameters = objectToString(doc.get(RodaConstants.LOG_PARAMETERS), null);
final String relatedObjectId = objectToString(doc.get(RodaConstants.LOG_RELATED_OBJECT_ID), null);
final String username = objectToString(doc.get(RodaConstants.LOG_USERNAME), null);
LOG_ENTRY_STATE state = null;
if (doc.containsKey(RodaConstants.LOG_STATE)) {
state = LOG_ENTRY_STATE
.valueOf(objectToString(doc.get(RodaConstants.LOG_STATE), LOG_ENTRY_STATE.UNKNOWN.toString()));
}
LogEntry entry = new LogEntry();
entry.setId(id);
entry.setActionComponent(actionComponent);
entry.setActionMethod(actionMethod);
entry.setAddress(address);
entry.setDatetime(datetime);
entry.setDuration(duration);
entry.setState(state);
try {
if (fieldsToReturn.isEmpty() || fieldsToReturn.contains(RodaConstants.LOG_PARAMETERS)) {
entry.setParameters(JsonUtils.getListFromJson(parameters == null ? "" : parameters, LogEntryParameter.class));
}
} catch (GenericException e) {
LOGGER.error("Error parsing log entry parameters", e);
}
entry.setRelatedObjectID(relatedObjectId);
entry.setUsername(username);
return entry;
}
public static SolrInputDocument logEntryToSolrDocument(LogEntry logEntry) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, logEntry.getId());
doc.addField(RodaConstants.LOG_ID, logEntry.getId());
doc.addField(RodaConstants.LOG_ACTION_COMPONENT, logEntry.getActionComponent());
doc.addField(RodaConstants.LOG_ACTION_METHOD, logEntry.getActionMethod());
doc.addField(RodaConstants.LOG_ADDRESS, logEntry.getAddress());
doc.addField(RodaConstants.LOG_DATETIME, logEntry.getDatetime());
doc.addField(RodaConstants.LOG_DURATION, logEntry.getDuration());
doc.addField(RodaConstants.LOG_PARAMETERS, JsonUtils.getJsonFromObject(logEntry.getParameters()));
doc.addField(RodaConstants.LOG_RELATED_OBJECT_ID, logEntry.getRelatedObjectID());
doc.addField(RodaConstants.LOG_USERNAME, logEntry.getUsername());
doc.addField(RodaConstants.LOG_STATE, logEntry.getState().toString());
return doc;
}
public static SolrInputDocument rodaMemberToSolrDocument(RODAMember member) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, member.getId());
doc.addField(RodaConstants.MEMBERS_ID, member.getId());
doc.addField(RodaConstants.MEMBERS_IS_ACTIVE, member.isActive());
doc.addField(RodaConstants.MEMBERS_IS_USER, member.isUser());
doc.addField(RodaConstants.MEMBERS_NAME, member.getName());
if (member.getDirectRoles() != null) {
doc.addField(RodaConstants.MEMBERS_ROLES_DIRECT, new ArrayList<String>(member.getDirectRoles()));
}
if (member.getAllRoles() != null) {
doc.addField(RodaConstants.MEMBERS_ROLES_ALL, new ArrayList<String>(member.getAllRoles()));
}
if (StringUtils.isNotBlank(member.getFullName())) {
doc.addField(RodaConstants.MEMBERS_FULLNAME, member.getFullName());
}
// Add user specific fields
if (member instanceof User) {
User user = (User) member;
doc.addField(RodaConstants.MEMBERS_EMAIL, user.getEmail());
if (user.getGroups() != null) {
doc.addField(RodaConstants.MEMBERS_GROUPS, new ArrayList<String>(user.getGroups()));
}
}
// Add group specific fields
if (member instanceof Group) {
Group group = (Group) member;
if (group.getUsers() != null) {
doc.addField(RodaConstants.MEMBERS_USERS, new ArrayList<String>(group.getUsers()));
}
}
return doc;
}
private static RODAMember solrDocumentToRodaMember(SolrDocument doc) {
final String id = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
final String name = objectToString(doc.get(RodaConstants.MEMBERS_NAME), null);
final boolean isActive = objectToBoolean(doc.get(RodaConstants.MEMBERS_IS_ACTIVE), Boolean.FALSE);
final boolean isUser = objectToBoolean(doc.get(RodaConstants.MEMBERS_IS_USER), Boolean.FALSE);
final String fullName = objectToString(doc.get(RodaConstants.MEMBERS_FULLNAME), null);
final String email = objectToString(doc.get(RodaConstants.MEMBERS_EMAIL), null);
final Set<String> groups = new HashSet<>(objectToListString(doc.get(RodaConstants.MEMBERS_GROUPS)));
final Set<String> users = new HashSet<>(objectToListString(doc.get(RodaConstants.MEMBERS_USERS)));
final Set<String> directRoles = new HashSet<>(objectToListString(doc.get(RodaConstants.MEMBERS_ROLES_DIRECT)));
final Set<String> allRoles = new HashSet<>(objectToListString(doc.get(RodaConstants.MEMBERS_ROLES_ALL)));
if (isUser) {
User user = new User();
user.setId(id);
user.setName(name);
user.setActive(isActive);
user.setFullName(fullName);
user.setDirectRoles(directRoles);
user.setAllRoles(allRoles);
user.setEmail(email);
user.setGroups(groups);
return user;
} else {
Group group = new Group();
group.setId(id);
group.setName(name);
group.setActive(isActive);
group.setFullName(fullName);
group.setDirectRoles(directRoles);
group.setAllRoles(allRoles);
group.setUsers(users);
return group;
}
}
private static IndexedPreservationEvent solrDocumentToIndexedPreservationEvent(SolrDocument doc) {
final String id = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
final String aipId = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_AIP_ID), null);
final String representationUUID = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_REPRESENTATION_UUID),
null);
final String fileUUID = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_FILE_UUID), null);
IndexedPreservationEvent ipe = new IndexedPreservationEvent();
ipe.setId(id);
ipe.setAipID(aipId);
ipe.setRepresentationUUID(representationUUID);
ipe.setFileUUID(fileUUID);
String objectClass = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_OBJECT_CLASS), null);
if (StringUtils.isNotBlank(objectClass)) {
ipe.setObjectClass(PreservationMetadataEventClass.valueOf(objectClass.toUpperCase()));
}
final Date eventDateTime = objectToDate(doc.get(RodaConstants.PRESERVATION_EVENT_DATETIME));
final String eventDetail = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_DETAIL), "");
final String eventType = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_TYPE), "");
final String eventOutcome = objectToString(doc.get(RodaConstants.PRESERVATION_EVENT_OUTCOME), "");
final List<String> agents = objectToListString(doc.get(RodaConstants.PRESERVATION_EVENT_LINKING_AGENT_IDENTIFIER));
final List<String> outcomes = objectToListString(
doc.get(RodaConstants.PRESERVATION_EVENT_LINKING_OUTCOME_OBJECT_IDENTIFIER));
final List<String> sources = objectToListString(
doc.get(RodaConstants.PRESERVATION_EVENT_LINKING_SOURCE_OBJECT_IDENTIFIER));
ipe.setEventDateTime(eventDateTime);
ipe.setEventDetail(eventDetail);
ipe.setEventType(eventType);
ipe.setEventOutcome(eventOutcome);
try {
List<LinkingIdentifier> ids = new ArrayList<>();
for (String source : sources) {
ids.add(JsonUtils.getObjectFromJson(source, LinkingIdentifier.class));
}
ipe.setSourcesObjectIds(ids);
} catch (GenericException | RuntimeException e) {
LOGGER.error("Error setting event linking source", e);
}
try {
List<LinkingIdentifier> ids = new ArrayList<>();
for (String outcome : outcomes) {
ids.add(JsonUtils.getObjectFromJson(outcome, LinkingIdentifier.class));
}
ipe.setOutcomeObjectIds(ids);
} catch (GenericException | RuntimeException e) {
LOGGER.error("Error setting event linking outcome", e);
}
try {
List<LinkingIdentifier> ids = new ArrayList<>();
for (String agent : agents) {
ids.add(JsonUtils.getObjectFromJson(agent, LinkingIdentifier.class));
}
ipe.setLinkingAgentIds(ids);
} catch (GenericException | RuntimeException e) {
LOGGER.error("Error setting event linking agents", e);
}
return ipe;
}
private static IndexedPreservationAgent solrDocumentToIndexedPreservationAgent(SolrDocument doc) {
final String id = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
final String name = objectToString(doc.get(RodaConstants.PRESERVATION_AGENT_NAME), null);
final String type = objectToString(doc.get(RodaConstants.PRESERVATION_AGENT_TYPE), null);
final String extension = objectToString(doc.get(RodaConstants.PRESERVATION_AGENT_EXTENSION), null);
final String version = objectToString(doc.get(RodaConstants.PRESERVATION_AGENT_VERSION), null);
final String note = objectToString(doc.get(RodaConstants.PRESERVATION_AGENT_NOTE), null);
final List<String> roles = objectToListString(doc.get(RodaConstants.PRESERVATION_AGENT_ROLES));
IndexedPreservationAgent ipa = new IndexedPreservationAgent();
ipa.setId(id);
ipa.setName(name);
ipa.setType(type);
ipa.setExtension(extension);
ipa.setVersion(version);
ipa.setNote(note);
ipa.setRoles(roles);
return ipa;
}
private static TransferredResource solrDocumentToTransferredResource(SolrDocument doc) {
String uuid = objectToString(doc.get(RodaConstants.INDEX_UUID), null);
String fullPath = objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_FULLPATH), null);
String id = objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_ID), null);
String parentId = null;
String parentUUID = null;
if (doc.containsKey(RodaConstants.TRANSFERRED_RESOURCE_PARENT_ID)) {
parentId = objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_PARENT_ID), null);
parentUUID = objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_PARENT_UUID), null);
}
String relativePath = objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_RELATIVEPATH), null);
Date d = objectToDate(doc.get(RodaConstants.TRANSFERRED_RESOURCE_DATE));
if (d == null) {
LOGGER.warn("Error parsing transferred resource date. Setting date to current date.");
d = new Date();
}
boolean isFile = objectToBoolean(doc.get(RodaConstants.TRANSFERRED_RESOURCE_ISFILE), Boolean.FALSE);
long size = objectToLong(doc.get(RodaConstants.TRANSFERRED_RESOURCE_SIZE), 0L);
String name = objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_NAME), null);
List<String> ancestorsPath = objectToListString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_ANCESTORS));
Date lastScanDate = objectToDate(doc.get(RodaConstants.TRANSFERRED_RESOURCE_LAST_SCAN_DATE));
TransferredResource tr = new TransferredResource();
tr.setUUID(uuid);
tr.setFullPath(fullPath);
tr.setId(id);
tr.setCreationDate(d);
tr.setName(name);
tr.setRelativePath(relativePath);
tr.setSize(size);
tr.setParentId(parentId);
tr.setParentUUID(parentUUID);
tr.setFile(isFile);
tr.setAncestorsPaths(ancestorsPath);
tr.setLastScanDate(lastScanDate);
return tr;
}
public static SolrInputDocument transferredResourceToSolrDocument(TransferredResource resource) {
SolrInputDocument transferredResource = new SolrInputDocument();
transferredResource.addField(RodaConstants.INDEX_UUID, resource.getUUID());
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_ID, resource.getId());
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_FULLPATH, resource.getFullPath());
if (resource.getParentId() != null) {
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_PARENT_ID, resource.getParentId());
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_PARENT_UUID,
IdUtils.createUUID(resource.getParentId()));
}
if (resource.getRelativePath() != null) {
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_RELATIVEPATH, resource.getRelativePath());
}
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_DATE, resource.getCreationDate());
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_ISFILE, resource.isFile());
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_SIZE, resource.getSize());
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_NAME, resource.getName());
if (resource.getAncestorsPaths() != null && !resource.getAncestorsPaths().isEmpty()) {
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_ANCESTORS, resource.getAncestorsPaths());
}
transferredResource.addField(RodaConstants.TRANSFERRED_RESOURCE_LAST_SCAN_DATE, resource.getLastScanDate());
return transferredResource;
}
public static SolrInputDocument jobToSolrDocument(Job job) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, job.getId());
doc.addField(RodaConstants.JOB_ID, job.getId());
doc.addField(RodaConstants.JOB_NAME, job.getName());
doc.addField(RodaConstants.JOB_USERNAME, job.getUsername());
doc.addField(RodaConstants.JOB_START_DATE, job.getStartDate());
doc.addField(RodaConstants.JOB_END_DATE, job.getEndDate());
doc.addField(RodaConstants.JOB_STATE, job.getState().toString());
doc.addField(RodaConstants.JOB_STATE_DETAILS, job.getStateDetails());
JobStats jobStats = job.getJobStats();
doc.addField(RodaConstants.JOB_COMPLETION_PERCENTAGE, jobStats.getCompletionPercentage());
doc.addField(RodaConstants.JOB_SOURCE_OBJECTS_COUNT, jobStats.getSourceObjectsCount());
doc.addField(RodaConstants.JOB_SOURCE_OBJECTS_WAITING_TO_BE_PROCESSED,
jobStats.getSourceObjectsWaitingToBeProcessed());
doc.addField(RodaConstants.JOB_SOURCE_OBJECTS_BEING_PROCESSED, jobStats.getSourceObjectsBeingProcessed());
doc.addField(RodaConstants.JOB_SOURCE_OBJECTS_PROCESSED_WITH_SUCCESS,
jobStats.getSourceObjectsProcessedWithSuccess());
doc.addField(RodaConstants.JOB_SOURCE_OBJECTS_PROCESSED_WITH_FAILURE,
jobStats.getSourceObjectsProcessedWithFailure());
doc.addField(RodaConstants.JOB_OUTCOME_OBJECTS_WITH_MANUAL_INTERVENTION,
jobStats.getOutcomeObjectsWithManualIntervention());
doc.addField(RodaConstants.JOB_PLUGIN_TYPE, job.getPluginType().toString());
doc.addField(RodaConstants.JOB_PLUGIN, job.getPlugin());
doc.addField(RodaConstants.JOB_PLUGIN_PARAMETERS, JsonUtils.getJsonFromObject(job.getPluginParameters()));
doc.addField(RodaConstants.JOB_SOURCE_OBJECTS, JsonUtils.getJsonFromObject(job.getSourceObjects()));
doc.addField(RodaConstants.JOB_OUTCOME_OBJECTS_CLASS, job.getOutcomeObjectsClass());
return doc;
}
public static Job solrDocumentToJob(SolrDocument doc, List<String> fieldsToReturn) {
Job job = new Job();
job.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
job.setName(objectToString(doc.get(RodaConstants.JOB_NAME), null));
job.setUsername(objectToString(doc.get(RodaConstants.JOB_USERNAME), null));
job.setStartDate(objectToDate(doc.get(RodaConstants.JOB_START_DATE)));
job.setEndDate(objectToDate(doc.get(RodaConstants.JOB_END_DATE)));
if (doc.containsKey(RodaConstants.JOB_STATE)) {
job.setState(JOB_STATE.valueOf(objectToString(doc.get(RodaConstants.JOB_STATE), null)));
}
job.setStateDetails(objectToString(doc.get(RodaConstants.JOB_STATE_DETAILS), null));
JobStats jobStats = job.getJobStats();
jobStats.setCompletionPercentage(objectToInteger(doc.get(RodaConstants.JOB_COMPLETION_PERCENTAGE), 0));
jobStats.setSourceObjectsCount(objectToInteger(doc.get(RodaConstants.JOB_SOURCE_OBJECTS_COUNT), 0));
jobStats.setSourceObjectsWaitingToBeProcessed(
objectToInteger(doc.get(RodaConstants.JOB_SOURCE_OBJECTS_WAITING_TO_BE_PROCESSED), 0));
jobStats
.setSourceObjectsBeingProcessed(objectToInteger(doc.get(RodaConstants.JOB_SOURCE_OBJECTS_BEING_PROCESSED), 0));
jobStats.setSourceObjectsProcessedWithSuccess(
objectToInteger(doc.get(RodaConstants.JOB_SOURCE_OBJECTS_PROCESSED_WITH_SUCCESS), 0));
jobStats.setSourceObjectsProcessedWithFailure(
objectToInteger(doc.get(RodaConstants.JOB_SOURCE_OBJECTS_PROCESSED_WITH_FAILURE), 0));
jobStats.setOutcomeObjectsWithManualIntervention(
objectToInteger(doc.get(RodaConstants.JOB_OUTCOME_OBJECTS_WITH_MANUAL_INTERVENTION), 0));
if (doc.containsKey(RodaConstants.JOB_PLUGIN_TYPE)) {
job.setPluginType(PluginType.valueOf(objectToString(doc.get(RodaConstants.JOB_PLUGIN_TYPE), null)));
}
job.setPlugin(objectToString(doc.get(RodaConstants.JOB_PLUGIN), null));
if (fieldsToReturn.isEmpty() || fieldsToReturn.contains(RodaConstants.JOB_PLUGIN_PARAMETERS)) {
job.setPluginParameters(
JsonUtils.getMapFromJson(objectToString(doc.get(RodaConstants.JOB_PLUGIN_PARAMETERS), "")));
}
try {
if (fieldsToReturn.isEmpty() || fieldsToReturn.contains(RodaConstants.JOB_SOURCE_OBJECTS)) {
job.setSourceObjects(JsonUtils.getObjectFromJson(objectToString(doc.get(RodaConstants.JOB_SOURCE_OBJECTS), ""),
SelectedItems.class));
}
} catch (GenericException e) {
LOGGER.error("Error parsing report in job objects", e);
}
job.setOutcomeObjectsClass(objectToString(doc.get(RodaConstants.JOB_OUTCOME_OBJECTS_CLASS), null));
return job;
}
public static <T extends Serializable> SolrInputDocument jobReportToSolrDocument(Report jobReport, Job job,
SolrClient index) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, jobReport.getId());
doc.addField(RodaConstants.JOB_REPORT_ID, jobReport.getId());
doc.addField(RodaConstants.JOB_REPORT_JOB_ID, jobReport.getJobId());
doc.addField(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ID, jobReport.getSourceObjectId());
doc.addField(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ORIGINAL_IDS, jobReport.getSourceObjectOriginalIds());
doc.addField(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ORIGINAL_NAME, jobReport.getSourceObjectOriginalName());
doc.addField(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_ID, jobReport.getOutcomeObjectId());
doc.addField(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_STATE, jobReport.getOutcomeObjectState().toString());
doc.addField(RodaConstants.JOB_REPORT_TITLE, jobReport.getTitle());
doc.addField(RodaConstants.JOB_REPORT_DATE_CREATED, jobReport.getDateCreated());
doc.addField(RodaConstants.JOB_REPORT_DATE_UPDATED, jobReport.getDateUpdated());
doc.addField(RodaConstants.JOB_REPORT_COMPLETION_PERCENTAGE, jobReport.getCompletionPercentage());
doc.addField(RodaConstants.JOB_REPORT_STEPS_COMPLETED, jobReport.getStepsCompleted());
doc.addField(RodaConstants.JOB_REPORT_TOTAL_STEPS, jobReport.getTotalSteps());
doc.addField(RodaConstants.JOB_REPORT_PLUGIN, jobReport.getPlugin());
doc.addField(RodaConstants.JOB_REPORT_PLUGIN_NAME, jobReport.getPluginName());
doc.addField(RodaConstants.JOB_REPORT_PLUGIN_VERSION, jobReport.getPluginVersion());
doc.addField(RodaConstants.JOB_REPORT_PLUGIN_STATE, jobReport.getPluginState().toString());
doc.addField(RodaConstants.JOB_REPORT_PLUGIN_DETAILS, jobReport.getPluginDetails());
doc.addField(RodaConstants.JOB_REPORT_HTML_PLUGIN_DETAILS, jobReport.isHtmlPluginDetails());
doc.addField(RodaConstants.JOB_REPORT_REPORTS, JsonUtils.getJsonFromObject(jobReport.getReports()));
doc.addField(RodaConstants.JOB_REPORT_SOURCE_OBJECT_CLASS, jobReport.getSourceObjectClass());
doc.addField(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_CLASS, jobReport.getOutcomeObjectClass());
doc.addField(RodaConstants.JOB_REPORT_JOB_NAME, job.getName());
doc.addField(RodaConstants.JOB_REPORT_SOURCE_OBJECT_LABEL,
getObjectLabel(index, jobReport.getSourceObjectClass(), jobReport.getSourceObjectId()));
doc.addField(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_LABEL,
getObjectLabel(index, jobReport.getOutcomeObjectClass(), jobReport.getOutcomeObjectId()));
return doc;
}
private static <T extends Serializable> String getObjectLabel(SolrClient index, String className, String id) {
if (StringUtils.isNotBlank(className) && StringUtils.isNotBlank(id)) {
try {
Class<T> objectClass = (Class<T>) Class.forName(className);
if (objectClass.equals(LiteRODAObject.class)) {
return null;
}
String field = getIndexName(objectClass).get(0);
SolrDocument doc = index.getById(field, id);
if (doc != null) {
if (objectClass.equals(AIP.class)) {
return objectToString(doc.get(RodaConstants.AIP_TITLE), null);
} else if (objectClass.equals(Representation.class)) {
return objectToString(doc.get(RodaConstants.REPRESENTATION_ID), null);
} else if (objectClass.equals(File.class)) {
return objectToString(doc.get(RodaConstants.FILE_FILE_ID), null);
} else if (objectClass.equals(TransferredResource.class)) {
return objectToString(doc.get(RodaConstants.TRANSFERRED_RESOURCE_ID), null);
} else if (objectClass.equals(DIP.class)) {
return objectToString(doc.get(RodaConstants.DIP_TITLE), null);
} else if (objectClass.equals(DIPFile.class)) {
return objectToString(doc.get(RodaConstants.DIPFILE_ID), null);
} else {
return objectToString(doc.get(RodaConstants.INDEX_UUID), null);
}
}
} catch (ClassNotFoundException | GenericException | SolrServerException | IOException e) {
LOGGER.error("Could not return object label of {} {}", className, id, e);
}
}
return null;
}
private static IndexedReport solrDocumentToJobReport(SolrDocument doc, List<String> fieldsToReturn) {
IndexedReport jobReport = new IndexedReport();
jobReport.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
jobReport.setJobId(objectToString(doc.get(RodaConstants.JOB_REPORT_JOB_ID), null));
jobReport.setSourceObjectId(objectToString(doc.get(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ID), null));
jobReport.setSourceObjectClass(objectToString(doc.get(RodaConstants.JOB_REPORT_SOURCE_OBJECT_CLASS), null));
jobReport
.setSourceObjectOriginalIds(objectToListString(doc.get(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ORIGINAL_IDS)));
jobReport
.setSourceObjectOriginalName(objectToString(doc.get(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ORIGINAL_NAME), null));
jobReport.setOutcomeObjectId(objectToString(doc.get(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_ID), null));
jobReport.setOutcomeObjectClass(objectToString(doc.get(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_CLASS), null));
if (doc.containsKey(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_STATE)) {
jobReport.setOutcomeObjectState(AIPState.valueOf(
objectToString(doc.get(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_STATE), AIPState.getDefault().toString())));
}
jobReport.setTitle(objectToString(doc.get(RodaConstants.JOB_REPORT_TITLE), null));
jobReport.setDateCreated(objectToDate(doc.get(RodaConstants.JOB_REPORT_DATE_CREATED)));
jobReport.setDateUpdated(objectToDate(doc.get(RodaConstants.JOB_REPORT_DATE_UPDATED)));
jobReport.setCompletionPercentage(objectToInteger(doc.get(RodaConstants.JOB_REPORT_COMPLETION_PERCENTAGE), 0));
jobReport.setStepsCompleted(objectToInteger(doc.get(RodaConstants.JOB_REPORT_STEPS_COMPLETED), 0));
jobReport.setTotalSteps(objectToInteger(doc.get(RodaConstants.JOB_REPORT_TOTAL_STEPS), 0));
jobReport.setPlugin(objectToString(doc.get(RodaConstants.JOB_REPORT_PLUGIN), null));
jobReport.setPluginName(objectToString(doc.get(RodaConstants.JOB_REPORT_PLUGIN_NAME), null));
jobReport.setPluginVersion(objectToString(doc.get(RodaConstants.JOB_REPORT_PLUGIN_VERSION), null));
jobReport.setPluginState(PluginState.valueOf(objectToString(doc.get(RodaConstants.JOB_REPORT_PLUGIN_STATE), null)));
jobReport.setPluginDetails(objectToString(doc.get(RodaConstants.JOB_REPORT_PLUGIN_DETAILS), null));
jobReport.setHtmlPluginDetails(objectToBoolean(doc.get(RodaConstants.JOB_REPORT_HTML_PLUGIN_DETAILS), false));
try {
if (fieldsToReturn.isEmpty() || fieldsToReturn.contains(RodaConstants.JOB_REPORT_REPORTS)) {
jobReport.setReports(
JsonUtils.getListFromJson(objectToString(doc.get(RodaConstants.JOB_REPORT_REPORTS), ""), Report.class));
}
} catch (GenericException e) {
LOGGER.error("Error parsing report in job report", e);
}
jobReport.setJobName(objectToString(doc.get(RodaConstants.JOB_REPORT_JOB_NAME), null));
jobReport.setSourceObjectLabel(objectToString(doc.get(RodaConstants.JOB_REPORT_SOURCE_OBJECT_LABEL), null));
jobReport.setOutcomeObjectLabel(objectToString(doc.get(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_LABEL), null));
return jobReport;
}
public static SolrInputDocument riskToSolrDocument(Risk risk, int incidences) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, risk.getId());
doc.addField(RodaConstants.RISK_ID, risk.getId());
doc.addField(RodaConstants.RISK_NAME, risk.getName());
doc.addField(RodaConstants.RISK_DESCRIPTION, risk.getDescription());
doc.addField(RodaConstants.RISK_IDENTIFIED_ON, risk.getIdentifiedOn());
doc.addField(RodaConstants.RISK_IDENTIFIED_BY, risk.getIdentifiedBy());
doc.addField(RodaConstants.RISK_CATEGORY, risk.getCategory());
doc.addField(RodaConstants.RISK_NOTES, risk.getNotes());
doc.addField(RodaConstants.RISK_PRE_MITIGATION_PROBABILITY, risk.getPreMitigationProbability());
doc.addField(RodaConstants.RISK_PRE_MITIGATION_IMPACT, risk.getPreMitigationImpact());
doc.addField(RodaConstants.RISK_PRE_MITIGATION_SEVERITY, risk.getPreMitigationSeverity());
doc.addField(RodaConstants.RISK_PRE_MITIGATION_SEVERITY_LEVEL, risk.getPreMitigationSeverityLevel().toString());
doc.addField(RodaConstants.RISK_PRE_MITIGATION_NOTES, risk.getPreMitigationNotes());
doc.addField(RodaConstants.RISK_POST_MITIGATION_PROBABILITY, risk.getPostMitigationProbability());
doc.addField(RodaConstants.RISK_POST_MITIGATION_IMPACT, risk.getPostMitigationImpact());
doc.addField(RodaConstants.RISK_POST_MITIGATION_SEVERITY, risk.getPostMitigationSeverity());
if (risk.getPostMitigationSeverityLevel() != null) {
doc.addField(RodaConstants.RISK_POST_MITIGATION_SEVERITY_LEVEL, risk.getPostMitigationSeverityLevel().toString());
}
doc.addField(RodaConstants.RISK_CURRENT_SEVERITY_LEVEL, risk.getCurrentSeverityLevel());
doc.addField(RodaConstants.RISK_POST_MITIGATION_NOTES, risk.getPostMitigationNotes());
doc.addField(RodaConstants.RISK_MITIGATION_STRATEGY, risk.getMitigationStrategy());
doc.addField(RodaConstants.RISK_MITIGATION_OWNER_TYPE, risk.getMitigationOwnerType());
doc.addField(RodaConstants.RISK_MITIGATION_OWNER, risk.getMitigationOwner());
doc.addField(RodaConstants.RISK_MITIGATION_RELATED_EVENT_IDENTIFIER_TYPE,
risk.getMitigationRelatedEventIdentifierType());
doc.addField(RodaConstants.RISK_MITIGATION_RELATED_EVENT_IDENTIFIER_VALUE,
risk.getMitigationRelatedEventIdentifierValue());
doc.addField(RodaConstants.RISK_CREATED_ON, risk.getCreatedOn());
doc.addField(RodaConstants.RISK_CREATED_BY, risk.getCreatedBy());
doc.addField(RodaConstants.RISK_UPDATED_ON, risk.getUpdatedOn());
doc.addField(RodaConstants.RISK_UPDATED_BY, risk.getUpdatedBy());
if (risk instanceof IndexedRisk) {
doc.addField(RodaConstants.RISK_INCIDENCES_COUNT, ((IndexedRisk) risk).getIncidencesCount());
doc.addField(RodaConstants.RISK_UNMITIGATED_INCIDENCES_COUNT,
((IndexedRisk) risk).getUnmitigatedIncidencesCount());
} else {
doc.addField(RodaConstants.RISK_INCIDENCES_COUNT, incidences);
doc.addField(RodaConstants.RISK_UNMITIGATED_INCIDENCES_COUNT, incidences);
}
return doc;
}
public static IndexedRisk solrDocumentToRisk(SolrDocument doc) {
IndexedRisk risk = new IndexedRisk();
risk.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
risk.setName(objectToString(doc.get(RodaConstants.RISK_NAME), null));
risk.setDescription(objectToString(doc.get(RodaConstants.RISK_DESCRIPTION), null));
risk.setIdentifiedOn(objectToDate(doc.get(RodaConstants.RISK_IDENTIFIED_ON)));
risk.setIdentifiedBy(objectToString(doc.get(RodaConstants.RISK_IDENTIFIED_BY), null));
risk.setCategory(objectToString(doc.get(RodaConstants.RISK_CATEGORY), null));
risk.setNotes(objectToString(doc.get(RodaConstants.RISK_NOTES), null));
risk.setPreMitigationProbability(objectToInteger(doc.get(RodaConstants.RISK_PRE_MITIGATION_PROBABILITY), 0));
risk.setPreMitigationImpact(objectToInteger(doc.get(RodaConstants.RISK_PRE_MITIGATION_IMPACT), 0));
risk.setPreMitigationSeverity(objectToInteger(doc.get(RodaConstants.RISK_PRE_MITIGATION_SEVERITY), 0));
if (doc.containsKey(RodaConstants.RISK_PRE_MITIGATION_SEVERITY_LEVEL)) {
risk.setPreMitigationSeverityLevel(
objectToEnum(doc.get(RodaConstants.RISK_PRE_MITIGATION_SEVERITY_LEVEL), Risk.SEVERITY_LEVEL.class, null));
}
risk.setPreMitigationNotes(objectToString(doc.get(RodaConstants.RISK_PRE_MITIGATION_NOTES), null));
risk.setPostMitigationProbability(objectToInteger(doc.get(RodaConstants.RISK_POST_MITIGATION_PROBABILITY), 0));
risk.setPostMitigationImpact(objectToInteger(doc.get(RodaConstants.RISK_POST_MITIGATION_IMPACT), 0));
risk.setPostMitigationSeverity(objectToInteger(doc.get(RodaConstants.RISK_POST_MITIGATION_SEVERITY), 0));
if (doc.containsKey(RodaConstants.RISK_POST_MITIGATION_SEVERITY_LEVEL)) {
risk.setPostMitigationSeverityLevel(
objectToEnum(doc.get(RodaConstants.RISK_POST_MITIGATION_SEVERITY_LEVEL), Risk.SEVERITY_LEVEL.class, null));
}
risk.setPostMitigationNotes(objectToString(doc.get(RodaConstants.RISK_POST_MITIGATION_NOTES), null));
risk.setMitigationStrategy(objectToString(doc.get(RodaConstants.RISK_MITIGATION_STRATEGY), null));
risk.setMitigationOwnerType(objectToString(doc.get(RodaConstants.RISK_MITIGATION_OWNER_TYPE), null));
risk.setMitigationOwner(objectToString(doc.get(RodaConstants.RISK_MITIGATION_OWNER), null));
risk.setMitigationRelatedEventIdentifierType(
objectToString(doc.get(RodaConstants.RISK_MITIGATION_RELATED_EVENT_IDENTIFIER_TYPE), null));
risk.setMitigationRelatedEventIdentifierValue(
objectToString(doc.get(RodaConstants.RISK_MITIGATION_RELATED_EVENT_IDENTIFIER_VALUE), null));
risk.setCreatedOn(objectToDate(doc.get(RodaConstants.RISK_CREATED_ON)));
risk.setCreatedBy(objectToString(doc.get(RodaConstants.RISK_CREATED_BY), null));
risk.setUpdatedOn(objectToDate(doc.get(RodaConstants.RISK_UPDATED_ON)));
risk.setUpdatedBy(objectToString(doc.get(RodaConstants.RISK_UPDATED_BY), null));
risk.setIncidencesCount(objectToInteger(doc.get(RodaConstants.RISK_INCIDENCES_COUNT), 0));
risk.setUnmitigatedIncidencesCount(objectToInteger(doc.get(RodaConstants.RISK_UNMITIGATED_INCIDENCES_COUNT), 0));
return risk;
}
public static SolrInputDocument formatToSolrDocument(Format format) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, format.getId());
doc.addField(RodaConstants.FORMAT_ID, format.getId());
doc.addField(RodaConstants.FORMAT_NAME, format.getName());
doc.addField(RodaConstants.FORMAT_NAME_SORT, format.getName());
doc.addField(RodaConstants.FORMAT_DEFINITION, format.getDefinition());
doc.addField(RodaConstants.FORMAT_CATEGORY, format.getCategories());
doc.addField(RodaConstants.FORMAT_CATEGORY_SORT,
(format.getCategories() != null && !format.getCategories().isEmpty()) ? format.getCategories().get(0) : null);
doc.addField(RodaConstants.FORMAT_LATEST_VERSION, format.getLatestVersion());
if (format.getPopularity() != null) {
doc.addField(RodaConstants.FORMAT_POPULARITY, format.getPopularity());
}
doc.addField(RodaConstants.FORMAT_DEVELOPER, format.getDeveloper());
doc.addField(RodaConstants.FORMAT_INITIAL_RELEASE, format.getInitialRelease());
doc.addField(RodaConstants.FORMAT_STANDARD, format.getStandard());
doc.addField(RodaConstants.FORMAT_IS_OPEN_FORMAT, format.isOpenFormat());
doc.addField(RodaConstants.FORMAT_WEBSITE, format.getWebsites());
doc.addField(RodaConstants.FORMAT_PROVENANCE_INFORMATION, format.getProvenanceInformation());
doc.addField(RodaConstants.FORMAT_EXTENSIONS, format.getExtensions());
doc.addField(RodaConstants.FORMAT_MIMETYPES, format.getMimetypes());
doc.addField(RodaConstants.FORMAT_PRONOMS, format.getPronoms());
doc.addField(RodaConstants.FORMAT_UTIS, format.getUtis());
doc.addField(RodaConstants.FORMAT_ALTERNATIVE_DESIGNATIONS, format.getAlternativeDesignations());
doc.addField(RodaConstants.FORMAT_VERSIONS, format.getVersions());
return doc;
}
public static Format solrDocumentToFormat(SolrDocument doc) {
Format format = new Format();
format.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
format.setName(objectToString(doc.get(RodaConstants.FORMAT_NAME), null));
format.setDefinition(objectToString(doc.get(RodaConstants.FORMAT_DEFINITION), null));
format.setCategories(objectToListString(doc.get(RodaConstants.FORMAT_CATEGORY)));
format.setLatestVersion(objectToString(doc.get(RodaConstants.FORMAT_LATEST_VERSION), null));
format.setPopularity(objectToInteger(doc.get(RodaConstants.FORMAT_POPULARITY), null));
format.setDeveloper(objectToString(doc.get(RodaConstants.FORMAT_DEVELOPER), null));
format.setInitialRelease(objectToDate(doc.get(RodaConstants.FORMAT_INITIAL_RELEASE)));
format.setStandard(objectToString(doc.get(RodaConstants.FORMAT_STANDARD), null));
format.setOpenFormat(objectToBoolean(doc.get(RodaConstants.FORMAT_IS_OPEN_FORMAT), Boolean.FALSE));
format.setWebsites(objectToListString(doc.get(RodaConstants.FORMAT_WEBSITE)));
format.setProvenanceInformation(objectToString(doc.get(RodaConstants.FORMAT_PROVENANCE_INFORMATION), null));
format.setExtensions(objectToListString(doc.get(RodaConstants.FORMAT_EXTENSIONS)));
format.setMimetypes(objectToListString(doc.get(RodaConstants.FORMAT_MIMETYPES)));
format.setPronoms(objectToListString(doc.get(RodaConstants.FORMAT_PRONOMS)));
format.setUtis(objectToListString(doc.get(RodaConstants.FORMAT_UTIS)));
format.setAlternativeDesignations(objectToListString(doc.get(RodaConstants.FORMAT_ALTERNATIVE_DESIGNATIONS)));
format.setVersions(objectToListString(doc.get(RodaConstants.FORMAT_VERSIONS)));
return format;
}
public static SolrInputDocument notificationToSolrDocument(Notification notification) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, notification.getId());
doc.addField(RodaConstants.NOTIFICATION_ID, notification.getId());
doc.addField(RodaConstants.NOTIFICATION_SUBJECT, notification.getSubject());
doc.addField(RodaConstants.NOTIFICATION_BODY, notification.getBody());
doc.addField(RodaConstants.NOTIFICATION_SENT_ON, notification.getSentOn());
doc.addField(RodaConstants.NOTIFICATION_FROM_USER, notification.getFromUser());
doc.addField(RodaConstants.NOTIFICATION_RECIPIENT_USERS, notification.getRecipientUsers());
doc.addField(RodaConstants.NOTIFICATION_ACKNOWLEDGE_TOKEN, notification.getAcknowledgeToken());
doc.addField(RodaConstants.NOTIFICATION_IS_ACKNOWLEDGED, notification.isAcknowledged());
doc.addField(RodaConstants.NOTIFICATION_ACKNOWLEDGED_USERS,
JsonUtils.getJsonFromObject(notification.getAcknowledgedUsers()));
doc.addField(RodaConstants.NOTIFICATION_STATE, notification.getState().toString());
return doc;
}
public static Notification solrDocumentToNotification(SolrDocument doc, List<String> fieldsToReturn) {
Notification notification = new Notification();
notification.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
notification.setSubject(objectToString(doc.get(RodaConstants.NOTIFICATION_SUBJECT), null));
notification.setBody(objectToString(doc.get(RodaConstants.NOTIFICATION_BODY), null));
notification.setSentOn(objectToDate(doc.get(RodaConstants.NOTIFICATION_SENT_ON)));
notification.setFromUser(objectToString(doc.get(RodaConstants.NOTIFICATION_FROM_USER), null));
notification.setRecipientUsers(objectToListString(doc.get(RodaConstants.NOTIFICATION_RECIPIENT_USERS)));
notification.setAcknowledgeToken(objectToString(doc.get(RodaConstants.NOTIFICATION_ACKNOWLEDGE_TOKEN), null));
notification.setAcknowledged(objectToBoolean(doc.get(RodaConstants.NOTIFICATION_IS_ACKNOWLEDGED), Boolean.FALSE));
if (fieldsToReturn.isEmpty() || fieldsToReturn.contains(RodaConstants.NOTIFICATION_ACKNOWLEDGED_USERS)) {
notification.setAcknowledgedUsers(
JsonUtils.getMapFromJson(objectToString(doc.get(RodaConstants.NOTIFICATION_ACKNOWLEDGED_USERS), "")));
}
if (doc.containsKey(RodaConstants.NOTIFICATION_STATE)) {
String defaultState = Notification.NOTIFICATION_STATE.COMPLETED.toString();
notification.setState(Notification.NOTIFICATION_STATE
.valueOf(objectToString(doc.get(RodaConstants.NOTIFICATION_STATE), defaultState)));
}
return notification;
}
public static SolrInputDocument riskIncidenceToSolrDocument(RiskIncidence incidence) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, incidence.getId());
doc.addField(RodaConstants.RISK_INCIDENCE_ID, incidence.getId());
doc.addField(RodaConstants.RISK_INCIDENCE_AIP_ID, incidence.getAipId());
doc.addField(RodaConstants.RISK_INCIDENCE_REPRESENTATION_ID, incidence.getRepresentationId());
doc.addField(RodaConstants.RISK_INCIDENCE_FILE_PATH, incidence.getFilePath());
doc.addField(RodaConstants.RISK_INCIDENCE_FILE_ID, incidence.getFileId());
doc.addField(RodaConstants.RISK_INCIDENCE_OBJECT_CLASS, incidence.getObjectClass());
doc.addField(RodaConstants.RISK_INCIDENCE_RISK_ID, incidence.getRiskId());
doc.addField(RodaConstants.RISK_INCIDENCE_DESCRIPTION, incidence.getDescription());
doc.addField(RodaConstants.RISK_INCIDENCE_BYPLUGIN, incidence.isByPlugin());
doc.addField(RodaConstants.RISK_INCIDENCE_STATUS, incidence.getStatus().toString());
doc.addField(RodaConstants.RISK_INCIDENCE_SEVERITY, incidence.getSeverity().toString());
doc.addField(RodaConstants.RISK_INCIDENCE_DETECTED_ON, incidence.getDetectedOn());
doc.addField(RodaConstants.RISK_INCIDENCE_DETECTED_BY, incidence.getDetectedBy());
doc.addField(RodaConstants.RISK_INCIDENCE_MITIGATED_ON, incidence.getMitigatedOn());
doc.addField(RodaConstants.RISK_INCIDENCE_MITIGATED_BY, incidence.getMitigatedBy());
doc.addField(RodaConstants.RISK_INCIDENCE_MITIGATED_DESCRIPTION, incidence.getMitigatedDescription());
doc.addField(RodaConstants.RISK_INCIDENCE_FILE_PATH_COMPUTED,
StringUtils.join(incidence.getFilePath(), RodaConstants.RISK_INCIDENCE_FILE_PATH_COMPUTED_SEPARATOR));
return doc;
}
public static RiskIncidence solrDocumentToRiskIncidence(SolrDocument doc) {
RiskIncidence incidence = new RiskIncidence();
incidence.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
incidence.setAipId(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_AIP_ID), null));
incidence.setRepresentationId(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_REPRESENTATION_ID), null));
incidence.setFilePath(objectToListString(doc.get(RodaConstants.RISK_INCIDENCE_FILE_PATH)));
incidence.setFileId(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_FILE_ID), null));
incidence.setObjectClass(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_OBJECT_CLASS), null));
incidence.setRiskId(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_RISK_ID), null));
incidence.setDescription(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_DESCRIPTION), null));
if (doc.containsKey(RodaConstants.RISK_INCIDENCE_STATUS)) {
incidence
.setStatus(RiskIncidence.INCIDENCE_STATUS.valueOf(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_STATUS),
RiskIncidence.INCIDENCE_STATUS.UNMITIGATED.toString())));
}
if (doc.containsKey(RodaConstants.RISK_INCIDENCE_SEVERITY)) {
incidence.setSeverity(Risk.SEVERITY_LEVEL.valueOf(
objectToString(doc.get(RodaConstants.RISK_INCIDENCE_SEVERITY), Risk.SEVERITY_LEVEL.MODERATE.toString())));
}
incidence.setDetectedOn(objectToDate(doc.get(RodaConstants.RISK_INCIDENCE_DETECTED_ON)));
incidence.setDetectedBy(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_DETECTED_BY), null));
incidence.setMitigatedOn(objectToDate(doc.get(RodaConstants.RISK_INCIDENCE_MITIGATED_ON)));
incidence.setMitigatedBy(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_MITIGATED_BY), null));
incidence
.setMitigatedDescription(objectToString(doc.get(RodaConstants.RISK_INCIDENCE_MITIGATED_DESCRIPTION), null));
return incidence;
}
public static SolrInputDocument dipToSolrDocument(DIP dip) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, dip.getId());
doc.addField(RodaConstants.DIP_ID, dip.getId());
doc.addField(RodaConstants.DIP_TITLE, dip.getTitle());
doc.addField(RodaConstants.DIP_DESCRIPTION, dip.getDescription());
doc.addField(RodaConstants.DIP_TYPE, dip.getType());
doc.addField(RodaConstants.DIP_DATE_CREATED, dip.getDateCreated());
doc.addField(RodaConstants.DIP_LAST_MODIFIED, dip.getLastModified());
doc.addField(RodaConstants.DIP_IS_PERMANENT, dip.getIsPermanent());
doc.addField(RodaConstants.DIP_PROPERTIES, JsonUtils.getJsonFromObject(dip.getProperties()));
doc.addField(RodaConstants.DIP_AIP_IDS, JsonUtils.getJsonFromObject(dip.getAipIds()));
doc.addField(RodaConstants.DIP_REPRESENTATION_IDS, JsonUtils.getJsonFromObject(dip.getRepresentationIds()));
doc.addField(RodaConstants.DIP_FILE_IDS, JsonUtils.getJsonFromObject(dip.getFileIds()));
List<String> allAipUUIDs = new ArrayList<>();
List<String> allRepresentationUUIDs = new ArrayList<>();
List<String> aipUUIDs = new ArrayList<>();
for (AIPLink aip : dip.getAipIds()) {
aipUUIDs.add(aip.getAipId());
}
allAipUUIDs.addAll(aipUUIDs);
List<String> representationUUIDs = new ArrayList<>();
for (RepresentationLink rep : dip.getRepresentationIds()) {
representationUUIDs.add(IdUtils.getRepresentationId(rep));
if (!allAipUUIDs.contains(rep.getAipId())) {
allAipUUIDs.add(rep.getAipId());
}
}
allRepresentationUUIDs.addAll(representationUUIDs);
List<String> fileUUIDs = new ArrayList<>();
for (FileLink file : dip.getFileIds()) {
fileUUIDs.add(IdUtils.getFileId(file));
if (!allAipUUIDs.contains(file.getAipId())) {
allAipUUIDs.add(file.getAipId());
}
String repUUID = IdUtils.getRepresentationId(file.getAipId(), file.getRepresentationId());
if (!allRepresentationUUIDs.contains(repUUID)) {
allRepresentationUUIDs.add(repUUID);
}
}
doc.addField(RodaConstants.DIP_AIP_UUIDS, aipUUIDs);
doc.addField(RodaConstants.DIP_REPRESENTATION_UUIDS, representationUUIDs);
doc.addField(RodaConstants.DIP_FILE_UUIDS, fileUUIDs);
doc.addField(RodaConstants.DIP_ALL_AIP_UUIDS, allAipUUIDs);
doc.addField(RodaConstants.DIP_ALL_REPRESENTATION_UUIDS, allRepresentationUUIDs);
setPermissions(dip.getPermissions(), doc);
OptionalWithCause<String> openURL = DIPUtils.getCompleteOpenExternalURL(dip);
if (openURL.isPresent()) {
doc.addField(RodaConstants.DIP_OPEN_EXTERNAL_URL, openURL.get());
} else if (openURL.getCause() != null) {
LOGGER.error("Error indexing DIP open external URL", openURL.getCause());
}
return doc;
}
public static IndexedDIP solrDocumentToIndexedDIP(SolrDocument doc, List<String> fieldsToReturn) {
IndexedDIP dip = new IndexedDIP();
dip.setId(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
dip.setTitle(objectToString(doc.get(RodaConstants.DIP_TITLE), null));
dip.setDescription(objectToString(doc.get(RodaConstants.DIP_DESCRIPTION), null));
dip.setType(objectToString(doc.get(RodaConstants.DIP_TYPE), null));
dip.setDateCreated(objectToDate(doc.get(RodaConstants.DIP_DATE_CREATED)));
dip.setLastModified(objectToDate(doc.get(RodaConstants.DIP_LAST_MODIFIED)));
dip.setIsPermanent(objectToBoolean(doc.get(RodaConstants.DIP_IS_PERMANENT), Boolean.FALSE));
boolean emptyFields = fieldsToReturn.isEmpty();
if (emptyFields || fieldsToReturn.contains(RodaConstants.DIP_PROPERTIES)) {
dip.setProperties(JsonUtils.getMapFromJson(objectToString(doc.get(RodaConstants.DIP_PROPERTIES), "")));
}
try {
if (emptyFields || fieldsToReturn.contains(RodaConstants.DIP_AIP_IDS)) {
String aipIds = objectToString(doc.get(RodaConstants.DIP_AIP_IDS), null);
dip.setAipIds(JsonUtils.getListFromJson(aipIds == null ? "" : aipIds, AIPLink.class));
}
if (emptyFields || fieldsToReturn.contains(RodaConstants.DIP_REPRESENTATION_IDS)) {
String representationIds = objectToString(doc.get(RodaConstants.DIP_REPRESENTATION_IDS), null);
dip.setRepresentationIds(
JsonUtils.getListFromJson(representationIds == null ? "" : representationIds, RepresentationLink.class));
}
if (emptyFields || fieldsToReturn.contains(RodaConstants.DIP_FILE_IDS)) {
String fileIds = objectToString(doc.get(RodaConstants.DIP_FILE_IDS), null);
dip.setFileIds(JsonUtils.getListFromJson(fileIds == null ? "" : fileIds, FileLink.class));
}
} catch (GenericException e) {
LOGGER.error("Error getting related ids from DIP index");
}
dip.setPermissions(getPermissions(doc));
dip.setOpenExternalURL(objectToString(doc.get(RodaConstants.DIP_OPEN_EXTERNAL_URL), null));
return dip;
}
public static SolrInputDocument dipFileToSolrDocument(DIP dip, DIPFile file) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, IdUtils.getDIPFileId(file));
List<String> path = file.getPath();
doc.addField(RodaConstants.DIPFILE_PATH, path);
if (path != null && !path.isEmpty()) {
List<String> ancestorsPath = getDIPFileAncestorsPath(file.getDipId(), path);
if (!ancestorsPath.isEmpty()) {
doc.addField(RodaConstants.DIPFILE_ANCESTORS_UUIDS, ancestorsPath);
}
doc.addField(RodaConstants.DIPFILE_PARENT_UUID,
IdUtils.getDIPFileId(file.getDipId(), path.subList(0, path.size() - 1), path.get(path.size() - 1)));
}
doc.addField(RodaConstants.DIPFILE_DIP_ID, file.getDipId());
doc.addField(RodaConstants.DIPFILE_ID, file.getId());
doc.addField(RodaConstants.DIPFILE_IS_DIRECTORY, file.isDirectory());
doc.addField(RodaConstants.DIPFILE_SIZE, Long.toString(file.getSize()));
// extra-fields
try {
StoragePath filePath = ModelUtils.getDIPFileStoragePath(file);
doc.addField(RodaConstants.DIPFILE_STORAGE_PATH, FSUtils.getStoragePathAsString(filePath, false));
} catch (RequestNotValidException e) {
LOGGER.warn("Could not index DIP file storage path", e);
}
setPermissions(dip.getPermissions(), doc);
return doc;
}
private static List<String> getDIPFileAncestorsPath(String dipId, List<String> path) {
List<String> parentFileDirectoryPath = new ArrayList<>();
List<String> ancestorsPath = new ArrayList<>();
parentFileDirectoryPath.addAll(path);
while (!parentFileDirectoryPath.isEmpty()) {
int lastElementIndex = parentFileDirectoryPath.size() - 1;
String parentFileId = parentFileDirectoryPath.get(lastElementIndex);
parentFileDirectoryPath.remove(lastElementIndex);
ancestorsPath.add(0, IdUtils.getDIPFileId(dipId, parentFileDirectoryPath, parentFileId));
}
return ancestorsPath;
}
public static DIPFile solrDocumentToDIPFile(SolrDocument doc) {
DIPFile file = new DIPFile();
file.setUUID(objectToString(doc.get(RodaConstants.INDEX_UUID), null));
file.setId(objectToString(doc.get(RodaConstants.DIPFILE_ID), null));
file.setDipId(objectToString(doc.get(RodaConstants.DIPFILE_DIP_ID), null));
file.setPath(objectToListString(doc.get(RodaConstants.DIPFILE_PATH)));
file.setAncestorsUUIDs(objectToListString(doc.get(RodaConstants.DIPFILE_ANCESTORS_UUIDS)));
file.setDirectory(objectToBoolean(doc.get(RodaConstants.DIPFILE_IS_DIRECTORY), Boolean.FALSE));
file.setStoragePath(objectToString(doc.get(RodaConstants.DIPFILE_STORAGE_PATH), null));
file.setSize(objectToLong(doc.get(RodaConstants.DIPFILE_SIZE), 0L));
return file;
}
/*
* Partial updates of RODA objects
* ____________________________________________________________________________________________________________________
*/
public static SolrInputDocument aipStateUpdateToSolrDocument(AIP aip) {
return stateUpdateToSolrDocument(aip.getId(), aip.getState());
}
public static SolrInputDocument representationStateUpdateToSolrDocument(Representation representation,
AIPState state) {
return stateUpdateToSolrDocument(IdUtils.getRepresentationId(representation), state);
}
public static SolrInputDocument fileStateUpdateToSolrDocument(File file, AIPState state) {
return stateUpdateToSolrDocument(IdUtils.getFileId(file), state);
}
public static SolrInputDocument preservationEventStateUpdateToSolrDocument(String preservationEventID,
String preservationEventAipId, AIPState state) {
SolrInputDocument document = stateUpdateToSolrDocument(preservationEventID, state);
document.addField(RodaConstants.PRESERVATION_EVENT_AIP_ID, preservationEventAipId);
return document;
}
private static SolrInputDocument stateUpdateToSolrDocument(String uuid, AIPState state) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, uuid);
doc.addField(RodaConstants.STATE, set(state.toString()));
return doc;
}
public static SolrInputDocument aipPermissionsUpdateToSolrDocument(AIP aip) {
SolrInputDocument document = new SolrInputDocument();
document.addField(RodaConstants.INDEX_UUID, aip.getId());
return permissionsUpdateToSolrDocument(document, aip.getPermissions());
}
public static SolrInputDocument dipPermissionsUpdateToSolrDocument(DIP dip) {
SolrInputDocument document = new SolrInputDocument();
document.addField(RodaConstants.INDEX_UUID, dip.getId());
return permissionsUpdateToSolrDocument(document, dip.getPermissions());
}
public static SolrInputDocument representationPermissionsUpdateToSolrDocument(Representation representation,
Permissions permissions) {
SolrInputDocument document = new SolrInputDocument();
document.addField(RodaConstants.INDEX_UUID, IdUtils.getRepresentationId(representation));
return permissionsUpdateToSolrDocument(document, permissions);
}
public static SolrInputDocument filePermissionsUpdateToSolrDocument(File file, Permissions permissions) {
SolrInputDocument document = new SolrInputDocument();
document.addField(RodaConstants.INDEX_UUID, IdUtils.getFileId(file));
return permissionsUpdateToSolrDocument(document, permissions);
}
public static SolrInputDocument preservationEventPermissionsUpdateToSolrDocument(String preservationEventID,
String preservationEventAipId, Permissions permissions, AIPState state) {
SolrInputDocument document = new SolrInputDocument();
document.addField(RodaConstants.INDEX_UUID, preservationEventID);
document = permissionsUpdateToSolrDocument(document, permissions);
document.addField(RodaConstants.STATE, state.toString());
document.addField(RodaConstants.PRESERVATION_EVENT_AIP_ID, preservationEventAipId);
return document;
}
private static SolrInputDocument permissionsUpdateToSolrDocument(SolrInputDocument doc, Permissions permissions) {
for (Entry<PermissionType, Set<String>> entry : permissions.getUsers().entrySet()) {
String key = RodaConstants.INDEX_PERMISSION_USERS_PREFIX + entry.getKey();
List<String> value = new ArrayList<>(entry.getValue());
doc.addField(key, set(value));
}
for (Entry<PermissionType, Set<String>> entry : permissions.getGroups().entrySet()) {
String key = RodaConstants.INDEX_PERMISSION_GROUPS_PREFIX + entry.getKey();
List<String> value = new ArrayList<>(entry.getValue());
doc.addField(key, set(value));
}
return doc;
}
public static SolrInputDocument updateAIPParentId(String aipId, String parentId, List<String> ancestors)
throws RequestNotValidException, GenericException, AuthorizationDeniedException {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, aipId);
doc.addField(RodaConstants.AIP_PARENT_ID, set(parentId));
doc.addField(RodaConstants.AIP_ANCESTORS, set(ancestors));
return doc;
}
public static SolrInputDocument updateAIPAncestors(String aipId, List<String> ancestors)
throws RequestNotValidException, GenericException, AuthorizationDeniedException {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, aipId);
doc.addField(RodaConstants.AIP_ANCESTORS, set(ancestors));
return doc;
}
public static SolrInputDocument updateRepresentationAncestors(String representationUUID, List<String> ancestors)
throws RequestNotValidException, GenericException, AuthorizationDeniedException {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, representationUUID);
doc.addField(RodaConstants.REPRESENTATION_ANCESTORS, set(ancestors));
return doc;
}
public static SolrInputDocument updateFileAncestors(String fileUUID, List<String> ancestors)
throws RequestNotValidException, GenericException, AuthorizationDeniedException {
SolrInputDocument doc = new SolrInputDocument();
doc.addField(RodaConstants.INDEX_UUID, fileUUID);
doc.addField(RodaConstants.FILE_ANCESTORS, set(ancestors));
return doc;
}
public static Map<String, Object> set(Object value) {
Map<String, Object> fieldModifier = new HashMap<>(1);
// 20160511 this workaround fixes solr wrong behaviour with partial update
// of empty lists
if (value instanceof List && ((List<?>) value).isEmpty()) {
fieldModifier.put("set", null);
} else {
fieldModifier.put("set", value);
}
return fieldModifier;
}
/*
* Crosswalks auxiliary methods: RODA Objects <-> Apache Solr documents
* ____________________________________________________________________________________________________________________
*/
private static Permissions getPermissions(SolrDocument doc) {
Permissions permissions = new Permissions();
EnumMap<PermissionType, Set<String>> userPermissions = new EnumMap<>(PermissionType.class);
for (PermissionType type : PermissionType.values()) {
String key = RodaConstants.INDEX_PERMISSION_USERS_PREFIX + type;
Set<String> users = new HashSet<>();
users.addAll(objectToListString(doc.get(key)));
userPermissions.put(type, users);
}
EnumMap<PermissionType, Set<String>> groupPermissions = new EnumMap<>(PermissionType.class);
for (PermissionType type : PermissionType.values()) {
String key = RodaConstants.INDEX_PERMISSION_GROUPS_PREFIX + type;
Set<String> groups = new HashSet<>();
groups.addAll(objectToListString(doc.get(key)));
groupPermissions.put(type, groups);
}
permissions.setUsers(userPermissions);
permissions.setGroups(groupPermissions);
return permissions;
}
private static void setPermissions(Permissions permissions, final SolrInputDocument ret) {
for (Entry<PermissionType, Set<String>> entry : permissions.getUsers().entrySet()) {
String key = RodaConstants.INDEX_PERMISSION_USERS_PREFIX + entry.getKey();
List<String> value = new ArrayList<>(entry.getValue());
ret.addField(key, value);
}
for (Entry<PermissionType, Set<String>> entry : permissions.getGroups().entrySet()) {
String key = RodaConstants.INDEX_PERMISSION_GROUPS_PREFIX + entry.getKey();
List<String> value = new ArrayList<>(entry.getValue());
ret.addField(key, value);
}
}
public static List<String> getAncestors(String parentId, ModelService model)
throws RequestNotValidException, GenericException, AuthorizationDeniedException {
List<String> ancestors = new ArrayList<>();
String nextAncestorId = parentId;
while (nextAncestorId != null) {
try {
AIP nextAncestor = model.retrieveAIP(nextAncestorId);
if (ancestors.contains(nextAncestorId)) {
break;
}
ancestors.add(nextAncestorId);
nextAncestorId = nextAncestor.getParentId();
} catch (NotFoundException e) {
LOGGER.warn("Could not find one AIP ancestor. Ancestor id: {}", nextAncestorId);
nextAncestorId = null;
}
}
return ancestors;
}
/**
* WARNING: this should only be used to debug/tests only
*
* @return
* @throws IOException
* @throws SolrServerException
*/
public static QueryResponse executeSolrQuery(SolrClient index, String collection, String solrQueryString)
throws SolrServerException, IOException {
LOGGER.trace("query string: {}", solrQueryString);
SolrQuery query = new SolrQuery();
for (String string : solrQueryString.split("&")) {
String[] split = string.split("=");
query.add(split[0], split[1]);
}
LOGGER.trace("executeSolrQuery: {}", query);
return index.query(collection, query);
}
public static SolrInputDocument premisToSolr(PreservationMetadataType preservationMetadataType, AIP aip,
String representationUUID, String fileUUID, Binary binary) throws GenericException {
SolrInputDocument doc;
Map<String, String> stylesheetOpt = new HashMap<>();
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_OBJECT_CLASS,
PreservationMetadataEventClass.REPOSITORY.toString());
if (aip != null) {
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_OBJECT_CLASS, PreservationMetadataEventClass.AIP.toString());
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_AIP_ID, aip.getId());
if (representationUUID != null) {
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_REPRESENTATION_UUID, representationUUID);
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_OBJECT_CLASS,
PreservationMetadataEventClass.REPRESENTATION.toString());
}
if (fileUUID != null) {
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_FILE_UUID, fileUUID);
stylesheetOpt.put(RodaConstants.PRESERVATION_EVENT_OBJECT_CLASS,
PreservationMetadataEventClass.FILE.toString());
}
}
Reader reader = null;
try {
reader = RodaUtils.applyMetadataStylesheet(binary, RodaConstants.CORE_CROSSWALKS_INGEST_OTHER,
RodaConstants.PREMIS_METADATA_TYPE, RodaConstants.PREMIS_METADATA_VERSION, stylesheetOpt);
XMLLoader loader = new XMLLoader();
XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(reader);
boolean parsing = true;
doc = null;
while (parsing) {
int event = parser.next();
if (event == XMLStreamConstants.END_DOCUMENT) {
parser.close();
parsing = false;
} else if (event == XMLStreamConstants.START_ELEMENT && "doc".equals(parser.getLocalName())) {
doc = loader.readDoc(parser);
}
}
} catch (XMLStreamException | FactoryConfigurationError e) {
throw new GenericException("Could not process PREMIS " + binary.getStoragePath(), e);
} finally {
IOUtils.closeQuietly(reader);
}
if (preservationMetadataType == PreservationMetadataType.EVENT && doc != null) {
try {
List<LinkingIdentifier> agents = PremisV3Utils.extractAgentsFromEvent(binary);
for (LinkingIdentifier id : agents) {
doc.addField(RodaConstants.PRESERVATION_EVENT_LINKING_AGENT_IDENTIFIER, JsonUtils.getJsonFromObject(id));
}
} catch (org.roda.core.data.v2.validation.ValidationException e) {
LOGGER.warn("Error setting linking agent field: {}", e.getMessage());
}
try {
List<LinkingIdentifier> sources = PremisV3Utils.extractObjectFromEvent(binary);
for (LinkingIdentifier id : sources) {
doc.addField(RodaConstants.PRESERVATION_EVENT_LINKING_SOURCE_OBJECT_IDENTIFIER,
JsonUtils.getJsonFromObject(id));
}
} catch (org.roda.core.data.v2.validation.ValidationException e) {
LOGGER.warn("Error setting linking source field: {}", e.getMessage());
}
try {
List<LinkingIdentifier> outcomes = PremisV3Utils.extractObjectFromEvent(binary);
for (LinkingIdentifier id : outcomes) {
doc.addField(RodaConstants.PRESERVATION_EVENT_LINKING_OUTCOME_OBJECT_IDENTIFIER,
JsonUtils.getJsonFromObject(id));
}
} catch (org.roda.core.data.v2.validation.ValidationException e) {
LOGGER.warn("Error setting linking outcome field: {}", e.getMessage());
}
// indexing active state and permissions
if (aip != null) {
doc.addField(RodaConstants.STATE, aip.getState().toString());
setPermissions(aip.getPermissions(), doc);
} else {
doc.addField(RodaConstants.STATE, AIPState.ACTIVE);
}
}
// set uuid from id defined in xslt
if (doc != null) {
doc.addField(RodaConstants.INDEX_UUID, doc.getFieldValue(RodaConstants.PRESERVATION_EVENT_ID));
} else {
doc = new SolrInputDocument();
}
return doc;
}
public static <T extends IsIndexed> List<String> suggest(SolrClient index, Class<T> classToRetrieve, String field,
String queryString, boolean justActive, User user, boolean allowPartial) throws GenericException {
StringBuilder queryBuilder = new StringBuilder();
appendKeyValue(queryBuilder, field + RodaConstants.INDEX_SEARCH_SUFFIX, queryString + "*");
SolrQuery query = new SolrQuery();
query.setParam("q.op", DEFAULT_QUERY_PARSER_OPERATOR);
query.setQuery(queryBuilder.toString());
if (hasPermissionFilters(classToRetrieve)) {
query.addFilterQuery(getFilterQueries(user, justActive, classToRetrieve));
}
parseAndConfigureFacets(new Facets(new SimpleFacetParameter(field)), query);
List<String> suggestions = new ArrayList<>();
try {
QueryResponse response = index.query(getIndexName(classToRetrieve).get(0), query);
response.getFacetField(field).getValues().forEach(count -> suggestions.add(count.getName()));
} catch (SolrServerException | IOException | SolrException e) {
throw new GenericException("Could not get suggestions", e);
} catch (RuntimeException e) {
throw new GenericException("Unexpected exception while querying index", e);
}
return suggestions;
}
public static <T extends IsIndexed> void execute(SolrClient index, Class<T> classToRetrieve, Filter filter,
List<String> fieldsToReturn, IndexRunnable<T> indexRunnable)
throws GenericException, RequestNotValidException, AuthorizationDeniedException {
Sorter sorter = null;
int offset = 0;
int pagesize = RodaConstants.DEFAULT_PAGINATION_VALUE;
boolean done;
do {
Sublist sublist = new Sublist(offset, pagesize);
IndexResult<T> find = SolrUtils.find(index, classToRetrieve, filter, sorter, sublist, fieldsToReturn);
for (T target : find.getResults()) {
indexRunnable.run(target);
}
done = find.getResults().isEmpty();
offset += pagesize;
} while (!done);
}
private static SolrInputDocument solrDocumentToSolrInputDocument(SolrDocument d) {
SolrInputDocument doc = new SolrInputDocument();
for (String name : d.getFieldNames()) {
doc.addField(name, d.getFieldValue(name));
}
return doc;
}
public static <T extends IsIndexed> void delete(SolrClient index, Class<T> classToDelete, List<String> ids)
throws GenericException {
try {
index.deleteById(getIndexName(classToDelete).get(0), ids);
} catch (SolrServerException | IOException e) {
throw new GenericException("Could not delete items", e);
}
}
public static <T extends IsIndexed> void delete(SolrClient index, Class<T> classToDelete, Filter filter)
throws GenericException, RequestNotValidException {
try {
index.deleteByQuery(getIndexName(classToDelete).get(0), parseFilter(filter));
} catch (SolrServerException | IOException e) {
throw new GenericException("Could not delete items", e);
}
}
}