/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2010-2016, Geomatys
*
* This library 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;
* version 2.1 of the License.
*
* This library 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.
*/
package org.geotoolkit.feature.xml;
import com.vividsolutions.jts.geom.Geometry;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import static org.geotoolkit.data.AbstractFeatureStore.GML_311_NAMESPACE;
import org.geotoolkit.util.NamesExt;
import org.geotoolkit.feature.xml.jaxb.JAXBFeatureTypeReader;
import org.geotoolkit.feature.xml.jaxb.JAXBFeatureTypeWriter;
import org.geotoolkit.xml.DomCompare;
import org.junit.*;
import static org.junit.Assert.*;
import static org.geotoolkit.feature.xml.XmlTestData.*;
import org.opengis.feature.AttributeType;
import org.opengis.feature.FeatureAssociationRole;
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyType;
import org.xml.sax.SAXException;
/**
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class XmlFeatureTypeTest extends org.geotoolkit.test.TestBase {
private static void removeGMLBaseTypes(List<FeatureType> types){
for(int i=types.size()-1;i>=0;i--){
final FeatureType candidate = types.get(i);
if(Utils.GML_FEATURE_TYPES.contains(candidate.getName())){
types.remove(i);
}
}
}
@Test
public void testReadSimpleFeatureType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleType.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
assertEquals(simpleTypeFull, types.get(0));
}
@Test
public void testReadSimpleFeatureTypeWithAny() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleTypeWithAny.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName(GML_311_NAMESPACE,"TestSimple");
ftb.setSuperTypes(GMLConvention.ABSTRACTFEATURETYPE_31);
ftb.addAttribute(Object.class).setName(NamesExt.create(GML_311_NAMESPACE, "any")).setMinimumOccurs(0).setMaximumOccurs(1);
final FeatureType simpleTypeAny = ftb.build();
assertEquals(simpleTypeAny, types.get(0));
}
@Test
public void testReadSimpleFeatureTypeWithRestriction() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleTypeWithRestriction.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName(GML_311_NAMESPACE,"TestSimple");
ftb.setSuperTypes(GMLConvention.ABSTRACTFEATURETYPE_31);
ftb.addAttribute(String.class).setName(NamesExt.create(GML_311_NAMESPACE, "attString")).setMaximalLength(3)
.addCharacteristic(GMLConvention.NILLABLE_CHARACTERISTIC).setDefaultValue(Boolean.TRUE);
final FeatureType simpleTypeRestriction = ftb.build();
assertEquals(simpleTypeRestriction, types.get(0));
}
@Test
public void testReadMultiGeomFeatureType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/MultiGeomType.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
assertEquals(multiGeomType, types.get(0));
}
@Test
public void testReadWfsFeatureType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/wfs1.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
final String ns = "http://mapserver.gis.umn.edu/mapserver";
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName(ns,"quadrige");
ftb.setSuperTypes(GMLConvention.ABSTRACTFEATURETYPE_31);
ftb.addAttribute(Geometry.class).setName(ns, "msGeometry").setMinimumOccurs(0).setMaximumOccurs(1);
ftb.addAttribute(String.class).setName(ns, "C_SIEPT38").setMinimumOccurs(1).setMaximumOccurs(1);
ftb.addAttribute(String.class).setName(ns, "L_SIEPT").setMinimumOccurs(1).setMaximumOccurs(1);
final FeatureType wfsType = ftb.build();
assertEquals(wfsType, types.get(0));
}
@Test
public void testReadComplexFeatureType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/ComplexType.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
assertEquals(complexType, types.get(0));
}
@Test
@Ignore("Random test failure due to connection timeout or when internet is not available. See #GEOTK-485")
public void testReadVeryComplexFeatureType() throws Exception {
final JAXBFeatureTypeReader reader = getReader(true);
final URL url = new URL("http://schemas.opengis.net/gml/3.1.1/base/feature.xsd");
final List<FeatureType> types = reader.read(url);
removeGMLBaseTypes(types);
System.out.println("RESULT:" + types);
}
@Test
public void testReadPropertyGroupFeatureType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/propertyGroupType.xsd"));
FeatureType type = null;
for(FeatureType ft : types){
if(ft.getName().tip().toString().equals("SF_SamplingFeature")){
type = ft;
}
}
assertNotNull(type);
assertEquals(7, type.getProperties(true).size());
}
@Test
public void testReadInheritType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/inheritType.xsd"));
FeatureType type = null;
for(FeatureType ft : types){
if(ft.getName().tip().toString().equals("SF_SpatialSamplingFeature")){
type = ft;
}
}
assertNotNull(type);
assertEquals(8, type.getProperties(true).size());
}
@Test
public void testAttributesType() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleTypeWithAttribute.xsd"));
FeatureType type = null;
for(FeatureType ft : types){
if(ft.getName().tip().toString().equals("TestSimple")){
type = ft;
}
}
assertNotNull(type);
assertEquals(typeWithAtts, type);
}
@Test
public void testReadSimpleFeatureEmpty() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleTypeEmpty.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
assertEquals(typeEmpty, types.get(0));
}
@Test
public void testReadSimpleFeatureEmpty2() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(false);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleTypeEmpty.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
System.out.println(types.get(0));
//TODO we should check all properties
final FeatureType type = types.get(0);
final PropertyType itype = type.getProperty("identifier");
assertNotNull(itype);
assertTrue(itype instanceof AttributeType);
final AttributeType ct = (AttributeType) itype;
assertEquals(String.class, ct.getValueClass());
assertNotNull(ct.characteristics().get("@codeSpace"));
//assertEquals("CodeWithAuthorityType", ct.getName().tip().toString());
}
@Test
public void testReadTypeWithNil() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/TypeWithNil.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
assertEquals(typeWithNil, types.get(0));
}
@Test
public void testReadTypeWithSubstitutions() throws JAXBException {
final JAXBFeatureTypeReader reader = getReader(true);
final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/TypeWithSubstitution.xsd"));
removeGMLBaseTypes(types);
assertEquals(1, types.size());
final FeatureType type = types.get(0);
assertEquals("TestSimple", type.getName().tip().toString());
//we do not count the substitution groups
assertEquals(3, type.getProperties(true).size());
}
@Test
public void testWriteSimpleFeatureType() throws JAXBException, IOException, ParserConfigurationException, SAXException{
final File temp = File.createTempFile("gml", ".xml");
temp.deleteOnExit();
final JAXBFeatureTypeWriter writer = new JAXBFeatureTypeWriter();
writer.write(simpleTypeFull, new FileOutputStream(temp));
DomCompare.compare(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/SimpleType.xsd"), temp);
}
@Test
public void testWriteMultiGeomFeatureType() throws JAXBException, IOException, ParserConfigurationException, SAXException{
final File temp = File.createTempFile("gml", ".xml");
temp.deleteOnExit();
final JAXBFeatureTypeWriter writer = new JAXBFeatureTypeWriter();
writer.write(multiGeomType, new FileOutputStream(temp));
DomCompare.compare(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/MultiGeomType.xsd"), temp);
}
@Test
public void testWriteComplexFeatureType() throws JAXBException, IOException, ParserConfigurationException, SAXException{
final File temp = File.createTempFile("gml", ".xml");
temp.deleteOnExit();
final JAXBFeatureTypeWriter writer = new JAXBFeatureTypeWriter();
writer.write(complexType, new FileOutputStream(temp));
DomCompare.compare(XmlFeatureTypeTest.class
.getResourceAsStream("/org/geotoolkit/feature/xml/ComplexType.xsd"), temp);
}
// @Ignore
// @Test
// public void testWriteTypeWithSubstitutions() throws JAXBException, IOException, ParserConfigurationException, SAXException {
// final JAXBFeatureTypeReader reader = getReader(true);
// final List<FeatureType> types = reader.read(XmlFeatureTypeTest.class
// .getResourceAsStream("/org/geotoolkit/feature/xml/TypeWithSubstitution.xsd"));
// removeGMLBaseTypes(types);
// assertEquals(1, types.size());
// final FeatureType type = types.get(0);
//
// final File temp = File.createTempFile("gml", ".xml");
// temp.deleteOnExit();
// final JAXBFeatureTypeWriter writer = new JAXBFeatureTypeWriter("3.2.1");
// writer.write(type, new FileOutputStream(temp));
//
// //NOTE : there are some variations since element references are lost in the way.
// DomCompare.compare(XmlFeatureTypeTest.class
// .getResourceAsStream("/org/geotoolkit/feature/xml/TypeWithSubstitution2.xsd"), temp);
//
// }
protected static String getStringResponse(URLConnection conec) throws UnsupportedEncodingException, IOException {
final StringWriter sw = new StringWriter();
final BufferedReader in = new BufferedReader(new InputStreamReader(conec.getInputStream(), "UTF-8"));
char [] buffer = new char[1024];
int size;
while ((size = in.read(buffer, 0, 1024)) > 0) {
sw.append(new String(buffer, 0, size));
}
return sw.toString();
}
private static JAXBFeatureTypeReader getReader(boolean skipStandardObjectProperties) {
final JAXBFeatureTypeReader reader = new JAXBFeatureTypeReader();
reader.setSkipStandardObjectProperties(skipStandardObjectProperties);
return reader;
}
}