List of usage examples for org.apache.commons.collections4.bidimap TreeBidiMap inverseBidiMap
public OrderedBidiMap<V, K> inverseBidiMap()
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./*from ww w . java 2s.co m*/ * * @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(); }