123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==================================================================== */
-
- package org.apache.poi.poifs.property;
-
- import java.io.IOException;
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Comparator;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Set;
- import java.util.Spliterator;
-
- /**
- * Directory property
- */
- public class DirectoryProperty extends Property implements Parent, Iterable<Property> {
-
- /** List of Property instances */
- private final List<Property> _children = new ArrayList<>();
-
- /** set of children's names */
- private final Set<String> _children_names = new HashSet<>();
-
- /**
- * Default constructor
- *
- * @param name the name of the directory
- */
- public DirectoryProperty(String name)
- {
- super();
- setName(name);
- setSize(0);
- setPropertyType(PropertyConstants.DIRECTORY_TYPE);
- setStartBlock(0);
- setNodeColor(_NODE_BLACK); // simplification
- }
-
- /**
- * reader constructor
- *
- * @param index index number
- * @param array byte data
- * @param offset offset into byte data
- */
- protected DirectoryProperty(final int index, final byte [] array,
- final int offset)
- {
- super(index, array, offset);
- }
-
- /**
- * Change a Property's name
- *
- * @param property the Property whose name is being changed
- * @param newName the new name for the Property
- *
- * @return true if the name change could be made, else false
- */
- public boolean changeName(Property property, String newName)
- {
- boolean result;
- String oldName = property.getName();
-
- property.setName(newName);
- String cleanNewName = property.getName();
-
- if (_children_names.contains(cleanNewName))
- {
-
- // revert the change
- property.setName(oldName);
- result = false;
- }
- else
- {
- _children_names.add(cleanNewName);
- _children_names.remove(oldName);
- result = true;
- }
- return result;
- }
-
- /**
- * Delete a Property
- *
- * @param property the Property being deleted
- *
- * @return true if the Property could be deleted, else false
- */
- public boolean deleteChild(Property property)
- {
- boolean result = _children.remove(property);
-
- if (result)
- {
- _children_names.remove(property.getName());
- }
- return result;
- }
-
- public static class PropertyComparator implements Comparator<Property>, Serializable {
-
- /**
- * compare method. Assumes both parameters are non-null
- * instances of Property. One property is less than another if
- * its name is shorter than the other property's name. If the
- * names are the same length, the property whose name comes
- * before the other property's name, alphabetically, is less
- * than the other property.
- *
- * @param o1 first object to compare, better be a Property
- * @param o2 second object to compare, better be a Property
- *
- * @return negative value if o1 < o2,
- * zero if o1 == o2,
- * positive value if o1 > o2.
- */
- public int compare(Property o1, Property o2)
- {
- String VBA_PROJECT = "_VBA_PROJECT";
- String name1 = o1.getName();
- String name2 = o2.getName();
- int result = name1.length() - name2.length();
-
- if (result == 0)
- {
- // _VBA_PROJECT, it seems, will always come last
- if (name1.compareTo(VBA_PROJECT) == 0)
- result = 1;
- else if (name2.compareTo(VBA_PROJECT) == 0)
- result = -1;
- else
- {
- if (name1.startsWith("__") && name2.startsWith("__"))
- {
- // Betweeen __SRP_0 and __SRP_1 just sort as normal
- result = name1.compareToIgnoreCase(name2);
- }
- else if (name1.startsWith("__"))
- {
- // If only name1 is __XXX then this will be placed after name2
- result = 1;
- }
- else if (name2.startsWith("__"))
- {
- // If only name2 is __XXX then this will be placed after name1
- result = -1;
- }
- else
- // result = name1.compareTo(name2);
- // The default case is to sort names ignoring case
- result = name1.compareToIgnoreCase(name2);
- }
- }
- return result;
- }
- }
-
- /**
- * @return true if a directory type Property
- */
- public boolean isDirectory()
- {
- return true;
- }
-
- /**
- * Perform whatever activities need to be performed prior to
- * writing
- */
- protected void preWrite()
- {
- if (_children.size() > 0)
- {
- Property[] children = _children.toArray(new Property[ 0 ]);
-
- Arrays.sort(children, new PropertyComparator());
- int midpoint = children.length / 2;
-
- setChildProperty(children[ midpoint ].getIndex());
- children[ 0 ].setPreviousChild(null);
- children[ 0 ].setNextChild(null);
- for (int j = 1; j < midpoint; j++)
- {
- children[ j ].setPreviousChild(children[ j - 1 ]);
- children[ j ].setNextChild(null);
- }
- if (midpoint != 0)
- {
- children[ midpoint ]
- .setPreviousChild(children[ midpoint - 1 ]);
- }
- if (midpoint != (children.length - 1))
- {
- children[ midpoint ].setNextChild(children[ midpoint + 1 ]);
- for (int j = midpoint + 1; j < children.length - 1; j++)
- {
- children[ j ].setPreviousChild(null);
- children[ j ].setNextChild(children[ j + 1 ]);
- }
- children[ children.length - 1 ].setPreviousChild(null);
- children[ children.length - 1 ].setNextChild(null);
- }
- else
- {
- children[ midpoint ].setNextChild(null);
- }
- }
- }
-
- /**
- * Get an iterator over the children of this Parent; all elements
- * are instances of Property.
- *
- * @return Iterator of children; may refer to an empty collection
- */
- public Iterator<Property> getChildren()
- {
- return _children.iterator();
- }
- /**
- * Get an iterator over the children of this Parent, alias for
- * {@link #getChildren()} which supports foreach use
- */
- public Iterator<Property> iterator() {
- return getChildren();
- }
- /**
- * Get a spliterator over the children of this Parent; all elements
- * are instances of Property.
- *
- * @return Spliterator of children; may refer to an empty collection
- *
- * @since POI 5.2.0
- */
- @Override
- public Spliterator<Property> spliterator() {
- return _children.spliterator();
- }
-
- /**
- * Add a new child to the collection of children
- *
- * @param property the new child to be added; must not be null
- *
- * @throws IOException if we already have a child with the same
- * name
- */
- public void addChild(final Property property)
- throws IOException
- {
- String name = property.getName();
-
- if (_children_names.contains(name))
- {
- throw new IOException("Duplicate name \"" + name + "\"");
- }
- _children_names.add(name);
- _children.add(property);
- }
- }
|