Package com.bbn.openmap.layer.vpf

Source Code of com.bbn.openmap.layer.vpf.DcwColumnInfo

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/layer/vpf/DcwColumnInfo.java,v $
// $Revision: 1.4.2.2 $ $Date: 2007/01/26 15:56:35 $ $Author: dietrick $
// **********************************************************************

package com.bbn.openmap.layer.vpf;

import com.bbn.openmap.io.FormatException;
import com.bbn.openmap.io.BinaryFile;

import java.io.EOFException;

/**
* Encapsulate the information about a particular column in a vpf
* table. This class can read both VPF V1 (MIL-STD-600006, dated 1992)
* and VPF V2 (MIL-STD-2407, dated 1996, supercedees V1)
*/
public class DcwColumnInfo {
    /** the name of the column */
    final private String columnName;
    /** the fieldtype of the contained data */
    final private char fieldType;
    /** the number of values (-1 indicates variable) */
    final private int numberOfElements;
    /** the keytype (primary key, non-key, foreign key) */
    final private char keyType;
    /** optional text description of what the column is for */
    final private String columnDescription;
    /**
     * optional table that provides descriptions of what the values in
     * this column are
     */
    private String valueDescriptionTable = null;
    /** name of the optional thematic index created for this column */
    private String thematicIndexName = null;
    /** name of the optional narrative table for this column */
    private String narrativeTable = null;

    /** VPF Column Type Constants */
    public static final char VPF_COLUMN_TEXT = 'T';
    public static final char VPF_COLUMN_TEXTL1 = 'L';
    public static final char VPF_COLUMN_TEXTL2 = 'M';
    public static final char VPF_COLUMN_TEXTL3 = 'N';
    public static final char VPF_COLUMN_FLOAT = 'F';
    public static final char VPF_COLUMN_DOUBLE = 'R';
    public static final char VPF_COLUMN_SHORT = 'S';
    public static final char VPF_COLUMN_INT = 'I';
    public static final char VPF_COLUMN_FLOAT_2COORD = 'C';
    public static final char VPF_COLUMN_DOUBLE_2COORD = 'B';
    public static final char VPF_COLUMN_FLOAT_3COORD = 'Z';
    public static final char VPF_COLUMN_DOUBLE_3COORD = 'Y';
    public static final char VPF_COLUMN_DATE = 'D';
    public static final char VPF_COLUMN_NULL = 'X';
    public static final char VPF_COLUMN_TRIPLET = 'K';
    /**
     * VPF Column Type Constant for a column that can be either int or
     * short. This value will never be read from a VPF file, its a
     * special value that is accepted by lookupSchema
     */
    public static final char VPF_COLUMN_INT_OR_SHORT = 'i';

    /** VPF Column Key Type Constants */
    public static final char VPF_COLUMN_PRIMARY_KEY = 'P';
    public static final char VPF_COLUMN_FOREIGN_KEY = 'F';
    public static final char VPF_COLUMN_NON_KEY = 'N';

