/* (c) 2015 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.csw.store.internal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.logging.Level;
import org.geoserver.catalog.CatalogInfo;
import org.geoserver.csw.DownloadLinkHandler;
import org.geoserver.csw.records.iso.MetaDataDescriptor;
import org.geotools.data.CloseableIterator;
import org.geotools.feature.AttributeImpl;
import org.geotools.feature.ComplexAttributeImpl;
import org.opengis.feature.ComplexAttribute;
import org.opengis.feature.Feature;
import org.opengis.feature.Property;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.ComplexType;
import org.opengis.feature.type.FeatureType;
import org.opengis.filter.expression.PropertyName;
/**
* {@link FeatureCustomizer} subclass to deal with ISO Metadata type
*/
public class MetadataCustomizer extends FeatureCustomizer {
private static final String TYPENAME = "MD_Metadata_Type";
private final static String ONLINE_PARENT_NODE = "gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine";
private final static AttributeDescriptor LINKAGE_ATTRIBUTE_DESCRIPTOR;
private final static AttributeDescriptor LINKAGE_URL_ATTRIBUTE_DESCRIPTOR;
private final static AttributeDescriptor ONLINE_RESOURCE_DESCRIPTOR;
static {
ComplexType distrPropType = (ComplexType) ((FeatureType) MetaDataDescriptor.METADATA_DESCRIPTOR
.getType()).getDescriptor("distributionInfo").getType();
ComplexType distrType = (ComplexType) distrPropType.getDescriptor("MD_Distribution")
.getType();
ComplexType transferOptionsPropType = (ComplexType) distrType.getDescriptor(
"transferOptions").getType();
ComplexType transferOptionsType = (ComplexType) transferOptionsPropType.getDescriptor(
"MD_DigitalTransferOptions").getType();
AttributeDescriptor onlinePropTypeDescr = (AttributeDescriptor) transferOptionsType
.getDescriptor("onLine");
ComplexType onlinePropType = (ComplexType) onlinePropTypeDescr.getType();
ONLINE_RESOURCE_DESCRIPTOR = (AttributeDescriptor) onlinePropType
.getDescriptor("CI_OnlineResource");
ComplexType onlineType = (ComplexType) ONLINE_RESOURCE_DESCRIPTOR.getType();
LINKAGE_ATTRIBUTE_DESCRIPTOR = (AttributeDescriptor) onlineType.getDescriptor("linkage");
ComplexType urlPropType = (ComplexType) LINKAGE_ATTRIBUTE_DESCRIPTOR.getType();
LINKAGE_URL_ATTRIBUTE_DESCRIPTOR = (AttributeDescriptor) urlPropType.getDescriptor("URL");
}
/** An instance of {@link DownloadLinkHandler}, used to deal with download links */
private DownloadLinkHandler downloadLinkHandler;
public void setDownloadLinkHandler(DownloadLinkHandler downloadLinkHandler) {
this.downloadLinkHandler = downloadLinkHandler;
}
public MetadataCustomizer() {
super(TYPENAME);
}
@Override
public void customizeFeature(Feature feature, CatalogInfo resource) {
PropertyName parentPropertyName = ff.property(ONLINE_PARENT_NODE,
MetaDataDescriptor.NAMESPACES);
Property parentProperty = (Property) parentPropertyName.evaluate(feature);
if (parentProperty == null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Unable to get the specified property for the current feature: "
+ ONLINE_PARENT_NODE + "\n No customization will be applied");
}
return;
}
// Getting feature values to be updated
Object value = parentProperty.getValue();
if (value == null || !(value instanceof Collection)) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Unable to get a value for the current property: "
+ parentPropertyName.getPropertyName()
+ "\n No customization will be applied");
}
return;
}
Collection<ComplexAttribute> onlineValues = (Collection<ComplexAttribute>) value;
// Copy the collection due to the immutable return
Collection<ComplexAttribute> updatedOnlineResources = new ArrayList<ComplexAttribute>(
(Collection<ComplexAttribute>) onlineValues);
// Invoke the DownloadLinkGenerator to generate links for the specified resource
CloseableIterator<String> links = null;
String link = null;
try {
links = downloadLinkHandler.generateDownloadLinks(resource);
if (links != null) {
while (links.hasNext()) {
link = links.next();
updatedOnlineResources.add(createOnlineResourceElement(link));
}
// link String should contain the last link generated
// let's recycle it to generate the full download link
updatedOnlineResources.add(createOnlineResourceElement(downloadLinkHandler.extractFullDownloadLink(link)));
}
} finally {
if (links != null) {
try {
links.close();
} catch (IOException e) {
// ignore it
}
}
}
// Update the onlineResources
parentProperty.setValue(updatedOnlineResources);
}
/**
* Create a new OnlineResource element for the link
*/
private ComplexAttribute createOnlineResourceElement(String link) {
// Setting new URL attribute
Property urlAttribute = new AttributeImpl(link, LINKAGE_URL_ATTRIBUTE_DESCRIPTOR, null);
// Setting linkageURL
Property linkage = new ComplexAttributeImpl(Collections.singletonList(urlAttribute),
LINKAGE_ATTRIBUTE_DESCRIPTOR, null);
return new ComplexAttributeImpl(Collections.singletonList(linkage), ONLINE_RESOURCE_DESCRIPTOR, null);
}
}