/** * 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.endpoint.reader; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.IOException; import java.io.Serializable; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import org.apache.commons.io.IOUtils; import org.codice.ddf.spatial.ogc.csw.catalog.common.CswConstants; import org.codice.ddf.spatial.ogc.csw.catalog.common.transaction.CswTransactionRequest; import org.codice.ddf.spatial.ogc.csw.catalog.common.transaction.DeleteAction; import org.codice.ddf.spatial.ogc.csw.catalog.common.transaction.InsertAction; import org.codice.ddf.spatial.ogc.csw.catalog.common.transaction.UpdateAction; import org.codice.ddf.spatial.ogc.csw.catalog.converter.CswRecordConverter; import org.codice.ddf.spatial.ogc.csw.catalog.endpoint.CswQueryFactoryTest; import org.junit.Before; import org.junit.Test; import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import ddf.catalog.data.AttributeRegistry; import ddf.catalog.data.Metacard; import ddf.catalog.data.impl.AttributeRegistryImpl; import ddf.catalog.data.impl.types.AssociationsAttributes; import ddf.catalog.data.impl.types.ContactAttributes; import ddf.catalog.data.impl.types.CoreAttributes; import ddf.catalog.data.impl.types.LocationAttributes; import ddf.catalog.data.impl.types.MediaAttributes; import ddf.catalog.data.impl.types.TopicAttributes; import ddf.catalog.data.types.Topic; import net.opengis.cat.csw.v_2_0_2.QueryConstraintType; import net.opengis.filter.v_1_1_0.FilterType; public class TestTransactionMessageBodyReader { private static final int COUNT = 100; private static final String INSERT_REQUEST_START = "<csw:Transaction service=\"CSW\" version=\"2.0.2\" verboseResponse=\"true\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\">\n" + " <csw:Insert typeName=\"csw:Record\">\n"; private static final String INSERT_REQUEST_END = "</csw:Insert>\n" + "</csw:Transaction>"; private static final String RECORD_XML = "<csw:Record\n" + " xmlns:ows=\"http://www.opengis.net/ows\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\"\n" + " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" + " xmlns:dct=\"http://purl.org/dc/terms/\"\n" + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n" + " <dc:identifier>123</dc:identifier>\n" + " <dc:title>Aliquam fermentum purus quis arcu</dc:title>\n" + " <dc:type>http://purl.org/dc/dcmitype/Text</dc:type>\n" + " <dc:subject>Hydrography--Dictionaries</dc:subject>\n" + " <dc:format>application/pdf</dc:format>\n" + " <dc:date>2006-05-12</dc:date>\n" + " <dct:abstract>Vestibulum quis ipsum sit amet metus imperdiet vehicula. Nulla scelerisque cursus mi.</dct:abstract>\n" + " <ows:BoundingBox crs=\"urn:x-ogc:def:crs:EPSG:6.11:4326\">\n" + " <ows:LowerCorner>44.792 -6.171</ows:LowerCorner>\n" + " <ows:UpperCorner>51.126 -2.228</ows:UpperCorner>\n" + " </ows:BoundingBox>\n" + " </csw:Record>\n"; private static final String DELETE_REQUEST_FILTER_XML = "<csw:Transaction service=\"CSW\"\n" + " version=\"2.0.2\" xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\"\n" + " xmlns:ogc=\"http://www.opengis.net/ogc\">\n" + " <csw:Delete typeName=\"csw:Record\" handle=\"something\">\n" + " <csw:Constraint version=\"2.0.0\">\n" + " <ogc:Filter>\n" + " <ogc:PropertyIsEqualTo>\n" + " <ogc:PropertyName>title</ogc:PropertyName>\n" + " <ogc:Literal>Aliquam fermentum purus quis arcu</ogc:Literal>\n" + " </ogc:PropertyIsEqualTo>\n" + " </ogc:Filter>\n" + " </csw:Constraint>\n" + " </csw:Delete>\n" + "</csw:Transaction>"; private static final String DELETE_REQUEST_CQL_XML = "<csw:Transaction service=\"CSW\"\n" + " version=\"2.0.2\" xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\"\n" + " xmlns:ogc=\"http://www.opengis.net/ogc\">\n" + " <csw:Delete typeName=\"csw:Record\" handle=\"something\">\n" + " <csw:Constraint version=\"2.0.0\">\n" + " <ogc:CqlText>\n" + " title = 'foo'\n" + " </ogc:CqlText>\n" + " </csw:Constraint>\n" + " </csw:Delete>\n" + "</csw:Transaction>"; private static final String INSERT_AND_DELETE_REQUEST_XML = "<csw:Transaction\n" + " service=\"CSW\"\n" + " version=\"2.0.2\"\n" + " verboseResponse=\"true\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\"\n" + " xmlns:ogc=\"http://www.opengis.net/ogc\">\n" + " <csw:Insert typeName=\"csw:Record\">\n" + " <csw:Record\n" + " xmlns:ows=\"http://www.opengis.net/ows\"\n" + " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" + " xmlns:dct=\"http://purl.org/dc/terms/\"\n" + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n" + " <dc:identifier>123</dc:identifier>\n" + " <dc:title>A Different Title</dc:title>\n" + " <dc:type>http://purl.org/dc/dcmitype/Text</dc:type>\n" + " <dc:subject>Hydrography--Dictionaries</dc:subject>\n" + " <dc:format>application/pdf</dc:format>\n" + " <dc:date>2006-05-12</dc:date>\n" + " <dct:abstract>Vestibulum quis ipsum sit amet metus imperdiet vehicula. Nulla scelerisque cursus mi.</dct:abstract>\n" + " <ows:BoundingBox crs=\"urn:x-ogc:def:crs:EPSG:6.11:4326\">\n" + " <ows:LowerCorner>44.792 -6.171</ows:LowerCorner>\n" + " <ows:UpperCorner>51.126 -2.228</ows:UpperCorner>\n" + " </ows:BoundingBox>\n" + " </csw:Record>\n" + " </csw:Insert>\n" + " <csw:Delete typeName=\"csw:Record\" handle=\"something\">\n" + " <csw:Constraint version=\"2.0.0\">\n" + " <ogc:CqlText>\n" + " title = 'foo'\n" + " </ogc:CqlText>\n" + " </csw:Constraint>\n" + " </csw:Delete>\n" + " </csw:Transaction>"; private static final String UPDATE_REQUEST_BY_RECORD_XML = "<csw:Transaction\n" + " service=\"CSW\"\n" + " version=\"2.0.2\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\">\n" + " <csw:Update>\n" + " <csw:Record\n" + " xmlns:ows=\"http://www.opengis.net/ows\"\n" + " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" + " xmlns:dct=\"http://purl.org/dc/terms/\"\n" + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n" + " <dc:identifier>123</dc:identifier>\n" + " <dc:title>Aliquam fermentum purus quis arcu</dc:title>\n" + " <dc:type>http://purl.org/dc/dcmitype/Text</dc:type>\n" + " <dc:subject>Hydrography--Dictionaries</dc:subject>\n" + " <dc:format>application/pdf</dc:format>\n" + " <dc:date>2008-08-10</dc:date>\n" + " <dct:abstract>Vestibulum quis ipsum sit amet metus imperdiet vehicula. Nulla scelerisque cursus mi.</dct:abstract>\n" + " <ows:BoundingBox crs=\"urn:x-ogc:def:crs:EPSG:6.11:4326\">\n" + " <ows:LowerCorner>1.0 2.0</ows:LowerCorner>\n" + " <ows:UpperCorner>3.0 4.0</ows:UpperCorner>\n" + " </ows:BoundingBox>\n" + " </csw:Record>\n" + " </csw:Update>\n" + "</csw:Transaction>"; private static final String UPDATE_REQUEST_BY_CONSTRAINT_XML = "<csw:Transaction\n" + " service=\"CSW\"\n" + " version=\"2.0.2\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\">\n" + " <csw:Update xmlns:ogc=\"http://www.opengis.net/ogc\">\n" + " <csw:RecordProperty>\n" + " <csw:Name>subject</csw:Name>\n" + " <csw:Value>Foo</csw:Value>\n" + " </csw:RecordProperty>\n" + " <csw:RecordProperty>\n" + " <csw:Name>date</csw:Name>\n" + " <csw:Value>2015-07-21</csw:Value>\n" + " </csw:RecordProperty>\n" + " <csw:RecordProperty>\n" + " <csw:Name>location</csw:Name>\n" + " <csw:Value>\n" + " <ows:BoundingBox>\n" + " <ows:LowerCorner>1.0 2.0</ows:LowerCorner>\n" + " <ows:UpperCorner>3.0 4.0</ows:UpperCorner>\n" + " </ows:BoundingBox>\n" + " </csw:Value>\n" + " </csw:RecordProperty>\n" + " <csw:RecordProperty>\n" + " <csw:Name>format</csw:Name>\n" + " </csw:RecordProperty>\n" + " <csw:Constraint version=\"2.0.0\">\n" + " <ogc:Filter>\n" + " <ogc:PropertyIsEqualTo>\n" + " <ogc:PropertyName>format</ogc:PropertyName>\n" + " <ogc:Literal>application/pdf</ogc:Literal>\n" + " </ogc:PropertyIsEqualTo>\n" + " </ogc:Filter>\n" + " </csw:Constraint>\n" + " </csw:Update>\n" + "</csw:Transaction>"; private static final String MULTIPLE_UPDATES_REQUEST_XML = "<csw:Transaction\n" + " service=\"CSW\"\n" + " version=\"2.0.2\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\"\n" + " xmlns:ogc=\"http://www.opengis.net/ogc\">\n" + " <csw:Update handle=\"handle1\">\n" + " <csw:Record\n" + " xmlns:ows=\"http://www.opengis.net/ows\"\n" + " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" + " xmlns:dct=\"http://purl.org/dc/terms/\"\n" + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n" + " <dc:identifier>123</dc:identifier>\n" + " <dc:title>Aliquam fermentum purus quis arcu</dc:title>\n" + " <dc:type>http://purl.org/dc/dcmitype/Text</dc:type>\n" + " <dc:subject>Hydrography--Dictionaries</dc:subject>\n" + " <dc:format>application/pdf</dc:format>\n" + " <dc:date>2008-08-10</dc:date>\n" + " <dct:abstract>Vestibulum quis ipsum sit amet metus imperdiet vehicula. Nulla scelerisque cursus mi.</dct:abstract>\n" + " <ows:BoundingBox crs=\"urn:x-ogc:def:crs:EPSG:6.11:4326\">\n" + " <ows:LowerCorner>1.0 2.0</ows:LowerCorner>\n" + " <ows:UpperCorner>3.0 4.0</ows:UpperCorner>\n" + " </ows:BoundingBox>\n" + " </csw:Record>\n" + " </csw:Update>\n" + " <csw:Update handle=\"handle2\" typeName=\"csw:Record\">\n" + " <csw:RecordProperty>\n" + " <csw:Name>subject</csw:Name>\n" + " <csw:Value>foo</csw:Value>\n" + " </csw:RecordProperty>\n" + " <csw:Constraint version=\"2.0.0\">\n" + " <ogc:CqlText>\n" + " title = 'bar'\n" + " </ogc:CqlText>\n" + " </csw:Constraint>\n" + " </csw:Update>\n" + "</csw:Transaction>"; private static final String UPDATE_REQUEST_NO_RECORDPROPERTY_NAME_XML = "<csw:Transaction\n" + " service=\"CSW\"\n" + " version=\"2.0.2\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\">\n" + " <csw:Update xmlns:ogc=\"http://www.opengis.net/ogc\">\n" + " <csw:RecordProperty>\n" + " <csw:Value>Foo</csw:Value>\n" + " </csw:RecordProperty>\n" + " <csw:Constraint version=\"2.0.0\">\n" + " <ogc:Filter>\n" + " <ogc:PropertyIsEqualTo>\n" + " <ogc:PropertyName>format</ogc:PropertyName>\n" + " <ogc:Literal>application/pdf</ogc:Literal>\n" + " </ogc:PropertyIsEqualTo>\n" + " </ogc:Filter>\n" + " </csw:Constraint>\n" + " </csw:Update>\n" + "</csw:Transaction>"; private static final String UPDATE_REQUEST_NO_CONSTRAINT_XML = "<csw:Transaction\n" + " service=\"CSW\"\n" + " version=\"2.0.2\"\n" + " xmlns:csw=\"http://www.opengis.net/cat/csw/2.0.2\">\n" + " <csw:Update>\n" + " <csw:RecordProperty>\n" + " <csw:Name>subject</csw:Name>\n" + " <csw:Value>Foo</csw:Value>\n" + " </csw:RecordProperty>\n" + " </csw:Update>\n" + "</csw:Transaction>"; private CswRecordConverter cswRecordConverter; private AttributeRegistry registry = new AttributeRegistryImpl(); @Before public void setup() { cswRecordConverter = new CswRecordConverter(CswQueryFactoryTest.getCswMetacardType()); new CoreAttributes().getAttributeDescriptors().stream().forEach(d -> registry.register(d)); new ContactAttributes().getAttributeDescriptors().stream().forEach(d -> registry.register(d)); new LocationAttributes().getAttributeDescriptors().stream().forEach(d -> registry.register(d)); new MediaAttributes().getAttributeDescriptors().stream().forEach(d -> registry.register(d)); new TopicAttributes().getAttributeDescriptors().stream().forEach(d -> registry.register(d)); new AssociationsAttributes().getAttributeDescriptors().stream().forEach(d -> registry.register(d)); } @Test public void testIsReadable() throws Exception { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(cswRecordConverter, CswQueryFactoryTest.getCswMetacardType(), registry); assertThat(reader.isReadable(CswTransactionRequest.class, null, null, null), is(true)); assertThat(reader.isReadable(Object.class, null, null, null), is(false)); } @Test public void testReadInsertFrom() throws Exception { Converter mockConverter = mock(Converter.class); when(mockConverter.canConvert(any(Metacard.class.getClass()))).thenReturn(true); when(mockConverter.unmarshal(any(HierarchicalStreamReader.class), any(UnmarshallingContext.class))).thenReturn(mock(Metacard.class)); TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mockConverter, CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(getInsertRequest(COUNT))); assertThat(request, notNullValue()); assertThat(request.getInsertActions() .size(), is(1)); assertThat(request.getDeleteActions() .size(), is(0)); assertThat(request.getUpdateActions() .size(), is(0)); InsertAction insertAction = request.getInsertActions() .get(0); assertThat(insertAction, notNullValue()); assertThat(insertAction.getRecords() .size(), is(COUNT)); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(true)); } @Test public void testReadDeleteWithFilterFrom() throws IOException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mock(Converter.class), CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(DELETE_REQUEST_FILTER_XML)); assertThat(request, notNullValue()); assertThat(request.getDeleteActions() .size(), is(1)); assertThat(request.getInsertActions() .size(), is(0)); assertThat(request.getUpdateActions() .size(), is(0)); DeleteAction deleteAction = request.getDeleteActions() .get(0); assertThat(deleteAction, notNullValue()); assertThat(deleteAction.getTypeName(), is(CswConstants.CSW_RECORD)); assertThat(deleteAction.getHandle(), is("something")); assertThat(deleteAction.getConstraint(), notNullValue()); assertThat(deleteAction.getConstraint() .getFilter(), notNullValue()); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(false)); } @Test public void testReadDeleteWithCqlFrom() throws IOException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mock(Converter.class), CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(DELETE_REQUEST_CQL_XML)); assertThat(request, notNullValue()); assertThat(request.getDeleteActions() .size(), is(1)); assertThat(request.getInsertActions() .size(), is(0)); assertThat(request.getUpdateActions() .size(), is(0)); DeleteAction deleteAction = request.getDeleteActions() .get(0); assertThat(deleteAction, notNullValue()); assertThat(deleteAction.getTypeName(), is(CswConstants.CSW_RECORD)); assertThat(deleteAction.getHandle(), is("something")); assertThat(deleteAction.getConstraint(), notNullValue()); assertThat(deleteAction.getConstraint() .getCqlText() .trim(), is("title = 'foo'")); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(false)); } @Test public void testReadInsertAndDeleteFrom() throws IOException { Converter mockConverter = mock(Converter.class); when(mockConverter.canConvert(any(Metacard.class.getClass()))).thenReturn(true); when(mockConverter.unmarshal(any(HierarchicalStreamReader.class), any(UnmarshallingContext.class))).thenReturn(mock(Metacard.class)); TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mockConverter, CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(INSERT_AND_DELETE_REQUEST_XML)); assertThat(request, notNullValue()); assertThat(request.getDeleteActions() .size(), is(1)); assertThat(request.getInsertActions() .size(), is(1)); assertThat(request.getUpdateActions() .size(), is(0)); DeleteAction deleteAction = request.getDeleteActions() .get(0); assertThat(deleteAction, notNullValue()); assertThat(deleteAction.getTypeName(), is(CswConstants.CSW_RECORD)); assertThat(deleteAction.getHandle(), is("something")); assertThat(deleteAction.getConstraint(), notNullValue()); assertThat(deleteAction.getConstraint() .getCqlText() .trim(), is("title = 'foo'")); InsertAction insertAction = request.getInsertActions() .get(0); assertThat(insertAction, notNullValue()); assertThat(insertAction.getRecords() .size(), is(1)); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(true)); } @Test public void testReadUpdateByNewRecordFrom() throws IOException, ParseException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(cswRecordConverter, CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(UPDATE_REQUEST_BY_RECORD_XML)); assertThat(request, notNullValue()); assertThat(request.getInsertActions() .size(), is(0)); assertThat(request.getDeleteActions() .size(), is(0)); assertThat(request.getUpdateActions() .size(), is(1)); UpdateAction updateAction = request.getUpdateActions() .get(0); assertThat(updateAction, notNullValue()); assertThat(updateAction.getMetacard(), notNullValue()); Metacard metacard = updateAction.getMetacard(); assertThat(metacard.getId(), is("123")); assertThat(metacard.getTitle(), is("Aliquam fermentum purus quis arcu")); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = simpleDateFormat.parse("2008-08-10"); assertThat(metacard.getModifiedDate(), is(date)); assertThat(metacard.getLocation(), is( "POLYGON ((1.0 2.0, 3.0 2.0, 3.0 4.0, 1.0 4.0, 1.0 2.0))")); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(false)); } @Test public void testReadUpdateByConstraintFrom() throws IOException, ParseException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mock(Converter.class), CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(UPDATE_REQUEST_BY_CONSTRAINT_XML)); assertThat(request, notNullValue()); assertThat(request.getInsertActions() .size(), is(0)); assertThat(request.getDeleteActions() .size(), is(0)); assertThat(request.getUpdateActions() .size(), is(1)); UpdateAction updateAction = request.getUpdateActions() .get(0); assertThat(updateAction, notNullValue()); assertThat(updateAction.getMetacard(), nullValue()); Map<String, Serializable> recordProperties = updateAction.getRecordProperties(); assertThat(recordProperties, notNullValue()); assertThat(recordProperties.size(), is(4)); Serializable newSubjectValue = recordProperties.get(Topic.CATEGORY); assertThat(newSubjectValue, notNullValue()); assertThat(newSubjectValue, is("Foo")); Serializable newDateValue = recordProperties.get("modified"); assertThat(newDateValue, notNullValue()); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = simpleDateFormat.parse("2015-07-21"); assertThat(newDateValue, is(date)); Serializable newLocationValue = recordProperties.get("location"); assertThat(newLocationValue, notNullValue()); assertThat(newLocationValue, is("POLYGON ((1.0 2.0, 3.0 2.0, 3.0 4.0, 1.0 4.0, 1.0 2.0))")); Serializable newFormatValue = recordProperties.get("media.format"); // No <Value> was specified in the request. assertThat(newFormatValue, nullValue()); QueryConstraintType constraint = updateAction.getConstraint(); assertThat(constraint, notNullValue()); FilterType filter = constraint.getFilter(); assertThat(filter, notNullValue()); assertThat(filter.isSetComparisonOps(), is(true)); assertThat(filter.isSetLogicOps(), is(false)); assertThat(filter.isSetSpatialOps(), is(false)); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(false)); } @Test public void testReadMultipleUpdatesFrom() throws IOException, ParseException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(cswRecordConverter, CswQueryFactoryTest.getCswMetacardType(), registry); CswTransactionRequest request = reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream(MULTIPLE_UPDATES_REQUEST_XML)); assertThat(request, notNullValue()); assertThat(request.getInsertActions() .size(), is(0)); assertThat(request.getDeleteActions() .size(), is(0)); assertThat(request.getUpdateActions() .size(), is(2)); UpdateAction firstUpdateAction = request.getUpdateActions() .get(0); assertThat(firstUpdateAction, notNullValue()); assertThat(firstUpdateAction.getMetacard(), notNullValue()); Metacard metacard = firstUpdateAction.getMetacard(); assertThat(metacard.getId(), is("123")); assertThat(metacard.getTitle(), is("Aliquam fermentum purus quis arcu")); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = simpleDateFormat.parse("2008-08-10"); assertThat(metacard.getModifiedDate(), is(date)); assertThat(metacard.getLocation(), is( "POLYGON ((1.0 2.0, 3.0 2.0, 3.0 4.0, 1.0 4.0, 1.0 2.0))")); assertThat(firstUpdateAction.getHandle(), is("handle1")); assertThat(firstUpdateAction.getTypeName(), is(CswConstants.CSW_RECORD)); UpdateAction secondUpdateAction = request.getUpdateActions() .get(1); assertThat(secondUpdateAction, notNullValue()); assertThat(secondUpdateAction.getMetacard(), nullValue()); Map<String, Serializable> recordProperties = secondUpdateAction.getRecordProperties(); assertThat(recordProperties, notNullValue()); assertThat(recordProperties.size(), is(1)); Serializable newSubject = recordProperties.get("topic.category"); assertThat(newSubject, is("foo")); QueryConstraintType constraint = secondUpdateAction.getConstraint(); assertThat(constraint, notNullValue()); assertThat(constraint.getCqlText() .trim(), is("title = 'bar'")); assertThat(secondUpdateAction.getHandle(), is("handle2")); assertThat(secondUpdateAction.getTypeName(), is(CswConstants.CSW_RECORD)); assertThat(request.getService(), is(CswConstants.CSW)); assertThat(request.getVersion(), is(CswConstants.VERSION_2_0_2)); assertThat(request.isVerbose(), is(false)); } @Test(expected = ConversionException.class) public void testConversionExceptionWhenNoNameInUpdateRecordProperty() throws IOException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mock(Converter.class), CswQueryFactoryTest.getCswMetacardType(), registry); reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream( UPDATE_REQUEST_NO_RECORDPROPERTY_NAME_XML)); } @Test(expected = ConversionException.class) public void testConversionExceptionWhenNoConstraintInUpdate() throws IOException { TransactionMessageBodyReader reader = new TransactionMessageBodyReader(mock(Converter.class), CswQueryFactoryTest.getCswMetacardType(), registry); reader.readFrom(CswTransactionRequest.class, null, null, null, null, IOUtils.toInputStream( UPDATE_REQUEST_NO_CONSTRAINT_XML)); } private String getInsertRequest(int count) { StringBuilder builder = new StringBuilder(); builder.append(INSERT_REQUEST_START); for (int i = 0; i < count; i++) { builder.append(RECORD_XML); } builder.append(INSERT_REQUEST_END); return builder.toString(); } }