001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/tools/shape/IndexFrame.java $
002 /*
003 Coyright 2003 IDgis BV
004
005 This library is free software; you can redistribute it and/or
006 modify it under the terms of the GNU Lesser General Public
007 License as published by the Free Software Foundation; either
008 version 2.1 of the License, or (at your option) any later version.
009
010 This library is distributed in the hope that it will be useful,
011 but WITHOUT ANY WARRANTY; without even the implied warranty of
012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 Lesser General Public License for more details.
014
015 You should have received a copy of the GNU Lesser General Public
016 License along with this library; if not, write to the Free Software
017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018 */
019
020 package org.deegree.tools.shape;
021
022 import java.awt.BorderLayout;
023 import java.awt.Container;
024 import java.awt.GridLayout;
025 import java.awt.event.ActionEvent;
026 import java.awt.event.ActionListener;
027 import java.io.File;
028
029 import javax.swing.JButton;
030 import javax.swing.JCheckBox;
031 import javax.swing.JFrame;
032 import javax.swing.JLabel;
033 import javax.swing.JOptionPane;
034 import javax.swing.JPanel;
035 import javax.swing.JProgressBar;
036 import javax.swing.event.ChangeEvent;
037 import javax.swing.event.ChangeListener;
038
039 import org.deegree.datatypes.QualifiedName;
040 import org.deegree.framework.log.ILogger;
041 import org.deegree.framework.log.LoggerFactory;
042 import org.deegree.io.dbaseapi.DBaseIndex;
043 import org.deegree.io.rtree.HyperBoundingBox;
044 import org.deegree.io.rtree.HyperPoint;
045 import org.deegree.io.rtree.RTree;
046 import org.deegree.io.shpapi.ShapeFile;
047 import org.deegree.model.feature.Feature;
048 import org.deegree.model.spatialschema.Envelope;
049 import org.deegree.model.spatialschema.Geometry;
050 import org.deegree.model.spatialschema.GeometryFactory;
051 import org.deegree.model.spatialschema.Point;
052
053 public class IndexFrame extends JFrame implements ActionListener, ChangeListener {
054
055 private static final ILogger LOG = LoggerFactory.getLogger( IndexFrame.class );
056
057 protected JCheckBox geometryCheckBox;
058
059 protected JCheckBox[] checkboxes;
060
061 protected ShapeFile shapeFile;
062
063 protected String[] properties;
064
065 protected JButton cancel;
066
067 protected Indexing indexing = null;
068
069 protected String fileName;
070
071 protected boolean hasGeometry;
072
073 protected boolean[] hasIndex;
074
075 protected JCheckBox[] uniqueBoxes;
076
077 class Indexing extends Thread {
078 boolean stop = false;
079
080 IndexFrame frame;
081
082 Indexing( IndexFrame frame ) {
083 this.frame = frame;
084 }
085
086 public void run() {
087 Container container = getContentPane();
088 container.removeAll();
089 container.setLayout( new GridLayout( 3, 1 ) );
090
091 int features = shapeFile.getRecordNum();
092 container.add( new JLabel( "Indexing..." ) );
093 JProgressBar progressBar = new JProgressBar( 1, features );
094 progressBar.setStringPainted( true );
095 container.add( progressBar );
096 cancel = new JButton( "Cancel" );
097 cancel.addActionListener( frame );
098 container.add( cancel );
099 pack();
100
101 boolean geometry = false;
102 DBaseIndex[] index = new DBaseIndex[properties.length];
103 RTree rtree = null;
104
105 try {
106 String[] dataTypes = shapeFile.getDataTypes();
107 int[] lengths = shapeFile.getDataLengths();
108
109 if ( geometryCheckBox.isSelected()
110 && !hasGeometry ) {
111 geometry = true;
112 rtree = new RTree( 2, 11, fileName + ".rti" );
113 }
114
115 boolean indexes = false;
116 for (int i = 0; i < index.length; i++) {
117 if ( checkboxes[i].isSelected() && !hasIndex[i] ) {
118 index[i] = DBaseIndex.createIndex( fileName
119 + "$" + properties[i], properties[i], lengths[i], uniqueBoxes[i]
120 .isSelected(), ( dataTypes[i].equalsIgnoreCase( "N" )
121 || dataTypes[i].equalsIgnoreCase( "I" ) || dataTypes[i]
122 .equalsIgnoreCase( "F" ) ) );
123 indexes = true;
124 } else
125 index[i] = null;
126 }
127
128 if ( geometry || indexes ) {
129 for (int i = 1; i < features + 1; i++) {
130 Feature feature = shapeFile.getFeatureByRecNo( i );
131
132 if ( geometry ) {
133 Geometry[] geometries = feature.getGeometryPropertyValues();
134 if ( geometries.length == 0 ) {
135 LOG.logInfo( "no geometries at recno" + i );
136 continue;
137 }
138 Envelope envelope = null;
139 // TODO: deal with more than one geometry; handle geometry=null (allowed
140 // in shapefile)
141 envelope = ( feature.getDefaultGeometryPropertyValue() ).getEnvelope();
142 if ( envelope == null ) { // assume a Point-geometry
143 Point pnt = (Point) geometries[0];
144 envelope = GeometryFactory.createEnvelope( pnt.getX(), pnt.getY(),
145 pnt.getX(), pnt.getY(), null );
146 }
147 HyperBoundingBox box = new HyperBoundingBox( new HyperPoint( envelope
148 .getMin().getAsArray() ), new HyperPoint( envelope.getMax()
149 .getAsArray() ) );
150 rtree.insert( new Integer( i ), box );
151 }
152
153 for (int j = 0; j < index.length; j++) {
154 if ( index[j] != null ) {
155 QualifiedName qn = new QualifiedName( properties[j] );
156 index[j].addKey( (Comparable) feature.getDefaultProperty( qn ), i );
157 }
158 }
159
160 progressBar.setValue( i );
161
162 synchronized (this) {
163 if ( stop ) {
164 shapeFile.close();
165 if ( geometry ) {
166 rtree.close();
167 new File( fileName
168 + ".rti" ).delete();
169 }
170 for (int j = 0; j < index.length; j++) {
171 if ( index[j] != null ) {
172 index[j].close();
173 new File( fileName
174 + "$" + properties[j] + ".ndx" ).delete();
175 }
176 }
177 System.exit( 3 );
178 }
179 }
180 }
181 }
182
183 try {
184 if ( geometry ) {
185 rtree.close();
186 }
187 shapeFile.close();
188
189 for (int i = 0; i < index.length; i++)
190 if ( index[i] != null )
191 index[i].close();
192 } catch (Exception e) {
193 e.printStackTrace();
194 JOptionPane.showMessageDialog( frame, e );
195 System.exit( 1 );
196 }
197
198 if ( !geometryCheckBox.isSelected() && hasGeometry ) {
199 new File( fileName + ".rti" ).delete();
200 }
201
202 for (int i = 0; i < index.length; i++) {
203 if ( !checkboxes[i].isSelected() && hasIndex[i] ) {
204 new File( fileName + "$" + properties[i] + ".ndx" ).delete();
205 }
206 }
207
208 System.exit( 0 );
209 } catch (Exception ex) {
210 ex.printStackTrace();
211 JOptionPane.showMessageDialog( frame, ex );
212 System.exit( 1 );
213 }
214 }
215
216 public void stopIndexing() {
217 synchronized (this) {
218 stop = true;
219 }
220 }
221 }
222
223 public IndexFrame( File file )
224 throws Exception {
225 super( "Deegree" );
226 fileName = file.getPath();
227 fileName = fileName.substring( 0, fileName.length() - 4 );
228 shapeFile = new ShapeFile( fileName );
229 properties = shapeFile.getProperties();
230
231 Container container = getContentPane();
232 container.setLayout( new BorderLayout() );
233 int size = properties.length;
234 JPanel panel = new JPanel( new GridLayout( 10 + 2, 2 ) );
235
236
237 panel.add( new JLabel( "Attributes" ) );
238 panel.add( new JLabel( "Unique" ) );
239
240 hasGeometry = shapeFile.hasRTreeIndex();
241 hasIndex = new boolean[size];
242 for (int i = 0; i < size; i++)
243 hasIndex[i] = shapeFile.hasDBaseIndex( properties[i] );
244
245 checkboxes = new JCheckBox[size];
246 uniqueBoxes = new JCheckBox[size];
247
248 geometryCheckBox = new JCheckBox( "Geometry" );
249 geometryCheckBox.setSelected( hasGeometry );
250
251 panel.add( geometryCheckBox );
252 panel.add( new JCheckBox( "" ) ).setEnabled( false );
253
254 for (int i = 0; i < checkboxes.length; i++) {
255 checkboxes[i] = new JCheckBox( properties[i] );
256 checkboxes[i].setSelected( hasIndex[i] );
257 if ( i < 10 ) {
258 panel.add( checkboxes[i] );
259
260 uniqueBoxes[i] = (JCheckBox) panel.add( new JCheckBox( "" ) );
261 if ( hasIndex[i] ) {
262 uniqueBoxes[i].setSelected( shapeFile.isUnique( properties[i] ) );
263 } else {
264 checkboxes[i].addChangeListener( this );
265 }
266 uniqueBoxes[i].setEnabled( false );
267 }
268 }
269
270 JButton start = new JButton( "Start indexing" );
271 start.addActionListener( this );
272 container.add( "South", start );
273 container.add( "Center", panel );
274
275 pack();
276 setResizable( true );
277 }
278
279 /**
280 * @param e
281 */
282 public void actionPerformed( ActionEvent e ) {
283 if ( e.getSource() == cancel ) {
284 if ( indexing != null ) {
285 if ( JOptionPane.showConfirmDialog( this, "Cancel indexing?", "Question",
286 JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION )
287 indexing.stopIndexing();
288 }
289 } else {
290 if ( hasGeometry != geometryCheckBox.isSelected() ) {
291 indexing = new Indexing( this );
292 indexing.start();
293 return;
294 }
295
296 for (int i = 0; i < hasIndex.length; i++) {
297 if ( hasIndex[i] != checkboxes[i].isSelected() ) {
298 indexing = new Indexing( this );
299 indexing.start();
300 return;
301 }
302 }
303
304 JOptionPane.showMessageDialog( this, "Nothing changed" );
305 }
306 }
307
308 /**
309 * @param e
310 */
311 public void stateChanged( ChangeEvent e ) {
312 JCheckBox checkbox = (JCheckBox) e.getSource();
313
314 for (int i = 0; i < checkboxes.length; i++) {
315 if ( checkbox == checkboxes[i] ) {
316 uniqueBoxes[i].setEnabled( checkbox.isSelected() );
317 if ( !checkbox.isSelected() ) {
318 uniqueBoxes[i].setSelected( false );
319 }
320 break;
321 }
322 }
323 }
324 }