HPSF: Change CustomProperties to delegate
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1793699 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d0630390d2
commit
76dbb5a1eb
@ -18,9 +18,15 @@
|
|||||||
package org.apache.poi.hpsf;
|
package org.apache.poi.hpsf;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -58,10 +64,14 @@ import org.apache.poi.util.POILogger;
|
|||||||
* internal representation. To external calls, it should appear as
|
* internal representation. To external calls, it should appear as
|
||||||
* HashMap<String,Object> mapping between Names and Custom Property Values.
|
* HashMap<String,Object> mapping between Names and Custom Property Values.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
public class CustomProperties implements Map<String,Object> {
|
||||||
public class CustomProperties extends HashMap<Long,CustomProperty> {
|
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(CustomProperties.class);
|
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.
|
* Maps property IDs to property names and vice versa.
|
||||||
*/
|
*/
|
||||||
@ -100,151 +110,141 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
|
|||||||
checkCodePage(name);
|
checkCodePage(name);
|
||||||
|
|
||||||
/* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a */
|
/* 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);
|
dictionary.put(cp.getID(), name);
|
||||||
|
|
||||||
/* Put the custom property into this map. */
|
/* 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
|
* Adds a named property.
|
||||||
* map. The method will allocate a suitable ID for the custom property:
|
|
||||||
*
|
*
|
||||||
* <ul>
|
* @param key The property's name.
|
||||||
* <li>If there is already a property with the same name, take the ID
|
* @param value The property's value.
|
||||||
* of that property.
|
* @return the property that was stored under the specified name before, or
|
||||||
*
|
* {@code null} if there was no such property before.
|
||||||
* <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 {
|
@Override
|
||||||
final String name = customProperty.getName();
|
public Object put(String key, Object value) {
|
||||||
|
int variantType;
|
||||||
/* Check whether a property with this name is in the map already. */
|
if (value instanceof String) {
|
||||||
final Long oldId = (name == null) ? null : dictionary.getKey(name);
|
variantType = Variant.VT_LPSTR;
|
||||||
if (oldId != null) {
|
} else if (value instanceof Short) {
|
||||||
customProperty.setID(oldId);
|
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 {
|
} else {
|
||||||
long lastKey = (dictionary.isEmpty()) ? 0 : dictionary.lastKey();
|
throw new IllegalStateException("unsupported datatype - currently String,Short,Integer,Long,Float,Double,Boolean,BigInteger(unsigned long),Date can be processed.");
|
||||||
long nextKey = Math.max(lastKey,PropertyIDMap.PID_MAX)+1;
|
|
||||||
customProperty.setID(nextKey);
|
|
||||||
}
|
}
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @see java.util.HashSet#remove(java.lang.Object)
|
|
||||||
*/
|
|
||||||
public Object remove(final String name) {
|
|
||||||
final Long id = dictionary.removeValue(name);
|
|
||||||
return super.remove(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a named string property.
|
* Gets a named value from the custom properties - only works for keys of type String
|
||||||
*
|
*
|
||||||
* @param name The property's name.
|
* @param key the name of the value to get
|
||||||
* @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 String value) {
|
|
||||||
final Property p = new MutableProperty(-1, Variant.VT_LPSTR, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* @return the value or {@code null} if a value with the specified
|
||||||
* name is not found in the custom properties.
|
* name is not found in the custom properties.
|
||||||
*/
|
*/
|
||||||
public Object get(final String name) {
|
@Override
|
||||||
final Long id = dictionary.getKey(name);
|
public Object get(final Object key) {
|
||||||
final CustomProperty cp = super.get(id);
|
final Long id = dictionary.getKey(key);
|
||||||
|
final CustomProperty cp = props.get(id);
|
||||||
return cp != null ? cp.getValue() : null;
|
return cp != null ? cp.getValue() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CustomProperty remove(Object key) {
|
||||||
|
final Long id = dictionary.removeValue(key);
|
||||||
|
return props.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return props.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return props.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
props.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return props.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a named date property.
|
* @return the list of properties
|
||||||
*
|
|
||||||
* @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 Date value) {
|
public List<CustomProperty> properties() {
|
||||||
final Property p = new MutableProperty(-1, Variant.VT_FILETIME, value);
|
List<CustomProperty> list = new ArrayList<CustomProperty>(props.size());
|
||||||
return put(new CustomProperty(p, name));
|
for (Long l : dictionary.keySet()) {
|
||||||
|
list.add(props.get(l));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the list of property values - use {@link #properties()} for the wrapped values
|
||||||
|
*/
|
||||||
|
@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
|
@Override
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public Set keySet() {
|
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
|
* @return a set of all the names of our custom properties
|
||||||
*/
|
*/
|
||||||
public Set<String> nameSet() {
|
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
|
* @return a set of all the IDs of our custom properties
|
||||||
*/
|
*/
|
||||||
public Set<String> idSet() {
|
public Set<Long> idSet() {
|
||||||
return dictionary.values();
|
return Collections.unmodifiableSet(dictionary.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -321,10 +321,10 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
if(value instanceof CustomProperty) {
|
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) {
|
if(cp.getValue() == value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -354,6 +354,36 @@ public class CustomProperties extends HashMap<Long,CustomProperty> {
|
|||||||
this.isPure = 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) {
|
private void checkCodePage(String value) {
|
||||||
int cp = getCodepage();
|
int cp = getCodepage();
|
||||||
if (cp == -1) {
|
if (cp == -1) {
|
||||||
|
@ -801,7 +801,7 @@ public class DocumentSummaryInformation extends SpecialPropertySet {
|
|||||||
customProperties.setCodepage(cpCodepage);
|
customProperties.setCodepage(cpCodepage);
|
||||||
section.setCodepage(cpCodepage);
|
section.setCodepage(cpCodepage);
|
||||||
section.setDictionary(dictionary);
|
section.setDictionary(dictionary);
|
||||||
for (CustomProperty p : customProperties.values()) {
|
for (CustomProperty p : customProperties.properties()) {
|
||||||
section.setProperty(p);
|
section.setProperty(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,9 +218,9 @@ public class TestReadAllFiles {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CustomProperty cp : cps.values()) {
|
for (CustomProperty cp : cps.properties()) {
|
||||||
cp.getName();
|
assertNotNull(cp.getName());
|
||||||
cp.getValue();
|
assertNotNull(cp.getValue());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
poifs.close();
|
poifs.close();
|
||||||
|
Loading…
Reference in New Issue
Block a user