Package com.bbn.openmap.dataAccess.iso8211

Source Code of com.bbn.openmap.dataAccess.iso8211.DDFFieldDefinition$DataTypeCode

/******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************/

package com.bbn.openmap.dataAccess.iso8211;

import com.bbn.openmap.layer.vpf.MutableInt;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;

import java.util.Iterator;
import java.util.Vector;

/**
* Information from the DDR defining one field. Note that just because
* a field is defined for a DDFModule doesn't mean that it actually
* occurs on any records in the module. DDFFieldDefns are normally
* just significant as containers of the DDFSubfieldDefinitions.
*/
public class DDFFieldDefinition implements DDFConstants {

    protected DDFModule poModule;
    protected String pszTag;

    protected String _fieldName;
    protected String _arrayDescr;
    protected String _formatControls;

    protected boolean bRepeatingSubfields;
    protected int nFixedWidth; // zero if variable.

    protected DataStructCode _data_struct_code;
    protected DataTypeCode _data_type_code;

    protected Vector paoSubfieldDefns;

    /**
     * Fetch a pointer to the field name (tag).
     *
     * @return this is an internal copy and shouldn't be freed.
     */
    public String getName() {
        return pszTag;
    }

    /**
     * Fetch a longer descriptio of this field.
     *
     * @return this is an internal copy and shouldn't be freed.
     */
    public String getDescription() {
        return _fieldName;
    }

    /**
     * Get the number of subfields.
     */
    public int getSubfieldCount() {
        if (paoSubfieldDefns != null) {
            return paoSubfieldDefns.size();
        }
        return 0;
    }

    /**
     * Get the width of this field. This function isn't normally used
     * by applications.
     *
     * @return The width of the field in bytes, or zero if the field
     *         is not apparently of a fixed width.
     */
    public int getFixedWidth() {
        return nFixedWidth;
    }

    /**
     * Fetch repeating flag.
     *
     * @return true if the field is marked as repeating.
     */
    public boolean isRepeating() {
        return bRepeatingSubfields;
    }

    /** this is just for an S-57 hack for swedish data */
    public void setRepeating(boolean val) {
        bRepeatingSubfields = val;
    }

    /** ********************************************************************* */
    /* DDFFieldDefn() */
    /** ********************************************************************* */

    public DDFFieldDefinition() {
        poModule = null;
        pszTag = null;
        _fieldName = null;
        _arrayDescr = null;
        _formatControls = null;
        paoSubfieldDefns = null;
        bRepeatingSubfields = false;
    }

    public DDFFieldDefinition(DDFModule poModuleIn, String pszTagIn,
            byte[] pachFieldArea) {

        initialize(poModuleIn, pszTagIn, pachFieldArea);
    }

