/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wfsv;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import net.opengis.wfs.DeleteElementType;
import net.opengis.wfs.InsertElementType;
import net.opengis.wfs.PropertyType;
import net.opengis.wfs.TransactionType;
import net.opengis.wfs.UpdateElementType;
import net.opengis.wfs.WfsFactory;
import org.eclipse.emf.common.util.EList;
import org.geoserver.wfs.WFSException;
import org.geotools.data.FeatureDiff;
import org.geotools.data.FeatureDiffReader;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.util.Converter;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.identity.FeatureId;
/**
* Converts a {@link FeatureDiffReader} or an array of them into a {@link TransactionType} object
*
* @author Andrea Aime - OpenGeo
*
*/
public class VersioningTransactionConverter implements Converter {
FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory(null);
public <T> T convert(Object source, Class<T> target) throws IOException {
if (!TransactionType.class.isAssignableFrom(target)) {
throw new IllegalArgumentException("Target can only be " + TransactionType.class);
}
final TransactionType transaction = WfsFactory.eINSTANCE.createTransactionType();
if (source instanceof FeatureDiffReader) {
convertReader((FeatureDiffReader) source, transaction);
} else if (source instanceof FeatureDiffReader[]) {
for (FeatureDiffReader reader : (FeatureDiffReader[]) source) {
convertReader(reader, transaction);
}
} else {
throw new IllegalArgumentException("The source can only be a "
+ "FeatureDiffReader or an array of such readers");
}
return (T) transaction;
}
void convertReader(FeatureDiffReader diffReader, TransactionType transaction)
throws IOException {
// create a single insert element, a single delete element, and as
// many update elements as needed
final SimpleFeatureType schema = diffReader.getSchema();
final QName typeName = new QName(schema.getName().getNamespaceURI(), schema.getTypeName());
final Set deletedIds = new HashSet();
final InsertElementType insert = WfsFactory.eINSTANCE.createInsertElementType();
while (diffReader.hasNext()) {
FeatureDiff diff = diffReader.next();
switch (diff.getState()) {
case FeatureDiff.INSERTED:
insert.getFeature().add(diff.getFeature());
break;
case FeatureDiff.DELETED:
deletedIds.add(filterFactory.featureId(diff.getID()));
break;
case FeatureDiff.UPDATED:
final UpdateElementType update = WfsFactory.eINSTANCE.createUpdateElementType();
final EList properties = update.getProperty();
SimpleFeature f = diff.getFeature();
for (Iterator it = diff.getChangedAttributes().iterator(); it.hasNext();) {
final PropertyType property = WfsFactory.eINSTANCE.createPropertyType();
String name = (String) it.next();
property.setName(new QName(name));
property.setValue(f.getAttribute(name));
properties.add(property);
}
FeatureId featureId = filterFactory.featureId(diff.getID());
final Filter filter = filterFactory.id(Collections.singleton(featureId));
update.setFilter(filter);
update.setTypeName(typeName);
transaction.getUpdate().add(update);
break;
default:
throw new WFSException("Could not handle diff type " + diff.getState());
}
}
diffReader.close();
// create insert and delete elements if needed
if (insert.getFeature().size() > 0) {
transaction.getInsert().add(insert);
}
if (deletedIds.size() > 0) {
final DeleteElementType delete = WfsFactory.eINSTANCE.createDeleteElementType();
delete.setFilter(filterFactory.id(deletedIds));
delete.setTypeName(typeName);
transaction.getDelete().add(delete);
}
}
}