/** * 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 org.codice.ddf.spatial.ogc.csw.catalog.converter; import java.util.List; import javax.measure.converter.ConversionException; import org.codice.ddf.spatial.ogc.csw.catalog.common.CswConstants; import org.codice.ddf.spatial.ogc.csw.catalog.common.CswRecordCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import ddf.catalog.data.Attribute; import ddf.catalog.data.Metacard; import ddf.catalog.data.impl.MetacardImpl; /** * Converts a {@link org.codice.ddf.spatial.ogc.csw.catalog.common.CswRecordCollection} into a * {@link net.opengis.cat.csw.v_2_0_2.GetRecordsResponseType} with CSW records */ public class GetRecordsResponseConverter implements Converter { private static final Logger LOGGER = LoggerFactory.getLogger(GetRecordsResponseConverter.class); private Converter transformProvider; /** * Creates a new GetRecordsResponseConverter Object * * @param transformProvider The converter which will transform a {@link Metacard} to a the appropriate XML * format and vice versa. */ public GetRecordsResponseConverter(Converter transformProvider) { this.transformProvider = transformProvider; } @Override public boolean canConvert(Class type) { boolean canConvert = CswRecordCollection.class.isAssignableFrom(type); LOGGER.debug("Can convert? {}", canConvert); return canConvert; } @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { throw new UnsupportedOperationException(); } /** * Parses GetRecordsResponse XML of this form: * <p> * <pre> * {@code * <csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw"> * <csw:SearchStatus status="subset" timestamp="2013-05-01T02:13:36+0200"/> * <csw:SearchResults elementSet="full" nextRecord="11" * numberOfRecordsMatched="479" numberOfRecordsReturned="10" * recordSchema="csw:Record"> * <csw:Record xmlns:csw="http://www.opengis.net/cat/csw"> * ... * </csw:Record> * <csw:Record xmlns:csw="http://www.opengis.net/cat/csw"> * ... * </csw:Record> * } * </pre> */ @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { if (transformProvider == null) { throw new ConversionException( "Unable to locate Converter for outputSchema: " + CswConstants.CSW_OUTPUT_SCHEMA); } CswRecordCollection cswRecords = new CswRecordCollection(); List<Metacard> metacards = cswRecords.getCswRecords(); XStreamAttributeCopier.copyXmlNamespaceDeclarationsIntoContext(reader, context); while (reader.hasMoreChildren()) { reader.moveDown(); if (reader.getNodeName() .contains("SearchResults")) { setSearchResults(reader, cswRecords); // Loop through the <SearchResults>, converting each // <csw:Record> into a Metacard while (reader.hasMoreChildren()) { reader.moveDown(); // move down to the <csw:Record> tag String name = reader.getNodeName(); LOGGER.debug("node name = {}", name); Metacard metacard = (Metacard) context.convertAnother(null, MetacardImpl.class, transformProvider); metacards.add(metacard); // move back up to the <SearchResults> parent of the // <csw:Record> tags reader.moveUp(); } } reader.moveUp(); } LOGGER.debug("Unmarshalled {} metacards", metacards.size()); if (LOGGER.isTraceEnabled()) { int index = 1; for (Metacard m : metacards) { LOGGER.trace("metacard {}: ", index); LOGGER.trace(" id = {}", m.getId()); LOGGER.trace(" title = {}", m.getTitle()); // Some CSW services return an empty bounding box, i.e., no lower // and/or upper corner positions Attribute boundingBoxAttr = m.getAttribute("BoundingBox"); if (boundingBoxAttr != null) { LOGGER.trace(" bounding box = {}", boundingBoxAttr.getValue()); } index++; } } return cswRecords; } private void setSearchResults(HierarchicalStreamReader reader, CswRecordCollection cswRecords) { String numberOfRecordsMatched = reader.getAttribute("numberOfRecordsMatched"); LOGGER.debug("numberOfRecordsMatched = {}", numberOfRecordsMatched); String numberOfRecordsReturned = reader.getAttribute("numberOfRecordsReturned"); LOGGER.debug("numberOfRecordsReturned = {}", numberOfRecordsReturned); cswRecords.setNumberOfRecordsMatched(Long.parseLong(numberOfRecordsMatched)); cswRecords.setNumberOfRecordsReturned(Long.parseLong(numberOfRecordsReturned)); } }