/**
* 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.core.resourcestatus.metacard;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.codice.ddf.configuration.SystemInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.cache.ResourceCacheInterface;
import ddf.catalog.cache.impl.CacheKey;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.data.impl.AttributeImpl;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.operation.ResourceRequest;
import ddf.catalog.operation.impl.ResourceRequestById;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.PostQueryPlugin;
import ddf.catalog.plugin.StopProcessingException;
import ddf.catalog.resource.data.ReliableResource;
/**
* {@link PostQueryPlugin} that checks the {@link ddf.catalog.cache.impl.ResourceCache} for existence
* of each {@link Metacard}'s related {@link ddf.catalog.resource.Resource} and
* adds an {@link ddf.catalog.data.Attribute} to each {@link Metacard} in the {@link QueryResponse}.
*/
public class MetacardResourceStatus implements PostQueryPlugin {
private static final Logger LOGGER = LoggerFactory.getLogger(MetacardResourceStatus.class);
private static final String INTERNAL_LOCAL_RESOURCE = "internal.local-resource";
private static final String LOCAL_CONTENT_SCHEME = "content:";
private ResourceCacheInterface cache;
public MetacardResourceStatus(ResourceCacheInterface cache) {
this.cache = cache;
}
@Override
public QueryResponse process(QueryResponse input)
throws PluginExecutionException, StopProcessingException {
List<Result> results = input.getResults();
results.stream()
.map(Result::getMetacard)
.filter(Objects::nonNull)
.forEach(this::addResourceLocalAttribute);
return input;
}
private void addResourceLocalAttribute(Metacard metacard) {
boolean isResourceLocal = false;
if (!hasResourceUri(metacard)) {
isResourceLocal = false;
} else {
isResourceLocal = isResourceLocal(metacard);
}
metacard.setAttribute(
new AttributeImpl(INTERNAL_LOCAL_RESOURCE, isResourceLocal));
}
private boolean isResourceLocal(Metacard metacard) {
return (doesSourceIdMatchLocalSiteName(metacard) && isResourceUriLocal(metacard))
|| isResourceCached(metacard, new ResourceRequestById(metacard.getId()));
}
private boolean isResourceCached(Metacard metacard, ResourceRequest resourceRequest) {
String key = getCacheKey(metacard, resourceRequest);
ReliableResource cachedResource = (ReliableResource) cache.getValid(key, metacard);
return cachedResource != null;
}
private boolean hasResourceUri(Metacard metacard) {
Optional<String> resourceUri = Optional.ofNullable(metacard.getResourceURI())
.map(uri -> uri.toString());
return resourceUri.isPresent();
}
private boolean isResourceUriLocal(Metacard metacard) {
return hasResourceUri(metacard) && metacard.getResourceURI()
.toString()
.startsWith(LOCAL_CONTENT_SCHEME);
}
private boolean doesSourceIdMatchLocalSiteName(Metacard metacard) {
Optional<String> sourceId = Optional.ofNullable(metacard.getSourceId());
if (sourceId.isPresent()) {
String sourceIdLowerCase = sourceId.get()
.toLowerCase();
return sourceIdLowerCase.equals(getLocalSiteName());
} else {
LOGGER.debug(
"Unable to determine if the source id in metacard {} matches the local site name because the metacard did not contain a source id attribute.",
metacard.getId());
return false;
}
}
private String getCacheKey(Metacard metacard, ResourceRequest resourceRequest) {
CacheKey cacheKey = new CacheKey(metacard, resourceRequest);
return cacheKey.generateKey();
}
String getLocalSiteName() {
return SystemInfo.getSiteName()
.toLowerCase();
}
}