1 /* ==================================================================== 2 * The Apache Software License, Version 1.1 3 * 4 * Copyright (c) 2000 The Apache Software Foundation. All rights 5 * reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. The end-user documentation included with the redistribution, 20 * if any, must include the following acknowledgment: 21 * "This product includes software developed by the 22 * Apache Software Foundation (http://www.apache.org/)." 23 * Alternately, this acknowledgment may appear in the software itself, 24 * if and wherever such third-party acknowledgments normally appear. 25 * 26 * 4. The names "Apache" and "Apache Software Foundation" must 27 * not be used to endorse or promote products derived from this 28 * software without prior written permission. For written 29 * permission, please contact apache@apache.org. 30 * 31 * 5. Products derived from this software may not be called "Apache", 32 * nor may "Apache" appear in their name, without prior written 33 * permission of the Apache Software Foundation. 34 * 35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This software consists of voluntary contributions made by many 50 * individuals on behalf of the Apache Software Foundation. For more 51 * information on the Apache Software Foundation, please see 52 * <http://www.apache.org/>. 53 */ 54 55 package org.apache.poi.hpsf; 56 57 import java.util.*; 58 import org.apache.poi.hpsf.littleendian.*; 59 import org.apache.poi.hpsf.wellknown.*; 60 61 /** 62 * <p>Represents a section in a {@link PropertySet}.</p> 63 * 64 * @author Rainer Klute (klute@rainer-klute.de) 65 * @author Drew Varner (Drew.Varner allUpIn sc.edu) 66 * 67 * @version $Id: Section.java,v 1.4 2002/05/03 07:29:09 klute Exp $ 68 * @since 2002-02-09 69 */ 70 public class Section 71 { 72 73 /** 74 * <p>Maps property IDs to section-private PID strings. These 75 * strings can be found in the property with ID 0.</p> 76 */ 77 protected Map dictionary; 78 79 80 81 private ClassID formatID; 82 83 /** 84 * <p>Returns the format ID. The format ID is the "type" of the 85 * section.</p> 86 */ 87 public ClassID getFormatID() 88 { 89 return formatID; 90 } 91 92 93 94 private int offset; 95 96 /** 97 * <p>Returns the offset of the section in the stream.</p> 98 */ 99 public int getOffset() 100 { 101 return offset; 102 } 103 104 105 106 private int size; 107 108 /** 109 * <p>Returns the section's size in bytes.</p> 110 */ 111 public int getSize() 112 { 113 return size; 114 } 115 116 117 118 private int propertyCount; 119 120 /** 121 * <p>Returns the number of properties in this section.</p> 122 */ 123 public int getPropertyCount() 124 { 125 return propertyCount; 126 } 127 128 129 130 private Property[] properties; 131 132 /** 133 * <p>Returns this section's properties.</p> 134 */ 135 public Property[] getProperties() 136 { 137 return properties; 138 } 139 140 141 142 /** 143 * <p>Creates a {@link Section} instance from a byte array.</p> 144 * 145 * @param src Contains the complete property set stream. 146 * 147 * @param offset The position in the stream that points to the 148 * section's format ID. 149 */ 150 public Section(final byte[] src, int offset) 151 { 152 /* Read the format ID. */ 153 formatID = new ClassID(src, offset); 154 offset += ClassID.LENGTH; 155 156 /* Read the offset from the stream's start and positions to 157 * the section header. */ 158 this.offset = new DWord(src, offset).intValue(); 159 offset = this.offset; 160 161 /* Read the section length. */ 162 size = new DWord(src, offset).intValue(); 163 offset += DWord.LENGTH; 164 165 /* Read the number of properties. */ 166 propertyCount = new DWord(src, offset).intValue(); 167 offset += DWord.LENGTH; 168 169 /* Read the properties. The offset is positioned at the first 170 * entry of the property list. */ 171 properties = new Property[propertyCount]; 172 for (int i = 0; i < properties.length; i++) 173 { 174 final int id = new DWord(src, offset).intValue(); 175 offset += DWord.LENGTH; 176 177 /* Offset from the section. */ 178 final int sOffset = new DWord(src, offset).intValue(); 179 offset += DWord.LENGTH; 180 181 /* Calculate the length of the property. */ 182 int length; 183 if (i == properties.length - 1) 184 length = src.length - this.offset - sOffset; 185 else 186 length = 187 new DWord(src, offset + DWord.LENGTH).intValue() - sOffset; 188 189 /* Create it. */ 190 properties[i] = 191 new Property(id, src, this.offset + sOffset, length); 192 } 193 194 /* Extract the dictionary (if available). */ 195 dictionary = (Map) getProperty(0); 196 } 197 198 199 200 /** 201 * <p>Returns the value of the property with the specified ID. If 202 * the property is not available, <code>null</code> is returned 203 * and a subsequent call to {@link #wasNull} will return 204 * <code>true</code>.</p> 205 */ 206 protected Object getProperty(final int id) 207 { 208 wasNull = false; 209 for (int i = 0; i < properties.length; i++) 210 if (id == properties[i].getID()) 211 return properties[i].getValue(); 212 wasNull = true; 213 return null; 214 } 215 216 217 218 /** 219 * <p>Returns the value of the numeric property with the specified 220 * ID. If the property is not available, 0 is returned. A 221 * subsequent call to {@link #wasNull} will return 222 * <code>true</code> to let the caller distinguish that case from 223 * a real property value of 0.</p> 224 */ 225 protected int getPropertyIntValue(final int id) 226 { 227 final Integer i = (Integer) getProperty(id); 228 if (i != null) 229 return i.intValue(); 230 else 231 return 0; 232 } 233 234 235 236 /** 237 * <p>Returns the value of the boolean property with the specified 238 * ID. If the property is not available, <code>false</code> is 239 * returned. A subsequent call to {@link #wasNull} will return 240 * <code>true</code> to let the caller distinguish that case from 241 * a real property value of <code>false</code>.</p> 242 */ 243 protected boolean getPropertyBooleanValue(final int id) 244 { 245 final Boolean b = (Boolean) getProperty(id); 246 if (b != null) 247 return b.booleanValue(); 248 else 249 return false; 250 } 251 252 253 254 private boolean wasNull; 255 256 /** 257 * <p>Checks whether the property which the last call to {@link 258 * #getPropertyIntValue} or {@link #getProperty} tried to access 259 * was available or not. This information might be important for 260 * callers of {@link #getPropertyIntValue} since the latter 261 * returns 0 if the property does not exist. Using {@link 262 * #wasNull} the caller can distiguish this case from a property's 263 * real value of 0.</p> 264 * 265 * @return <code>true</code> if the last call to {@link 266 * #getPropertyIntValue} or {@link #getProperty} tried to access a 267 * property that was not available, else <code>false</code>. 268 */ 269 public boolean wasNull() 270 { 271 return wasNull; 272 } 273 274 275 276 /** 277 * <p>Returns the PID string associated with a property ID. The ID 278 * is first looked up in the {@link Section}'s private 279 * dictionary. If it is not found there, the method calls {@link 280 * SectionIDMap#getPIDString}.</p> 281 */ 282 public String getPIDString(final int pid) 283 { 284 String s = null; 285 if (dictionary != null) 286 s = (String) dictionary.get(new Integer(pid)); 287 if (s == null) 288 s = SectionIDMap.getPIDString(getFormatID().getBytes(), pid); 289 if (s == null) 290 s = SectionIDMap.UNDEFINED; 291 return s; 292 } 293 294 } 295