/** * 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.wfs.catalog.endpoint; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.xml.namespace.QName; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaComplexContent; import org.apache.ws.commons.schema.XmlSchemaComplexContentExtension; import org.apache.ws.commons.schema.XmlSchemaComplexType; import org.apache.ws.commons.schema.XmlSchemaElement; import org.apache.ws.commons.schema.XmlSchemaSequence; import org.apache.ws.commons.schema.XmlSchemaSequenceMember; import org.apache.ws.commons.schema.XmlSchemaType; import org.apache.ws.commons.schema.constants.Constants; import org.codice.ddf.spatial.ogc.wfs.catalog.common.WfsQnameBuilder; import org.codice.ddf.spatial.ogc.wfs.catalog.endpoint.utils.ServicePropertiesMap; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import ddf.catalog.CatalogFramework; import ddf.catalog.data.AttributeDescriptor; import ddf.catalog.data.AttributeType.AttributeFormat; import ddf.catalog.data.ContentType; import ddf.catalog.data.MetacardType; import ddf.catalog.data.impl.BasicTypes; import ddf.catalog.data.impl.ContentTypeImpl; import ddf.catalog.operation.SourceInfoRequest; import ddf.catalog.operation.SourceInfoResponse; import ddf.catalog.source.SourceDescriptor; import ddf.catalog.source.SourceUnavailableException; import ddf.catalog.source.impl.SourceDescriptorImpl; public class TestFeatureTypeSchemaCache { private static final String REPORT = "report"; private static final String THING = "thing"; private static BundleContext mockContext = mock(BundleContext.class); private static ServicePropertiesMap<MetacardType> mockServiceList = new ServicePropertiesMap<MetacardType>(); private static CatalogFramework catalogFramework = mock(CatalogFramework.class); private static SourceInfoResponse mockSourceInfoResponse = mock(SourceInfoResponse.class); private FeatureTypeSchemaCache cache; private Set<ContentType> contentTypes = new HashSet<ContentType>(); private List<String> basicNames = getBasicAttributeNames(); @BeforeClass public static void beforeClass() { when(mockContext.getService(any(ServiceReference.class))) .thenReturn(new MockMetacardType()); } @Before public void setUp() throws SourceUnavailableException { mockServiceList.bindService(new MockMetacardType(), MockMetacardType.PROPERTIES); when(catalogFramework.getSourceInfo(any(SourceInfoRequest.class))) .thenReturn(mockSourceInfoResponse); Set<SourceDescriptor> sourceDescriptors = new HashSet<SourceDescriptor>(); contentTypes.add(new ContentTypeImpl(MockMetacardType.IMAGE, MockMetacardType.IMAGE)); contentTypes.add(new ContentTypeImpl(MockMetacardType.VIDEO, MockMetacardType.VIDEO)); sourceDescriptors.add(new SourceDescriptorImpl("sourceId", contentTypes)); when(mockSourceInfoResponse.getSourceInfo()).thenReturn(sourceDescriptors); cache = new FeatureTypeSchemaCache(mockContext, mockServiceList, catalogFramework); } @Test public void testGetSchemaByQnameMockMetacard() throws UnsupportedEncodingException { XmlSchema schema = cache.getSchemaByQname( WfsQnameBuilder.buildQName(MockMetacardType.NAME, MockMetacardType.IMAGE)); StringWriter writer = new StringWriter(); schema.write(writer); assertNotNull(schema); // Get the root element XmlSchemaElement rootElement = schema.getElementByName(MockMetacardType.IMAGE); assertNotNull(rootElement); // Validate the type its defined as exists XmlSchemaType rootType = schema.getTypeByName(rootElement.getSchemaTypeName()); assertNotNull(rootType); assertTrue(rootType instanceof XmlSchemaComplexType); XmlSchemaComplexType complexType = (XmlSchemaComplexType) rootType; // Validate the Complex Type is formed correctly assertTrue(complexType.getContentModel() instanceof XmlSchemaComplexContent); XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent) complexType .getContentModel(); assertTrue(complexContent.getContent() instanceof XmlSchemaComplexContentExtension); XmlSchemaSequence sequence = (XmlSchemaSequence) ((XmlSchemaComplexContentExtension) complexContent .getContent()).getParticle(); assertNotNull(sequence); List<XmlSchemaSequenceMember> elements = sequence.getItems(); // Check each of the AttributeDescriptors were translated as expected. Set<AttributeDescriptor> descriptors = new MockMetacardType().getAttributeDescriptors(); for (AttributeDescriptor descriptor : descriptors) { // We cannot translate "OBJECT" if (descriptor.getType().getAttributeFormat() != AttributeFormat.OBJECT) { Boolean found = false; for (XmlSchemaSequenceMember xmlSchemaSequenceMember : elements) { XmlSchemaElement element = (XmlSchemaElement) xmlSchemaSequenceMember; if (descriptor.getName().equals(element.getName())) { assertTrue(compareDescriptorTypeToElementType( descriptor.getType().getAttributeFormat(), element.getSchemaTypeName())); assertNotBasicAttribute(element); found = true; } } } } } @Test public void testGetSchemaByQnameInvalidQname() { XmlSchema schema = cache.getSchemaByQname(new QName("DNE")); assertNull(schema); } @Test public void testGetFeatureTypesByContentTypes() { // Have the mockService Reference return a different list. mockServiceList.unbindService(new MockMetacardType()); contentTypes.clear(); contentTypes.add(new ContentTypeImpl(THING, THING)); contentTypes.add(new ContentTypeImpl(REPORT, REPORT)); Set<QName> qnames = cache.getFeatureTypeQnames(); assertEquals(2, qnames.size()); for (QName qName : qnames) { assertTrue(REPORT.equals(qName.getLocalPart()) || THING.equals(qName.getLocalPart())); } } @Test public void testGetFeatureTypesByContentTypesNullList() { Set<QName> qnames = cache.getFeatureTypeQnames(); assertEquals(2, qnames.size()); for (QName qName : qnames) { assertTrue(MockMetacardType.IMAGE.equals(qName.getLocalPart()) || MockMetacardType.VIDEO .equals(qName.getLocalPart())); assertTrue(qName.getPrefix().startsWith(MockMetacardType.NAME)); } } @Test public void testRegisterRemoveOldContentTypes() { assertEquals(contentTypes.size(), cache.getFeatureTypeQnames().size()); ContentType ct = new ContentTypeImpl(REPORT, REPORT); contentTypes.add(ct); assertEquals(contentTypes.size(), cache.getFeatureTypeQnames().size()); contentTypes.remove(ct); assertEquals(contentTypes.size(), cache.getFeatureTypeQnames().size()); } private Boolean compareDescriptorTypeToElementType(AttributeFormat format, QName schemaType) { switch (format) { case STRING: return Constants.XSD_STRING.equals(schemaType); case XML: return Constants.XSD_ANYTYPE.equals(schemaType); case BOOLEAN: return Constants.XSD_BOOLEAN.equals(schemaType); case DATE: return Constants.XSD_DATETIME.equals(schemaType); case SHORT: return Constants.XSD_SHORT.equals(schemaType); case INTEGER: return Constants.XSD_INTEGER.equals(schemaType); case LONG: return Constants.XSD_LONG.equals(schemaType); case FLOAT: return Constants.XSD_FLOAT.equals(schemaType); case DOUBLE: return Constants.XSD_DOUBLE.equals(schemaType); case GEOMETRY: return FeatureTypeSchemaCache.GML_GEO_PROPERTY_TYPE.equals(schemaType); case BINARY: return Constants.XSD_BASE64.equals(schemaType); case OBJECT: default: return false; } } private boolean assertNotBasicAttribute(XmlSchemaElement element) { return !basicNames.contains(element.getName()); } private List<String> getBasicAttributeNames() { List<String> basicNames = new ArrayList<String>( BasicTypes.BASIC_METACARD.getAttributeDescriptors().size()); for (AttributeDescriptor ad : BasicTypes.BASIC_METACARD.getAttributeDescriptors()) { basicNames.add(ad.getName()); } return basicNames; } }