001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/shpapi/FileHeader.java $
002    
003    /*----------------------------------------------------------------------------
004     This file is part of deegree, http://deegree.org/
005     Copyright (C) 2001-2009 by:
006       Department of Geography, University of Bonn
007     and
008       lat/lon GmbH
009    
010     This library is free software; you can redistribute it and/or modify it under
011     the terms of the GNU Lesser General Public License as published by the Free
012     Software Foundation; either version 2.1 of the License, or (at your option)
013     any later version.
014     This library is distributed in the hope that it will be useful, but WITHOUT
015     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
016     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
017     details.
018     You should have received a copy of the GNU Lesser General Public License
019     along with this library; if not, write to the Free Software Foundation, Inc.,
020     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021    
022     Contact information:
023    
024     lat/lon GmbH
025     Aennchenstr. 19, 53177 Bonn
026     Germany
027     http://lat-lon.de/
028    
029     Department of Geography, University of Bonn
030     Prof. Dr. Klaus Greve
031     Postfach 1147, 53001 Bonn
032     Germany
033     http://www.geographie.uni-bonn.de/deegree/
034    
035     e-mail: info@deegree.org
036    ----------------------------------------------------------------------------*/
037    
038    package org.deegree.io.shpapi;
039    
040    import java.io.IOException;
041    import java.io.RandomAccessFile;
042    
043    import org.deegree.model.spatialschema.ByteUtils;
044    
045    /**
046     * Class representing an ESRI Index File Header.
047     * <p>
048     * Uses class ByteUtils ShapeUtils modified from the original package com.bbn.openmap.layer.shape
049     * <br>
050     * Copyright (C) 1998 BBN Corporation 10 Moulton St. Cambridge, MA 02138 <br>
051     *
052     * @version 16.08.2000
053     * @author Andreas Poth
054     *
055     */
056    
057    public class FileHeader {
058    
059        /*
060         * The buffer that holds the 100 byte header.
061         */
062        private byte[] header;
063    
064        /*
065         * Holds the length of the file, in bytes.
066         */
067        private long fileLength;
068    
069        /*
070         * Holds the version of the file, as an int.
071         */
072        private int fileVersion;
073    
074        /*
075         * Holds the shape type of the file.
076         */
077        private int fileShapeType;
078    
079        /*
080         * Holds the bounds of the file (four pairs of doubles).
081         */
082        private SHPEnvelope fileMBR;
083    
084        /*
085         * local copy of the index-file randomaccess variable;
086         */
087        private RandomAccessFile rafShp = null;
088    
089        /**
090         * Construct a IndexFileHeader from a file name.
091         *
092         * @param rafShp_
093         * @throws IOException
094         */
095        public FileHeader( RandomAccessFile rafShp_ ) throws IOException {
096    
097            rafShp = rafShp_;
098    
099            initHeader( false );
100        }
101    
102        /**
103         * Construct a IndexFileHeader from a file name.
104         *
105         * @param rafShp_
106         * @param newHeader
107         * @throws IOException
108         */
109        public FileHeader( RandomAccessFile rafShp_, boolean newHeader ) throws IOException {
110    
111            rafShp = rafShp_;
112    
113            initHeader( newHeader );
114        }
115    
116        /**
117         * method: getFileMBR();<BR>
118         * Returns the bounding box of this shape file. The bounding box<BR>
119         * is the smallest rectangle that encloses all the shapes in the<BR>
120         * file.<BR>
121         *
122         * @return the bounding box of this shape file. The bounding box<BR>
123         *         is the smallest rectangle that encloses all the shapes in the<BR>
124         *         file.<BR>
125         */
126    
127        public SHPEnvelope getFileMBR() {
128    
129            return fileMBR;
130    
131        }
132    
133        /**
134         * method: getFileLength()<BR>
135         * returns the length of the shape file in bytes<BR>
136         *
137         * @return the length of the shape file in bytes<BR>
138         */
139        public long getFileLength() {
140    
141            return fileLength;
142    
143        }
144    
145        /**
146         * method: getFileVersion()<BR>
147         * returns the version of the shape file<BR>
148         *
149         * @return the version of the shape file<BR>
150         */
151        public int getFileVersion() {
152    
153            return fileVersion;
154    
155        }
156    
157        /**
158         * method: getFileShapeType()<BR>
159         * returns the code for the shape type of the file<BR>
160         *
161         * @return the code for the shape type of the file<BR>
162         */
163        public int getFileShapeType() {
164            return fileShapeType;
165        }
166    
167        /**
168         * Reads the header of a Shape file. If the file<BR>
169         * is empty, a blank header is written and then read. If the<BR>
170         * file is not empty, the header is read.<BR>
171         * After this function runs, the file pointer is set to byte 100,<BR>
172         * the first byte of the first record in the file.<BR>
173         */
174    
175        private void initHeader( boolean newHeader )
176                                throws IOException {
177    
178            if ( newHeader )
179                writeHeader();
180            /*
181             * if (rafShp.read() == -1) { //File is empty, write a new one (what else???) writeHeader(); }
182             */
183            readHeader();
184        }
185    
186        /**
187         * method: writeHeader()<BR>
188         * Writes a blank header into the shape file.<BR>
189         *
190         * @throws IOException
191         */
192        public void writeHeader()
193                                throws IOException {
194    
195            header = new byte[ShapeConst.SHAPE_FILE_HEADER_LENGTH];
196    
197            ByteUtils.writeBEInt( header, 0, ShapeConst.SHAPE_FILE_CODE );
198            ByteUtils.writeBEInt( header, 24, 50 );
199    
200            // empty shape file size in 16 bit words
201            ByteUtils.writeLEInt( header, 28, ShapeConst.SHAPE_FILE_VERSION );
202            ByteUtils.writeLEInt( header, 32, ShapeConst.SHAPE_TYPE_NULL );
203            ByteUtils.writeLEDouble( header, 36, 0.0 );
204            ByteUtils.writeLEDouble( header, 44, 0.0 );
205            ByteUtils.writeLEDouble( header, 52, 0.0 );
206            ByteUtils.writeLEDouble( header, 60, 0.0 );
207    
208            rafShp.seek( 0 );
209            rafShp.write( header, 0, ShapeConst.SHAPE_FILE_HEADER_LENGTH );
210    
211        }
212    
213        /**
214         * method: writeHeader(int filelength, byte shptype,SHPEnvelope mbr)<BR>
215         * Writes a header into the shape file.<BR>
216         *
217         * @param filelength
218         * @param shptype
219         * @param mbr
220         * @throws IOException
221         */
222        public void writeHeader( int filelength, int shptype, SHPEnvelope mbr )
223                                throws IOException {
224    
225            header = new byte[ShapeConst.SHAPE_FILE_HEADER_LENGTH];
226    
227            ByteUtils.writeBEInt( header, 0, ShapeConst.SHAPE_FILE_CODE );
228            ByteUtils.writeBEInt( header, 24, filelength / 2 );
229            ByteUtils.writeLEInt( header, 28, ShapeConst.SHAPE_FILE_VERSION );
230            ByteUtils.writeLEInt( header, 32, shptype );
231            ShapeUtils.writeBox( header, 36, mbr );
232    
233            rafShp.seek( 0 );
234            rafShp.write( header, 0, ShapeConst.SHAPE_FILE_HEADER_LENGTH );
235        }
236    
237        /**
238         * Reads and parses the header of the file. Values from the header<BR>
239         * are stored in the fields of this class.<BR>
240         */
241        private void readHeader()
242                                throws IOException {
243    
244            header = new byte[ShapeConst.SHAPE_FILE_HEADER_LENGTH];
245    
246            /*
247             * Make sure we're at the beginning of the file
248             */
249            rafShp.seek( 0 );
250    
251            rafShp.read( header, 0, ShapeConst.SHAPE_FILE_HEADER_LENGTH );
252    
253            int fileCode = ByteUtils.readBEInt( header, 0 );
254    
255            if ( fileCode != ShapeConst.SHAPE_FILE_CODE ) {
256    
257                throw new IOException( "Invalid file code, " + "probably not a shape file" );
258    
259            }
260    
261            fileVersion = ByteUtils.readLEInt( header, 28 );
262    
263            if ( fileVersion != ShapeConst.SHAPE_FILE_VERSION ) {
264    
265                throw new IOException( "Unable to read shape files with version " + fileVersion );
266    
267            }
268    
269            fileLength = ByteUtils.readBEInt( header, 24 );
270    
271            /*
272             * convert from 16-bit words to 8-bit bytes
273             */
274            fileLength *= 2;
275    
276            fileShapeType = ByteUtils.readLEInt( header, 32 );
277    
278            /*
279             * read ESRIBoundingBox and convert to SHPEnvelope
280             */
281            fileMBR = new SHPEnvelope( ShapeUtils.readBox( header, 36 ) );
282    
283        }
284    
285    }