/**
* Copyright (c) Codice Foundation
*
* 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.
*
* 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.transformer;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.apache.commons.lang.StringUtils;
import org.codice.ddf.spatial.ogc.csw.catalog.common.CswConstants;
import org.codice.ddf.spatial.ogc.csw.catalog.common.CswJAXBElementProvider;
import org.codice.ddf.spatial.ogc.csw.catalog.common.CswRecordCollection;
import org.codice.ddf.spatial.ogc.csw.catalog.converter.CswTransformProvider;
import org.codice.ddf.spatial.ogc.csw.catalog.converter.GetRecordsResponseConverter;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.opengis.filter.Filter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import ddf.catalog.data.BinaryContent;
import ddf.catalog.data.Result;
import ddf.catalog.data.impl.MetacardImpl;
import ddf.catalog.data.impl.ResultImpl;
import ddf.catalog.operation.SourceResponse;
import ddf.catalog.operation.impl.QueryImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.operation.impl.SourceResponseImpl;
import ddf.catalog.transform.CatalogTransformerException;
import net.opengis.cat.csw.v_2_0_2.AcknowledgementType;
import net.opengis.cat.csw.v_2_0_2.GetRecordsType;
import net.opengis.cat.csw.v_2_0_2.ResultType;
public class TestCswQueryResponseTransformer {
private CswQueryResponseTransformer transformer;
private GetRecordsResponseConverter mockConverter;
private CswTransformProvider mockTransformProvider;
private Filter filter = mock(Filter.class);
@Before
public void before() {
mockConverter = mock(GetRecordsResponseConverter.class);
mockTransformProvider = mock(CswTransformProvider.class);
transformer = new CswQueryResponseTransformer(mockConverter);
when(mockConverter.canConvert(any(Class.class))).thenReturn(true);
when(mockTransformProvider.canConvert(any(Class.class))).thenReturn(true);
}
@Test
public void testMarshalRecordCollection() throws WebApplicationException, IOException,
JAXBException, CatalogTransformerException {
GetRecordsType query = new GetRecordsType();
query.setResultType(ResultType.RESULTS);
query.setMaxRecords(BigInteger.valueOf(6));
query.setStartPosition(BigInteger.valueOf(4));
SourceResponse sourceResponse = createSourceResponse(query, 22);
Map<String, Serializable> args = new HashMap<>();
args.put(CswConstants.OUTPUT_SCHEMA_PARAMETER, CswConstants.CSW_OUTPUT_SCHEMA);
args.put(CswConstants.RESULT_TYPE_PARAMETER, ResultType.RESULTS);
ArgumentCaptor<CswRecordCollection> captor = ArgumentCaptor
.forClass(CswRecordCollection.class);
BinaryContent content = transformer.transform(sourceResponse, args);
verify(mockConverter, times(1))
.marshal(captor.capture(), any(HierarchicalStreamWriter.class),
any(MarshallingContext.class));
CswRecordCollection collection = captor.getValue();
assertThat(collection.getResultType(), is(ResultType.RESULTS));
assertThat(collection.getOutputSchema(), is(CswConstants.CSW_OUTPUT_SCHEMA));
assertThat(collection.getStartPosition(), is(4));
assertThat(collection.isById(), is(false));
assertThat(collection.getNumberOfRecordsMatched(), is(22L));
assertThat(collection.getNumberOfRecordsReturned(), is(6L));
assertThat(collection.getCswRecords().isEmpty(), is(false));
}
@Test
public void testMarshalAcknowledgement() throws WebApplicationException, IOException,
JAXBException, CatalogTransformerException {
GetRecordsType query = new GetRecordsType();
query.setResultType(ResultType.VALIDATE);
query.setMaxRecords(BigInteger.valueOf(6));
query.setStartPosition(BigInteger.valueOf(4));
SourceResponse sourceResponse = createSourceResponse(query, 22);
Map<String, Serializable> args = new HashMap<String, Serializable>();
args.put(CswConstants.RESULT_TYPE_PARAMETER, ResultType.VALIDATE);
args.put(CswConstants.GET_RECORDS, query);
BinaryContent content = transformer.transform(sourceResponse, args);
String xml = new String(content.getByteArray());
JAXBElement<?> jaxb = (JAXBElement<?>) getJaxBContext().createUnmarshaller()
.unmarshal(new ByteArrayInputStream(xml.getBytes("UTF-8")));
assertThat(jaxb.getValue(), is(instanceOf(AcknowledgementType.class)));
AcknowledgementType response = (AcknowledgementType) jaxb.getValue();
assertThat(response.getEchoedRequest().getAny(), is(instanceOf(JAXBElement.class)));
JAXBElement<?> jaxB = (JAXBElement<?>) response.getEchoedRequest().getAny();
assertThat(jaxB.getValue(), is(instanceOf(GetRecordsType.class)));
}
@Test
public void testMarshalRecordCollectionByIdRequest() throws WebApplicationException,
IOException, JAXBException, CatalogTransformerException {
SourceResponse sourceResponse = createSourceResponse(null, 2);
Map<String, Serializable> args = new HashMap<String, Serializable>();
args.put(CswConstants.IS_BY_ID_QUERY, true);
ArgumentCaptor<CswRecordCollection> captor = ArgumentCaptor
.forClass(CswRecordCollection.class);
BinaryContent content = transformer.transform(sourceResponse, args);
verify(mockConverter, times(1))
.marshal(captor.capture(), any(HierarchicalStreamWriter.class),
any(MarshallingContext.class));
CswRecordCollection collection = captor.getValue();
assertThat(collection.isById(), is(true));
}
private SourceResponse createSourceResponse(GetRecordsType request, int resultCount) {
int first = 1;
int last = 2;
int max = 0;
if (request != null) {
first = request.getStartPosition().intValue();
max = request.getMaxRecords().intValue();
int next = request.getMaxRecords().intValue() + first;
last = next - 1;
if (last >= resultCount) {
last = resultCount;
next = 0;
}
}
int returned = last - first + 1;
QueryImpl query = new QueryImpl(filter, first, max, null, true, 0);
SourceResponseImpl sourceResponse = new SourceResponseImpl(new QueryRequestImpl(query),
createResults(first, last));
sourceResponse.setHits(resultCount);
return sourceResponse;
}
private List<Result> createResults(int start, int finish) {
List<Result> list = new LinkedList<Result>();
for (int i = start; i <= finish; i++) {
MetacardImpl metacard = new MetacardImpl();
metacard.setId("id_" + i);
metacard.setSourceId("source_" + i);
metacard.setTitle("title " + i);
list.add(new ResultImpl(metacard));
}
return list;
}
private JAXBContext getJaxBContext() throws JAXBException {
JAXBContext context = null;
String contextPath = StringUtils
.join(new String[] {CswConstants.OGC_CSW_PACKAGE, CswConstants.OGC_FILTER_PACKAGE,
CswConstants.OGC_GML_PACKAGE, CswConstants.OGC_OWS_PACKAGE}, ":");
context = JAXBContext
.newInstance(contextPath, CswJAXBElementProvider.class.getClassLoader());
return context;
}
}