Example usage for org.apache.commons.collections4.bidimap TreeBidiMap entrySet

List of usage examples for org.apache.commons.collections4.bidimap TreeBidiMap entrySet

Introduction

In this page you can find the example usage for org.apache.commons.collections4.bidimap TreeBidiMap entrySet.

Prototype

Set entrySet

To view the source code for org.apache.commons.collections4.bidimap TreeBidiMap entrySet.

Click Source Link

Usage

From source file:org.apache.poi.hpsf.Section.java

/**
 * Creates a {@link Section} instance from a byte array.
 *
 * @param src Contains the complete property set stream.
 * @param offset The position in the stream that points to the
 * section's format ID./* w w w.j a v  a 2s.com*/
 *
 * @exception UnsupportedEncodingException if the section's codepage is not
 * supported.
 */
public Section(final byte[] src, final int offset) throws UnsupportedEncodingException {
    /*
     * Read the format ID.
     */
    formatID = new ClassID(src, offset);

    /*
     * Read the offset from the stream's start and positions to
     * the section header.
     */
    int offFix = (int) LittleEndian.getUInt(src, offset + ClassID.LENGTH);

    // some input files have a invalid (padded?) offset, which need to be fixed
    // search for beginning of size field
    if (src[offFix] == 0) {
        for (int i = 0; i < 3 && src[offFix] == 0; i++, offFix++)
            ;
        // cross check with propertyCount field and the property list field
        for (int i = 0; i < 3
                && (src[offFix + 3] != 0 || src[offFix + 7] != 0 || src[offFix + 11] != 0); i++, offFix--)
            ;
    }

    this._offset = offFix;

    LittleEndianByteArrayInputStream leis = new LittleEndianByteArrayInputStream(src, offFix);

    /*
     * Read the section length.
     */
    int size = (int) Math.min(leis.readUInt(), src.length - _offset);

    /*
     * Read the number of properties.
     */
    final int propertyCount = (int) leis.readUInt();

    /*
     * Read the properties. The offset is positioned at the first
     * entry of the property list. There are two problems:
     *
     * 1. For each property we have to find out its length. In the
     *    property list we find each property's ID and its offset relative
     *    to the section's beginning. Unfortunately the properties in the
     *    property list need not to be in ascending order, so it is not
     *    possible to calculate the length as
     *    (offset of property(i+1) - offset of property(i)). Before we can
     *    that we first have to sort the property list by ascending offsets.
     *
     * 2. We have to read the property with ID 1 before we read other
     *    properties, at least before other properties containing strings.
     *    The reason is that property 1 specifies the codepage. If it is
     *    1200, all strings are in Unicode. In other words: Before we can
     *    read any strings we have to know whether they are in Unicode or
     *    not. Unfortunately property 1 is not guaranteed to be the first in
     *    a section.
     *
     *    The algorithm below reads the properties in two passes: The first
     *    one looks for property ID 1 and extracts the codepage number. The
     *    seconds pass reads the other properties.
     */
    /* Pass 1: Read the property list. */
    final TreeBidiMap<Long, Long> offset2Id = new TreeBidiMap<Long, Long>();
    for (int i = 0; i < propertyCount; i++) {
        /* Read the property ID. */
        long id = (int) leis.readUInt();

        /* Offset from the section's start. */
        long off = (int) leis.readUInt();

        offset2Id.put(off, id);
    }

    Long cpOffset = offset2Id.getKey((long) PropertyIDMap.PID_CODEPAGE);

    /* Look for the codepage. */
    int codepage = -1;
    if (cpOffset != null) {
        /* Read the property's value type. It must be VT_I2. */
        leis.setReadIndex((int) (this._offset + cpOffset));
        final long type = leis.readUInt();

        if (type != Variant.VT_I2) {
            throw new HPSFRuntimeException("Value type of property ID 1 is not VT_I2 but " + type + ".");
        }

        /* Read the codepage number. */
        codepage = leis.readUShort();
        setCodepage(codepage);
    }

    /* Pass 2: Read all properties - including the codepage property,
     * if available. */
    for (Map.Entry<Long, Long> me : offset2Id.entrySet()) {
        long off = me.getKey();
        long id = me.getValue();

        if (id == PropertyIDMap.PID_CODEPAGE) {
            continue;
        }

        int pLen = propLen(offset2Id, off, size);
        leis.setReadIndex((int) (this._offset + off));

        if (id == PropertyIDMap.PID_DICTIONARY) {
            leis.mark(100000);
            if (!readDictionary(leis, pLen, codepage)) {
                // there was an error reading the dictionary, maybe because the pid (0) was used wrong
                // try reading a property instead
                leis.reset();
                try {
                    // fix id
                    id = Math.max(PropertyIDMap.PID_MAX, offset2Id.inverseBidiMap().lastKey()) + 1;
                    setProperty(new MutableProperty(id, leis, pLen, codepage));
                } catch (RuntimeException e) {
                    LOG.log(POILogger.INFO, "Dictionary fallback failed - ignoring property");
                }
            }
            ;
        } else {
            setProperty(new MutableProperty(id, leis, pLen, codepage));
        }
    }

    sectionBytes.write(src, (int) _offset, size);
    padSectionBytes();
}