    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/io/shpapi/shape_new/ShapeFileWriter.java $
    002    /*----------------------------------------------------------------------------
    003     This file is part of deegree, http://deegree.org/
    004     Copyright (C) 2001-2009 by:
    005       Department of Geography, University of Bonn
    006     and
    007       lat/lon GmbH
    008
    009     This library is free software; you can redistribute it and/or modify it under
    010     the terms of the GNU Lesser General Public License as published by the Free
    011     Software Foundation; either version 2.1 of the License, or (at your option)
    012     any later version.
    013     This library is distributed in the hope that it will be useful, but WITHOUT
    014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    016     details.
    017     You should have received a copy of the GNU Lesser General Public License
    018     along with this library; if not, write to the Free Software Foundation, Inc.,
    019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    020
    021     Contact information:
    022
    023     lat/lon GmbH
    024     Aennchenstr. 19, 53177 Bonn
    025     Germany
    026     http://lat-lon.de/
    027
    028     Department of Geography, University of Bonn
    029     Prof. Dr. Klaus Greve
    030     Postfach 1147, 53001 Bonn
    031     Germany
    032     http://www.geographie.uni-bonn.de/deegree/
    033
    034     e-mail: info@deegree.org
    035    ----------------------------------------------------------------------------*/
    036    package org.deegree.io.shpapi.shape_new;
    037
    038    import java.io.BufferedOutputStream;
    039    import java.io.File;
    040    import java.io.FileOutputStream;
    041    import java.io.IOException;
    042    import java.io.OutputStream;
    043
    044    import org.deegree.framework.log.ILogger;
    045    import org.deegree.framework.log.LoggerFactory;
    046    import org.deegree.io.dbaseapi.DBaseException;
    047    import org.deegree.model.spatialschema.ByteUtils;
    048
    049    /**
    050     * <code>ShapeFileWriter</code> is a class to write shapefiles.
    051     *
    052     * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a>
    053     * @author last edited by: $Author: mschneider $
    054     *
    055     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    056     */
    057    public class ShapeFileWriter {
    058
    059        private ShapeFile shapeFile;
    060
    061        private static final ILogger LOG = LoggerFactory.getLogger( ShapeFileWriter.class );
    062
    063        /**
    064         * @param shapes
    065         */
    066        public ShapeFileWriter( ShapeFile shapes ) {
    067            shapeFile = shapes;
    068        }
    069
    070        private void writeHeader( OutputStream out, int length )
    071                                throws IOException {
    072
    073            // what's funny about shapefiles:
    074            // 1) in the headers, they use big endian for some values, little endian for others
    075            // (the rest of the file is little endian)
    076            // 2) Only 4 byte ints and 8 byte doubles are used in the file, however,
    077            // the size is measured in 16 bit words...
    078
    079            byte[] header = new byte[100];
    080
    081            ByteUtils.writeBEInt( header, 0, ShapeFile.FILETYPE );
    082            ByteUtils.writeBEInt( header, 24, length );
    083            ByteUtils.writeLEInt( header, 28, ShapeFile.VERSION );
    084            ByteUtils.writeLEInt( header, 32, shapeFile.getShapeType() );
    085
    086            ShapeEnvelope envelope = shapeFile.getEnvelope();
    087            envelope.write( header, 36 );
    088
    089            // it shouldn't hurt to write these values as doubles default to 0.0 anyway
    090            ByteUtils.writeLEDouble( header, 68, envelope.zmin );
    091            ByteUtils.writeLEDouble( header, 76, envelope.zmax );
    092            ByteUtils.writeLEDouble( header, 84, envelope.mmin );
    093            ByteUtils.writeLEDouble( header, 92, envelope.mmax );
    094
    095            out.write( header, 0, 100 );
    096        }
    097
    098        private void writeShapes( OutputStream mainOut, OutputStream indexOut )
    099                                throws IOException {
    100            // allocate the WHOLE shape file
    101            byte[] bytes = new byte[shapeFile.getSize()];
    102            byte[] indexBytes = new byte[8 * shapeFile.getShapes().size()];
    103
    104            int recordNum = 1;
    105            int offset = 0;
    106            int indexOffset = 0;
    107
    108            for ( Shape s : shapeFile.getShapes() ) {
    109                ByteUtils.writeBEInt( indexBytes, indexOffset, ( 100 + offset ) / 2 );
    110                indexOffset += 4;
    111                ByteUtils.writeBEInt( indexBytes, indexOffset, s.getByteLength() / 2 );
    112                indexOffset += 4;
    113
    114                ByteUtils.writeBEInt( bytes, offset, recordNum++ );
    115                offset += 4;
    116                ByteUtils.writeBEInt( bytes, offset, s.getByteLength() / 2 ); // again 16-bit words
    117                offset += 4;
    118
    119                LOG.logDebug( "Writing a " + s.getClass().getSimpleName() + ", size " + s.getByteLength() + " from offset "
    120                              + offset );
    121                offset = s.write( bytes, offset );
    122            }
    123
    124            mainOut.write( bytes, 0, bytes.length );
    125            indexOut.write( indexBytes, 0, indexBytes.length );
    126        }
    127
    128        /**
    129         * Writes the shapes to the files with the given base name.
    130         *
    131         * @param baseName
    132         * @throws IOException
    133         * @throws DBaseException
    134         * @deprecated
    135         */
    136        @Deprecated
    137        public void write( String baseName )
    138                                throws IOException, DBaseException {
    139            LOG.logWarning( "Base name parameter " + baseName + " is ignored! Base name of " + shapeFile.getBaseName()
    140                            + " is used instead." );
    141            write();
    142        }
    143
    144        /**
    145         * Writes the shapes to file.
    146         *
    147         * @throws IOException
    148         * @throws DBaseException
    149         */
    150        public void write()
    151                                throws IOException, DBaseException {
    152            String baseName = shapeFile.getBaseName();
    153            File mainFile = new File( baseName + ".shp" );
    154            BufferedOutputStream mainOut = new BufferedOutputStream( new FileOutputStream( mainFile ) );
    155            writeHeader( mainOut, ( shapeFile.getSize() + 100 ) / 2 );
    156
    157            File indexFile = new File( baseName + ".shx" );
    158            BufferedOutputStream indexOut = new BufferedOutputStream( new FileOutputStream( indexFile ) );
    159            writeHeader( indexOut, ( shapeFile.getShapes().size() * 8 + 100 ) / 2 );
    160
    161            writeShapes( mainOut, indexOut );
    162
    163            mainOut.close();
    164            indexOut.close();
    165
    166            shapeFile.writeDBF();
    167        }
    168
    169    }