    /**
     * Construct a DcwColumnInfo from the specified input stream.
     *
     * @param inputFile the filestream to construct from
     * @exception EOFException when the first character read is a ';',
     *            indicating that we've reached the end of the column
     *            list; also thrown for an end of file
     * @exception FormatException some error was detected while
     *            reading the info for the column.
     */
    public DcwColumnInfo(BinaryFile inputFile) throws EOFException,
            FormatException {
        char delim = inputFile.readChar();
        if (delim == ';')
            throw new EOFException();

        StringBuffer buildstring = new StringBuffer();
        do {
            buildstring.append(Character.toLowerCase(delim));
        } while ((delim = inputFile.readChar()) != '=');

        columnName = buildstring.toString().trim().intern();// Collapse all blanks

        fieldType = inputFile.readChar();

        delim = inputFile.readChar();
        if (delim != ',') { //only legal delimiter
            if (delim != ' ') { //one DCW file uses this instead
                throw new com.bbn.openmap.io.InvalidCharException("Illegal delimiter character", delim);
            }
        }

        buildstring = new StringBuffer();
        while ((delim = inputFile.readChar()) != ',') {
            // field length occasionally has trailing whitespace...
            if (!Character.isWhitespace(delim)) {
                buildstring.append(delim); //assumes not like "1 4"
            }
        }
        String nEls = buildstring.toString();
        numberOfElements = (nEls.equals("*")) ? -1 : Integer.parseInt(nEls);

        // Sanity check the column schema... a few VPF primitives are
        // not
        // allowed to show up in arrays. complain about that now...
        if (numberOfElements != 1) {
            switch (fieldType) {
            case VPF_COLUMN_FLOAT:
            case VPF_COLUMN_DOUBLE:
            case VPF_COLUMN_SHORT:
            case VPF_COLUMN_INT:
            case VPF_COLUMN_DATE:
            case VPF_COLUMN_NULL:
            case VPF_COLUMN_TRIPLET:
                throw new FormatException("Illegal array type: " + fieldType
                        + "for column " + columnName);
            default:
                //legal
                break;
            }
        }

        String tmpkeyType = readColumnText(inputFile);
        if (tmpkeyType == null) {
            throw new FormatException("keyType is required column info");
        }
        tmpkeyType = tmpkeyType.trim();
        if (tmpkeyType.length() == 1) {
            keyType = tmpkeyType.charAt(0);
        } else {
            throw new FormatException("keyType is supposed to be 1 character");
        }
        columnDescription = readColumnText(inputFile);
        if (columnDescription == null) {
            return;
        }

        valueDescriptionTable = readColumnTextLowerCase(inputFile);
        if (valueDescriptionTable == null) {
            return;
        }
        if (valueDescriptionTable.equals("-")) {
            valueDescriptionTable = null;
        } else {
            valueDescriptionTable = valueDescriptionTable.intern();
        }

        thematicIndexName = readColumnTextLowerCase(inputFile);
        if (thematicIndexName == null) {
            return;
        }
        if (thematicIndexName.equals("-")) {
            thematicIndexName = null;
        } else {
            thematicIndexName = thematicIndexName.intern();
        }

        narrativeTable = readColumnTextLowerCase(inputFile);
        if (narrativeTable == null) {
            return;
        }
        if (narrativeTable.equals("-")) {
            narrativeTable = null;
        } else {
            narrativeTable = narrativeTable.intern();
        }

        inputFile.assertChar(':');
    }

    /**
     * Reads a string until the field separator is detected, the
     * column record separator is detected, or and end-of-file is hit.
     *
     * @return the string read from the file
     * @param inputFile the file to read the field from
     * @param toLower convert the string to lower-case
     * @exception FormatException ReadChar IOExceptions rethrown as
     *            FormatExceptions
     */
    private String readColumnText(BinaryFile inputFile) throws FormatException {
        StringBuffer buildretval = new StringBuffer();
        boolean skipnext = false;
        char tmp;
        try {
            while ((tmp = inputFile.readChar()) != ',') {
                if ((tmp == ':') && !skipnext) {
                    return null;
                }
                if (tmp == '\\') {
                    skipnext = true;
                } else {
                    skipnext = false;
                    buildretval.append(tmp);
                }
            }
        } catch (EOFException e) {
            //allowable
        }
        return buildretval.toString();
    }

    /**
     * Reads a string until the field separator is detected, the
     * column record separator is detected, or and end-of-file is hit,
     * and converts in to lowercase.
     *
     * @return the string read from the file, all in lowercase
     * @param inputFile the file to read the field from
     * @param toLower convert the string to lower-case
     * @exception FormatException ReadChar IOExceptions rethrown as
     *            FormatExceptions
     */
    private String readColumnTextLowerCase(BinaryFile inputFile)
            throws FormatException {
        StringBuffer buildretval = new StringBuffer();
        boolean skipnext = false;
        char tmp;
        try {
            while ((tmp = inputFile.readChar()) != ',') {
                if ((tmp == ':') && !skipnext) {
                    return null;
                }
                if (tmp == '\\') {
                    skipnext = true;
                } else {
                    skipnext = false;
                    buildretval.append(Character.toLowerCase(tmp));
                }
            }
        } catch (EOFException e) {
            //allowable
        }
        return buildretval.toString();
    }

    /**
     * Claim that the column has a particular schema
     *
     * @param type the FieldType (datatype) this column is expected to
     *        contain legal values are specified by the VPF standard.
     *        the non-standard value 'i' is also accepted (equivalent
     *        to 'I' or 'S'), indicating an integral type.
     * @param length the number of elements in this column
     * @param strictlength false means that variable length columns
     *        can be fixed length instead
     * @exception FormatException the column is not of the particular
     *            type/length
     */
    public void assertSchema(char type, int length, boolean strictlength)
            throws FormatException {
        if ((type != fieldType)
                && !((type == 'i') && ((fieldType == VPF_COLUMN_INT) || (fieldType == VPF_COLUMN_SHORT)))) {
            throw new FormatException("AssertSchema failed on fieldType!");
        }
        if ((strictlength && (length != numberOfElements))
                || (!strictlength && (length != -1) && (length != numberOfElements))) {
            throw new FormatException("AssertSchema failed on length!");
        }
    }

