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    }