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 }