001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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() && !hasGeometry ) {
110 geometry = true;
111 rtree = new RTree( 2, 11, fileName + ".rti" );
112 }
113
114 boolean indexes = false;
115 for ( int i = 0; i < index.length; i++ ) {
116 if ( checkboxes[i].isSelected() && !hasIndex[i] ) {
117 index[i] = DBaseIndex.createIndex(
118 fileName + "$" + properties[i],
119 properties[i],
120 lengths[i],
121 uniqueBoxes[i].isSelected(),
122 ( dataTypes[i].equalsIgnoreCase( "N" )
123 || dataTypes[i].equalsIgnoreCase( "I" ) || dataTypes[i].equalsIgnoreCase( "F" ) ) );
124 indexes = true;
125 } else
126 index[i] = null;
127 }
128
129 if ( geometry || indexes ) {
130 for ( int i = 1; i < features + 1; i++ ) {
131 Feature feature = shapeFile.getFeatureByRecNo( i );
132
133 if ( geometry ) {
134 Geometry[] geometries = feature.getGeometryPropertyValues();
135 if ( geometries.length == 0 ) {
136 LOG.logInfo( "no geometries at recno" + i );
137 continue;
138 }
139 Envelope envelope = null;
140 // TODO: deal with more than one geometry; handle geometry=null (allowed
141 // in shapefile)
142 envelope = ( feature.getDefaultGeometryPropertyValue() ).getEnvelope();
143 if ( envelope == null ) { // assume a Point-geometry
144 Point pnt = (Point) geometries[0];
145 envelope = GeometryFactory.createEnvelope( pnt.getX(), pnt.getY(), pnt.getX(),
146 pnt.getY(), null );
147 }
148 HyperBoundingBox box = new HyperBoundingBox(
149 new HyperPoint( envelope.getMin().getAsArray() ),
150 new HyperPoint( envelope.getMax().getAsArray() ) );
151 rtree.insert( new Integer( i ), box );
152 }
153
154 for ( int j = 0; j < index.length; j++ ) {
155 if ( index[j] != null ) {
156 QualifiedName qn = new QualifiedName( properties[j] );
157 index[j].addKey( (Comparable) feature.getDefaultProperty( qn ), i );
158 }
159 }
160
161 progressBar.setValue( i );
162
163 synchronized ( this ) {
164 if ( stop ) {
165 shapeFile.close();
166 if ( geometry ) {
167 rtree.close();
168 new File( fileName + ".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 + "$" + properties[j] + ".ndx" ).delete();
174 }
175 }
176 System.exit( 3 );
177 }
178 }
179 }
180 }
181
182 try {
183 if ( geometry ) {
184 rtree.close();
185 }
186 shapeFile.close();
187
188 for ( int i = 0; i < index.length; i++ )
189 if ( index[i] != null )
190 index[i].close();
191 } catch ( Exception e ) {
192 e.printStackTrace();
193 JOptionPane.showMessageDialog( frame, e );
194 System.exit( 1 );
195 }
196
197 if ( !geometryCheckBox.isSelected() && hasGeometry ) {
198 new File( fileName + ".rti" ).delete();
199 }
200
201 for ( int i = 0; i < index.length; i++ ) {
202 if ( !checkboxes[i].isSelected() && hasIndex[i] ) {
203 new File( fileName + "$" + properties[i] + ".ndx" ).delete();
204 }
205 }
206
207 System.exit( 0 );
208 } catch ( Exception ex ) {
209 ex.printStackTrace();
210 JOptionPane.showMessageDialog( frame, ex );
211 System.exit( 1 );
212 }
213 }
214
215 public void stopIndexing() {
216 synchronized ( this ) {
217 stop = true;
218 }
219 }
220 }
221
222 public IndexFrame( File file ) throws Exception {
223 super( "Deegree" );
224 fileName = file.getPath();
225 fileName = fileName.substring( 0, fileName.length() - 4 );
226 shapeFile = new ShapeFile( fileName );
227 properties = shapeFile.getProperties();
228
229 Container container = getContentPane();
230 container.setLayout( new BorderLayout() );
231 int size = properties.length;
232 JPanel panel = new JPanel( new GridLayout( 10 + 2, 2 ) );
233
234 panel.add( new JLabel( "Attributes" ) );
235 panel.add( new JLabel( "Unique" ) );
236
237 hasGeometry = shapeFile.hasRTreeIndex();
238 hasIndex = new boolean[size];
239 for ( int i = 0; i < size; i++ )
240 hasIndex[i] = shapeFile.hasDBaseIndex( properties[i] );
241
242 checkboxes = new JCheckBox[size];
243 uniqueBoxes = new JCheckBox[size];
244
245 geometryCheckBox = new JCheckBox( "Geometry" );
246 geometryCheckBox.setSelected( hasGeometry );
247
248 panel.add( geometryCheckBox );
249 panel.add( new JCheckBox( "" ) ).setEnabled( false );
250
251 for ( int i = 0; i < checkboxes.length; i++ ) {
252 checkboxes[i] = new JCheckBox( properties[i] );
253 checkboxes[i].setSelected( hasIndex[i] );
254 if ( i < 10 ) {
255 panel.add( checkboxes[i] );
256
257 uniqueBoxes[i] = (JCheckBox) panel.add( new JCheckBox( "" ) );
258 if ( hasIndex[i] ) {
259 uniqueBoxes[i].setSelected( shapeFile.isUnique( properties[i] ) );
260 } else {
261 checkboxes[i].addChangeListener( this );
262 }
263 uniqueBoxes[i].setEnabled( false );
264 }
265 }
266
267 JButton start = new JButton( "Start indexing" );
268 start.addActionListener( this );
269 container.add( "South", start );
270 container.add( "Center", panel );
271
272 setBounds( 100, 100, 100, 100 );
273 pack();
274
275 setResizable( true );
276 }
277
278 /**
279 * @param e
280 */
281 public void actionPerformed( ActionEvent e ) {
282 if ( e.getSource() == cancel ) {
283 if ( indexing != null ) {
284 if ( JOptionPane.showConfirmDialog( this, "Cancel indexing?", "Question", JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION )
285 indexing.stopIndexing();
286 }
287 } else {
288 if ( hasGeometry != geometryCheckBox.isSelected() ) {
289 indexing = new Indexing( this );
290 indexing.start();
291 return;
292 }
293
294 for ( int i = 0; i < hasIndex.length; i++ ) {
295 if ( hasIndex[i] != checkboxes[i].isSelected() ) {
296 indexing = new Indexing( this );
297 indexing.start();
298 return;
299 }
300 }
301
302 JOptionPane.showMessageDialog( this, "Nothing changed" );
303 }
304 }
305
306 /**
307 * @param e
308 */
309 public void stateChanged( ChangeEvent e ) {
310 JCheckBox checkbox = (JCheckBox) e.getSource();
311
312 for ( int i = 0; i < checkboxes.length; i++ ) {
313 if ( checkbox == checkboxes[i] ) {
314 uniqueBoxes[i].setEnabled( checkbox.isSelected() );
315 if ( !checkbox.isSelected() ) {
316 uniqueBoxes[i].setSelected( false );
317 }
318 break;
319 }
320 }
321 }
322 }