You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

POIFSDocumentPath.java 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.filesystem;
  16. import java.io.File;
  17. import java.util.Arrays;
  18. import java.util.Objects;
  19. import java.util.function.Predicate;
  20. import java.util.stream.Stream;
  21. import org.apache.logging.log4j.LogManager;
  22. import org.apache.logging.log4j.Logger;
  23. /**
  24. * Class POIFSDocumentPath
  25. */
  26. public class POIFSDocumentPath {
  27. private static final Logger LOGGER = LogManager.getLogger(POIFSDocumentPath.class);
  28. private final String[] components;
  29. private int hashcode; //lazy-compute hashCode
  30. /**
  31. * simple constructor for the path of a document that is in the root of the POIFSFileSystem.
  32. * The constructor that takes an array of Strings can also be used to create such a
  33. * POIFSDocumentPath by passing it a null or empty String array
  34. */
  35. public POIFSDocumentPath() {
  36. components = new String[0];
  37. }
  38. /**
  39. * constructor for the path of a document that is not in the root of the POIFSFileSystem
  40. *
  41. * @param components the Strings making up the path to a document.
  42. * The Strings must be ordered as they appear in the directory hierarchy of the the document.
  43. * The first string must be the name of a directory in the root of the POIFSFileSystem, and
  44. * every Nth (for N > 1) string thereafter must be the name of a directory in the directory
  45. * identified by the (N-1)th string. <p> If the components parameter is null or has zero length,
  46. * the POIFSDocumentPath is appropriate for a document that is in the root of a POIFSFileSystem
  47. *
  48. * @exception IllegalArgumentException
  49. * if any of the elements in the components parameter are null or have zero length
  50. */
  51. public POIFSDocumentPath(final String [] components) throws IllegalArgumentException {
  52. this(null, components);
  53. }
  54. /**
  55. * constructor that adds additional subdirectories to an existing path
  56. *
  57. * @param path the existing path
  58. * @param components the additional subdirectory names to be added
  59. *
  60. * @exception IllegalArgumentException
  61. * if any of the Strings in components is null or zero length
  62. */
  63. public POIFSDocumentPath(final POIFSDocumentPath path, final String[] components) throws IllegalArgumentException {
  64. String[] s1 = (path == null) ? new String[0] : path.components;
  65. String[] s2 = (components == null) ? new String[0] : components;
  66. // TODO: Although the Javadoc says empty strings are forbidden, the adapted legacy
  67. // implementation allowed it in case a path was specified...
  68. Predicate<String> p = (path != null) ? Objects::isNull : (s) -> (s == null || s.isEmpty());
  69. if (Stream.of(s2).anyMatch(p)) {
  70. throw new IllegalArgumentException("components cannot contain null or empty strings");
  71. }
  72. this.components = Stream.concat(Stream.of(s1),Stream.of(s2)).toArray(String[]::new);
  73. }
  74. /**
  75. * Two POIFSDocumentPath instances are equal if they have the same number of component Strings,
  76. * and if each component String is equal to its corresponding component String
  77. *
  78. * @param o the object we're checking equality for
  79. *
  80. * @return true if the object is equal to this object
  81. */
  82. public boolean equals(final Object o) {
  83. if (this == o) {
  84. return true;
  85. }
  86. if ((o != null) && (o.getClass() == this.getClass())) {
  87. POIFSDocumentPath path = ( POIFSDocumentPath ) o;
  88. return Arrays.equals(this.components, path.components);
  89. }
  90. return false;
  91. }
  92. /**
  93. * calculate and return the hashcode
  94. *
  95. * @return hashcode
  96. */
  97. public int hashCode() {
  98. return (hashcode == 0) ? (hashcode = Arrays.hashCode(components)) : hashcode;
  99. }
  100. /**
  101. * @return the number of components
  102. */
  103. public int length() {
  104. return components.length;
  105. }
  106. /**
  107. * get the specified component
  108. *
  109. * @param n which component (0 ... length() - 1)
  110. *
  111. * @return the nth component;
  112. *
  113. * @exception ArrayIndexOutOfBoundsException if n &lt; 0 or n >= length()
  114. */
  115. public String getComponent(int n) throws ArrayIndexOutOfBoundsException {
  116. return components[ n ];
  117. }
  118. /**
  119. * <p>Returns the path's parent or <code>null</code> if this path
  120. * is the root path.</p>
  121. *
  122. * @since 2002-01-24
  123. * @return path of parent, or null if this path is the root path
  124. */
  125. public POIFSDocumentPath getParent() {
  126. return (components.length == 0) ? null : new POIFSDocumentPath(Arrays.copyOf(components, components.length - 1));
  127. }
  128. /**
  129. * <p>Returns the last name in the document path's name sequence.
  130. * If the document path's name sequence is empty, then the empty string is returned.</p>
  131. *
  132. * @since 2016-04-09
  133. * @return The last name in the document path's name sequence, or empty string if this is the root path
  134. */
  135. public String getName() {
  136. return components.length == 0 ? "" : components[components.length - 1];
  137. }
  138. /**
  139. * <p>Returns a string representation of the path. Components are
  140. * separated by the platform-specific file separator {@link File#separatorChar}</p>
  141. *
  142. * @return string representation
  143. *
  144. * @since 2002-01-24
  145. */
  146. public String toString() {
  147. return File.separatorChar + String.join(String.valueOf(File.separatorChar), components);
  148. }
  149. }