All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.io.pof.reflect.ComplexPofValue Maven / Gradle / Ivy

There is a newer version: 24.03
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.io.pof.reflect;


import com.tangosol.io.ReadBuffer;

import com.tangosol.io.pof.PofConstants;
import com.tangosol.io.pof.PofContext;
import com.tangosol.io.pof.PofHelper;

import com.tangosol.util.SparseArray;

import java.util.Iterator;
import java.io.IOException;


/**
* An abstract base class for complex POF types, such as collections, arrays,
* maps, and user types.
*
* @author as 2009.02.12
* @since Coherence 3.5
*/
public abstract class ComplexPofValue
        extends AbstractPofValue
    {
    // ----- constructors ---------------------------------------------------

    /**
    * Construct a PofValue instance wrapping the supplied buffer.
    *
    * @param valueParent parent value within the POF stream
    * @param bufValue    buffer containing POF representation of this value
    * @param ctx         POF context to use when reading or writing properties
    * @param of          offset of this value from the beginning of POF stream
    * @param nType       POF type identifier for this value
    * @param ofChildren  offset of the first child element within this value
    */
    public ComplexPofValue(PofValue valueParent, ReadBuffer bufValue,
                           PofContext ctx, int of, int nType, int ofChildren)
        {
        super(valueParent, bufValue, ctx, of, nType);

        m_aChildren  = new SparseArray();
        m_ofChildren = ofChildren;
        }


    // ----- PofValue interface ---------------------------------------------

    /**
    * {@inheritDoc}
    */
    public PofValue getChild(int nIndex)
        {
        PofValue valueChild = (PofValue) m_aChildren.get(nIndex);
        if (valueChild == null)
            {
            valueChild = findChild(nIndex);
            m_aChildren.set(nIndex, valueChild);
            }
        return valueChild;
        }


    // ----- public members -------------------------------------------------

    /**
    * Return an iterator over all parsed child values.
    *
    * @return a children iterator
    */
    public Iterator getChildrenIterator()
        {
        return m_aChildren.iterator();
        }


    // ----- internal members -----------------------------------------------

    /**
    * Return the uniform element type (if this is a uniform collection).
    *
    * @return uniform element type, or {@link PofConstants#T_UNKNOWN}
    *         if this is not a uniform collection
    */
    protected int getUniformElementType()
        {
        return m_nElementType;
        }

    /**
    * Set the uniform element type for this collection.
    *
    * @param nElementType uniform element type
    */
    protected void setUniformElementType(int nElementType)
        {
        m_nElementType = nElementType;
        }

    /**
    * Find the child value with the specified index.
    *
    * @param nIndex  index of the child value to find
    *
    * @return the child value
    */
    protected PofValue findChild(int nIndex)
        {
        int ofStart = m_ofChildren;
        int iStart  = getLastChildIndex(nIndex);
        if (iStart >= 0)
            {
            AbstractPofValue lastChild = (AbstractPofValue) m_aChildren.get(iStart);
            ofStart = lastChild.getOffset() - getOffset() + lastChild.getSize();
            iStart  = iStart + 1;
            }
        else
            {
            iStart  = 0;
            }

        return findChildInternal(nIndex, ofStart, iStart);
        }

    /**
    * Return index of the last parsed child with an index lower than the
    * specified one.
    *
    * @param nIndex  index to find the preceding child index for
    *
    * @return index of the last parsed child, or -1 if one does not exist
    */
    protected int getLastChildIndex(int nIndex)
        {
        SparseArray aChildren = m_aChildren;
        int         nLast     = (int) aChildren.getLastIndex();

        if (nIndex < nLast)
            {
            nLast = nIndex;
            while (nLast >= 0 && !aChildren.exists(nLast))
                {
                nLast--;
                }
            }
        return nLast;
        }

    /**
    * Return true if this complex value is encoded as one of uniform
    * collection types.
    *
    * @return true if this is a uniform collection
    */
    protected boolean isUniformCollection()
        {
        return m_nElementType != PofConstants.T_UNKNOWN;
        }

    /**
    * Skip a single child value.
    *
    * @param in  buffer input containing child values
    *
    * @throws IOException  if an I/O error occurs
    */
    protected void skipChild(ReadBuffer.BufferInput in)
            throws IOException
        {
        if (isUniformCollection())
            {
            PofHelper.skipUniformValue(in, m_nElementType);
            }
        else
            {
            PofHelper.skipValue(in);
            }
        }

    /**
    * Extract child PofValue from a buffer.
    *
    * @param buf  parent buffer to extract the child from
    * @param of   offset of the child within the parent buffer
    * @param cb   length of the child in bytes
    *
    * @return extracted PofValue
    */
    protected PofValue extractChild(ReadBuffer buf, int of, int cb)
        {
        return isUniformCollection()
               ? PofValueParser.parseUniformValue(this, m_nElementType,
                        buf.getReadBuffer(of, cb), getPofContext(),  getOffset() + of)
               : PofValueParser.parseValue(this, buf.getReadBuffer(of, cb),
                        getPofContext(), getOffset() + of);
        }


    // ----- abstract members -----------------------------------------------

    /**
    * Find the child value with the specified index.
    *
    * @param nIndex   index of the child value to find
    * @param ofStart  offset within the parent buffer to start search from
    * @param iStart   index of the child value to start search from
    *
    * @return the child value
    */
    protected abstract PofValue findChildInternal(int nIndex, int ofStart, int iStart);


    // ----- data members ---------------------------------------------------

    /**
    * Sparse array of child values.
    */
    private SparseArray m_aChildren;

    /**
    * Offset of the first child element within this value.
    */
    private int m_ofChildren;

    /**
    * Type of the child values, if this is a uniform collection.
    */
    private int m_nElementType = PofConstants.T_UNKNOWN;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy