001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/dbaseapi/DBFDataSection.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.dbaseapi;
047
048 import java.util.ArrayList;
049 import java.util.List;
050
051 /**
052 * Class representing a record of the data section of a dBase III/IV file<BR>
053 * at the moment only the daata types character ("C") and numeric ("N") are supported
054 *
055 *
056 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
057 * @author last edited by: $Author: apoth $
058 *
059 * @version. $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $
060 */
061 public class DBFDataSection {
062
063 /**
064 * length of one record in bytes
065 */
066 private int recordlength = 0;
067
068 private FieldDescriptor[] fieldDesc = null;
069
070 private List<ByteContainer> data = new ArrayList<ByteContainer>();
071
072 /**
073 * constructor
074 */
075 public DBFDataSection( FieldDescriptor[] fieldDesc ) {
076
077 this.fieldDesc = fieldDesc;
078
079 // calculate length of the data section
080 recordlength = 0;
081 for ( int i = 0; i < this.fieldDesc.length; i++ ) {
082
083 byte[] fddata = this.fieldDesc[i].getFieldDescriptor();
084
085 recordlength += fddata[16];
086
087 fddata = null;
088
089 }
090
091 recordlength++;
092
093 }
094
095 /**
096 * method: public setRecord(ArrayList recData) writes a data record to byte array representing
097 * the data section of the dBase file. The method gets the data type of each field in recData
098 * from fieldDesc wich has been set at the constructor.
099 */
100 public void setRecord( ArrayList recData )
101 throws DBaseException {
102
103 setRecord( data.size(), recData );
104
105 }
106
107 /**
108 * method: public setRecord(int index, ArrayList recData) writes a data record to byte array
109 * representing the data section of the dBase file. The method gets the data type of each field
110 * in recData from fieldDesc wich has been set at the constructor. index specifies the location
111 * of the retrieved record in the datasection. if an invalid index is used an exception will be
112 * thrown
113 */
114 public void setRecord( int index, ArrayList recData )
115 throws DBaseException {
116
117 ByteContainer datasec = new ByteContainer( recordlength );
118
119 if ( ( index < 0 ) || ( index > data.size() ) )
120 throw new DBaseException( "invalid index: " + index );
121
122 if ( recData.size() != this.fieldDesc.length )
123 throw new DBaseException( "invalid size of recData" );
124
125 int offset = 0;
126
127 datasec.data[offset] = 0x20;
128
129 offset++;
130
131 byte[] b = null;
132
133 // write every field on the ArrayList to the data byte array
134 for ( int i = 0; i < recData.size(); i++ ) {
135 byte[] fddata = this.fieldDesc[i].getFieldDescriptor();
136 switch ( fddata[11] ) {
137
138 // if data type is character
139 case (byte) 'C':
140 if ( recData.get( i ) != null && !( recData.get( i ) instanceof String ) ) {
141 throw new DBaseException( "invalid data type at field: " + i );
142 }
143 if ( recData.get( i ) == null ) {
144 b = new byte[0];
145 } else {
146 b = ( (String) recData.get( i ) ).getBytes();
147 }
148 if ( b.length > fddata[16] )
149 throw new DBaseException( "string contains too many characters " + (String) recData.get( i ) );
150 for ( int j = 0; j < b.length; j++ )
151 datasec.data[offset + j] = b[j];
152 for ( int j = b.length; j < fddata[16]; j++ )
153 datasec.data[offset + j] = 0x20;
154 break;
155 case (byte) 'N':
156 if ( recData.get( i ) != null && !( recData.get( i ) instanceof Number ) )
157 throw new DBaseException( "invalid data type at field: " + i );
158 if ( recData.get( i ) == null ) {
159 b = new byte[0];
160 } else {
161 b = ( (Number) recData.get( i ) ).toString().getBytes();
162 }
163 if ( b.length > fddata[16] )
164 throw new DBaseException( "string contains too many characters " + (String) recData.get( i ) );
165 for ( int j = 0; j < b.length; j++ )
166 datasec.data[offset + j] = b[j];
167 for ( int j = b.length; j < fddata[16]; j++ )
168 datasec.data[offset + j] = 0x0;
169 break;
170 default:
171 throw new DBaseException( "data type not supported" );
172
173 }
174
175 offset += fddata[16];
176
177 }
178
179 // puts the record to the ArrayList (container)
180 data.add( index, datasec );
181
182 }
183
184 /**
185 * method: public byte[] getDataSection() returns the data section as a byte array.
186 */
187 public byte[] getDataSection() {
188
189 // allocate memory for all datarecords on one array + 1 byte
190 byte[] outdata = new byte[data.size() * recordlength + 1];
191
192 // set the file terminating byte
193 outdata[outdata.length - 1] = 0x1A;
194
195 // get all records from the ArrayList and put it
196 // on a single array
197 int j = 0;
198 for ( int i = 0; i < data.size(); i++ ) {
199
200 ByteContainer bc = data.get( i );
201
202 for ( int k = 0; k < recordlength; k++ ) {
203 outdata[j++] = bc.data[k];
204 }
205
206 }
207
208 return outdata;
209
210 }
211
212 /**
213 * method: public int getNoOfRecords() returns the number of records within the container
214 */
215 public int getNoOfRecords() {
216
217 return data.size();
218
219 }
220
221 }
222
223 class ByteContainer {
224
225 public byte[] data = null;
226
227 public ByteContainer( int size ) {
228
229 data = new byte[size];
230
231 }
232
233 }