/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.data.complex;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.awt.RenderingHints.Key;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.geotools.data.DataAccess;
import org.geotools.data.DataAccessFactory;
import org.geotools.data.DataAccessFinder;
import org.geotools.data.FeatureListener;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.data.QueryCapabilities;
import org.geotools.data.ResourceInfo;
import org.geotools.data.ServiceInfo;
import org.geotools.data.complex.config.CatalogUtilities;
import org.geotools.data.complex.config.EmfAppSchemaReader;
import org.geotools.data.complex.config.FeatureTypeRegistry;
import org.geotools.data.property.PropertyDataStore;
import org.geotools.feature.AttributeImpl;
import org.geotools.feature.CollectionListener;
import org.geotools.feature.ComplexAttributeImpl;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureImpl;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.NameImpl;
import org.geotools.feature.Types;
import org.geotools.feature.type.AttributeDescriptorImpl;
import org.geotools.feature.type.FeatureTypeImpl;
import org.geotools.filter.FilterFactoryImplNamespaceAware;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.gml3.GMLSchema;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.geotools.xml.SchemaIndex;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureVisitor;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.ComplexType;
import org.opengis.feature.type.FeatureType;
import org.opengis.feature.type.Name;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.sort.SortBy;
import org.opengis.util.ProgressListener;
import org.xml.sax.helpers.NamespaceSupport;
/**
* This is to test integration of a non-app-schema data access with an app-schema data access. An
* app-schema data access can chain features from a non-app-schema data access.
*
* @author Rini Angreani, Curtin University of Technology
*
* @source $URL$
*/
public class DataAccessIntegrationTest {
protected static final String GSMLNS = "http://www.cgi-iugs.org/xml/GeoSciML/2";
protected static final String GMLNS = "http://www.opengis.net/gml";
protected static final Name MAPPED_FEATURE = Types.typeName(GSMLNS, "MappedFeature");
private static final Name GEOLOGIC_UNIT_TYPE = Types.typeName(GSMLNS, "GeologicUnitType");
protected static final Name GEOLOGIC_UNIT = Types.typeName(GSMLNS, "GeologicUnit");
private static final Name COMPOSITION_PART_TYPE = Types.typeName(GSMLNS, "CompositionPartType");
private static final Name COMPOSITION_PART = Types.typeName(GSMLNS, "CompositionPart");
protected static final String schemaBase = "/test-data/";
/**
* App schema config reader
*/
protected static EmfAppSchemaReader reader;
protected static FeatureTypeRegistry typeRegistry;
/**
* Mapped Feature data access in GSML form
*/
protected static DataAccess<FeatureType, Feature> mfDataAccess;
/**
* GSML:geologicUnit feature source coming from the mapped data access
*/
protected static FeatureSource<FeatureType, Feature> guFeatureSource;
/**
* Collection of MO:earthResource complex features
*/
protected static ArrayList<Feature> inputFeatures;
/**
* Collection of GSML:compositionPart complex features
*/
protected static ArrayList<Feature> cpFeatures;
/**
* Collection of GSML:mappedFeature complex features
*/
protected static ArrayList<Feature> mfFeatures;
/**
* Filter factory instance
*/
protected static FilterFactory ff;
/**
* Create the input data access containing complex features of MO form.
*/
@BeforeClass
public static void setUp() throws Exception {
setFilterFactory();
loadGeologicUnitDataAccess();
// Load CGI Term Value data access
URL url = DataAccessIntegrationTest.class.getResource(schemaBase + "CGITermValue.xml");
assertNotNull(url);
Map<String, Serializable> dsParams = new HashMap<String, Serializable>();
dsParams.put("dbtype", "app-schema");
dsParams.put("url", url.toExternalForm());
DataAccess<FeatureType, Feature> cgiDataAccess = DataAccessFinder.getDataStore(dsParams);
assertNotNull(cgiDataAccess);
// Load composition part data access
url = DataAccessIntegrationTest.class.getResource(schemaBase + "CompositionPart.xml");
assertNotNull(url);
dsParams.put("url", url.toExternalForm());
DataAccessFinder.getDataStore(dsParams);
// Load Mapped Feature data access
loadDataAccess("MappedFeaturePropertyfile.xml");
}
/**
* Create Geologic Unit complex features from the simple features and complex type.
*
* @param fCollection
* @param geologicUnitType
* @return
* @throws IOException
*/
private static ArrayList<Feature> getInputFeatures(
FeatureCollection<SimpleFeatureType, SimpleFeature> fCollection,
FeatureType geologicUnitType) throws IOException {
ArrayList<Feature> features = new ArrayList<Feature>();
AttributeDescriptor featureDesc = new AttributeDescriptorImpl(geologicUnitType,
GEOLOGIC_UNIT, 0, -1, false, null);
// gml:description
AttributeDescriptor descriptionDescriptor = (AttributeDescriptor) geologicUnitType
.getDescriptor(Types.typeName(GMLNS, "description"));
// gml:name
AttributeDescriptor nameDescriptor = (AttributeDescriptor) GMLSchema.ABSTRACTGMLTYPE_TYPE
.getDescriptor(Types.typeName(GMLNS, "name"));
// for simple string properties
Name name = new NameImpl(null, "simpleContent");
AttributeType simpleContentType = typeRegistry.getAttributeType(Types.typeName(
"http://www.w3.org/2001/XMLSchema", "string"));
AttributeDescriptor stringDescriptor = new AttributeDescriptorImpl(simpleContentType, name,
1, 1, true, (Object) null);
Iterator<SimpleFeature> simpleFeatures = fCollection.iterator();
// keep track of the last feature, so we can group them as 1 if they're the same
Feature lastFeature = null;
while (simpleFeatures.hasNext()) {
SimpleFeature next = simpleFeatures.next();
String propertyName;
ArrayList<Property> value = new ArrayList<Property>();
Collection<Property> properties = new ArrayList<Property>();
if (lastFeature != null && lastFeature.getIdentifier().equals(next.getIdentifier())) {
// ATTENTION: so far only NAME has different values in the properties file,
// if you edit the properties file involving other values, you have to add
// the code here accordingly.
Collection<Property> values = lastFeature.getProperties(Types.typeName(GMLNS,
"name"));
Iterator<Property> iterator = values.iterator();
Object existingValue = ((Collection<Property>) iterator.next().getValue())
.iterator().next().getValue();
Object nameValue = next.getProperty("NAME").getValue();
if (!existingValue.equals(nameValue)) {
value.add(new AttributeImpl(nameValue, stringDescriptor, null));
properties.addAll(lastFeature.getProperties());
properties.add(new ComplexAttributeImpl(value, nameDescriptor, null));
lastFeature = new FeatureImpl(properties, lastFeature.getDescriptor(),
lastFeature.getIdentifier());
}
existingValue = ((Collection<Property>) iterator.next().getValue()).iterator()
.next().getValue();
nameValue = next.getProperty("ABBREVIATION").getValue();
if (!existingValue.equals(nameValue)) {
value.add(new AttributeImpl(nameValue, stringDescriptor, null));
properties.addAll(lastFeature.getProperties());
properties.add(new ComplexAttributeImpl(value, nameDescriptor, null));
lastFeature = new FeatureImpl(properties, lastFeature.getDescriptor(),
lastFeature.getIdentifier());
}
} else {
// description
propertyName = "TEXTDESCRIPTION";
value.add(new AttributeImpl(next.getProperty(propertyName).getValue(),
stringDescriptor, null));
properties.add(new ComplexAttributeImpl(value, descriptionDescriptor, null));
// name 1
propertyName = "NAME";
value = new ArrayList<Property>();
value.add(new AttributeImpl(next.getProperty(propertyName).getValue(),
stringDescriptor, null));
ComplexAttributeImpl name1 = new ComplexAttributeImpl(value, nameDescriptor, null);
properties.add(name1);
// name 2
value = new ArrayList<Property>();
propertyName = "ABBREVIATION";
value.add(new AttributeImpl(next.getProperty(propertyName).getValue(),
stringDescriptor, null));
properties.add(new ComplexAttributeImpl(value, nameDescriptor, null));
// composition part
ComplexType cpType = (ComplexType) typeRegistry
.getAttributeType(COMPOSITION_PART_TYPE);
ArrayList<Property> compositionParts = new ArrayList<Property>();
compositionParts.add(name1);
value = new ArrayList<Property>();
value.add(new ComplexAttributeImpl(compositionParts, cpType, null));
properties.add(new ComplexAttributeImpl(value,
(AttributeDescriptor) geologicUnitType.getDescriptor(Types.typeName(GSMLNS,
"composition")), null));
// feature chaining link
properties.add(new AttributeImpl(next.getID(),
(AttributeDescriptor) ComplexFeatureConstants.FEATURE_CHAINING_LINK, null));
lastFeature = new FeatureImpl(properties, featureDesc, next.getIdentifier());
features.add(lastFeature);
}
}
fCollection.close(simpleFeatures);
return features;
}
/**
* Test that mapping geologic unit inside mapped feature type is successful.
*
* @throws IOException
*/
@Test
public void testMappings() throws IOException {
Iterator<Feature> mfIterator = mfFeatures.iterator();
Iterator<Feature> guIterator = inputFeatures.iterator();
// Extract all geological unit features into a map by id
Map<String, Feature> guMap = new HashMap<String, Feature>();
Feature guFeature;
while (guIterator.hasNext()) {
guFeature = (Feature) guIterator.next();
String guId = guFeature.getIdentifier().getID();
if (!guMap.containsKey(guId)) {
guMap.put(guId, guFeature);
}
}
Feature mfFeature;
Collection<Property> nestedGuFeatures;
String guId;
final String NESTED_LINK = "specification";
while (mfIterator.hasNext()) {
mfFeature = (Feature) mfIterator.next();
String mfId = mfFeature.getIdentifier().toString();
String[] guIds = FeatureChainingTest.mfToGuMap.get(mfId).split(";");
// make sure we have the right number of nested features
nestedGuFeatures = (Collection<Property>) mfFeature.getProperties(NESTED_LINK);
assertEquals(guIds.length, nestedGuFeatures.size());
ArrayList<String> nestedGuIds = new ArrayList<String>();
for (Property property : nestedGuFeatures) {
Object value = property.getValue();
assertNotNull(value);
assertTrue(value instanceof Collection);
assertEquals(1, ((Collection) value).size());
Feature nestedGuFeature = (Feature) ((Collection) value).iterator().next();
/**
* Test geological unit
*/
// make sure each of the nested geologic unit is valid
guId = nestedGuFeature.getIdentifier().toString();
assertTrue(guMap.containsKey(guId));
nestedGuIds.add(guId);
// make sure the nested geologic unit feature has the right properties
guFeature = guMap.get(guId.toString());
Collection<Property> guProperties = guFeature.getProperties();
assertEquals(nestedGuFeature.getProperties(), guProperties);
}
// make sure all the nested geological unit features are there
assertTrue(nestedGuIds.containsAll(Arrays.asList(guIds)));
}
}
/**
* Make sure filters are working.
*
* @throws IOException
*/
@Test
public void testFilters() throws IOException {
// make sure filter query can be made on MappedFeature based on GU properties
//
// <ogc:Filter>
// <ogc:PropertyIsLike>
// <ogc:PropertyName>
// gsml:specification/gsml:GeologicUnit/gml:description
// </ogc:PropertyName>
// <ogc:Literal>Olivine basalt, tuff, microgabbro, minor sedimentary rocks</ogc:Literal>
// </ogc:PropertyIsLike>
// </ogc:Filter>
// <ogc:PropertyName>
// gsml:specification/gsml:GeologicUnit/gml:description
Expression property = ff.property("gsml:specification/gsml:GeologicUnit/gml:description");
Filter filter = ff.like(property,
"Olivine basalt, tuff, microgabbro, minor sedimentary rocks");
FeatureCollection<FeatureType, Feature> filteredResults = mfDataAccess.getFeatureSource(
MAPPED_FEATURE).getFeatures(filter);
assertEquals(3, filteredResults.size());
}
/**
* Load non-app-schema Geologic Unit data access.
*
* @throws IOException
*/
private static void loadGeologicUnitDataAccess() throws IOException {
Map<String, Serializable> moParams = new HashMap<String, Serializable>();
moParams.put("dbtype", "input-data-access");
DataAccess<FeatureType, Feature> inputDataAccess = DataAccessFinder.getDataStore(moParams);
guFeatureSource = inputDataAccess.getFeatureSource(GEOLOGIC_UNIT);
}
/**
* Load all the data accesses.
*
* @param mfMappingFile
* Mapped feature mapping file with geologic unit as specification
* @throws IOException
*/
protected static void loadDataAccess(String mfMappingFile) throws IOException {
/**
* Load mapped feature data access
*/
Map<String, Serializable> dsParams = new HashMap<String, Serializable>();
URL url = DataAccessIntegrationTest.class.getResource(schemaBase + mfMappingFile);
assertNotNull(url);
dsParams.put("dbtype", "app-schema");
dsParams.put("url", url.toExternalForm());
mfDataAccess = DataAccessFinder.getDataStore(dsParams);
assertNotNull(mfDataAccess);
FeatureType mappedFeatureType = mfDataAccess.getSchema(MAPPED_FEATURE);
assertNotNull(mappedFeatureType);
FeatureSource<FeatureType, Feature> mfSource = mfDataAccess
.getFeatureSource(MAPPED_FEATURE);
FeatureCollection<FeatureType, Feature> mfCollection = mfSource.getFeatures();
Iterator<Feature> mfIterator = mfCollection.iterator();
mfFeatures = new ArrayList<Feature>();
while (mfIterator.hasNext()) {
mfFeatures.add(mfIterator.next());
}
mfCollection.close(mfIterator);
/**
* Get composition part data access features
*/
DataAccess<FeatureType, Feature> cpDataAccess = DataAccessRegistry.getDataAccess(COMPOSITION_PART);
assertNotNull(cpDataAccess);
FeatureSource<FeatureType, Feature> cpSource = cpDataAccess
.getFeatureSource(COMPOSITION_PART);
FeatureCollection<FeatureType, Feature> cpCollection = cpSource.getFeatures();
Iterator<Feature> cpIterator = cpCollection.iterator();
cpFeatures = new ArrayList<Feature>();
while (cpIterator.hasNext()) {
cpFeatures.add(cpIterator.next());
}
cpCollection.close(cpIterator);
}
/**
* Dispose all the data accesses so that there is no mapping conflicts for other tests
*/
@AfterClass
public static void tearDown() {
DataAccessRegistry.unregisterAll();
}
/**
* This is a test data access factory to create non-app-schema data access as an input for the
* tests above.
*
* @author ang05a
*/
public static class InputDataAccessFactory implements DataAccessFactory {
public InputDataAccessFactory() {
}
public boolean canProcess(Map<String, Serializable> params) {
Object dbType = params.get("dbtype");
return dbType == null ? false : dbType.equals("input-data-access");
}
public DataAccess<? extends FeatureType, ? extends Feature> createDataStore(
Map<String, Serializable> params) throws IOException {
URL schemaURL = getClass().getResource(schemaBase);
File dir;
try {
dir = new File(schemaURL.toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
// get geologic unit properties file
PropertyDataStore dataStore = new PropertyDataStore(dir);
FeatureSource<SimpleFeatureType, SimpleFeature> simpleFeatureSource = dataStore
.getFeatureSource(GEOLOGIC_UNIT);
FeatureCollection<SimpleFeatureType, SimpleFeature> fCollection = simpleFeatureSource
.getFeatures();
reader = EmfAppSchemaReader.newInstance();
// set catalog
URL catalogLocation = getClass().getResource(schemaBase + "mappedPolygons.oasis.xml");
reader.setCatalog(CatalogUtilities.buildPrivateCatalog(catalogLocation));
// set schema URI
SchemaIndex schemaIndex = reader.parse(new URL(schemaURL.toString() + File.separator
+ "commonSchemas_new/GeoSciML/geologicUnit.xsd"), null);
typeRegistry = new FeatureTypeRegistry();
typeRegistry.addSchemas(schemaIndex);
// get simple features
FeatureType simpleType = (FeatureType) typeRegistry
.getAttributeType(GEOLOGIC_UNIT_TYPE);
inputFeatures = getInputFeatures(fCollection, simpleType);
// create complex feature type
FeatureType guSchema = new FeatureTypeImpl(GEOLOGIC_UNIT, simpleType.getDescriptors(),
null, true, simpleType.getRestrictions(), GMLSchema.ABSTRACTFEATURETYPE_TYPE,
null);
return new InputDataAccess(inputFeatures, guSchema,
FeatureChainingTest.GEOLOGIC_UNIT_NAME);
}
public String getDescription() {
return null;
}
public String getDisplayName() {
return null;
}
public Param[] getParametersInfo() {
return null;
}
public boolean isAvailable() {
return true;
}
public Map<Key, ?> getImplementationHints() {
return null;
}
/**
* This is a test non app-schema MO:data access
*
* @author ang05a
*/
class InputDataAccess implements DataAccess<FeatureType, Feature> {
private FeatureSource<FeatureType, Feature> fSource;
private ArrayList<Name> names = new ArrayList<Name>();
public InputDataAccess(Collection<Feature> features, FeatureType schema, Name fTypeName) {
InputFeatureCollection fCollection = new InputFeatureCollection(schema, features);
fSource = new InputFeatureSource(fCollection, this);
names.add(fTypeName);
DataAccessRegistry.register(this);
}
public void createSchema(FeatureType featureType) throws IOException {
throw new UnsupportedOperationException();
}
public void dispose() {
this.fSource = null;
this.names.clear();
DataAccessRegistry.unregister(this);
}
public FeatureSource<FeatureType, Feature> getFeatureSource(Name typeName)
throws IOException {
return fSource;
}
public ServiceInfo getInfo() {
throw new UnsupportedOperationException();
}
public List<Name> getNames() throws IOException {
return names;
}
public FeatureType getSchema(Name name) throws IOException {
return fSource.getFeatures().getSchema();
}
public void updateSchema(Name typeName, FeatureType featureType) throws IOException {
throw new UnsupportedOperationException();
}
}
/**
* This is a test feature source for non-app-schema complex features.
*
* @author ang05a
*/
private class InputFeatureSource implements FeatureSource<FeatureType, Feature> {
private FeatureCollection<FeatureType, Feature> fCollection;
private DataAccess<FeatureType, Feature> dataAccess;
public InputFeatureSource(FeatureCollection<FeatureType, Feature> fCollection,
DataAccess<FeatureType, Feature> dataAccess) {
this.fCollection = fCollection;
this.dataAccess = dataAccess;
}
public void addFeatureListener(FeatureListener listener) {
throw new UnsupportedOperationException();
}
public ReferencedEnvelope getBounds() throws IOException {
throw new UnsupportedOperationException();
}
public ReferencedEnvelope getBounds(Query query) throws IOException {
throw new UnsupportedOperationException();
}
public int getCount(Query query) throws IOException {
return fCollection.size();
}
public DataAccess<FeatureType, Feature> getDataStore() {
return dataAccess;
}
public FeatureCollection<FeatureType, Feature> getFeatures(Query query)
throws IOException {
return getFeatures(query.getFilter());
}
public FeatureCollection<FeatureType, Feature> getFeatures(Filter filter)
throws IOException {
return fCollection.subCollection(filter);
}
public FeatureCollection<FeatureType, Feature> getFeatures() throws IOException {
return fCollection;
}
public ResourceInfo getInfo() {
throw new UnsupportedOperationException();
}
public Name getName() {
return fCollection.getSchema().getName();
}
public QueryCapabilities getQueryCapabilities() {
throw new UnsupportedOperationException();
}
public FeatureType getSchema() {
return fCollection.getSchema();
}
public Set<Key> getSupportedHints() {
throw new UnsupportedOperationException();
}
public void removeFeatureListener(FeatureListener listener) {
throw new UnsupportedOperationException();
}
}
/**
* This is a test feature collection of non-app-schema complex features
*
* @author ang05a
*/
private class InputFeatureCollection implements FeatureCollection<FeatureType, Feature> {
private ArrayList<Feature> fList = new ArrayList<Feature>();
private FeatureType schema;
public InputFeatureCollection(FeatureType schema, Collection<Feature> features) {
this.schema = schema;
this.addAll(features);
}
public void accepts(FeatureVisitor visitor, ProgressListener progress)
throws IOException {
throw new UnsupportedOperationException();
}
public boolean add(Feature obj) {
return fList.add(obj);
}
public boolean addAll(Collection<? extends Feature> collection) {
return fList.addAll(collection);
}
public boolean addAll(
FeatureCollection<? extends FeatureType, ? extends Feature> resource) {
throw new UnsupportedOperationException();
}
public void addListener(CollectionListener listener) throws NullPointerException {
throw new UnsupportedOperationException();
}
public void clear() {
fList.clear();
}
public void close(FeatureIterator<Feature> close) {
close.close();
}
public void close(Iterator<Feature> close) {
((InputFeatureIterator) close).close();
}
public boolean contains(Object o) {
return fList.contains(o);
}
public boolean containsAll(Collection<?> o) {
return fList.containsAll(o);
}
public FeatureIterator<Feature> features() {
return new InputFeatureIterator(fList);
}
public ReferencedEnvelope getBounds() {
throw new UnsupportedOperationException();
}
public String getID() {
return null;
}
public FeatureType getSchema() {
return schema;
}
public boolean isEmpty() {
return this.fList.isEmpty();
}
public Iterator<Feature> iterator() {
return (Iterator<Feature>) features();
}
public void purge() {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
return this.fList.remove(o);
}
public boolean removeAll(Collection<?> c) {
return this.fList.removeAll(c);
}
public void removeListener(CollectionListener listener) throws NullPointerException {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> c) {
return this.fList.retainAll(c);
}
public int size() {
return this.fList.size();
}
public FeatureCollection<FeatureType, Feature> sort(SortBy order) {
throw new UnsupportedOperationException();
}
public FeatureCollection<FeatureType, Feature> subCollection(Filter filter) {
if (filter == Filter.INCLUDE) {
return this;
}
FeatureCollection<FeatureType, Feature> fCollection = new InputFeatureCollection(
this.schema, new ArrayList<Feature>());
for (Feature feature : this.fList) {
if (filter.evaluate(feature)) {
fCollection.add(feature);
}
}
return fCollection;
}
public Object[] toArray() {
return fList.toArray();
}
public <O> O[] toArray(O[] a) {
return fList.toArray(a);
}
}
/**
* This is a test feature iterator for non-app-schema complex features
*
* @author ang05a
*/
private class InputFeatureIterator implements Iterator<Feature>, FeatureIterator<Feature> {
Iterator<Feature> iterator;
public InputFeatureIterator(ArrayList<Feature> features) {
iterator = features.iterator();
}
public void close() {
iterator = null;
}
public boolean hasNext() {
return iterator.hasNext();
}
public Feature next() throws NoSuchElementException {
return iterator.next();
}
public void remove() {
iterator.remove();
}
}
}
/**
* Set filter factory with name spaces
*/
public static void setFilterFactory() {
NamespaceSupport namespaces = new NamespaceSupport();
namespaces.declarePrefix("gsml", GSMLNS);
namespaces.declarePrefix("gml", GMLNS);
ff = new FilterFactoryImplNamespaceAware(namespaces);
}
}