1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   package org.apache.poi.poifs.property;
57   
58   import java.io.*;
59   
60   import java.util.*;
61   
62   import org.apache.poi.poifs.common.POIFSConstants;
63   import org.apache.poi.poifs.dev.POIFSViewable;
64   import org.apache.poi.util.ByteField;
65   import org.apache.poi.util.IntegerField;
66   import org.apache.poi.util.LittleEndianConsts;
67   import org.apache.poi.util.ShortField;
68   
69   /**
70    * This abstract base class is the ancestor of all classes
71    * implementing POIFS Property behavior.
72    *
73    * @author Marc Johnson (mjohnson at apache dot org)
74    */
75   
76   public abstract class Property
77       implements Child, POIFSViewable
78   {
79       static final private byte   _default_fill             = ( byte ) 0x00;
80       static final private int    _name_size_offset         = 0x40;
81       static final private int    _max_name_length          =
82           (_name_size_offset / LittleEndianConsts.SHORT_SIZE) - 1;
83       static final protected int  _NO_INDEX                 = -1;
84   
85       // useful offsets
86       static final private int    _node_color_offset        = 0x43;
87       static final private int    _previous_property_offset = 0x44;
88       static final private int    _next_property_offset     = 0x48;
89       static final private int    _child_property_offset    = 0x4C;
90       static final private int    _seconds_1_offset         = 0x64;
91       static final private int    _days_1_offset            = 0x68;
92       static final private int    _seconds_2_offset         = 0x6C;
93       static final private int    _days_2_offset            = 0x70;
94       static final private int    _start_block_offset       = 0x74;
95       static final private int    _size_offset              = 0x78;
96   
97       // node colors
98       static final protected byte _NODE_BLACK               = 1;
99       static final protected byte _NODE_RED                 = 0;
100  
101      // documents must be at least this size to be stored in big blocks
102      static final private int    _big_block_minimum_bytes  = 4096;
103      private String              _name;
104      private ShortField          _name_size;
105      private ByteField           _property_type;
106      private ByteField           _node_color;
107      private IntegerField        _previous_property;
108      private IntegerField        _next_property;
109      private IntegerField        _child_property;
110      private IntegerField        _seconds_1;
111      private IntegerField        _days_1;
112      private IntegerField        _seconds_2;
113      private IntegerField        _days_2;
114      private IntegerField        _start_block;
115      private IntegerField        _size;
116      private byte[]              _raw_data;
117      private int                 _index;
118      private Child               _next_child;
119      private Child               _previous_child;
120  
121      /**
122       * Default constructor
123       */
124  
125      protected Property()
126      {
127          _raw_data = new byte[ POIFSConstants.PROPERTY_SIZE ];
128          Arrays.fill(_raw_data, _default_fill);
129          _name_size         = new ShortField(_name_size_offset);
130          _property_type     =
131              new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET);
132          _node_color        = new ByteField(_node_color_offset);
133          _previous_property = new IntegerField(_previous_property_offset,
134                                                _NO_INDEX, _raw_data);
135          _next_property     = new IntegerField(_next_property_offset,
136                                                _NO_INDEX, _raw_data);
137          _child_property    = new IntegerField(_child_property_offset,
138                                                _NO_INDEX, _raw_data);
139          _seconds_1         = new IntegerField(_seconds_1_offset, 0,
140                                                _raw_data);
141          _days_1            = new IntegerField(_days_1_offset, 0, _raw_data);
142          _seconds_2         = new IntegerField(_seconds_2_offset, 0,
143                                                _raw_data);
144          _days_2            = new IntegerField(_days_2_offset, 0, _raw_data);
145          _start_block       = new IntegerField(_start_block_offset);
146          _size              = new IntegerField(_size_offset, 0, _raw_data);
147          _index             = _NO_INDEX;
148          setName("");
149          setNextChild(null);
150          setPreviousChild(null);
151      }
152  
153      /**
154       * Constructor from byte data
155       *
156       * @param index index number
157       * @param array byte data
158       * @param offset offset into byte data
159       */
160  
161      protected Property(final int index, final byte [] array, final int offset)
162      {
163          _raw_data = new byte[ POIFSConstants.PROPERTY_SIZE ];
164          System.arraycopy(array, offset, _raw_data, 0,
165                           POIFSConstants.PROPERTY_SIZE);
166          _name_size         = new ShortField(_name_size_offset, _raw_data);
167          _property_type     =
168              new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET, _raw_data);
169          _node_color        = new ByteField(_node_color_offset, _raw_data);
170          _previous_property = new IntegerField(_previous_property_offset,
171                                                _raw_data);
172          _next_property     = new IntegerField(_next_property_offset,
173                                                _raw_data);
174          _child_property    = new IntegerField(_child_property_offset,
175                                                _raw_data);
176          _seconds_1         = new IntegerField(_seconds_1_offset, _raw_data);
177          _days_1            = new IntegerField(_days_1_offset, _raw_data);
178          _seconds_2         = new IntegerField(_seconds_2_offset, _raw_data);
179          _days_2            = new IntegerField(_days_2_offset, _raw_data);
180          _start_block       = new IntegerField(_start_block_offset, _raw_data);
181          _size              = new IntegerField(_size_offset, _raw_data);
182          _index             = index;
183          int name_length = (_name_size.get() / LittleEndianConsts.SHORT_SIZE)
184                            - 1;
185  
186          if (name_length < 1)
187          {
188              _name = "";
189          }
190          else
191          {
192              char[] char_array  = new char[ name_length ];
193              int    name_offset = 0;
194  
195              for (int j = 0; j < name_length; j++)
196              {
197                  char_array[ j ] = ( char ) new ShortField(name_offset,
198                                                            _raw_data).get();
199                  name_offset     += LittleEndianConsts.SHORT_SIZE;
200              }
201              _name = new String(char_array, 0, name_length);
202          }
203          _next_child     = null;
204          _previous_child = null;
205      }
206  
207      /**
208       * Write the raw data to an OutputStream.
209       *
210       * @param stream the OutputStream to which the data should be
211       *               written.
212       *
213       * @exception IOException on problems writing to the specified
214       *            stream.
215       */
216  
217      public void writeData(final OutputStream stream)
218          throws IOException
219      {
220          stream.write(_raw_data);
221      }
222  
223      /**
224       * Set the start block for the document referred to by this
225       * Property.
226       *
227       * @param startBlock the start block index
228       */
229  
230      public void setStartBlock(final int startBlock)
231      {
232          _start_block.set(startBlock, _raw_data);
233      }
234  
235      /**
236       * @return the start block
237       */
238  
239      public int getStartBlock()
240      {
241          return _start_block.get();
242      }
243  
244      /**
245       * find out the document size
246       *
247       * @return size in bytes
248       */
249  
250      public int getSize()
251      {
252          return _size.get();
253      }
254  
255      /**
256       * Based on the currently defined size, should this property use
257       * small blocks?
258       *
259       * @return true if the size is less than _big_block_minimum_bytes
260       */
261  
262      public boolean shouldUseSmallBlocks()
263      {
264          return Property.isSmall(_size.get());
265      }
266  
267      /**
268       * does the length indicate a small document?
269       *
270       * @param length length in bytes
271       *
272       * @return true if the length is less than
273       *         _big_block_minimum_bytes
274       */
275  
276      public static boolean isSmall(final int length)
277      {
278          return length < _big_block_minimum_bytes;
279      }
280  
281      /**
282       * Get the name of this property
283       *
284       * @return property name as String
285       */
286  
287      public String getName()
288      {
289          return _name;
290      }
291  
292      /**
293       * @return true if a directory type Property
294       */
295  
296      abstract public boolean isDirectory();
297  
298      /**
299       * Set the name; silently truncates the name if it's too long.
300       *
301       * @param name the new name
302       */
303  
304      protected final void setName(final String name)
305      {
306          char[] char_array = name.toCharArray();
307          int    limit      = Math.min(char_array.length, _max_name_length);
308  
309          _name = new String(char_array, 0, limit);
310          short offset = 0;
311          int   j      = 0;
312  
313          for (; j < limit; j++)
314          {
315              new ShortField(offset, ( short ) char_array[ j ], _raw_data);
316              offset += LittleEndianConsts.SHORT_SIZE;
317          }
318          for (; j < _max_name_length + 1; j++)
319          {
320              new ShortField(offset, ( short ) 0, _raw_data);
321              offset += LittleEndianConsts.SHORT_SIZE;
322          }
323  
324          // double the count, and include the null at the end
325          _name_size
326              .set(( short ) ((limit + 1)
327                              * LittleEndianConsts.SHORT_SIZE), _raw_data);
328      }
329  
330      /**
331       * Set the property type. Makes no attempt to validate the value.
332       *
333       * @param propertyType the property type (root, file, directory)
334       */
335  
336      protected void setPropertyType(final byte propertyType)
337      {
338          _property_type.set(propertyType, _raw_data);
339      }
340  
341      /**
342       * Set the node color.
343       *
344       * @param nodeColor the node color (red or black)
345       */
346  
347      protected void setNodeColor(final byte nodeColor)
348      {
349          _node_color.set(nodeColor, _raw_data);
350      }
351  
352      /**
353       * Set the child property.
354       *
355       * @param child the child property's index in the Property Table
356       */
357  
358      protected void setChildProperty(final int child)
359      {
360          _child_property.set(child, _raw_data);
361      }
362  
363      /**
364       * Get the child property (its index in the Property Table)
365       *
366       * @return child property index
367       */
368  
369      protected int getChildIndex()
370      {
371          return _child_property.get();
372      }
373  
374      /**
375       * Set the size of the document associated with this Property
376       *
377       * @param size the size of the document, in bytes
378       */
379  
380      protected void setSize(final int size)
381      {
382          _size.set(size, _raw_data);
383      }
384  
385      /**
386       * Set the index for this Property
387       *
388       * @param index this Property's index within its containing
389       *              Property Table
390       */
391  
392      protected void setIndex(final int index)
393      {
394          _index = index;
395      }
396  
397      /**
398       * get the index for this Property
399       *
400       * @return the index of this Property within its Property Table
401       */
402  
403      protected int getIndex()
404      {
405          return _index;
406      }
407  
408      /**
409       * Perform whatever activities need to be performed prior to
410       * writing
411       */
412  
413      abstract protected void preWrite();
414  
415      /**
416       * get the next sibling
417       *
418       * @return index of next sibling
419       */
420  
421      int getNextChildIndex()
422      {
423          return _next_property.get();
424      }
425  
426      /**
427       * get the previous sibling
428       *
429       * @return index of previous sibling
430       */
431  
432      int getPreviousChildIndex()
433      {
434          return _previous_property.get();
435      }
436  
437      /**
438       * determine whether the specified index is valid
439       *
440       * @param index value to be checked
441       *
442       * @return true if the index is valid
443       */
444  
445      static boolean isValidIndex(int index)
446      {
447          return index != _NO_INDEX;
448      }
449  
450      /* ********** START implementation of Child ********** */
451  
452      /**
453       * Get the next Child, if any
454       *
455       * @return the next Child; may return null
456       */
457  
458      public Child getNextChild()
459      {
460          return _next_child;
461      }
462  
463      /**
464       * Get the previous Child, if any
465       *
466       * @return the previous Child; may return null
467       */
468  
469      public Child getPreviousChild()
470      {
471          return _previous_child;
472      }
473  
474      /**
475       * Set the next Child
476       *
477       * @param child the new 'next' child; may be null, which has the
478       *              effect of saying there is no 'next' child
479       */
480  
481      public void setNextChild(final Child child)
482      {
483          _next_child = child;
484          _next_property.set((child == null) ? _NO_INDEX
485                                             : (( Property ) child)
486                                                 .getIndex(), _raw_data);
487      }
488  
489      /**
490       * Set the previous Child
491       *
492       * @param child the new 'previous' child; may be null, which has
493       *              the effect of saying there is no 'previous' child
494       */
495  
496      public void setPreviousChild(final Child child)
497      {
498          _previous_child = child;
499          _previous_property.set((child == null) ? _NO_INDEX
500                                                 : (( Property ) child)
501                                                     .getIndex(), _raw_data);
502      }
503  
504      /* **********  END  implementation of Child ********** */
505      /* ********** START begin implementation of POIFSViewable ********** */
506  
507      /**
508       * Get an array of objects, some of which may implement
509       * POIFSViewable
510       *
511       * @return an array of Object; may not be null, but may be empty
512       */
513  
514      public Object [] getViewableArray()
515      {
516          Object[] results = new Object[ 5 ];
517  
518          results[ 0 ] = "Name          = \"" + getName() + "\"";
519          results[ 1 ] = "Property Type = " + _property_type.get();
520          results[ 2 ] = "Node Color    = " + _node_color.get();
521          long time = _days_1.get();
522  
523          time         <<= 32;
524          time         += (( long ) _seconds_1.get()) & 0x0000FFFFL;
525          results[ 3 ] = "Time 1        = " + time;
526          time         = _days_2.get();
527          time         <<= 32;
528          time         += (( long ) _seconds_2.get()) & 0x0000FFFFL;
529          results[ 4 ] = "Time 2        = " + time;
530          return results;
531      }
532  
533      /**
534       * Get an Iterator of objects, some of which may implement
535       * POIFSViewable
536       *
537       * @return an Iterator; may not be null, but may have an empty
538       * back end store
539       */
540  
541      public Iterator getViewableIterator()
542      {
543          return Collections.EMPTY_LIST.iterator();
544      }
545  
546      /**
547       * Give viewers a hint as to whether to call getViewableArray or
548       * getViewableIterator
549       *
550       * @return true if a viewer should call getViewableArray, false if
551       *         a viewer should call getViewableIterator
552       */
553  
554      public boolean preferArray()
555      {
556          return true;
557      }
558  
559      /**
560       * Provides a short description of the object, to be used when a
561       * POIFSViewable object has not provided its contents.
562       *
563       * @return short description
564       */
565  
566      public String getShortDescription()
567      {
568          StringBuffer buffer = new StringBuffer();
569  
570          buffer.append("Property: \"").append(getName()).append("\"");
571          return buffer.toString();
572      }
573  
574      /* **********  END  begin implementation of POIFSViewable ********** */
575  }   // end public abstract class Property
576  
577  ￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿limit￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setPropertyType￿￿￿￿￿￿￿￿￿_property_type￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿propertyType￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setNodeColor￿￿￿￿￿￿￿￿￿_node_color￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿nodeColor￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setChildProperty￿￿￿￿￿￿￿￿￿_child_property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getChildIndex￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_child_property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setSize￿￿￿￿￿￿￿￿￿_size￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿size￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setIndex￿￿￿￿￿￿￿￿￿_index￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿index￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getIndex￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_index￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿preWrite￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getNextChildIndex￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_next_property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getPreviousChildIndex￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_previous_property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿isValidIndex￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿index￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_NO_INDEX￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿Child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getNextChild￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_next_child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿Child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getPreviousChild￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_previous_child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setNextChild￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿Child￿￿￿￿￿￿￿￿￿_next_child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿_next_property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_NO_INDEX￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿Property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿setPreviousChild￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿Child￿￿￿￿￿￿￿￿￿_previous_child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿_previous_property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿set￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_NO_INDEX￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿Property￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿child￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_raw_data￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getViewableArray￿￿￿￿￿￿￿￿￿results￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getName￿￿￿￿￿￿￿￿￿results￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_property_type￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿results￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_node_color￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_days_1￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_seconds_1￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿results￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_days_2￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿_seconds_2￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿get￿￿￿￿￿￿￿￿￿results￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿time￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿results￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getViewableIterator￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿preferArray￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getShortDescription￿￿￿￿￿￿￿￿￿buffer￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿getName￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿buffer￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