    /**
     * the number of bytes a field of this type takes in the input
     * file
     *
     * @return the number of bytes (-1 for a variable-length field)
     * @exception FormatException the FieldType of this Column is not
     *            a valid VPF fieldtype
     */
    public int fieldLength() throws FormatException {
        if (numberOfElements == -1) {
            return -1;
        }

        switch (fieldType) {
        case VPF_COLUMN_TEXT:
        case VPF_COLUMN_TEXTL1:
        case VPF_COLUMN_TEXTL3:
        case VPF_COLUMN_TEXTL2: //various text string types
            return numberOfElements;
        case VPF_COLUMN_FLOAT: //floats
            return 4;
        case VPF_COLUMN_DOUBLE: //doubles
            return 8;
        case VPF_COLUMN_SHORT: //shorts
            return 2;
        case VPF_COLUMN_INT: //ints
            return 4;
        case VPF_COLUMN_FLOAT_2COORD: //2-coord floats
            return numberOfElements * 8;
        case VPF_COLUMN_DOUBLE_2COORD: //2-coord doubles
            return numberOfElements * 16;
        case VPF_COLUMN_FLOAT_3COORD: //3-coord floats
            return numberOfElements * 12;
        case VPF_COLUMN_DOUBLE_3COORD: //3-coord doubles
            return numberOfElements * 24;
        case VPF_COLUMN_DATE: //dates
            return 20;
        case VPF_COLUMN_NULL: //nulls
            return 0;
        case VPF_COLUMN_TRIPLET: //cross-tile identifiers
            return -1; //variable length
        default: {
            throw new FormatException("Unknown field type: " + fieldType);
        }
        }
        //unreached
    }

    /**
     * get the name of the column
     *
     * @return the name of the column
     */
    public String getColumnName() {
        return columnName;
    }

    /**
     * get the VPF datatype of the column
     *
     * @return the VPF datatype
     */
    public char getFieldType() {
        return fieldType;
    }

    /**
     * get the number of elements
     *
     * @return the number of elements
     */
    public int getNumberOfElements() {
        return numberOfElements;
    }

    /**
     * get the VPF key type (one of VPF_COLUMN_PRIMARY_KEY,
     * VPF_COLUMN_FOREIGN_KEY, or VPF_COLUMN_NON_KEY)
     *
     * @return the vpf key type
     */
    public char getKeyType() {
        return keyType;
    }

    /**
     * Return <code>true</code> if this column is a primary key. For
     * any valid column, exactly one of isPrimaryKey, isForeignKey and
     * isNonKey will be <code>true</code>.
     *
     * @return true for a primary key, false otherwise.
     * @see #isForeignKey()
     * @see #isNonKey()
     */
    public boolean isPrimaryKey() {
        return (keyType == VPF_COLUMN_PRIMARY_KEY);
    }

    /**
     * Return <code>true</code> if this column is a foreign key. For
     * any valid column, exactly one of isPrimaryKey, isForeignKey and
     * isNonKey will be <code>true</code>.
     *
     * @return true for a foreign key, false otherwise.
     * @see #isPrimaryKey()
     * @see #isNonKey()
     */
    public boolean isForeignKey() {
        return (keyType == VPF_COLUMN_FOREIGN_KEY);
    }

    /**
     * Return <code>true</code> if this column is not a key column.
     * For any valid column, exactly one of isPrimaryKey, isForeignKey
     * and isNonKey will be <code>true</code>.
     *
     * @return false for a primary or foreign key, true otherwise.
     * @see #isForeignKey()
     * @see #isPrimaryKey()
     */
    public boolean isNonKey() {
        return (keyType == VPF_COLUMN_NON_KEY);
    }

    /**
     * Get the column description
     *
     * @return the column description (possibly <code>null</code>)
     */
    public String getColumnDescription() {
        return columnDescription;
    }

    /**
     * Get the name of the value description table
     *
     * @return the name of the value description table (possibly
     *         <code>null</code>). The same as getVDT()
     * @see #getVDT()
     */
    public String getValueDescriptionTable() {
        return valueDescriptionTable;
    }

    /**
     * Get the name of the value description table
     *
     * @return the name of the value description table (possibly
     *         <code>null</code>). The same as
     *         getValueDescriptionTable
     * @see #getValueDescriptionTable()
     */
    public String getVDT() {
        return valueDescriptionTable;
    }

