import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
if (part.getContentType().equals(contentType))
retArr.add(part);
}
+ Collections.sort(retArr);
return retArr;
}
retArr.add(part);
}
}
+ Collections.sort(retArr);
return retArr;
}
+ /**
+ * Retrieve parts by name
+ *
+ * @param namePattern
+ * The pattern for matching the names
+ * @return All parts associated to the specified content type, sorted
+ * in alphanumerically by the part-name
+ */
public List<PackagePart> getPartsByName(final Pattern namePattern) {
if (namePattern == null) {
throw new IllegalArgumentException("name pattern must not be null");
}
+ Matcher matcher = namePattern.matcher("");
ArrayList<PackagePart> result = new ArrayList<PackagePart>();
for (PackagePart part : partList.values()) {
PackagePartName partName = part.getPartName();
- String name = partName.getName();
- Matcher matcher = namePattern.matcher(name);
- if (matcher.matches()) {
+ if (matcher.reset(partName.getName()).matches()) {
result.add(part);
}
}
+ Collections.sort(result);
return result;
}
}
}
}
- return new ArrayList<PackagePart>(partList.values());
+ ArrayList<PackagePart> result = new ArrayList<PackagePart>(partList.values());
+ java.util.Collections.sort(result);
+ return result;
}
/**
package org.apache.poi.openxml4j.opc;
+import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
}
/**
- * Compare two part name following the rule M1.12 :
+ * Compare two part names following the rule M1.12 :
*
* Part name equivalence is determined by comparing part names as
* case-insensitive ASCII strings. Packages shall not contain equivalent
* part names and package implementers shall neither create nor recognize
* packages with equivalent part names. [M1.12]
*/
- public int compareTo(PackagePartName otherPartName) {
- if (otherPartName == null)
- return -1;
- return this.partNameURI.toASCIIString().toLowerCase().compareTo(
- otherPartName.partNameURI.toASCIIString().toLowerCase());
- }
+ @Override
+ public int compareTo(PackagePartName other)
+ {
+ // compare with natural sort order
+ return compare(this, other);
+ }
+
/**
* Retrieves the extension of the part name if any. If there is no extension
* packages with equivalent part names. [M1.12]
*/
@Override
- public boolean equals(Object otherPartName) {
- if (otherPartName == null
- || !(otherPartName instanceof PackagePartName))
- return false;
- return this.partNameURI.toASCIIString().toLowerCase().equals(
- ((PackagePartName) otherPartName).partNameURI.toASCIIString()
- .toLowerCase());
- }
+ public boolean equals(Object other) {
+ if (other instanceof PackagePartName) {
+ // String.equals() is compatible with our compareTo(), but cheaper
+ return this.partNameURI.toASCIIString().toLowerCase().equals
+ (
+ ((PackagePartName) other).partNameURI.toASCIIString().toLowerCase()
+ );
+ } else {
+ return false;
+ }
+ }
@Override
public int hashCode() {
public URI getURI() {
return this.partNameURI;
}
+
+
+ /**
+ * A natural sort order for package part names, consistent with the
+ * requirements of {@code java.util.Comparator}, but simply implemented
+ * as a static method.
+ * <p>
+ * For example, this sorts "file10.png" after "file2.png" (comparing the
+ * numerical portion), but sorts "File10.png" before "file2.png"
+ * (lexigraphical sort)
+ *
+ * <p>
+ * When comparing part names, the rule M1.12 is followed:
+ *
+ * Part name equivalence is determined by comparing part names as
+ * case-insensitive ASCII strings. Packages shall not contain equivalent
+ * part names and package implementers shall neither create nor recognize
+ * packages with equivalent part names. [M1.12]
+ */
+ public static int compare(PackagePartName obj1, PackagePartName obj2)
+ {
+ // NOTE could also throw a NullPointerException() if desired
+ if (obj1 == null)
+ {
+ // (null) == (null), (null) < (non-null)
+ return (obj2 == null ? 0 : -1);
+ }
+ else if (obj2 == null)
+ {
+ // (non-null) > (null)
+ return 1;
+ }
+
+ return compare
+ (
+ obj1.getURI().toASCIIString().toLowerCase(),
+ obj2.getURI().toASCIIString().toLowerCase()
+ );
+ }
+
+
+ /**
+ * A natural sort order for strings, consistent with the
+ * requirements of {@code java.util.Comparator}, but simply implemented
+ * as a static method.
+ * <p>
+ * For example, this sorts "file10.png" after "file2.png" (comparing the
+ * numerical portion), but sorts "File10.png" before "file2.png"
+ * (lexigraphical sort)
+ */
+ public static int compare(String str1, String str2)
+ {
+ if (str1 == null)
+ {
+ // (null) == (null), (null) < (non-null)
+ return (str2 == null ? 0 : -1);
+ }
+ else if (str2 == null)
+ {
+ // (non-null) > (null)
+ return 1;
+ }
+
+ int len1 = str1.length();
+ int len2 = str2.length();
+ for (int idx1 = 0, idx2 = 0; idx1 < len1 && idx2 < len2; /*nil*/)
+ {
+ char c1 = str1.charAt(idx1++);
+ char c2 = str2.charAt(idx2++);
+
+ if (Character.isDigit(c1) && Character.isDigit(c2))
+ {
+ int beg1 = idx1 - 1; // undo previous increment
+ while (idx1 < len1 && Character.isDigit(str1.charAt(idx1)))
+ {
+ ++idx1;
+ }
+
+ int beg2 = idx2 - 1; // undo previous increment
+ while (idx2 < len2 && Character.isDigit(str2.charAt(idx2)))
+ {
+ ++idx2;
+ }
+
+ // note: BigInteger for extra safety
+ int cmp = new BigInteger(str1.substring(beg1, idx1)).compareTo
+ (
+ new BigInteger(str2.substring(beg2, idx2))
+ );
+ if (cmp != 0) return cmp;
+ }
+ else if (c1 != c2)
+ {
+ return (c1 - c2);
+ }
+ }
+
+ return (len1 - len2);
+ }
+
}
+
+/* ************************************************************************** */