/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2010, 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.data;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.apache.sis.feature.FeatureExt;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.storage.DataStoreException;
import org.geotoolkit.data.query.Query;
import org.geotoolkit.data.query.QueryBuilder;
import org.geotoolkit.data.query.QueryUtilities;
import org.geotoolkit.data.query.Selector;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.factory.Hints;
import org.geotoolkit.util.collection.CloseableIterator;
import org.opengis.feature.MismatchedFeatureException;
import org.opengis.filter.Filter;
import org.opengis.filter.Id;
import org.opengis.filter.identity.Identifier;
import org.opengis.geometry.Envelope;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
/**
* Feature collection that takes it's source from a single selector.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class DefaultSelectorFeatureCollection extends AbstractFeatureCollection{
private final Query query;
public DefaultSelectorFeatureCollection(final String id, final Query query){
super(id,query.getSource());
if(!(query.getSource() instanceof Selector)){
throw new IllegalArgumentException("Query must have a selector source.");
}
if(!QueryUtilities.isAbsolute(query.getSource())){
throw new IllegalArgumentException("Selector must be absolute.");
}
this.query = query;
}
@Override
public Selector getSource() {
return (Selector) super.getSource();
}
/**
* {@inheritDoc }
*/
@Override
public FeatureCollection subCollection(final Query query) throws DataStoreException {
return getSession().getFeatureCollection(QueryUtilities.subQuery(this.query, query));
}
/**
* {@inheritDoc }
*/
@Override
public FeatureType getFeatureType() throws FeatureStoreRuntimeException{
try {
return getSession().getFeatureStore().getFeatureType(query);
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
} catch (MismatchedFeatureException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}
/**
* {@inheritDoc }
*/
@Override
public FeatureIterator iterator(final Hints hints) throws FeatureStoreRuntimeException{
final Query iteQuery;
if(hints != null){
final QueryBuilder qb = new QueryBuilder(this.query);
final Hints hts = new Hints(this.query.getHints());
hts.add(hints);
qb.setHints(hts);
iteQuery = qb.buildQuery();
}else{
iteQuery = this.query;
}
try {
return getSession().getFeatureIterator(iteQuery);
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}
/**
* {@inheritDoc }
*/
@Override
public int size() throws FeatureStoreRuntimeException {
try {
return (int) getSession().getCount(query);
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}
/**
* {@inheritDoc }
*/
@Override
public Envelope getEnvelope() throws FeatureStoreRuntimeException{
try {
return getSession().getEnvelope(query);
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}
/**
* {@inheritDoc }
*/
@Override
public boolean add(final Feature e) {
return addAll(Collections.singletonList(e));
}
/**
* {@inheritDoc }
*/
@Override
public boolean addAll(final Collection<? extends Feature> clctn) {
try {
getSession().addFeatures(query.getTypeName(), clctn);
return true;
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}
@Override
public boolean isWritable(){
try {
return getSession().getFeatureStore().isWritable(query.getTypeName().toString());
} catch (DataStoreException ex) {
Logging.getLogger("org.geotoolkit.data").log(Level.WARNING, null, ex);
return false;
}
}
@Override
public boolean remove(final Object o) throws FeatureStoreRuntimeException{
if(isWritable()){
if(o instanceof Feature){
Id filter = FactoryFinder.getFilterFactory(null).id(Collections.singleton(FeatureExt.getId((Feature)o)));
try {
getSession().removeFeatures(query.getTypeName(), filter);
return true;
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}else{
//trying to remove an object which is not a feature
//it has no effect
//should we be strict and raise an error ? or log it ?
}
}else{
throw new FeatureStoreRuntimeException("this collection is readable only");
}
return false;
}
@Override
public boolean removeAll(final Collection<?> clctn) {
if(isWritable()){
final Set<Identifier> ids = new HashSet<Identifier>();
final Iterator<?> ite = clctn.iterator();
try{
while(ite.hasNext()){
final Object o = ite.next();
if(o instanceof Feature){
ids.add(FeatureExt.getId((Feature)o));
}
}
}finally{
if(ite instanceof CloseableIterator){
((CloseableIterator)ite).close();
}
}
if(!ids.isEmpty()){
Id filter = FactoryFinder.getFilterFactory(null).id(ids);
try {
getSession().removeFeatures(query.getTypeName(), filter);
return true;
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}
}else{
throw new FeatureStoreRuntimeException("this collection is readable only");
}
return false;
}
@Override
public void clear() {
if(isWritable()){
try {
getSession().removeFeatures(query.getTypeName(), query.getFilter());
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex);
}
}else{
throw new FeatureStoreRuntimeException("this collection is readable only");
}
}
/**
* {@inheritDoc }
*/
@Override
public void update(final Filter filter, final Map<String,?> values) throws DataStoreException {
if(filter == Filter.INCLUDE){
getSession().updateFeatures(query.getTypeName(),query.getFilter(),values);
}else{
getSession().updateFeatures(query.getTypeName(),FactoryFinder.getFilterFactory(null).and(query.getFilter(), filter),values);
}
}
/**
* {@inheritDoc }
*/
@Override
public void remove(final Filter filter) throws DataStoreException {
if(filter == Filter.INCLUDE){
getSession().removeFeatures(query.getTypeName(),query.getFilter());
}else{
getSession().removeFeatures(query.getTypeName(),FactoryFinder.getFilterFactory(null).and(query.getFilter(), filter));
}
}
}