    /**
     * get the name of the thematic index
     *
     * @return the thematic index name (possibly <code>null</code>)
     */
    public String getThematicIndexName() {
        return thematicIndexName;
    }

    /**
     * get the name of the narrative table
     *
     * @return the name of the narrative table (possibly
     *         <code>null</code>)
     */
    public String getNarrativeTable() {
        return narrativeTable;
    }

    /**
     * Read an element of the type specified by the column
     *
     * @return the value read from the input file
     * @exception EOFException an end-of-file was encountered before
     *            reading any of the field
     * @exception FormatException some data-consistency check failed
     *            while reading the data, or an end-of-file condition
     *            popped up in the middle of reading a field (partial
     *            read)
     */
    public Object parseField(BinaryFile inputFile) throws EOFException,
            FormatException {
        // See table 56, p 79 of MIL-STD-600006 (1992 VPF Standard)
        // See table 10, p 51 of MIL-STD-2407 (1996 VPF Standard
        // supercedes 600006)
        boolean haveElements = (numberOfElements != -1);
        int numels = numberOfElements;

        switch (fieldType) {
        case VPF_COLUMN_TEXT: {
            if (!haveElements) {//Variable length string
                numels = inputFile.readInteger();
            }
            if (numels == 0) {
                return "";
            }
            String s = inputFile.readFixedLengthString(numels);
            if (haveElements) {//Fixed Length Strings loose trailing
                               // whitespace
                s = s.trim();
            }
            return s;
        }
        case VPF_COLUMN_TEXTL1: {
            if (!haveElements) {//Variable length string
                numels = inputFile.readInteger();
            }
            if (numels == 0) {
                return "";
            }
            byte[] str = inputFile.readBytes(numels, false);
            try {
                String s = new String(str, "ISO8859_1");
                if (haveElements) {//Fixed Length Strings loose
                                   // trailing whitespace
                    s = s.trim();
                }
                return s;
            } catch (java.io.UnsupportedEncodingException uee) {
                return str;
            }
        }
        case VPF_COLUMN_TEXTL2:
        case VPF_COLUMN_TEXTL3: {
            if (!haveElements) {//Variable length string
                numels = inputFile.readInteger();
            }
            if (numels == 0) {
                return new byte[0];
            }
            return inputFile.readBytes(numels, false);
        }
        case VPF_COLUMN_FLOAT: {
            return new Float(inputFile.readFloat());
        }
        case VPF_COLUMN_DOUBLE: {
            return new Double(inputFile.readDouble());
        }
        case VPF_COLUMN_SHORT: {
            return new Short(inputFile.readShort());
        }
        case VPF_COLUMN_INT: {
            return new Integer(inputFile.readInteger());
        }
        case VPF_COLUMN_FLOAT_2COORD: { //2-coord floats
            if (!haveElements) {
                numels = inputFile.readInteger();
            }
            return new CoordFloatString(numels, 2, inputFile);
        }
        case VPF_COLUMN_DOUBLE_2COORD: { //2-coord doubles
            if (!haveElements) {
                numels = inputFile.readInteger();
            }
            return new CoordDoubleString(numels, 2, inputFile);
        }
        case VPF_COLUMN_FLOAT_3COORD: { //3-coord floats
            if (!haveElements) {
                numels = inputFile.readInteger();
            }
            return new CoordFloatString(numels, 3, inputFile);
        }
        case VPF_COLUMN_DOUBLE_3COORD: { //3-coord doubles
            if (!haveElements) {
                numels = inputFile.readInteger();
            }
            return new CoordDoubleString(numels, 3, inputFile);
        }
        case VPF_COLUMN_DATE: {
            inputFile.readBytes(20, false);
            return "[skipped date]";
        }
        case VPF_COLUMN_NULL: {
            return "[Null Field Type]";
        }
        case VPF_COLUMN_TRIPLET: {
            return new DcwCrossTileID(inputFile);
        }
        default: {
            throw new FormatException("Unknown field type: " + fieldType);
        }
        }
        //unreached
    }

    /**
     * produce a nice printed version of all our contained information
     *
     * @return a nice little string
     */
    public String toString() {
        StringBuffer output = new StringBuffer();
        output.append(columnName + " " + fieldType + " ");
        output.append(numberOfElements).append(" ");
        output.append(keyType).append(" ");
        output.append(columnDescription + " " + valueDescriptionTable + " ");
        output.append(thematicIndexName + " " + narrativeTable);
        return output.toString();
    }
}
TOP

Related Classes of com.bbn.openmap.layer.vpf.DcwColumnInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.