/**
* Copyright (c) Codice Foundation
* <p/>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p/>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.catalog.impl.operations;
import static ddf.catalog.Constants.CONTENT_PATHS;
import java.io.Serializable;
import java.nio.file.Path;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.opengis.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Iterables;
import ddf.catalog.Constants;
import ddf.catalog.content.StorageException;
import ddf.catalog.content.data.ContentItem;
import ddf.catalog.content.operation.UpdateStorageRequest;
import ddf.catalog.content.operation.UpdateStorageResponse;
import ddf.catalog.content.operation.impl.UpdateStorageRequestImpl;
import ddf.catalog.content.plugin.PostUpdateStoragePlugin;
import ddf.catalog.content.plugin.PreUpdateStoragePlugin;
import ddf.catalog.data.Attribute;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.data.impl.AttributeImpl;
import ddf.catalog.federation.FederationException;
import ddf.catalog.history.Historian;
import ddf.catalog.impl.FrameworkProperties;
import ddf.catalog.operation.Operation;
import ddf.catalog.operation.OperationTransaction;
import ddf.catalog.operation.ProcessingDetails;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.operation.Update;
import ddf.catalog.operation.UpdateRequest;
import ddf.catalog.operation.UpdateResponse;
import ddf.catalog.operation.impl.OperationTransactionImpl;
import ddf.catalog.operation.impl.ProcessingDetailsImpl;
import ddf.catalog.operation.impl.QueryImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.operation.impl.UpdateRequestImpl;
import ddf.catalog.operation.impl.UpdateResponseImpl;
import ddf.catalog.plugin.AccessPlugin;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.PolicyPlugin;
import ddf.catalog.plugin.PolicyResponse;
import ddf.catalog.plugin.PostIngestPlugin;
import ddf.catalog.plugin.PreAuthorizationPlugin;
import ddf.catalog.plugin.PreIngestPlugin;
import ddf.catalog.plugin.StopProcessingException;
import ddf.catalog.source.CatalogStore;
import ddf.catalog.source.IngestException;
import ddf.catalog.source.InternalIngestException;
import ddf.catalog.source.SourceUnavailableException;
import ddf.catalog.util.impl.Requests;
import ddf.security.SecurityConstants;
/**
* Support class for update delegate operations for the {@code CatalogFrameworkImpl}.
* <p>
* This class contains two delegated update methods and methods to support them. No
* operations/support methods should be added to this class except in support of CFI
* update operations.
*/
public class UpdateOperations {
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateOperations.class);
private static final Logger INGEST_LOGGER =
LoggerFactory.getLogger(Constants.INGEST_LOGGER_NAME);
private static final String PRE_INGEST_ERROR = "Error during pre-ingest:\n\n";
// Inject properties
private final FrameworkProperties frameworkProperties;
private final QueryOperations queryOperations;
private final SourceOperations sourceOperations;
private final OperationsSecuritySupport opsSecuritySupport;
private final OperationsMetacardSupport opsMetacardSupport;
private final OperationsCatalogStoreSupport opsCatStoreSupport;
private final OperationsStorageSupport opsStorageSupport;
private Historian historian;
public UpdateOperations(FrameworkProperties frameworkProperties,
QueryOperations queryOperations, SourceOperations sourceOperations,
OperationsSecuritySupport opsSecuritySupport,
OperationsMetacardSupport opsMetacardSupport,
OperationsCatalogStoreSupport opsCatStoreSupport,
OperationsStorageSupport opsStorageSupport) {
this.frameworkProperties = frameworkProperties;
this.queryOperations = queryOperations;
this.sourceOperations = sourceOperations;
this.opsSecuritySupport = opsSecuritySupport;
this.opsMetacardSupport = opsMetacardSupport;
this.opsCatStoreSupport = opsCatStoreSupport;
this.opsStorageSupport = opsStorageSupport;
}
public void setHistorian(Historian historian) {
this.historian = historian;
}
//
// Delegate methods
//
public UpdateResponse update(UpdateRequest updateRequest)
throws IngestException, SourceUnavailableException {
UpdateResponse updateResponse = doUpdate(updateRequest);
updateResponse = doPostIngest(updateResponse);
return updateResponse;
}
@SuppressWarnings("unchecked")
private Map<String, Metacard> getUpdateMap(UpdateRequest updateRequest) {
return (Map<String, Metacard>) Optional.of(updateRequest)
.map(Operation::getProperties)
.map(p -> p.get(Constants.ATTRIBUTE_UPDATE_MAP_KEY))
.filter(Map.class::isInstance)
.map(Map.class::cast)
.orElseGet(HashMap::new);
}
public UpdateResponse update(UpdateStorageRequest streamUpdateRequest)
throws IngestException, SourceUnavailableException {
Map<String, Metacard> metacardMap = new HashMap<>();
List<ContentItem> contentItems = new ArrayList<>(streamUpdateRequest.getContentItems()
.size());
HashMap<String, Map<String, Path>> tmpContentPaths = new HashMap<>();
UpdateResponse updateResponse = null;
UpdateStorageRequest updateStorageRequest = null;
UpdateStorageResponse updateStorageResponse = null;
streamUpdateRequest = opsStorageSupport.prepareStorageRequest(streamUpdateRequest,
streamUpdateRequest::getContentItems);
// Operation populates the metacardMap, contentItems, and tmpContentPaths
opsMetacardSupport.generateMetacardAndContentItems(streamUpdateRequest.getContentItems(),
metacardMap,
contentItems,
tmpContentPaths);
streamUpdateRequest.getProperties()
.put(CONTENT_PATHS, tmpContentPaths);
streamUpdateRequest = applyAttributeOverrides(streamUpdateRequest, metacardMap);
try {
if (!contentItems.isEmpty()) {
updateStorageRequest = new UpdateStorageRequestImpl(contentItems,
streamUpdateRequest.getId(),
streamUpdateRequest.getProperties());
updateStorageRequest = processPreUpdateStoragePlugins(updateStorageRequest);
try {
updateStorageResponse = sourceOperations.getStorage()
.update(updateStorageRequest);
updateStorageResponse.getProperties()
.put(CONTENT_PATHS, tmpContentPaths);
} catch (StorageException e) {
throw new IngestException(
"Could not store content items. Removed created metacards.",
e);
}
updateStorageResponse = processPostUpdateStoragePlugins(updateStorageResponse);
for (ContentItem contentItem : updateStorageResponse.getUpdatedContentItems()) {
if (StringUtils.isBlank(contentItem.getQualifier())) {
Metacard metacard = metacardMap.get(contentItem.getId());
Metacard overrideMetacard = contentItem.getMetacard();
Metacard updatedMetacard = OverrideAttributesSupport.overrideMetacard(
metacard,
overrideMetacard,
true,
true);
updatedMetacard.setAttribute(new AttributeImpl(Metacard.RESOURCE_SIZE,
String.valueOf(contentItem.getSize())));
metacardMap.put(contentItem.getId(), updatedMetacard);
}
}
}
UpdateRequestImpl updateRequest =
new UpdateRequestImpl(Iterables.toArray(metacardMap.values()
.stream()
.map(Metacard::getId)
.collect(Collectors.toList()), String.class),
new ArrayList<>(metacardMap.values()));
updateRequest.setProperties(streamUpdateRequest.getProperties());
historian.setSkipFlag(updateRequest);
updateResponse = doUpdate(updateRequest);
historian.version(streamUpdateRequest, updateStorageResponse, updateResponse);
} catch (Exception e) {
if (updateStorageRequest != null) {
try {
sourceOperations.getStorage()
.rollback(updateStorageRequest);
} catch (StorageException e1) {
LOGGER.info("Unable to remove temporary content for id: {}",
updateStorageRequest.getId(),
e1);
}
}
throw new IngestException(
"Unable to store products for request: " + streamUpdateRequest.getId(), e);
} finally {
opsStorageSupport.commitAndCleanup(updateStorageRequest, tmpContentPaths);
}
updateResponse = doPostIngest(updateResponse);
return updateResponse;
}
//
// Private helper methods
//
private UpdateResponse doUpdate(UpdateRequest updateRequest)
throws IngestException, SourceUnavailableException {
updateRequest = queryOperations.setFlagsOnRequest(updateRequest);
updateRequest = validateUpdateRequest(updateRequest);
updateRequest = validateLocalSource(updateRequest);
try {
updateRequest = injectAttributes(updateRequest);
updateRequest = setDefaultValues(updateRequest);
updateRequest = populateMetacards(updateRequest);
updateRequest = processPreAuthorizationPlugins(updateRequest);
updateRequest = populateUpdateRequestPolicyMap(updateRequest);
updateRequest = processPreUpdateAccessPlugins(updateRequest);
updateRequest = processPreIngestPlugins(updateRequest);
updateRequest = validateUpdateRequest(updateRequest);
// Call the update on the catalog
LOGGER.debug("Calling catalog.update() with {} updates.",
updateRequest.getUpdates()
.size());
UpdateResponse updateResponse = performLocalUpdate(updateRequest);
updateResponse = performRemoteUpdate(updateRequest, updateResponse);
// Handle the posting of messages to pubsub
updateResponse = validateFixUpdateResponse(updateResponse, updateRequest);
return updateResponse;
} catch (StopProcessingException see) {
throw new IngestException(PRE_INGEST_ERROR, see);
} catch (RuntimeException re) {
throw new InternalIngestException("Exception during runtime while performing update",
re);
}
}
private UpdateResponse doPostIngest(UpdateResponse currentUpdateResponse) {
UpdateResponse updateResponse = currentUpdateResponse;
try {
updateResponse = processPostIngestPlugins(currentUpdateResponse);
} catch (RuntimeException re) {
LOGGER.info(
"Exception during runtime while performing doing post update operations (plugins and pubsub)",
re);
}
// if debug is enabled then catalog might take a significant performance hit w/r/t string
// building
if (INGEST_LOGGER.isDebugEnabled()) {
INGEST_LOGGER.debug("{} metacards were successfully updated. {}",
updateResponse.getRequest()
.getUpdates()
.size(),
buildUpdateLog(updateResponse.getRequest()));
}
return updateResponse;
}
private String buildUpdateLog(UpdateRequest createReq) {
StringBuilder strBuilder = new StringBuilder();
List<Metacard> metacards = createReq.getUpdates()
.stream()
.map(Map.Entry::getValue)
.collect(Collectors.toList());
String metacardTitleLabel = "Metacard Title: ";
String metacardIdLabel = "Metacard ID: ";
for (int i = 0; i < metacards.size(); i++) {
Metacard card = metacards.get(i);
strBuilder.append(System.lineSeparator())
.append("Batch #: ")
.append(i + 1)
.append(" | ");
if (card != null) {
if (card.getTitle() != null) {
strBuilder.append(metacardTitleLabel)
.append(card.getTitle())
.append(" | ");
}
if (card.getId() != null) {
strBuilder.append(metacardIdLabel)
.append(card.getId())
.append(" | ");
}
} else {
strBuilder.append("Null Metacard");
}
}
return strBuilder.toString();
}
private UpdateRequest rewriteRequestToAvoidHistoryConflicts(UpdateRequest updateRequest,
QueryResponse response) {
final String attributeName = updateRequest.getAttributeName();
if (Metacard.ID.equals(attributeName)) {
return updateRequest;
}
List<Map.Entry<Serializable, Metacard>> updatedList = response.getResults()
.stream()
.map(Result::getMetacard)
.map(this::toEntryById)
.collect(Collectors.toList());
return new UpdateRequestImpl(updatedList,
Metacard.ID,
updateRequest.getProperties(),
updateRequest.getStoreIds());
}
private boolean foundAllUpdateRequestMetacards(UpdateRequest updateRequest,
QueryResponse response) {
Set<String> originalKeys = updateRequest.getUpdates()
.stream()
.map(Map.Entry::getKey)
.map(Object::toString)
.collect(Collectors.toSet());
Set<String> responseKeys = response.getResults()
.stream()
.map(Result::getMetacard)
.map(m -> m.getAttribute(updateRequest.getAttributeName()))
.filter(Objects::nonNull)
.map(Attribute::getValue)
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.toSet());
return originalKeys.equals(responseKeys);
}
private Map.Entry<Serializable, Metacard> toEntryById(Metacard metacard) {
return new AbstractMap.SimpleEntry<>(metacard.getId(), metacard);
}
private UpdateRequest injectAttributes(UpdateRequest request) {
request.getUpdates()
.forEach(updateEntry -> {
Metacard original = updateEntry.getValue();
Metacard metacard = opsMetacardSupport.applyInjectors(original,
frameworkProperties.getAttributeInjectors());
updateEntry.setValue(metacard);
});
return request;
}
private UpdateRequest setDefaultValues(UpdateRequest updateRequest) {
updateRequest.getUpdates()
.stream()
.filter(Objects::nonNull)
.map(Map.Entry::getValue)
.filter(Objects::nonNull)
.forEach(opsMetacardSupport::setDefaultValues);
return updateRequest;
}
/**
* Validates that the {@link UpdateRequest} is non-null, has a non-empty list of
* {@link Metacard}s in it, and a non-null attribute name (which specifies if the update is
* being done by product URI or ID).
*
* @param updateRequest the {@link UpdateRequest}
* @throws IngestException if the {@link UpdateRequest} is null, or has null or empty {@link Metacard} list,
* or a null attribute name.
*/
private UpdateRequest validateUpdateRequest(UpdateRequest updateRequest)
throws IngestException {
if (updateRequest == null) {
throw new IngestException(
"UpdateRequest was null, either passed in from endpoint, or as output from PreIngestPlugins");
}
List<Map.Entry<Serializable, Metacard>> entries = updateRequest.getUpdates();
if (CollectionUtils.isEmpty(entries) || updateRequest.getAttributeName() == null) {
throw new IngestException(
"Cannot perform update with null/empty attribute value list or null attributeName, "
+ "either passed in from endpoint, or as output from PreIngestPlugins");
}
return updateRequest;
}
private UpdateResponse doRemoteUpdate(UpdateRequest updateRequest) {
HashSet<ProcessingDetails> exceptions = new HashSet<>();
Map<String, Serializable> properties = new HashMap<>();
List<CatalogStore> stores = opsCatStoreSupport.getCatalogStoresForRequest(updateRequest,
exceptions);
List<Update> updates = new ArrayList<>();
for (CatalogStore store : stores) {
try {
if (!store.isAvailable()) {
exceptions.add(new ProcessingDetailsImpl(store.getId(),
null,
"CatalogStore is not available"));
} else {
UpdateResponse response = store.update(updateRequest);
properties.put(store.getId(), new ArrayList<>(response.getUpdatedMetacards()));
updates = response.getUpdatedMetacards();
}
} catch (IngestException e) {
INGEST_LOGGER.error("Error updating metacards for CatalogStore {}",
store.getId(),
e);
exceptions.add(new ProcessingDetailsImpl(store.getId(), e));
}
}
return new UpdateResponseImpl(updateRequest, properties, updates, exceptions);
}
/**
* Validates that the {@link UpdateResponse} has one or more {@link Metacard}s in it that were
* updated in the catalog, and that the original {@link UpdateRequest} is included in the
* response.
*
* @param updateResponse the original {@link UpdateResponse} returned from the catalog provider
* @param updateRequest the original {@link UpdateRequest} sent to the catalog provider
* @return the updated {@link UpdateResponse}
* @throws IngestException if original {@link UpdateResponse} passed in is null or the {@link Metacard}s
* list in the response is null
*/
private UpdateResponse validateFixUpdateResponse(UpdateResponse updateResponse,
UpdateRequest updateRequest) throws IngestException {
UpdateResponse updateResp = updateResponse;
if (updateResp != null) {
if (updateResp.getUpdatedMetacards() == null) {
throw new IngestException(
"CatalogProvider returned null list of results from update method.");
}
if (updateResp.getRequest() == null) {
updateResp = new UpdateResponseImpl(updateRequest,
updateResponse.getProperties(),
updateResponse.getUpdatedMetacards());
}
} else {
throw new IngestException("CatalogProvider returned null UpdateResponse Object.");
}
return updateResp;
}
private UpdateResponse processPostIngestPlugins(UpdateResponse updateResponse) {
for (final PostIngestPlugin plugin : frameworkProperties.getPostIngest()) {
try {
updateResponse = plugin.process(updateResponse);
} catch (PluginExecutionException e) {
LOGGER.info("Plugin exception", e);
}
}
return updateResponse;
}
private UpdateResponse performRemoteUpdate(UpdateRequest updateRequest,
UpdateResponse updateResponse) {
if (opsCatStoreSupport.isCatalogStoreRequest(updateRequest)) {
UpdateResponse remoteUpdateResponse = doRemoteUpdate(updateRequest);
if (updateResponse == null) {
updateResponse = remoteUpdateResponse;
} else {
updateResponse.getProperties()
.putAll(remoteUpdateResponse.getProperties());
updateResponse.getProcessingErrors()
.addAll(remoteUpdateResponse.getProcessingErrors());
}
}
return updateResponse;
}
private UpdateResponse performLocalUpdate(UpdateRequest updateRequest)
throws IngestException, SourceUnavailableException {
if (!Requests.isLocal(updateRequest)) {
return null;
}
UpdateResponse updateResponse = sourceOperations.getCatalog()
.update(updateRequest);
updateResponse = historian.version(updateResponse);
return updateResponse;
}
private UpdateRequest processPreIngestPlugins(UpdateRequest updateRequest)
throws StopProcessingException {
for (PreIngestPlugin plugin : frameworkProperties.getPreIngest()) {
try {
updateRequest = plugin.process(updateRequest);
} catch (PluginExecutionException e) {
LOGGER.debug("error processing update in PreIngestPlugin", e);
}
}
return updateRequest;
}
private UpdateRequest processPreUpdateAccessPlugins(UpdateRequest updateRequest)
throws StopProcessingException {
Map<String, Metacard> metacardMap = getUpdateMap(updateRequest);
for (AccessPlugin plugin : frameworkProperties.getAccessPlugins()) {
updateRequest = plugin.processPreUpdate(updateRequest, metacardMap);
}
return updateRequest;
}
private UpdateRequest populateUpdateRequestPolicyMap(UpdateRequest updateRequest)
throws StopProcessingException {
Map<String, Metacard> metacardMap = getUpdateMap(updateRequest);
HashMap<String, Set<String>> requestPolicyMap = new HashMap<>();
for (Map.Entry<Serializable, Metacard> update : updateRequest.getUpdates()) {
HashMap<String, Set<String>> itemPolicyMap = new HashMap<>();
HashMap<String, Set<String>> oldItemPolicyMap = new HashMap<>();
Metacard oldMetacard = metacardMap.get(update.getKey()
.toString());
for (PolicyPlugin plugin : frameworkProperties.getPolicyPlugins()) {
PolicyResponse updatePolicyResponse = plugin.processPreUpdate(update.getValue(),
Collections.unmodifiableMap(updateRequest.getProperties()));
PolicyResponse oldPolicyResponse = plugin.processPreUpdate(oldMetacard,
Collections.unmodifiableMap(updateRequest.getProperties()));
opsSecuritySupport.buildPolicyMap(itemPolicyMap,
updatePolicyResponse.itemPolicy()
.entrySet());
opsSecuritySupport.buildPolicyMap(oldItemPolicyMap,
oldPolicyResponse.itemPolicy()
.entrySet());
opsSecuritySupport.buildPolicyMap(requestPolicyMap,
updatePolicyResponse.operationPolicy()
.entrySet());
}
update.getValue()
.setAttribute(new AttributeImpl(Metacard.SECURITY, itemPolicyMap));
if (oldMetacard != null) {
oldMetacard.setAttribute(new AttributeImpl(Metacard.SECURITY, oldItemPolicyMap));
}
}
updateRequest.getProperties()
.put(PolicyPlugin.OPERATION_SECURITY, requestPolicyMap);
return updateRequest;
}
private UpdateRequest populateMetacards(UpdateRequest updateRequest) throws IngestException {
final String attributeName = updateRequest.getAttributeName();
QueryRequestImpl queryRequest = createQueryRequest(updateRequest);
QueryResponse query;
try {
query = queryOperations.doQuery(queryRequest,
frameworkProperties.getFederationStrategy());
} catch (FederationException e) {
LOGGER.debug("Unable to complete query for updated metacards.", e);
throw new IngestException("Exception during runtime while performing update");
}
if (!foundAllUpdateRequestMetacards(updateRequest, query)) {
logFailedQueryInfo(updateRequest, query);
throw new IngestException("Could not find all metacards specified in request");
}
updateRequest = rewriteRequestToAvoidHistoryConflicts(updateRequest, query);
HashMap<String, Metacard> metacardMap = new HashMap<>(query.getResults()
.stream()
.map(Result::getMetacard)
.collect(Collectors.toMap(metacard -> getAttributeStringValue(metacard,
attributeName), Function.identity())));
updateRequest.getProperties()
.put(Constants.ATTRIBUTE_UPDATE_MAP_KEY, metacardMap);
updateRequest.getProperties()
.put(Constants.OPERATION_TRANSACTION_KEY,
new OperationTransactionImpl(OperationTransaction.OperationType.UPDATE,
metacardMap.values()));
return updateRequest;
}
private UpdateRequest processPreAuthorizationPlugins(UpdateRequest updateRequest)
throws StopProcessingException {
Map<String, Metacard> metacardMap = getUpdateMap(updateRequest);
for (PreAuthorizationPlugin plugin : frameworkProperties.getPreAuthorizationPlugins()) {
updateRequest = plugin.processPreUpdate(updateRequest, metacardMap);
}
return updateRequest;
}
private QueryRequestImpl createQueryRequest(UpdateRequest updateRequest) {
List<Filter> idFilters = updateRequest.getUpdates()
.stream()
.map(update -> frameworkProperties.getFilterBuilder()
.attribute(updateRequest.getAttributeName())
.is()
.equalTo()
.text(update.getKey()
.toString()))
.collect(Collectors.toList());
QueryImpl queryImpl =
new QueryImpl(queryOperations.getFilterWithAdditionalFilters(idFilters),
1, /* start index */
0, /* page size */
null,
false, /* total result count */
0 /* timeout */);
Map<String, Serializable> properties = new HashMap<>();
properties.put(SecurityConstants.SECURITY_SUBJECT,
opsSecuritySupport.getSubject(updateRequest));
return new QueryRequestImpl(queryImpl, false, updateRequest.getStoreIds(), properties);
}
private UpdateRequest validateLocalSource(UpdateRequest updateRequest)
throws SourceUnavailableException {
if (Requests.isLocal(updateRequest)
&& !sourceOperations.isSourceAvailable(sourceOperations.getCatalog())) {
throw new SourceUnavailableException(
"Local provider is not available, cannot perform update operation.");
}
return updateRequest;
}
private UpdateStorageResponse processPostUpdateStoragePlugins(
UpdateStorageResponse updateStorageResponse) {
for (final PostUpdateStoragePlugin plugin : frameworkProperties.getPostUpdateStoragePlugins()) {
try {
updateStorageResponse = plugin.process(updateStorageResponse);
} catch (PluginExecutionException e) {
LOGGER.debug("Plugin processing failed. This is allowable. Skipping to next plugin.",
e);
}
}
return updateStorageResponse;
}
private UpdateStorageRequest processPreUpdateStoragePlugins(
UpdateStorageRequest updateStorageRequest) {
for (final PreUpdateStoragePlugin plugin : frameworkProperties.getPreUpdateStoragePlugins()) {
try {
updateStorageRequest = plugin.process(updateStorageRequest);
} catch (PluginExecutionException e) {
LOGGER.debug("Plugin processing failed. This is allowable. Skipping to next plugin.",
e);
}
}
return updateStorageRequest;
}
private String getAttributeStringValue(Metacard mcard, String attribute) {
return Optional.of(mcard)
.map(m -> m.getAttribute(attribute))
.map(Attribute::getValue)
.map(Object::toString)
.orElse("");
}
private void logFailedQueryInfo(UpdateRequest updateRequest, QueryResponse query) {
if (LOGGER.isDebugEnabled()) {
final String attributeName = updateRequest.getAttributeName();
Set<String> queryResults = query.getResults()
.stream()
.map(Result::getMetacard)
.map(m -> m.getAttribute(attributeName))
.filter(Objects::nonNull)
.map(Attribute::getValue)
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.toSet());
LOGGER.debug(
"While rewriting the query, did not get a metacardId corresponding to every attribute.");
LOGGER.debug("Original Update By attribute was: {}", attributeName);
LOGGER.debug("Unable to get Metacard IDs from metacards:: {}",
updateRequest.getUpdates()
.stream()
.map(Map.Entry::getKey)
.map(Object::toString)
.filter(s -> !queryResults.contains(s))
.collect(Collectors.joining(", ", "[", "]")));
}
}
private UpdateStorageRequest applyAttributeOverrides(UpdateStorageRequest updateStorageRequest,
Map<String, Metacard> metacardMap) {
OverrideAttributesSupport.overrideAttributes(updateStorageRequest.getContentItems(),
metacardMap);
return updateStorageRequest;
}
}