/[schmitzm]/branches/2.2.x/src/skrueger/geotools/StyledFeatureCollectionTableModel.java
ViewVC logotype

Diff of /branches/2.2.x/src/skrueger/geotools/StyledFeatureCollectionTableModel.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/src/skrueger/geotools/StyledFeatureCollectionTableModel.java revision 62 by alfonx, Fri Apr 17 18:56:17 2009 UTC branches/2.2.x/src/skrueger/geotools/StyledFeatureCollectionTableModel.java revision 1042 by alfonx, Wed Sep 22 11:17:48 2010 UTC
# Line 1  Line 1 
1  /** SCHMITZM - This file is part of the java library of Martin O.J. Schmitz (SCHMITZM)  /*******************************************************************************
2     * Copyright (c) 2009 Martin O. J. Schmitz.
3      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; either version 2.1 of the License, or (at your option) any later version.   *
4      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.   * This file is part of the SCHMITZM library - a collection of utility
5      You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA   * classes based on Java 1.6, focusing (not only) on Java Swing
6     * and the Geotools library.
7      Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.   *
8      Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.   * The SCHMITZM project is hosted at:
9      Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.   * http://wald.intevation.org/projects/schmitzm/
10   **/   *
11  package skrueger.geotools;   * This program is free software; you can redistribute it and/or
12     * modify it under the terms of the GNU Lesser General Public License
13  import java.util.Iterator;   * as published by the Free Software Foundation; either version 3
14  import java.util.Map;   * of the License, or (at your option) any later version.
15  import java.util.TreeMap;   *
16  import java.util.Vector;   * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  import org.geotools.data.DefaultQuery;   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  import org.geotools.data.FeatureSource;   * GNU General Public License for more details.
20  import org.geotools.data.Query;   *
21  import org.geotools.data.memory.MemoryDataStore;   * You should have received a copy of the GNU Lesser General Public License (license.txt)
22  import org.geotools.feature.FeatureCollection;   * along with this program; if not, write to the Free Software
23  import org.opengis.filter.Filter;   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24     * or try this link: http://www.gnu.org/licenses/lgpl.html
25  import com.vividsolutions.jts.geom.Envelope;   *
26     * Contributors:
27  import schmitzm.geotools.gui.FeatureCollectionTableModel;   *     Martin O. J. Schmitz - initial API and implementation
28  import skrueger.AttributeMetaData;   *     Stefan A. Tzeggai - additional utility classes
29  import skrueger.i8n.I8NUtil;   ******************************************************************************/
30  import skrueger.i8n.Translation;  package skrueger.geotools;
31    
32  /**  import java.util.HashMap;
33   * This class extends the the {@link FeatureCollectionTableModel} with the  import java.util.LinkedHashSet;
34   * functionalities of the {@link AttributeMetaData} of  import java.util.List;
35   * {@linkplain StyledMapInterface styled objects}.  import java.util.Vector;
36   * <ul>  
37   *   <li>column names are translated according to {@link AttributeMetaData#getTitle()}</li>  import org.apache.log4j.Logger;
38   *   <li>columns are hidden according to {@link AttributeMetaData#isVisible()()}</li>  import org.geotools.data.DefaultQuery;
39   * </ul>  import org.geotools.data.FeatureSource;
40   * @author <a href="mailto:[email protected]">Martin Schmitz</a> (University of Bonn/Germany)  import org.geotools.data.Query;
41   */  import org.geotools.feature.FeatureCollection;
42  public class StyledFeatureCollectionTableModel extends FeatureCollectionTableModel {  import org.opengis.feature.simple.SimpleFeature;
43    /** Holds the data source as styled map. */  import org.opengis.feature.simple.SimpleFeatureType;
44    protected StyledMapInterface map = null;  import org.opengis.feature.type.AttributeDescriptor;
45    /** Contains only the visible elements of the {@link AttributeMetaData}-Map */  import org.opengis.feature.type.Name;
46    protected Map<Integer, AttributeMetaData> visibleAMD = null;  import org.opengis.filter.Filter;
47    /** Holds the data source for the table as {@code FeatureSource}. */  
48    protected FeatureSource featureSource = null;  import schmitzm.geotools.feature.FeatureUtil;
49    /** Contains the complete {@link AttributeMetaData}-Map of the styled layer. */  import schmitzm.geotools.gui.FeatureCollectionTableModel;
50    protected Map<Integer, AttributeMetaData> origAMD = null;  import skrueger.AttributeMetadataImpl;
51    /** Holds the current filter on the table */  import skrueger.AttributeMetadataInterface;
52    protected Filter filter = null;  
53    /** Holds the Bounds for all features. Only set once during the constructor **/  import com.vividsolutions.jts.geom.Envelope;
54    protected Envelope bounds;  
55    /**
56    /**   * This class extends the the {@link FeatureCollectionTableModel} with the
57     * Creates a new table model for a styled map.   * functionalities of the {@link AttributeMetadataImpl}.
58     * @param map the styled map   * <ul>
59     */   * <li>column names are translated according to
60    public StyledFeatureCollectionTableModel(StyledFeatureCollectionInterface map) {   * {@link AttributeMetadataImpl#getTitle()}</li>
61      this(map,Filter.INCLUDE);   * <li>columns are hidden according to {@link AttributeMetaData#isVisible()()}</li>
62    }   * <li>Any filter defined in the {@link StyledFeaturesInterface} will be
63     * applied.</li>
64    /**   * </ul>
65     * Creates a new table model for a styled map.   *
66     * @param map the styled map   * @author Stefan A. Tzeggai
67     * @param filter filter applied to the table   */
68     */  public class StyledFeatureCollectionTableModel extends
69    public StyledFeatureCollectionTableModel(StyledFeatureCollectionInterface map, Filter filter) {                  FeatureCollectionTableModel {
70      super();          final static private Logger LOGGER = Logger
71      setFeatureCollection(map, filter);                          .getLogger(StyledFeatureCollectionTableModel.class);
72    }          /** Contains the complete {@link AttributeMetadataImpl}-Map of the styled layer. */
73            protected AttributeMetadataMap<? extends AttributeMetadataInterface> amdMap = null;
74    /**          /** Holds the current filter on the table */
75     * Creates a new table model for a styled map.          protected Filter filter = null;
76     * @param map the styled map          /** Holds the Bounds for all features. Only set once during the constructor **/
77     */          protected Envelope bounds;
78    public StyledFeatureCollectionTableModel(StyledFeatureSourceInterface map) {          /**
79      this(map,Filter.INCLUDE);           * Tooltips für die Spaltennamen. Wird nur beim Aufruf von
80    }           * {@link #reorganize} befuellt.
81             */
82    /**          protected String[] colTooltips = null;
83     * Creates a new table model for a styled map.  
84     * @param map the styled map          /** A cache for the #sortedValuesVisibleOnly() **/
85     * @param filter filter applied to the table          protected List<? extends AttributeMetadataInterface> amdMapVisibleOnly = null;
86     */  
87    public StyledFeatureCollectionTableModel(StyledFeatureSourceInterface map, Filter filter) {          /**
88      super();           * Creates a new table model for a styled layer.
89      setFeatureCollection(map, filter);           *
90    }           * @param styledFeatures
91             *            the styled layer
92    /**           * @param filter
93     * Sets a new data source for the table.           *            filter applied to the table
94     * @param fs     the feature source           */
95     * @param amd    {@link AttributeMetaData}-Map to define the visible attributes          public StyledFeatureCollectionTableModel(
96     *               and translation                          StyledFeaturesInterface<?> styledFeatures) {
97     */                  setStyledFeatures(styledFeatures);
98    protected void setFeatureSource(FeatureSource fs, Map<Integer, AttributeMetaData> amd, Filter filter) throws Exception {          }
99      if ( filter == null )  
100        filter = Filter.INCLUDE;          /**
101                 * This overwritten method filters the values for NODATA-values defined in
102      this.featureSource = fs;           * the {@link AttributeMetadataImpl}
103      this.filter        = filter;           */
104      this.origAMD       = amd;          @Override
105      this.visibleAMD    = null;          public Object getValueAt(int row, int col) {
106                        Object rawValue = super.getValueAt(row, col);
107      FeatureCollection fc = null;                  return amdMap.sortedValuesVisibleOnly().get(col).fiterNodata(rawValue);
108      if (fs != null) {          }
109                    
110         bounds = fs.getBounds();          /**
111                     * Sets a new data source for the table.
112        Query query = new DefaultQuery(fs.getSchema().getTypeName(), filter);           *
113        if (amd != null) {           * @param fs
114          // determine the names of the visible Attributes           *            the feature source
115          this.visibleAMD = StyledMapUtil.getVisibleAttributeMetaData(amd, true);           * @param amdm
116          Vector<String> visibleAttrNames = new Vector<String>();           *            {@link AttributeMetadataImpl}-Map to define the visible attributes
117          // Add the column with the geometry (usually "the_geom")           *            and translation
118          visibleAttrNames.add(fs.getSchema().getDefaultGeometry().getLocalName());           */
119          for (int attrIdx : visibleAMD.keySet())          protected void setFeatureSource(
120            visibleAttrNames.add(fs.getSchema().getAttributeType(attrIdx).getLocalName());                          FeatureSource<SimpleFeatureType, SimpleFeature> fs,
121                            AttributeMetadataMap<? extends AttributeMetadataInterface> amdm, Filter filter) throws Exception {
122          // create a query for the visible attributes  
123          String[] properties = visibleAttrNames.toArray(new String[0]);                  if (filter == null)
124                                    filter = Filter.INCLUDE;
125          query = new DefaultQuery(fs.getSchema().getTypeName(), filter, properties);  
126        }                  // this.featureSource = fs;
127        fc = fs.getFeatures(query);                  this.filter = filter;
128                    this.amdMap = amdm;
129  // FAILS:!!!, even with  query = new DefaultQuery(fs.getSchema().getTypeName(), filter);                  this.amdMapVisibleOnly = amdMap.sortedValuesVisibleOnly();
130                          // java.lang.UnsupportedOperationException: Unknown feature  
131                          // attribute: PQM_MOD                  FeatureCollection<SimpleFeatureType, SimpleFeature> fc = null;
132                          // at                  if (fs != null) {
133                          // schmitzm.geotools.feature.FeatureOperationTree.evaluate(FeatureOperationTree.java:93)  
134                          // bounds = fc.getBounds();                          bounds = fs.getBounds();
135                          // SK, 17.4.2009  
136                          //                                final SimpleFeatureType schema = fs.getSchema();
137                          // System.out.println("Filter = "+filter);                          Query query = new DefaultQuery(schema.getTypeName(), filter);
138                          // System.out.println("Size of FC = "+fc.size());                          if (amdm != null) {
139                          // System.out.println("anz att= "+fc.getNumberOfAttributes());                                  LinkedHashSet<String> visibleAttrNames = new LinkedHashSet<String>();
140      }  
141      setFeatureCollection(fc);                                  // Add the column with the geometry (usually "the_geom") always
142    }                                  String geomColumnLocalName = schema.getGeometryDescriptor()
143                                                    .getLocalName();
144    /**                                  visibleAttrNames.add(geomColumnLocalName);
145     * Converts the {@code StyledFeatureCollection} to a {@code FeatureSource}  
146     * and sets this as the new data source for the table.                                  // Add other visible attributes as ordered by weights
147     * @param fs     the feature source                                  for (AttributeMetadataInterface a : amdMapVisibleOnly) {
148     * @param amd    {@link AttributeMetaData}-Map to define the visible attributes                                          visibleAttrNames.add(a.getLocalName());
149     *               and translation                                  }
150     */  
151    public void setFeatureCollection(StyledFeatureCollectionInterface map, Filter filter) {                                  // Tested with 2.6.x trunk from 2009-11-26 and it now works. So
152      this.map = map;                                  // we only request the properties we need!
153      try {                                  // /**
154        if (map == null)                                  // * I got NPEs when properties contained only [the_geom]
155          setFeatureSource(null, null, null);                                  // ?!??!!??
156        else {                                  // */
157          FeatureCollection fc = map.getGeoObject();                                  // if (properties.length > 1) {
158          String fcName = fc.getFeatureType().getTypeName();                                  query = new DefaultQuery(schema.getTypeName(), filter,
159          FeatureSource fs = new MemoryDataStore(fc).getFeatureSource(fcName);                                                  visibleAttrNames.toArray(new String[] {}));
160          setFeatureSource(fs, map.getAttributeMetaDataMap(), filter);                                  // } else {
161        }                                  // query = new DefaultQuery(schema.getTypeName(), filter);
162      } catch (Exception err) {                                  // }
163        throw new RuntimeException(err);                                  
164      }                                  System.out.println(query.getPropertyNames());
165    }                          }
166                            fc = fs.getFeatures(query);
167    /**                  }
168     * Sets the {@code StyledFeatureCollection} as new data source for the table.                  setFeatureCollection(fc);
169     * @param fs     the feature source          }
170     * @param amd    {@link AttributeMetaData}-Map to define the visible attributes  
171     *               and translation          /**
172     */           * Converts the {@code StyledFeatureCollection} to a {@code FeatureSource}
173    public void setFeatureCollection(StyledFeatureSourceInterface map, Filter filter) {           * and sets this as the new data source for the table.
174      this.map = map;           *
175      try {           * @param fs
176        if (map == null)           *            the feature source
177          setFeatureSource(null, null, null);           * @param amd
178        else           *            {@link AttributeMetadataImpl}-Map to define the visible attributes
179          setFeatureSource(map.getGeoObject(), map.getAttributeMetaDataMap(), filter);           *            and translation
180      } catch (Exception err) {           */
181        throw new RuntimeException(err);          public void setStyledFeatures(StyledFeaturesInterface<?> styledFeatures) {
182      }                  try {
183    }                          if (styledFeatures == null)
184                                      setFeatureSource(null, null, null);
185    /**                          else {
186     * Resets the filter for the table.                                  setFeatureSource(styledFeatures.getFeatureSource(),
187     * @param filter a filter                                                  styledFeatures.getAttributeMetaDataMap(),
188     */                                                  styledFeatures.getFilter());
189    public void setFilter(Filter filter) {                          }
190      try{                  } catch (Exception err) {
191        setFeatureSource(this.featureSource, this.origAMD, filter);                          throw new RuntimeException(err);
192      } catch (Exception err) {                  }
193        throw new RuntimeException(err);          }
194      }  
195    }          /**
196               * After calling {@code super.reorganize(.)} this method replaced the column
197    /**           * descriptions with the titles of the {@code AttributeMetaData}.
198     * @return <code>Filter.INCLUDE</code> or the {@link Filter} applied to the Features           *
199     */           * @param fireTableStructureChanged
200    public Filter getFilter() {           *            indicates whether a table event is initiated after reorganize
201            return this.filter;           */
202    }          @Override
203            protected void reorganize(boolean fireTableStructureChanged) {
204    /**  
205     * After calling {@code super.reorganize(.)} this method replaced the                  featureArray = FeatureUtil.featuresToArray(featureTable);
206     * column descriptions with the titles of the {@code AttributeMetaData}.                  if (featureArray == null || featureArray.length == 0) {
207     * @param fireTableStructureChanged indicates whether a table event is                          colNames = new String[0];
208     *        initiated after reorganize                          colTooltips = new String[0]; // Only set and used in
209     */                          // StyledFeatureCollectionTableModel
210    @Override                          colClass = new Class[0];
211    protected void reorganize(boolean fireTableStructureChanged) {                  } else {
212      super.reorganize(false);                          // Struktur der Tabelle vom AttributeMetaDtaaMap übernehmen
213      // translate the column names                          SimpleFeatureType schema = featureArray[0].getFeatureType();
214      if (visibleAMD != null) {                          // Pruefen, welche Attribute angezeigt werden
215        Iterator<Integer> keys = visibleAMD.keySet().iterator();                          attrTypes.clear();
216        for (int i = 0; i < colNames.length && keys.hasNext(); i++) {                          for (AttributeMetadataInterface amd : amdMapVisibleOnly) {
217          Translation title = visibleAMD.get(keys.next()).getTitle();                                  Name name = amd.getName();
218          if (!I8NUtil.isEmpty(title)) {                  AttributeDescriptor type = schema.getDescriptor(name);
219  //          System.out.println("set colname " + i + " to " + title.toString());                  // if type can not be determined by complete name,
220            colNames[i] = title.toString();                  // try only the local name
221          }                  if ( type == null )
222        }                    type = schema.getDescriptor(name.getLocalPart());
223      }                                  if (attrFilter == null || attrFilter.accept(type))
224      if ( fireTableStructureChanged )                                          attrTypes.add(type);
225        fireTableStructureChanged();                          }
226    }                          // Namen und Attribut-Indizes der angezeigten Spalten ermitteln
227                            colNames = new String[attrTypes.size()];
228    /**                          colTooltips = new String[attrTypes.size()]; // Only set and used in
229           * @returns Cached bounds for the whole dataset (without applying the                          // StyledFeatureCollectionTableModel
230           *          filter) or <code>null</code>                          colClass = new Class[attrTypes.size()];
231           */                          attrIdxForCol = new int[attrTypes.size()];
232          public Envelope getBounds() {                          for (int i = 0; i < colNames.length; i++) {
233                  return bounds;                                  Name name = amdMapVisibleOnly.get(i).getName();
234          }                  AttributeDescriptor descriptor = schema.getDescriptor(name);
235  }                  // if type can not be determined by complete name,
236                    // try only the local name
237                    if ( descriptor == null )
238                      descriptor = schema.getDescriptor(name.getLocalPart());
239    
240                                    // Not so nice in 26: find the index of an attribute...
241                                    int idx = schema.getAttributeDescriptors().indexOf(descriptor);
242                                    attrIdxForCol[i] = idx;
243    
244                                    String attName = schema.getAttributeDescriptors().get(idx)
245                                                    .getLocalName();
246                                    colNames[i] = amdMap.get(attName).getTitle().toString();
247                                    AttributeMetadataInterface amd = amdMap.get(attName);
248                                    colTooltips[i] = "<html>" + amd.getDesc().toString() + "<br>"
249                                                    + amd.getName() + "</html>";
250                                    colClass[i] = schema.getAttributeDescriptors().get(idx)
251                                                    .getType().getBinding();
252                            }
253                    }
254    
255                    // store feature indexes in HashMap to optimize findFeature(.)
256                    featureIdx = new HashMap<String, Integer>();
257                    for (int i = 0; i < featureArray.length; i++)
258                            if (featureArray[i] != null)
259                                    featureIdx.put(featureArray[i].getID(), i);
260                    //
261                    // // translate the column names
262                    // if (amdMap != null) {
263                    // for (int i = 0; i < colNames.length; i++) {
264                    // colTooltips[i] = amdMap.get(colNames[i]).getDesc().toString()
265                    // + "<br>" + colNames[i];
266                    // colNames[i] = amdMap.get(colNames[i]).getTitle().toString();
267                    //
268                    // }
269                    // }
270                    if (fireTableStructureChanged)
271                            fireTableStructureChanged();
272    
273            }
274    
275            /**
276             * @return Cached bounds for the whole dataset (without applying the filter)
277             *         or <code>null</code>
278             */
279            public Envelope getBounds() {
280                    return bounds;
281            }
282    }

Legend:
Removed from v.62  
changed lines
  Added in v.1042

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26