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