    /**
     * Initialize the field definition from the information in the DDR
     * record. This is called by DDFModule.open().
     *
     * @param poModuleIn DDFModule reprsenting file being read.
     * @param pszTagIn the name of this field.
     * @param pachFieldArea the data bytes in the file representing
     *        the field from the header.
     */
    public boolean initialize(DDFModule poModuleIn, String pszTagIn,
                              byte[] pachFieldArea) {

        /// pachFieldArea needs to be specified better. It's an
        /// offset into a character array, and we need to know what
        // it
        /// is to scope it better in Java.

        int iFDOffset = poModuleIn._fieldControlLength;

        poModule = poModuleIn;
        pszTag = pszTagIn;

        /* -------------------------------------------------------------------- */
        /* Set the data struct and type codes. */
        /* -------------------------------------------------------------------- */
        _data_struct_code = DataStructCode.get((char) pachFieldArea[0]);
        _data_type_code = DataTypeCode.get((char) pachFieldArea[1]);

        if (Debug.debugging("iso8211")) {
            Debug.output("DDFFieldDefinition.initialize(" + pszTagIn
                    + "):\n\t\t data_struct_code = " + _data_struct_code
                    + "\n\t\t data_type_code = " + _data_type_code
                    + "\n\t\t iFDOffset = " + iFDOffset);
        }

        /* -------------------------------------------------------------------- */
        /* Capture the field name, description (sub field names), and */
        /* format statements. */
        /* -------------------------------------------------------------------- */

        byte[] tempData = new byte[pachFieldArea.length - iFDOffset];
        System.arraycopy(pachFieldArea,
                iFDOffset,
                tempData,
                0,
                pachFieldArea.length - iFDOffset);

        MutableInt nCharsConsumed = new MutableInt();

        _fieldName = DDFUtils.fetchVariable(tempData,
                tempData.length,
                DDF_UNIT_TERMINATOR,
                DDF_FIELD_TERMINATOR,
                nCharsConsumed);
        if (Debug.debugging("iso8211")) {
            Debug.output("DDFFieldDefinition.initialize(" + pszTagIn
                    + "): created field name " + _fieldName);
        }

        iFDOffset += nCharsConsumed.value;

        tempData = new byte[pachFieldArea.length - iFDOffset];
        System.arraycopy(pachFieldArea,
                iFDOffset,
                tempData,
                0,
                pachFieldArea.length - iFDOffset);
        _arrayDescr = DDFUtils.fetchVariable(tempData,
                tempData.length,
                DDF_UNIT_TERMINATOR,
                DDF_FIELD_TERMINATOR,
                nCharsConsumed);
        iFDOffset += nCharsConsumed.value;

        tempData = new byte[pachFieldArea.length - iFDOffset];
        System.arraycopy(pachFieldArea,
                iFDOffset,
                tempData,
                0,
                pachFieldArea.length - iFDOffset);

        _formatControls = DDFUtils.fetchVariable(tempData,
                tempData.length,
                DDF_UNIT_TERMINATOR,
                DDF_FIELD_TERMINATOR,
                nCharsConsumed);

        /* -------------------------------------------------------------------- */
        /* Parse the subfield info. */
        /* -------------------------------------------------------------------- */
        if (_data_struct_code != DataStructCode.ELEMENTARY) {
            if (!buildSubfieldDefns(_arrayDescr)) {
                return false;
            }

            if (!applyFormats(_formatControls)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Write out field definition info.
     *
     * A variety of information about this field definition, and all
     * its subfields are written out too.
     */
    public String toString() {
        StringBuffer buf = new StringBuffer("  DDFFieldDefn:\n");
        buf.append("      Tag = " + pszTag + "\n");
        buf.append("      _fieldName = " + _fieldName + "\n");
        buf.append("      _arrayDescr = " + _arrayDescr + "\n");
        buf.append("      _formatControls = " + _formatControls + "\n");
        buf.append("      _data_struct_code = " + _data_struct_code + "\n");
        buf.append("      _data_type_code = " + _data_type_code + "\n");

        if (paoSubfieldDefns != null) {
            for (Iterator it = paoSubfieldDefns.iterator(); it.hasNext();) {
                buf.append((DDFSubfieldDefinition) it.next());
            }
        }

        return buf.toString();
    }

    /**
     * Based on the list contained in the string, build a set of
     * subfield definitions.
     */
    protected boolean buildSubfieldDefns(String pszSublist) {

        if (pszSublist.charAt(0) == '*') {
            bRepeatingSubfields = true;
            pszSublist = pszSublist.substring(1);
        }

        Vector papszSubfieldNames = PropUtils.parseMarkers(pszSublist, "!");

        paoSubfieldDefns = new Vector();

        for (Iterator it = papszSubfieldNames.iterator(); it.hasNext();) {
            DDFSubfieldDefinition ddfsd = new DDFSubfieldDefinition();
            ddfsd.setName((String) it.next());
            paoSubfieldDefns.add(ddfsd);
        }

        return true;
    }

    /**
     * Extract a substring terminated by a comma (or end of string).
     * Commas in brackets are ignored as terminated with bracket
     * nesting understood gracefully. If the returned string would
     * being and end with a bracket then strip off the brackets.
     * <P>
     * Given a string like "(A,3(B,C),D),X,Y)" return "A,3(B,C),D".
     * Give a string like "3A,2C" return "3A".
     */
    protected String extractSubstring(String pszSrc) {
        int nBracket = 0;
        int i;
        String pszReturn;

        for (i = 0; i < pszSrc.length()
                && (nBracket > 0 || pszSrc.charAt(i) != ','); i++) {
            if (pszSrc.charAt(i) == '(') {
                nBracket++;
            } else if (pszSrc.charAt(i) == ')') {
                nBracket--;
            }
        }

        if (pszSrc.charAt(0) == '(') {
            pszReturn = pszSrc.substring(1, i - 2);
        } else {
            pszReturn = pszSrc.substring(0, i);
        }

        return pszReturn;
    }

    /**
     * Given a string that contains a coded size symbol, expand it
     * out.
     */
    protected String expandFormat(String pszSrc) {
        StringBuffer szDest = new StringBuffer();
        int iSrc = 0;
        int nRepeat = 0;

        while (iSrc < pszSrc.length()) {
            /*
             * This is presumably an extra level of brackets around
             * some binary stuff related to rescaning which we don't
             * care to do (see 6.4.3.3 of the standard. We just strip
             * off the extra layer of brackets
             */
            if ((iSrc == 0 || pszSrc.charAt(iSrc - 1) == ',')
                    && pszSrc.charAt(iSrc) == '(') {
                String pszContents = extractSubstring(pszSrc + iSrc);
                String pszExpandedContents = expandFormat(pszContents);

                szDest.append(pszExpandedContents);
                iSrc = iSrc + pszContents.length() + 2;

            } else if ((iSrc == 0 || pszSrc.charAt(iSrc - 1) == ',') /*
                                                                      * this
                                                                      * is a
                                                                      * repeated
                                                                      * subclause
                                                                      */
                    && Character.isDigit(pszSrc.charAt(iSrc))) {

                int orig_iSrc = iSrc;

                // skip over repeat count.
                for (; Character.isDigit(pszSrc.charAt(iSrc)); iSrc++) {
                }
                String nRepeatString = pszSrc.substring(orig_iSrc, iSrc);
                nRepeat = Integer.parseInt(nRepeatString);

                String pszContents = extractSubstring(pszSrc.substring(iSrc));
                String pszExpandedContents = expandFormat(pszContents);

                for (int i = 0; i < nRepeat; i++) {
                    szDest.append(pszExpandedContents);
                    if (i < nRepeat - 1) {
                        szDest.append(",");
                    }
                }

                if (iSrc == '(') {
                    iSrc += pszContents.length() + 2;
                } else {
                    iSrc += pszContents.length();
                }

            } else {
                szDest.append(pszSrc.charAt(iSrc++));
            }
        }

        return szDest.toString();
    }

    /**
     * This method parses the format string partially, and then
     * applies a subfield format string to each subfield object. It in
     * turn does final parsing of the subfield formats.
     */
    protected boolean applyFormats(String _formatControls) {
        String pszFormatList;
        Vector papszFormatItems;

        /* -------------------------------------------------------------------- */
        /* Verify that the format string is contained within brackets. */
        /* -------------------------------------------------------------------- */
        if (_formatControls.length() < 2 || !_formatControls.startsWith("(")
                || !_formatControls.endsWith(")")) {

            Debug.error("DDFFieldDefinition: Format controls for " + pszTag
                    + " field missing brackets {" + _formatControls
                    + "} : length = " + _formatControls.length()
                    + ", starts with {" + _formatControls.charAt(0)
                    + "}, ends with {"
                    + _formatControls.charAt(_formatControls.length() - 1)
                    + "}");

            return false;
        }

        /* -------------------------------------------------------------------- */
        /* Duplicate the string, and strip off the brackets. */
        /* -------------------------------------------------------------------- */

        pszFormatList = expandFormat(_formatControls);

        if (Debug.debugging("iso8211")) {
            Debug.output("DDFFieldDefinition.applyFormats{" + _formatControls
                    + "} expanded to {" + pszFormatList + "} ");
        }

        /* -------------------------------------------------------------------- */
        /* Tokenize based on commas. */
        /* -------------------------------------------------------------------- */
        papszFormatItems = PropUtils.parseMarkers(pszFormatList, ",");

        /* -------------------------------------------------------------------- */
        /* Apply the format items to subfields. */
        /* -------------------------------------------------------------------- */

        int iFormatItem = 0;
        for (Iterator it = papszFormatItems.iterator(); it.hasNext(); iFormatItem++) {

            String pszPastPrefix = (String) it.next();

            int pppIndex = 0;
            // Skip over digits...
            for (; Character.isDigit(pszPastPrefix.charAt(pppIndex)); pppIndex++) {
            }
            pszPastPrefix = pszPastPrefix.substring(pppIndex);

            ///////////////////////////////////////////////////////////////
            // Did we get too many formats for the subfields created
            // by names? This may be legal by the 8211 specification,
            // but
            // isn't encountered in any formats we care about so we
            // just
            // blow.

            if (iFormatItem > paoSubfieldDefns.size()) {
                Debug.error("DDFFieldDefinition: Got more formats than subfields for field "
                        + pszTag);
                break;
            }

            if (!((DDFSubfieldDefinition) paoSubfieldDefns.elementAt(iFormatItem)).setFormat(pszPastPrefix)) {
                Debug.output("DDFFieldDefinition had problem setting format for "
                        + pszPastPrefix);
                return false;
            }
        }

        /* -------------------------------------------------------------------- */
        /* Verify that we got enough formats, cleanup and return. */
        /* -------------------------------------------------------------------- */
        if (iFormatItem < paoSubfieldDefns.size()) {
            Debug.error("DDFFieldDefinition: Got fewer formats than subfields for field "
                    + pszTag
                    + " got ("
                    + iFormatItem
                    + ", should have "
                    + paoSubfieldDefns.size() + ")");
            return false;
        }

        /* -------------------------------------------------------------------- */
        /* If all the fields are fixed width, then we are fixed width */
        /* too. This is important for repeating fields. */
        /* -------------------------------------------------------------------- */
        nFixedWidth = 0;
        for (int i = 0; i < paoSubfieldDefns.size(); i++) {
            DDFSubfieldDefinition ddfsd = (DDFSubfieldDefinition) paoSubfieldDefns.elementAt(i);
            if (ddfsd.getWidth() == 0) {
                nFixedWidth = 0;
                break;
            } else {
                nFixedWidth += ddfsd.getWidth();
            }
        }

        return true;
    }

    /**
     * Find a subfield definition by it's mnemonic tag.
     *
     * @param pszMnemonic The name of the field.
     *
     * @return The subfield pointer, or null if there isn't any such
     *         subfield.
     */
    public DDFSubfieldDefinition findSubfieldDefn(String pszMnemonic) {
        if (paoSubfieldDefns != null) {
            for (Iterator it = paoSubfieldDefns.iterator(); pszMnemonic != null
                    && it.hasNext();) {
                DDFSubfieldDefinition ddfsd = (DDFSubfieldDefinition) it.next();
                if (pszMnemonic.equalsIgnoreCase(ddfsd.getName())) {
                    return ddfsd;
                }
            }
        }

        return null;
    }

    /**
     * Fetch a subfield by index.
     *
     * @param i The index subfield index. (Between 0 and
     *        GetSubfieldCount()-1)
     * @return The subfield pointer, or null if the index is out of
     *         range.
     */
    public DDFSubfieldDefinition getSubfieldDefn(int i) {
        if (paoSubfieldDefns == null || i < 0 || i >= paoSubfieldDefns.size()) {
            return null;
        }

        return (DDFSubfieldDefinition) paoSubfieldDefns.elementAt(i);
    }

    public static class DataStructCode {
        public final static DataStructCode ELEMENTARY = new DataStructCode('0', "elementary");
        public final static DataStructCode VECTOR = new DataStructCode('1', "vector");
        public final static DataStructCode ARRAY = new DataStructCode('2', "array");
        public final static DataStructCode CONCATENATED = new DataStructCode('3', "concatenated");

        char code = '0';
        String prettyName;

        public DataStructCode(char structCode, String name) {
            code = structCode;
            prettyName = name;
        }

        public char getCode() {
            return code;
        }

        public String toString() {
            return prettyName;
        }

        public static DataStructCode get(char c) {
            if (c == CONCATENATED.getCode())
                return CONCATENATED;
            if (c == VECTOR.getCode())
                return VECTOR;
            if (c == ARRAY.getCode())
                return ARRAY;
            if (c == ELEMENTARY.getCode())
                return ELEMENTARY;

            if (Debug.debugging("iso8211")) {
                Debug.output("DDFFieldDefinition tested for unknown code: " + c);
            }
            return ELEMENTARY;
        }
    }

    public static class DataTypeCode {
        public final static DataTypeCode CHAR_STRING = new DataTypeCode('0', "character string");
        public final static DataTypeCode IMPLICIT_POINT = new DataTypeCode('1', "implicit point");
        public final static DataTypeCode EXPLICIT_POINT = new DataTypeCode('2', "explicit point");
        public final static DataTypeCode EXPLICIT_POINT_SCALED = new DataTypeCode('3', "explicit point scaled");
        public final static DataTypeCode CHAR_BIT_STRING = new DataTypeCode('4', "character bit string");
        public final static DataTypeCode BIT_STRING = new DataTypeCode('5', "bit string");
        public final static DataTypeCode MIXED_DATA_TYPE = new DataTypeCode('6', "mixed data type");

        char code = '0';
        String prettyName;

        public DataTypeCode(char structCode, String desc) {
            code = structCode;
            prettyName = desc;
        }

        public char getCode() {
            return code;
        }

        public String toString() {
            return prettyName;
        }

        public static DataTypeCode get(char c) {
            if (c == IMPLICIT_POINT.getCode())
                return IMPLICIT_POINT;
            if (c == EXPLICIT_POINT.getCode())
                return EXPLICIT_POINT;
            if (c == EXPLICIT_POINT_SCALED.getCode())
                return EXPLICIT_POINT_SCALED;
            if (c == CHAR_BIT_STRING.getCode())
                return CHAR_BIT_STRING;
            if (c == BIT_STRING.getCode())
                return BIT_STRING;
            if (c == MIXED_DATA_TYPE.getCode())
                return MIXED_DATA_TYPE;
            if (c == CHAR_STRING.getCode())
                return CHAR_STRING;

            if (Debug.debugging("iso8211")) {
                Debug.output("DDFFieldDefinition tested for unknown data type code: "
                        + c);
            }
            return CHAR_STRING;
        }
    }
}
TOP

Related Classes of com.bbn.openmap.dataAccess.iso8211.DDFFieldDefinition$DataTypeCode

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.