Hello Erik (and Jody),
Following your code in the debugger, it is catching an exception in
your changeValue method...
catch( Exception eek){
transaction.rollback();
}
Here is the top of the stack trace...
java.lang.UnsupportedOperationException: FeatureWriter not supported
at
org.geotools.data.AbstractDataStore.createFeatureWriter(AbstractDataStore.java:210)
at
org.geotools.data.TransactionStateDiff.applyDiff(TransactionStateDiff.java:191)
at
org.geotools.data.TransactionStateDiff.commit(TransactionStateDiff.java:148)
at
org.geotools.data.DefaultTransaction.commit(DefaultTransaction.java:183)
at org.geotools.userlist.MainGUI.changeValue(MainGUI.java:165)
I _think_ what is happening is the following...
Your app is creating an in-memory feature collection, taking values
from the csv file and geometries from the shapefile. It then creates a
FeatureLayer to display with the feature collection as a parameter...
final Layer layer = new FeatureLayer(fc, style);
Under the hood, GeoTools creates a basic feature source and store
(using the DataUtilities.source method) to wrap the feature
collection.
Later, in your changeValue method you retrieve the feature store from
the layer and attempt to call its modifyFeatures method. But the basic
store that was created by GeoTools does not support this operation -
hence the Exception.
(Jody - is there a simple way around this that you can suggest to Erik ?)
But there is really no need for the feature store / transaction code
in your app because you are dealing with a simple, in-memory feature
collection, so you can just modify the feature directly. However, this
leads to another pesky problem - when feature is modified directly the
map pane will not receive an event to tell it that the data have
changed, so it will not redraw the features. Calling the repaint()
method will have no effect here - it only redisplays the component but
does not refresh the image of the features.
Below is a modified version of your app. I've replaced use of
JMapFrame with custom map pane and map frame classes. The map pane
class simple extends JMapPane and adds a method to force the features
to be re-drawn (this should probably be added to GeoTools). The frame
class holds the map pane and your button panel, as well as handling
the feature value updates. When you click the button one of the
polygons turns yellow which I think is what you wanted.
Please note - the arrangement of the modified code is just the first
one I thought of. You can experiment with your own custom frame and
pane classes etc.
Michael
package org.geotools.userlist;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPolygon;
import org.geotools.data.FeatureSource;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.map.FeatureLayer;
import org.geotools.map.MapContent;
import org.geotools.styling.SLDParser;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.swing.JMapPane;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
/**
* SimpleEditor
*/
public class MainGUI {
private static final String shapeFileName = "./data/test.shp";
private static final String fileSLD = "./data/styles.sld";
private static final String inputTxt = "./data/input.csv";
private static final String outputTxt = "./data/output.csv";
private static String ID_KEY = "2";
public static void main(String[] args) throws IOException {
new MainGUI().doExample();
}
private void doExample() throws IOException {
File file = new File(shapeFileName);
FileDataStore store = FileDataStoreFinder.getDataStore(file);
FeatureSource<SimpleFeatureType, SimpleFeature> featureSource
= store.getFeatureSource();
FeatureIterator<SimpleFeature> iteratorShp =
featureSource.getFeatures().features();
SimpleFeatureCollection fc = FeatureCollections.newCollection();
SimpleFeatureTypeBuilder sftb = new SimpleFeatureTypeBuilder();
sftb.setName("test");
sftb.add("geo", MultiPolygon.class);
sftb.add("value", Object.class);
sftb.add("id", Integer.class); // <- for ID field
SimpleFeatureType mapFType = sftb.buildFeatureType();
BufferedReader reader = new BufferedReader(new FileReader(inputTxt));
try {
/*
* First line of the data file is the header
*/
String line = reader.readLine();
System.out.println("Header: " + line);
//for simplicity we assume that the ids are sorted in
ascending in shapefile
for (line = reader.readLine(); line != null; line =
reader.readLine()) {
if (line.trim().length() > 0) { // skip blank lines
String tokens[] = line.split("\\,");
int id = Integer.parseInt(tokens[0]);
int value = Integer.parseInt(tokens[1]);
SimpleFeature f = iteratorShp.next();
SimpleFeature newf = SimpleFeatureBuilder.template(
mapFType, new Integer(id).toString());
newf.setAttribute("geo", (Geometry) f.getDefaultGeometry());
newf.setAttribute("value", value);
fc.add(newf);
}
}
} finally {
reader.close();
}
Style style = createFromSLD(fileSLD);
MyMapFrame.showFeatures("Test", fc, style);
}
private static Style createFromSLD(String str) {
File sld = new File(str);
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
try {
SLDParser stylereader = new SLDParser(styleFactory, sld);
Style[] style = stylereader.readXML();
return style[0];
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static class MyMapPane extends JMapPane {
/**
* Forces the map pane to refresh its display.
*/
public void refresh() {
drawLayers(true);
repaint();
}
}
static class MyMapFrame extends JFrame {
private SimpleFeatureCollection fc;
private MyMapPane mapPane;
public static void showFeatures(final String title,
final SimpleFeatureCollection fc, final Style style) {
// Swing components should only be created and shown on the event
// dispatch thread
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MapContent map = new MapContent();
map.addLayer(new FeatureLayer(fc, style));
MyMapPane pane = new MyMapPane();
pane.setMapContent(map);
MyMapFrame frame = new MyMapFrame(title, pane, fc);
frame.setVisible(true);
}
});
}
private MyMapFrame(String title, MyMapPane pane,
SimpleFeatureCollection fc) {
super(title);
this.mapPane = pane;
add(mapPane, BorderLayout.CENTER);
this.fc = fc;
JPanel buttons = new JPanel();
JButton infoButton = new JButton("change value, color and
save as txt");
infoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
changeValue();
mapPane.refresh();
// save to txt-file
//write_txt();
} catch (Exception ex) {
// ignore
}
}
});
buttons.add(infoButton);
add(buttons, BorderLayout.NORTH);
setSize(600, 400);
}
private void changeValue() {
FilterFactory ff =
CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints());
Filter filter =
ff.id(Collections.singleton(ff.featureId((ID_KEY))));
SimpleFeatureIterator iter = fc.subCollection(filter).features();
try {
while (iter.hasNext()) {
iter.next().setAttribute("value", Integer.valueOf(44));
}
} finally {
iter.close();
}
}
}
}
------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
GeoTools-GT2-Users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users