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.filesystem;
57   
58   import java.io.File;
59   
60   /**
61    * Class POIFSDocumentPath
62    *
63    * @author Marc Johnson (mjohnson at apache dot org)
64    * @version %I%, %G%
65    */
66   
67   public class POIFSDocumentPath
68   {
69       private String[] components;
70       private int      hashcode = 0;
71   
72       /**
73        * constructor for the path of a document that is not in the root
74        * of the POIFSFileSystem
75        *
76        * @param components the Strings making up the path to a document.
77        *                   The Strings must be ordered as they appear in
78        *                   the directory hierarchy of the the document
79        *                   -- the first string must be the name of a
80        *                   directory in the root of the POIFSFileSystem,
81        *                   and every Nth (for N > 1) string thereafter
82        *                   must be the name of a directory in the
83        *                   directory identified by the (N-1)th string.
84        *                   <p>
85        *                   If the components parameter is null or has
86        *                   zero length, the POIFSDocumentPath is
87        *                   appropriate for a document that is in the
88        *                   root of a POIFSFileSystem
89        *
90        * @exception IllegalArgumentException if any of the elements in
91        *                                     the components parameter
92        *                                     are null or have zero
93        *                                     length
94        */
95   
96       public POIFSDocumentPath(final String [] components)
97           throws IllegalArgumentException
98       {
99           if (components == null)
100          {
101              this.components = new String[ 0 ];
102          }
103          else
104          {
105              this.components = new String[ components.length ];
106              for (int j = 0; j < components.length; j++)
107              {
108                  if ((components[ j ] == null)
109                          || (components[ j ].length() == 0))
110                  {
111                      throw new IllegalArgumentException(
112                          "components cannot contain null or empty strings");
113                  }
114                  this.components[ j ] = components[ j ];
115              }
116          }
117      }
118  
119      /**
120       * simple constructor for the path of a document that is in the
121       * root of the POIFSFileSystem. The constructor that takes an
122       * array of Strings can also be used to create such a
123       * POIFSDocumentPath by passing it a null or empty String array
124       */
125  
126      public POIFSDocumentPath()
127      {
128          this.components = new String[ 0 ];
129      }
130  
131      /**
132       * constructor that adds additional subdirectories to an existing
133       * path
134       *
135       * @param path the existing path
136       * @param components the additional subdirectory names to be added
137       *
138       * @exception IllegalArgumentException if any of the Strings in
139       *                                     components is null or zero
140       *                                     length
141       */
142  
143      public POIFSDocumentPath(final POIFSDocumentPath path,
144                               final String [] components)
145          throws IllegalArgumentException
146      {
147          if (components == null)
148          {
149              this.components = new String[ path.components.length ];
150          }
151          else
152          {
153              this.components =
154                  new String[ path.components.length + components.length ];
155          }
156          for (int j = 0; j < path.components.length; j++)
157          {
158              this.components[ j ] = path.components[ j ];
159          }
160          if (components != null)
161          {
162              for (int j = 0; j < components.length; j++)
163              {
164                  if ((components[ j ] == null)
165                          || (components[ j ].length() == 0))
166                  {
167                      throw new IllegalArgumentException(
168                          "components cannot contain null or empty strings");
169                  }
170                  this.components[ j + path.components.length ] =
171                      components[ j ];
172              }
173          }
174      }
175  
176      /**
177       * equality. Two POIFSDocumentPath instances are equal if they
178       * have the same number of component Strings, and if each
179       * component String is equal to its coresponding component String
180       *
181       * @param o the object we're checking equality for
182       *
183       * @return true if the object is equal to this object
184       */
185  
186      public boolean equals(final Object o)
187      {
188          boolean rval = false;
189  
190          if ((o != null) && (o.getClass() == this.getClass()))
191          {
192              if (this == o)
193              {
194                  rval = true;
195              }
196              else
197              {
198                  POIFSDocumentPath path = ( POIFSDocumentPath ) o;
199  
200                  if (path.components.length == this.components.length)
201                  {
202                      rval = true;
203                      for (int j = 0; j < this.components.length; j++)
204                      {
205                          if (!path.components[ j ]
206                                  .equals(this.components[ j ]))
207                          {
208                              rval = false;
209                              break;
210                          }
211                      }
212                  }
213              }
214          }
215          return rval;
216      }
217  
218      /**
219       * calculate and return the hashcode
220       *
221       * @return hashcode
222       */
223  
224      public int hashCode()
225      {
226          if (hashcode == 0)
227          {
228              for (int j = 0; j < components.length; j++)
229              {
230                  hashcode += components[ j ].hashCode();
231              }
232          }
233          return hashcode;
234      }
235  
236      /**
237       * @return the number of components
238       */
239  
240      public int length()
241      {
242          return components.length;
243      }
244  
245      /**
246       * get the specified component
247       *
248       * @param n which component (0 ... length() - 1)
249       *
250       * @return the nth component;
251       *
252       * @exception ArrayIndexOutOfBoundsException if n < 0 or n >=
253       *                                           length()
254       */
255  
256      public String getComponent(int n)
257          throws ArrayIndexOutOfBoundsException
258      {
259          return components[ n ];
260      }
261  
262      /**
263       * <p>Returns the path's parent or <code>null</code> if this path
264       * is the root path.</p>
265       *
266       * @author Rainer Klute (klute@rainer-klute.de)
267       * @since 2002-01-24
268       *
269       * @return path of parent, or null if this path is the root path
270       */
271  
272      public POIFSDocumentPath getParent()
273      {
274          final int length = components.length - 1;
275  
276          if (length < 0)
277          {
278              return null;
279          }
280          POIFSDocumentPath parent = new POIFSDocumentPath(null);
281  
282          parent.components = new String[ length ];
283          System.arraycopy(components, 0, parent.components, 0, length);
284          return parent;
285      }
286  
287      /**
288       * <p>Returns a string representation of the path. Components are
289       * separated by the platform-specific file separator.</p>
290       *
291       * @author Rainer Klute (klute@rainer-klute.de)
292       * @since 2002-01-24
293       *
294       * @return string representation
295       */
296  
297      public String toString()
298      {
299          final StringBuffer b = new StringBuffer();
300          final int          l = length();
301  
302          b.append(File.separatorChar);
303          for (int i = 0; i < l; i++)
304          {
305              b.append(getComponent(i));
306              if (i < l - 1)
307              {
308                  b.append(File.separatorChar);
309              }
310          }
311          return b.toString();
312      }
313  }   // end public class POIFSDocumentPath
314  
315