FileDocCategorySizeDatePackage
ComplexArrayDefinition.javaAPI DocExample8034Thu Feb 17 20:00:42 GMT 2000com.togethersoft.modules.genidl

ComplexArrayDefinition.java

/*----------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft LLC. Patents pending. All rights reserved.
----------------------------------------------------------------------------*/

package com.togethersoft.modules.genidl;

import java.util.StringTokenizer;

/** Codec of complex array definition - sequences and arrays. */
class ComplexArrayDefinition {
    public ComplexArrayDefinition(ScopeProcessor scopeProcessor) {
        myScopeProcessor = scopeProcessor;
    }

    public void setTypedefsBuffer(StringBuffer buffer) {
        myTypedefsBuffer = buffer;
    }

    /**
     * Get idl attribute definition, without leading "attribute" and closing ";"
     * Define types as needed. For typedef insertion, ScopeProcessor.addTypedefBeforeMember() is used
     *  @see ScopeProcessor#addTypedefBeforeMember
     */
    public String getIdlDefinitionString(String attrType, String attrName, String sequenceValue, boolean isASequence, String initialValue) {
        boolean isSequence = isASequence;
        myAttrName = attrName;
        String resultingType;
        StringBuffer attrDefinition = new StringBuffer();
        String newType = attrType.trim();
        String allBrackets = "";
        if (newType.endsWith("*")) {
            newType = StringUtility.cutAsterisksAndAmpersands(newType);
            newType = myScopeProcessor.checkTypeAndConvert(false, myScopeProcessor.getCurrentScope(), newType);
            // FIXME: Build typedef here. Its name should be in resultingType
            StringBuffer typedefOperator = new StringBuffer("sequence <");
            typedefOperator.append(newType);
            typedefOperator.append("> ");
            resultingType = buildTypeName();
            typedefOperator.append(resultingType);
            if (myTypedefsBuffer == null) {
                myScopeProcessor.addTypedefBeforeMember(typedefOperator.toString());
            }
            else {
                myScopeProcessor.addTypedefToBuffer(myTypedefsBuffer, typedefOperator.toString(), "");
            }
            // FIXME: (3) make it follow the standard procedure of building attribute declaration
            // WAS HERE: return attrName + "_type";
        }
        allBrackets = StringUtility.extractArrayDimensionFromAllocator(attrType);
        if (initialValue != null && initialValue.length() > 0) {
            allBrackets = StringUtility.extractArrayDimensionFromAllocator(initialValue);
            if (allBrackets.length() == 0) {
                allBrackets = StringUtility.extractArrayDimensionFromInitializer(initialValue);
            }
        }
        dimensions = StringUtility.getArrayDimensionFromBrackets(allBrackets);
        int[] altdimensions = getDimensionsFromTagValue(sequenceValue);
        if (altdimensions.length != 0) {
            dimensions = altdimensions; // FIXME: diagnose if they don't match
        }
        newType = StringUtility.cutBrackets(newType);
        newType = myScopeProcessor.checkTypeAndConvert(false, myScopeProcessor.getCurrentScope(), newType);
        myAttrType = newType;
        // Here: if idlSequence tag is present, we should convert everything to sequences
        //       otherwise, convert to sequences only arrays without specified dimensions
        //      E.g.: if we have int[3][][8] fooattr, the result should look like this:
        //      typedef sequence <int, 8> fooattr_seq1 ;
        //      typedef sequence <fooattr_seq1> fooattr_seq2;
        //      typedef sequence <fooattr_seq2, 3> fooattr_seq3;
        //      attribute fooattr_seq3 fooattr;
        //
        if (!isSequence) {
            for (int i = 0; i < dimensions.length; i++) {
                if (dimensions[i] == -1) {
                    isSequence = true;
                }
            }
        }
        if (isSequence) {
            String[] typedefs = new String[dimensions.length];
            for (int i = dimensions.length - 1; i >= 0; i--) {
                String typeName = buildTypeName(i);
                StringBuffer typedefOperator = new StringBuffer("sequence <");
                typedefOperator.append(i == dimensions.length - 1 ? newType : buildTypeName(i + 1));
                if (dimensions[i] != -1) {

                    /* Insert maximum length here */

                    typedefOperator.append(", ");
                    typedefOperator.append(Integer.toString(dimensions[i]));
                }
                typedefOperator.append("> ");
                typedefOperator.append(typeName);
                if (myTypedefsBuffer == null) {
                    myScopeProcessor.addTypedefBeforeMember(typedefOperator.toString());
                }
                else {
                    myScopeProcessor.addTypedefToBuffer(myTypedefsBuffer, typedefOperator.toString(), "");
                }
            }
            resultingType = buildTypeName(0);
        }
        else {

            /* Not a sequence: no @idlSequence tag present and array size is known.
             * In this case, typedef looks like this:
             *    typedef long foo_type[10][20];
             *    attribute foo_type foo;
             */

            StringBuffer typedefOperator = new StringBuffer(newType);
            typedefOperator.append(" ");
            typedefOperator.append(buildTypeName());
            typedefOperator.append(buildBrackets()); // FIXME
            // FIXME: see (1)
            //addTypedef( attrDefinition, typedefOperator.toString() );
            if (myTypedefsBuffer == null) {
                myScopeProcessor.addTypedefBeforeMember(typedefOperator.toString());
            }
            else {
                myScopeProcessor.addTypedefToBuffer(myTypedefsBuffer, typedefOperator.toString(), "");
            }
            resultingType = buildTypeName();
        }

        /* All types defined, create attribute definition. */

        attrDefinition.append(resultingType);
        attrDefinition.append(" ");
        //attrDefinition.append(attrName);
        return attrDefinition.toString();
    }

    private int[] getDimensionsFromTagValue(String tag) {
        StringTokenizer st = new StringTokenizer(tag, " ,");
        int[] foobaz = new int[st.countTokens()];
        int i = 0;
        while (st.hasMoreTokens()) {
            try {
                foobaz[i] = Integer.parseInt(st.nextToken());
            }
            catch(NumberFormatException nfe) {
                foobaz[i] = -1;
            }
            i++;
        }
        return foobaz;
    }

    private void addTypedef(StringBuffer definition, String typedef) {
        definition.append(typedef);
    }

    protected String buildTypeName(int dimension) {
        StringBuffer typeName = new StringBuffer(myAttrName);
        typeName.append("_seq_");
        typeName.append(Integer.toString(dimension + 1));
        return typeName.toString();
    }

    protected String buildTypeName() {
        StringBuffer typeName = new StringBuffer(myAttrName);
        typeName.append("_type");
        return typeName.toString();
    }

    /**
     * Build bracket part of array definition from <code>dimensions</code>.
     * For example: for <code>dimensions[3]={3, 2, 5}</code> result would be: [3][2][5]
     *  @see #dimensions
     */
    protected String buildBrackets() {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < dimensions.length; i++) {
            result.append("[");
            result.append(dimensions[i] != -1 ? Integer.toString(dimensions[i]) : "");
            result.append("]");
        }
        return result.toString();
    }

    private int[] dimensions;
    private String myAttrName;
    private String myAttrType;
    private ScopeProcessor myScopeProcessor;
    private StringBuffer myTypedefsBuffer = null;
}