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    }