summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Beeker <kiwiwings@apache.org>2017-05-03 19:18:45 +0000
committerAndreas Beeker <kiwiwings@apache.org>2017-05-03 19:18:45 +0000
commit2da5cb12769f62961ea4a86eba9fdc75239c2547 (patch)
treeb611fa7928aefe986a3c1f43e205a9151b140154
parent267ee8a2a02dab1eb7d075943676d48d0bb5c831 (diff)
downloadpoi-2da5cb12769f62961ea4a86eba9fdc75239c2547.tar.gz
poi-2da5cb12769f62961ea4a86eba9fdc75239c2547.zip
HPSF: Change CustomProperties to delegate
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1793699 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/poi/hpsf/CustomProperties.java272
-rw-r--r--src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java2
-rw-r--r--src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java6
3 files changed, 155 insertions, 125 deletions
diff --git a/src/java/org/apache/poi/hpsf/CustomProperties.java b/src/java/org/apache/poi/hpsf/CustomProperties.java
index a279e2321e..da4e9277bc 100644
--- a/src/java/org/apache/poi/hpsf/CustomProperties.java
+++ b/src/java/org/apache/poi/hpsf/CustomProperties.java
@@ -18,9 +18,15 @@
package org.apache.poi.hpsf;
import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -58,10 +64,14 @@ import org.apache.poi.util.POILogger;
* internal representation. To external calls, it should appear as
* HashMap&lt;String,Object&gt; mapping between Names and Custom Property Values.
*/
-@SuppressWarnings("serial")
-public class CustomProperties extends HashMap<Long,CustomProperty> {
+public class CustomProperties implements Map<String,Object> {
private static final POILogger LOG = POILogFactory.getLogger(CustomProperties.class);
-
+
+ /**
+ * The custom properties
+ */
+ private final HashMap<Long,CustomProperty> props = new HashMap<Long,CustomProperty>();
+
/**
* Maps property IDs to property names and vice versa.
*/
@@ -100,151 +110,141 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
checkCodePage(name);
/* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a */
- super.remove(dictionary.getKey(name));
+ props.remove(dictionary.getKey(name));
dictionary.put(cp.getID(), name);
/* Put the custom property into this map. */
- return super.put(cp.getID(), cp);
+ return props.put(cp.getID(), cp);
}
-
-
/**
- * Puts a {@link CustomProperty} that has not yet a valid ID into this
- * map. The method will allocate a suitable ID for the custom property:
+ * Adds a named property.
*
- * <ul>
- * <li>If there is already a property with the same name, take the ID
- * of that property.
- *
- * <li>Otherwise find the highest ID and use its value plus one.
- * </ul>
- *
- * @param customProperty
- * @return If there was already a property with the same name, the old property
- * @throws ClassCastException
+ * @param key The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * {@code null} if there was no such property before.
*/
- private Object put(final CustomProperty customProperty) throws ClassCastException {
- final String name = customProperty.getName();
-
- /* Check whether a property with this name is in the map already. */
- final Long oldId = (name == null) ? null : dictionary.getKey(name);
- if (oldId != null) {
- customProperty.setID(oldId);
+ @Override
+ public Object put(String key, Object value) {
+ int variantType;
+ if (value instanceof String) {
+ variantType = Variant.VT_LPSTR;
+ } else if (value instanceof Short) {
+ variantType = Variant.VT_I2;
+ } else if (value instanceof Integer) {
+ variantType = Variant.VT_I4;
+ } else if (value instanceof Long) {
+ variantType = Variant.VT_I8;
+ } else if (value instanceof Float) {
+ variantType = Variant.VT_R4;
+ } else if (value instanceof Double) {
+ variantType = Variant.VT_R8;
+ } else if (value instanceof Boolean) {
+ variantType = Variant.VT_BOOL;
+ } else if (value instanceof BigInteger
+ && ((BigInteger)value).bitLength() <= 64
+ && ((BigInteger)value).compareTo(BigInteger.ZERO) >= 0) {
+ variantType = Variant.VT_UI8;
+ } else if (value instanceof Date) {
+ variantType = Variant.VT_FILETIME;
} else {
- long lastKey = (dictionary.isEmpty()) ? 0 : dictionary.lastKey();
- long nextKey = Math.max(lastKey,PropertyIDMap.PID_MAX)+1;
- customProperty.setID(nextKey);
+ throw new IllegalStateException("unsupported datatype - currently String,Short,Integer,Long,Float,Double,Boolean,BigInteger(unsigned long),Date can be processed.");
}
- return this.put(name, customProperty);
+ final Property p = new MutableProperty(-1, variantType, value);
+ return put(new CustomProperty(p, key));
}
-
-
-
+
/**
- * Removes a custom property.
- * @param name The name of the custom property to remove
- * @return The removed property or {@code null} if the specified property was not found.
+ * Gets a named value from the custom properties - only works for keys of type String
*
- * @see java.util.HashSet#remove(java.lang.Object)
+ * @param key the name of the value to get
+ * @return the value or {@code null} if a value with the specified
+ * name is not found in the custom properties.
*/
- public Object remove(final String name) {
- final Long id = dictionary.removeValue(name);
- return super.remove(id);
+ @Override
+ public Object get(final Object key) {
+ final Long id = dictionary.getKey(key);
+ final CustomProperty cp = props.get(id);
+ return cp != null ? cp.getValue() : null;
}
/**
- * Adds a named string property.
- *
- * @param name The property's name.
- * @param value The property's value.
- * @return the property that was stored under the specified name before, or
- * {@code null} if there was no such property before.
+ * Removes a custom property - only works for keys of type String
+ * @param key The name of the custom property to remove
+ * @return The removed property or {@code null} if the specified property was not found.
*/
- public Object put(final String name, final String value) {
- final Property p = new MutableProperty(-1, Variant.VT_LPSTR, value);
- return put(new CustomProperty(p, name));
+ @Override
+ public CustomProperty remove(Object key) {
+ final Long id = dictionary.removeValue(key);
+ return props.remove(id);
}
- /**
- * Adds a named long property.
- *
- * @param name The property's name.
- * @param value The property's value.
- * @return the property that was stored under the specified name before, or
- * {@code null} if there was no such property before.
- */
- public Object put(final String name, final Long value) {
- final Property p = new MutableProperty(-1, Variant.VT_I8, value);
- return put(new CustomProperty(p, name));
+ @Override
+ public int size() {
+ return props.size();
}
- /**
- * Adds a named double property.
- *
- * @param name The property's name.
- * @param value The property's value.
- * @return the property that was stored under the specified name before, or
- * {@code null} if there was no such property before.
- */
- public Object put(final String name, final Double value) {
- final Property p = new MutableProperty(-1, Variant.VT_R8, value);
- return put(new CustomProperty(p, name));
+ @Override
+ public boolean isEmpty() {
+ return props.isEmpty();
}
- /**
- * Adds a named integer property.
- *
- * @param name The property's name.
- * @param value The property's value.
- * @return the property that was stored under the specified name before, or
- * {@code null} if there was no such property before.
- */
- public Object put(final String name, final Integer value) {
- final Property p = new MutableProperty(-1, Variant.VT_I4, value);
- return put(new CustomProperty(p, name));
+ @Override
+ public void clear() {
+ props.clear();
+ }
+
+ @Override
+ public int hashCode() {
+ return props.hashCode();
}
- /**
- * Adds a named boolean property.
- *
- * @param name The property's name.
- * @param value The property's value.
- * @return the property that was stored under the specified name before, or
- * {@code null} if there was no such property before.
- */
- public Object put(final String name, final Boolean value) {
- final Property p = new MutableProperty(-1, Variant.VT_BOOL, value);
- return put(new CustomProperty(p, name));
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CustomProperties)) {
+ return false;
+ }
+ return props.equals(((CustomProperties)obj).props);
}
+ @Override
+ public void putAll(Map<? extends String, ? extends Object> m) {
+ for (Map.Entry<? extends String, ? extends Object> me : m.entrySet()) {
+ put(me.getKey(), me.getValue());
+ }
+ }
/**
- * Gets a named value from the custom properties.
- *
- * @param name the name of the value to get
- * @return the value or {@code null} if a value with the specified
- * name is not found in the custom properties.
+ * @return the list of properties
*/
- public Object get(final String name) {
- final Long id = dictionary.getKey(name);
- final CustomProperty cp = super.get(id);
- return cp != null ? cp.getValue() : null;
+ public List<CustomProperty> properties() {
+ List<CustomProperty> list = new ArrayList<CustomProperty>(props.size());
+ for (Long l : dictionary.keySet()) {
+ list.add(props.get(l));
+ }
+ return Collections.unmodifiableList(list);
}
-
-
-
+
/**
- * Adds a named date property.
- *
- * @param name The property's name.
- * @param value The property's value.
- * @return the property that was stored under the specified name before, or
- * {@code null} if there was no such property before.
+ * @return the list of property values - use {@link #properties()} for the wrapped values
*/
- public Object put(final String name, final Date value) {
- final Property p = new MutableProperty(-1, Variant.VT_FILETIME, value);
- return put(new CustomProperty(p, name));
+ @Override
+ public Collection<Object> values() {
+ List<Object> list = new ArrayList<Object>(props.size());
+ for (Long l : dictionary.keySet()) {
+ list.add(props.get(l).getValue());
+ }
+ return Collections.unmodifiableCollection(list);
+ }
+
+ @Override
+ public Set<Entry<String, Object>> entrySet() {
+ Map<String,Object> set = new LinkedHashMap<String,Object>(props.size());
+ for (Entry<Long,String> se : dictionary.entrySet()) {
+ set.put(se.getValue(), props.get(se.getKey()).getValue());
+ }
+ return Collections.unmodifiableSet(set.entrySet());
}
/**
@@ -256,7 +256,7 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public Set keySet() {
- return dictionary.values();
+ return Collections.unmodifiableSet(dictionary.values());
}
/**
@@ -265,7 +265,7 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
* @return a set of all the names of our custom properties
*/
public Set<String> nameSet() {
- return dictionary.values();
+ return Collections.unmodifiableSet(dictionary.values());
}
/**
@@ -273,8 +273,8 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
*
* @return a set of all the IDs of our custom properties
*/
- public Set<String> idSet() {
- return dictionary.values();
+ public Set<Long> idSet() {
+ return Collections.unmodifiableSet(dictionary.keySet());
}
@@ -321,10 +321,10 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
@Override
public boolean containsValue(Object value) {
if(value instanceof CustomProperty) {
- return super.containsValue(value);
+ return props.containsValue(value);
}
- for(CustomProperty cp : super.values()) {
+ for(CustomProperty cp : props.values()) {
if(cp.getValue() == value) {
return true;
}
@@ -353,7 +353,37 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
public void setPure(final boolean isPure) {
this.isPure = isPure;
}
-
+
+ /**
+ * Puts a {@link CustomProperty} that has not yet a valid ID into this
+ * map. The method will allocate a suitable ID for the custom property:
+ *
+ * <ul>
+ * <li>If there is already a property with the same name, take the ID
+ * of that property.
+ *
+ * <li>Otherwise find the highest ID and use its value plus one.
+ * </ul>
+ *
+ * @param customProperty
+ * @return If there was already a property with the same name, the old property
+ * @throws ClassCastException
+ */
+ private Object put(final CustomProperty customProperty) throws ClassCastException {
+ final String name = customProperty.getName();
+
+ /* Check whether a property with this name is in the map already. */
+ final Long oldId = (name == null) ? null : dictionary.getKey(name);
+ if (oldId != null) {
+ customProperty.setID(oldId);
+ } else {
+ long lastKey = (dictionary.isEmpty()) ? 0 : dictionary.lastKey();
+ long nextKey = Math.max(lastKey,PropertyIDMap.PID_MAX)+1;
+ customProperty.setID(nextKey);
+ }
+ return this.put(name, customProperty);
+ }
+
private void checkCodePage(String value) {
int cp = getCodepage();
if (cp == -1) {
diff --git a/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java b/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
index 7dd41a0cc3..cea4d5dd9f 100644
--- a/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
+++ b/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
@@ -801,7 +801,7 @@ public class DocumentSummaryInformation extends SpecialPropertySet {
customProperties.setCodepage(cpCodepage);
section.setCodepage(cpCodepage);
section.setDictionary(dictionary);
- for (CustomProperty p : customProperties.values()) {
+ for (CustomProperty p : customProperties.properties()) {
section.setProperty(p);
}
}
diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java b/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java
index 0df2f56cb2..ce3cf6d34d 100644
--- a/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java
+++ b/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java
@@ -218,9 +218,9 @@ public class TestReadAllFiles {
return;
}
- for (CustomProperty cp : cps.values()) {
- cp.getName();
- cp.getValue();
+ for (CustomProperty cp : cps.properties()) {
+ assertNotNull(cp.getName());
+ assertNotNull(cp.getValue());
}
} finally {
poifs.close();