001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.vpf.io;
017:
018: import java.io.IOException;
019: import java.io.RandomAccessFile;
020: import java.util.LinkedList;
021: import java.util.List;
022:
023: import org.geotools.data.vpf.ifc.DataTypesDefinition;
024: import org.geotools.data.vpf.ifc.FileConstants;
025: import org.geotools.data.vpf.ifc.VPFHeader;
026: import org.geotools.data.vpf.ifc.VPFRow;
027: import org.geotools.data.vpf.util.DataUtils;
028: import org.geotools.geometry.DirectPosition2D;
029: import org.geotools.geometry.GeneralDirectPosition;
030: import org.opengis.geometry.DirectPosition;
031:
032: /**
033: * VPFInputStream.java Created: Mon Feb 24 22:39:57 2003
034: *
035: * @author <a href="mailto:kobit@users.sourceforge.net">Artur Hefczyc</a>
036: * @author <a href="mailto:knuterik@onemap.org">Knut-Erik Johnsen</a>, Project OneMap
037: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/vpf/src/main/java/org/geotools/data/vpf/io/VPFInputStream.java $
038: * @version $Id: VPFInputStream.java 24925 2007-03-27 20:12:08Z jgarnett $
039: */
040: public abstract class VPFInputStream implements FileConstants,
041: DataTypesDefinition {
042: /**
043: * Describe variable <code>input</code> here.
044: *
045: */
046: protected RandomAccessFile input = null;
047:
048: /**
049: * Describe variable <code>header</code> here.
050: *
051: */
052: protected VPFHeader header = null;
053:
054: /**
055: * Describe variable <code>streamFile</code> here.
056: *
057: */
058: protected String streamFile = null;
059:
060: /**
061: * Describe variable <code>rowsReadAhead</code> here.
062: *
063: */
064: private List rowsReadAhead = new LinkedList();
065:
066: /**
067: * Describe variable <code>variableIndex</code> here.
068: *
069: */
070: private VPFInputStream variableIndex = null;
071:
072: /**
073: * Describe variable <code>byteOrder</code> here.
074: *
075: */
076: private char byteOrder = LITTLE_ENDIAN_ORDER;
077:
078: /**
079: * Describe variable <code>accessMode</code> here.
080: *
081: */
082: private String accessMode = "r";
083:
084: /**
085: * Creates a new <code>VPFInputStream</code> instance.
086: *
087: * @param file a <code>String</code> value
088: * @exception IOException if an error occurs
089: */
090: public VPFInputStream(String file) throws IOException {
091: this .streamFile = file;
092: input = new RandomAccessFile(streamFile, accessMode);
093: header = readHeader();
094:
095: // condeb("("+streamFile+
096: // ") header.getRecordSize()="+header.getRecordSize());
097: if (header.getRecordSize() < 0) {
098: variableIndex = new VariableIndexInputStream(
099: getVariableIndexFileName(), getByteOrder());
100: }
101:
102: // end of if (header.getRecordSize() == -1)
103: }
104:
105: /**
106: * Creates a new <code>VPFInputStream</code> instance.
107: *
108: * @param file a <code>String</code> value
109: * @param byteOrder a <code>char</code> value
110: * @exception IOException if an error occurs
111: */
112: public VPFInputStream(String file, char byteOrder)
113: throws IOException {
114: this .streamFile = file;
115: this .byteOrder = byteOrder;
116: input = new RandomAccessFile(streamFile, accessMode);
117: header = readHeader();
118: }
119:
120: // VariableIndexInputStream constructor
121:
122: /**
123: * Describe <code>readHeader</code> method here.
124: *
125: * @return a <code>VPFHeader</code> value
126: * @exception IOException if an error occurs
127: */
128: public abstract VPFHeader readHeader() throws IOException;
129:
130: /**
131: * Describe <code>readRow</code> method here.
132: *
133: * @return a <code>VPFRow</code> value
134: * @exception IOException if an error occurs
135: */
136: public abstract VPFRow readRow() throws IOException;
137:
138: /**
139: * Describe <code>tableSize</code> method here.
140: *
141: * @return an <code>int</code> value
142: * @exception IOException if an error occurs
143: */
144: public abstract int tableSize() throws IOException;
145:
146: /**
147: * Describe <code>getVariableIndexFileName</code> method here.
148: *
149: * @return a <code>String</code> value
150: */
151: public String getVariableIndexFileName() {
152: if (streamFile.equals("fcs")) {
153: return "fcz";
154: } else {
155: return streamFile.substring(0, streamFile.length() - 1)
156: + "x";
157: }
158: }
159:
160: /**
161: * Describe <code>getHeader</code> method here.
162: *
163: * @return a <code>VPFHeader</code> value
164: */
165: public VPFHeader getHeader() {
166: return header;
167: }
168:
169: /**
170: * Get the ByteOrder value.
171: *
172: * @return the ByteOrder value.
173: */
174: public char getByteOrder() {
175: return byteOrder;
176: }
177:
178: /**
179: * Set the ByteOrder value.
180: *
181: * @param newByteOrder The new ByteOrder value.
182: */
183: public void setByteOrder(char newByteOrder) {
184: this .byteOrder = newByteOrder;
185: }
186:
187: /**
188: * Describe <code>unread</code> method here.
189: *
190: * @param bytes a <code>long</code> value
191: * @exception IOException if an error occurs
192: */
193: protected void unread(long bytes) throws IOException {
194: input.seek(input.getFilePointer() - bytes);
195: }
196:
197: /**
198: * Describe <code>seek</code> method here.
199: *
200: * @param pos a <code>long</code> value
201: * @exception IOException if an error occurs
202: */
203: protected void seek(long pos) throws IOException {
204: input.seek(pos);
205: }
206:
207: /**
208: * DOCUMENT ME!
209: *
210: * @param pos DOCUMENT ME!
211: *
212: * @throws IOException DOCUMENT ME!
213: */
214: public void setPosition(long pos) throws IOException {
215: // condeb("setPosition: "+pos);
216: // condeb("header.getRecordSize(): "+header.getRecordSize());
217: if (header.getRecordSize() < 0) {
218: VariableIndexRow varRow = (VariableIndexRow) variableIndex
219: .readRow((int) pos);
220:
221: // condeb("Variable index info:\noffset="+varRow.getOffset()+
222: // "\nsize="+varRow.getSize());
223: seek(varRow.getOffset());
224:
225: // condeb("seek: "+varRow.getOffset());
226: } else {
227: seek(header.getLength()
228: + ((pos - 1) * header.getRecordSize()));
229:
230: // condeb("seek: "+(header.getLength()+(pos-1)*header.getRecordSize()));
231: }
232: }
233:
234: /**
235: * Method <code>readRow</code> is used to perform
236: *
237: * @param index an <code><code>int</code></code> value
238: *
239: * @return a <code><code>VPFRow</code></code> value
240: *
241: * @exception IOException if an error occurs
242: */
243: public VPFRow readRow(int index) throws IOException {
244: setPosition(index);
245:
246: return readRow();
247: }
248:
249: /**
250: * Describe <code>readAllRows</code> method here.
251: *
252: * @return a <code>List</code> value
253: * @exception IOException if an error occurs
254: */
255: public List readAllRows() throws IOException {
256: LinkedList list = new LinkedList();
257: try {
258: setPosition(1);
259: } catch (IOException exc) {
260: // This indicates that there are no rows
261: return list;
262: }
263: VPFRow row = readRow();
264:
265: while (row != null) {
266: list.add(row);
267: row = readRow();
268: }
269:
270: return list;
271: }
272:
273: /**
274: * Method <code>readRows</code> is used to perform
275: *
276: * @param rows a <code><code>VPFRow[]</code></code> value
277: *
278: * @return an <code><code>int</code></code> value
279: *
280: * @exception IOException if an error occurs
281: */
282: public int readRows(VPFRow[] rows) throws IOException {
283: int counter = 0;
284: VPFRow row = readRow();
285:
286: while ((row != null) && (counter < rows.length)) {
287: rows[counter++] = row;
288: row = readRow();
289: }
290:
291: return counter;
292: }
293:
294: /**
295: * Describe <code>readRows</code> method here.
296: *
297: * @param rows a <code>VPFRow[]</code> value
298: * @param fromIndex an <code>int</code> value
299: * @return an <code>int</code> value
300: * @exception IOException if an error occurs
301: */
302: public int readRows(VPFRow[] rows, int fromIndex)
303: throws IOException {
304: setPosition(fromIndex);
305:
306: return readRows(rows);
307: }
308:
309: /**
310: * Describe <code>readChar</code> method here.
311: *
312: * @return a <code>char</code> value
313: * @exception IOException if an error occurs
314: */
315: protected char readChar() throws IOException {
316: return (char) input.read();
317: }
318:
319: /**
320: * Describe <code>readString</code> method here.
321: *
322: * @param terminators a <code>String</code> value
323: * @return a <code>String</code> value
324: * @exception IOException if an error occurs
325: */
326: protected String readString(String terminators) throws IOException {
327: StringBuffer text = new StringBuffer();
328: char ctrl = readChar();
329:
330: if (terminators.indexOf(ctrl) != -1) {
331: if (ctrl == VPF_FIELD_SEPARATOR) {
332: unread(1);
333: }
334:
335: return null;
336: }
337:
338: while (terminators.indexOf(ctrl) == -1) {
339: text.append(ctrl);
340: ctrl = readChar();
341: }
342:
343: if (text.toString().equals(STRING_NULL_VALUE)) {
344: return null;
345: } else {
346: return text.toString();
347: }
348: }
349:
350: /**
351: * Describe <code>readVariableSizeData</code> method here.
352: *
353: * @param dataType a <code>char</code> value
354: * @return an <code>Object</code> value
355: * @exception IOException if an error occurs
356: */
357: protected Object readVariableSizeData(char dataType)
358: throws IOException {
359: int instances = readInteger();
360:
361: return readFixedSizeData(dataType, instances);
362: }
363:
364: /**
365: * Describe <code>readFixedSizeData</code> method here.
366: *
367: * @param dataType a <code>char</code> value
368: * @param instancesCount an <code>int</code> value
369: * @return an <code>Object</code> value
370: * @exception IOException if an error occurs
371: */
372: protected Object readFixedSizeData(char dataType, int instancesCount)
373: throws IOException {
374: Object result = null;
375:
376: switch (dataType) {
377: case DATA_TEXT:
378: case DATA_LEVEL1_TEXT:
379: case DATA_LEVEL2_TEXT:
380: case DATA_LEVEL3_TEXT:
381:
382: byte[] dataBytes = new byte[instancesCount
383: * DataUtils.getDataTypeSize(dataType)];
384: input.readFully(dataBytes);
385: result = DataUtils.decodeData(dataBytes, dataType);
386:
387: break;
388:
389: case DATA_SHORT_FLOAT:
390: result = new Float(readFloat());
391:
392: break;
393:
394: case DATA_LONG_FLOAT:
395: result = new Double(readDouble());
396:
397: break;
398:
399: case DATA_SHORT_INTEGER:
400: result = new Short(readShort());
401:
402: break;
403:
404: case DATA_LONG_INTEGER:
405: result = new Integer(readInteger());
406:
407: break;
408:
409: case DATA_NULL_FIELD:
410: result = "NULL";
411:
412: break;
413:
414: case DATA_TRIPLET_ID:
415: result = readTripletId();
416:
417: break;
418:
419: case DATA_2_COORD_F:
420: result = readCoord2DFloat(instancesCount);
421:
422: break;
423:
424: case DATA_2_COORD_R:
425: result = readCoord2DDouble(instancesCount);
426:
427: break;
428:
429: case DATA_3_COORD_F:
430: result = readCoord3DFloat(instancesCount);
431:
432: break;
433:
434: case DATA_3_COORD_R:
435: result = readCoord3DDouble(instancesCount);
436:
437: break;
438:
439: default:
440: break;
441: } // end of switch (dataType)
442:
443: return result;
444: }
445:
446: /**
447: * Describe <code>readNumber</code> method here.
448: *
449: * @param cnt an <code>int</code> value
450: * @return a <code>byte[]</code> value
451: * @exception IOException if an error occurs
452: */
453: protected byte[] readNumber(int cnt) throws IOException {
454: byte[] dataBytes = new byte[cnt];
455: input.readFully(dataBytes);
456: if (byteOrder == LITTLE_ENDIAN_ORDER) {
457: dataBytes = DataUtils.toBigEndian(dataBytes);
458: }
459:
460: return dataBytes;
461: }
462:
463: /**
464: * Describe <code>readShort</code> method here.
465: *
466: * @return a <code>short</code> value
467: * @exception IOException if an error occurs
468: */
469: protected short readShort() throws IOException {
470: return DataUtils
471: .decodeShort(readNumber(DATA_SHORT_INTEGER_LEN));
472: }
473:
474: /**
475: * Describe <code>readInteger</code> method here.
476: *
477: * @return an <code>int</code> value
478: * @exception IOException if an error occurs
479: */
480: protected int readInteger() throws IOException {
481: return DataUtils.decodeInt(readNumber(DATA_LONG_INTEGER_LEN));
482: }
483:
484: /**
485: * Describe <code>readFloat</code> method here.
486: *
487: * @return a <code>float</code> value
488: * @exception IOException if an error occurs
489: */
490: protected float readFloat() throws IOException {
491: return DataUtils.decodeFloat(readNumber(DATA_SHORT_FLOAT_LEN));
492: }
493:
494: /**
495: * Describe <code>readDouble</code> method here.
496: *
497: * @return a <code>double</code> value
498: * @exception IOException if an error occurs
499: */
500: protected double readDouble() throws IOException {
501: return DataUtils.decodeDouble(readNumber(DATA_LONG_FLOAT_LEN));
502: }
503:
504: protected TripletId readTripletId() throws IOException {
505: byte tripletDef = (byte) input.read();
506: int dataSize = TripletId.calculateDataSize(tripletDef);
507: byte[] tripletData = new byte[dataSize + 1];
508: tripletData[0] = tripletDef;
509:
510: if (dataSize > 0) {
511: input.readFully(tripletData, 1, dataSize);
512: }
513:
514: return new TripletId(tripletData);
515: }
516:
517: protected DirectPosition[] readCoord3DFloat(int instancesCount)
518: throws IOException {
519: DirectPosition[] result = new DirectPosition[instancesCount];
520:
521: for (int inx = 0; inx < instancesCount; inx++) {
522: result[inx] = new GeneralDirectPosition(readFloat(),
523: readFloat(), readFloat());
524: }
525:
526: return result;
527: }
528:
529: protected DirectPosition[] readCoord2DFloat(int instancesCount)
530: throws IOException {
531: DirectPosition[] result = new DirectPosition[instancesCount];
532:
533: for (int inx = 0; inx < instancesCount; inx++) {
534: result[inx] = new DirectPosition2D(readFloat(), readFloat());
535: }
536:
537: return result;
538: }
539:
540: protected DirectPosition[] readCoord2DDouble(int instancesCount)
541: throws IOException {
542: DirectPosition[] result = null;
543: result = new DirectPosition[instancesCount];
544:
545: for (int inx = 0; inx < instancesCount; inx++) {
546: result[inx] = new DirectPosition2D(readDouble(),
547: readDouble());
548: }
549:
550: return result;
551: }
552:
553: protected DirectPosition[] readCoord3DDouble(int instancesCount)
554: throws IOException {
555: DirectPosition[] result = null;
556: result = new DirectPosition[instancesCount];
557:
558: for (int inx = 0; inx < instancesCount; inx++) {
559: result[inx] = new GeneralDirectPosition(readDouble(),
560: readDouble(), readDouble());
561: }
562:
563: return result;
564: }
565:
566: /**
567: * Describe <code>availableRows</code> method here.
568: *
569: * @return an <code>int</code> value
570: */
571: public int availableRows() {
572: return (rowsReadAhead != null) ? rowsReadAhead.size() : 0;
573: }
574:
575: /**
576: * Describe <code>close</code> method here.
577: *
578: * @exception IOException if an error occurs
579: */
580: public void close() throws IOException {
581: if (variableIndex != null) {
582: variableIndex.close();
583: variableIndex = null;
584: }
585:
586: input.close();
587: input = null;
588: }
589:
590: /**
591: * Describe <code>condeb</code> method here.
592: *
593: * @param msg a <code>String</code> value
594: */
595: protected void condeb(String msg) {
596: System.out.println(msg);
597: }
598: }
599:
600: // VPFInputStream
|