/components/forks/poi/src/loci/poi/hpsf/CustomProperties.java
Java | 391 lines | 156 code | 42 blank | 193 comment | 16 complexity | f1e598413903d1dc0b1adc5794c23463 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, BSD-2-Clause, MPL-2.0-no-copyleft-exception
- /*
- * #%L
- * Fork of Apache Jakarta POI.
- * %%
- * Copyright (C) 2008 - 2013 Open Microscopy Environment:
- * - Board of Regents of the University of Wisconsin-Madison
- * - Glencoe Software, Inc.
- * - University of Dundee
- * %%
- * Licensed 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.
- * #L%
- */
- /* ====================================================================
- 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 loci.poi.hpsf;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import loci.poi.hpsf.wellknown.PropertyIDMap;
- /**
- * <p>Maintains the instances of {@link CustomProperty} that belong to a
- * {@link DocumentSummaryInformation}. The class maintains the names of the
- * custom properties in a dictionary. It implements the {@link Map} interface
- * and by this provides a simplified view on custom properties: A property's
- * name is the key that maps to a typed value. This implementation hides
- * property IDs from the developer and regards the property names as keys to
- * typed values.</p>
- *
- * <p>While this class provides a simple API to custom properties, it ignores
- * the fact that not names, but IDs are the real keys to properties. Under the
- * hood this class maintains a 1:1 relationship between IDs and names. Therefore
- * you should not use this class to process property sets with several IDs
- * mapping to the same name or with properties without a name: the result will
- * contain only a subset of the original properties. If you really need to deal
- * such property sets, use HPSF's low-level access methods.</p>
- *
- * <p>An application can call the {@link #isPure} method to check whether a
- * property set parsed by {@link CustomProperties} is still pure (i.e.
- * unmodified) or whether one or more properties have been dropped.</p>
- *
- * <p>This class is not thread-safe; concurrent access to instances of this
- * class must be syncronized.</p>
- *
- * @author Rainer Klute <a
- * href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
- * @since 2006-02-09
- * @version $Id$
- */
- public class CustomProperties extends HashMap
- {
- /**
- * <p>Maps property IDs to property names.</p>
- */
- private Map dictionaryIDToName = new HashMap();
- /**
- * <p>Maps property names to property IDs.</p>
- */
- private Map dictionaryNameToID = new HashMap();
-
- /**
- * <p>Tells whether this object is pure or not.</p>
- */
- private boolean isPure = true;
- /**
- * <p>Puts a {@link CustomProperty} into this map. It is assumed that the
- * {@link CustomProperty} already has a valid ID. Otherwise use
- * {@link #put(CustomProperty)}.</p>
- */
- public Object put(final Object name, final Object customProperty) throws ClassCastException
- {
- final CustomProperty cp = (CustomProperty) customProperty;
- if (name == null)
- {
- /* Ignoring a property without a name. */
- isPure = false;
- return null;
- }
- if (!(name instanceof String))
- throw new ClassCastException("The name of a custom property must " +
- "be a java.lang.String, but it is a " +
- name.getClass().getName());
- if (!(name.equals(cp.getName())))
- throw new IllegalArgumentException("Parameter \"name\" (" + name +
- ") and custom property's name (" + cp.getName() +
- ") do not match.");
- /* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a */
- final Long idKey = new Long(cp.getID());
- final Object oldID = dictionaryNameToID.get(name);
- dictionaryIDToName.remove(oldID);
- dictionaryNameToID.put(name, idKey);
- dictionaryIDToName.put(idKey, name);
- /* Put the custom property into this map. */
- final Object oldCp = super.remove(oldID);
- super.put(idKey, cp);
- return oldCp;
- }
- /**
- * <p>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:</p>
- *
- * <ul>
- *
- * <li><p>If there is already a property with the same name, take the ID
- * of that property.</p></li>
- *
- * <li><p>Otherwise find the highest ID and use its value plus one.</p></li>
- *
- * </ul>
- *
- * @param customProperty
- * @return If the was already a property with the same name, the
- * @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 = (Long) dictionaryNameToID.get(name);
- if (oldId != null)
- customProperty.setID(oldId.longValue());
- else
- {
- long max = 1;
- for (final Iterator i = dictionaryIDToName.keySet().iterator(); i.hasNext();)
- {
- final long id = ((Long) i.next()).longValue();
- if (id > max)
- max = id;
- }
- customProperty.setID(max + 1);
- }
- return this.put(name, customProperty);
- }
- /**
- * <p>Removes a custom property.</p>
- * @param name The name of the custom property to remove
- * @return The removed property or <code>null</code> if the specified property was not found.
- *
- * @see java.util.HashSet#remove(java.lang.Object)
- */
- public Object remove(final String name)
- {
- final Long id = (Long) dictionaryNameToID.get(name);
- if (id == null)
- return null;
- dictionaryIDToName.remove(id);
- dictionaryNameToID.remove(name);
- return super.remove(id);
- }
- /**
- * <p>Adds a named string property.</p>
- *
- * @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</code> if there was no such property before.
- */
- public Object put(final String name, final String value)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(-1);
- p.setType(Variant.VT_LPWSTR);
- p.setValue(value);
- final CustomProperty cp = new CustomProperty(p, name);
- return put(cp);
- }
- /**
- * <p>Adds a named long property.</p>
- *
- * @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</code> if there was no such property before.
- */
- public Object put(final String name, final Long value)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(-1);
- p.setType(Variant.VT_I8);
- p.setValue(value);
- final CustomProperty cp = new CustomProperty(p, name);
- return put(cp);
- }
- /**
- * <p>Adds a named double property.</p>
- *
- * @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</code> if there was no such property before.
- */
- public Object put(final String name, final Double value)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(-1);
- p.setType(Variant.VT_R8);
- p.setValue(value);
- final CustomProperty cp = new CustomProperty(p, name);
- return put(cp);
- }
- /**
- * <p>Adds a named integer property.</p>
- *
- * @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</code> if there was no such property before.
- */
- public Object put(final String name, final Integer value)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(-1);
- p.setType(Variant.VT_I4);
- p.setValue(value);
- final CustomProperty cp = new CustomProperty(p, name);
- return put(cp);
- }
- /**
- * <p>Adds a named boolean property.</p>
- *
- * @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</code> if there was no such property before.
- */
- public Object put(final String name, final Boolean value)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(-1);
- p.setType(Variant.VT_BOOL);
- p.setValue(value);
- final CustomProperty cp = new CustomProperty(p, name);
- return put(cp);
- }
-
- /**
- * <p>Gets a named value from the custom properties.</p>
- *
- * @param name the name of the value to get
- * @return the value or <code>null</code> if a value with the specified
- * name is not found in the custom properties.
- */
- public Object get(final String name)
- {
- final Long id = (Long) dictionaryNameToID.get(name);
- final CustomProperty cp = (CustomProperty) super.get(id);
- return cp != null ? cp.getValue() : null;
- }
- /**
- * <p>Adds a named date property.</p>
- *
- * @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</code> if there was no such property before.
- */
- public Object put(final String name, final Date value)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(-1);
- p.setType(Variant.VT_FILETIME);
- p.setValue(value);
- final CustomProperty cp = new CustomProperty(p, name);
- return put(cp);
- }
- /**
- * <p>Sets the codepage.</p>
- *
- * @param codepage the codepage
- */
- public void setCodepage(final int codepage)
- {
- final MutableProperty p = new MutableProperty();
- p.setID(PropertyIDMap.PID_CODEPAGE);
- p.setType(Variant.VT_I2);
- p.setValue(new Integer(codepage));
- put(new CustomProperty(p));
- }
- /**
- * <p>Gets the dictionary which contains IDs and names of the named custom
- * properties.
- *
- * @return the dictionary.
- */
- Map getDictionary()
- {
- return dictionaryIDToName;
- }
- /**
- * <p>Gets the codepage.</p>
- *
- * @return the codepage or -1 if the codepage is undefined.
- */
- public int getCodepage()
- {
- int codepage = -1;
- for (final Iterator i = this.values().iterator(); codepage == -1 && i.hasNext();)
- {
- final CustomProperty cp = (CustomProperty) i.next();
- if (cp.getID() == PropertyIDMap.PID_CODEPAGE)
- codepage = ((Integer) cp.getValue()).intValue();
- }
- return codepage;
- }
- /**
- * <p>Tells whether this {@link CustomProperties} instance is pure or one or
- * more properties of the underlying low-level property set has been
- * dropped.</p>
- *
- * @return <code>true</code> if the {@link CustomProperties} is pure, else
- * <code>false</code>.
- */
- public boolean isPure()
- {
- return isPure;
- }
- /**
- * <p>Sets the purity of the custom property set.</p>
- *
- * @param isPure the purity
- */
- public void setPure(final boolean isPure)
- {
- this.isPure = isPure;
- }
- }