diff options
Diffstat (limited to 'XMPCore/src/com/adobe/xmp/XMPUtils.java')
-rw-r--r-- | XMPCore/src/com/adobe/xmp/XMPUtils.java | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/XMPCore/src/com/adobe/xmp/XMPUtils.java b/XMPCore/src/com/adobe/xmp/XMPUtils.java new file mode 100644 index 0000000..043d533 --- /dev/null +++ b/XMPCore/src/com/adobe/xmp/XMPUtils.java @@ -0,0 +1,506 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2006 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +package com.adobe.xmp; + +import com.adobe.xmp.impl.Base64; +import com.adobe.xmp.impl.ISO8601Converter; +import com.adobe.xmp.impl.XMPUtilsImpl; +import com.adobe.xmp.options.PropertyOptions; + + +/** + * Utility methods for XMP. I included only those that are different from the + * Java default conversion utilities. + * + * @since 21.02.2006 + */ +public class XMPUtils +{ + /** Private constructor */ + private XMPUtils() + { + // EMPTY + } + + + /** + * Create a single edit string from an array of strings. + * + * @param xmp + * The XMP object containing the array to be catenated. + * @param schemaNS + * The schema namespace URI for the array. Must not be null or + * the empty string. + * @param arrayName + * The name of the array. May be a general path expression, must + * not be null or the empty string. Each item in the array must + * be a simple string value. + * @param separator + * The string to be used to separate the items in the catenated + * string. Defaults to "; ", ASCII semicolon and space + * (U+003B, U+0020). + * @param quotes + * The characters to be used as quotes around array items that + * contain a separator. Defaults to '"' + * @param allowCommas + * Option flag to control the catenation. + * @return Returns the string containing the catenated array items. + * @throws XMPException Forwards the Exceptions from the metadata processing + */ + public static String catenateArrayItems(XMPMeta xmp, String schemaNS, String arrayName, + String separator, String quotes, boolean allowCommas) throws XMPException + { + return XMPUtilsImpl + .catenateArrayItems(xmp, schemaNS, arrayName, separator, quotes, allowCommas); + } + + + /** + * Separate a single edit string into an array of strings. + * + * @param xmp + * The XMP object containing the array to be updated. + * @param schemaNS + * The schema namespace URI for the array. Must not be null or + * the empty string. + * @param arrayName + * The name of the array. May be a general path expression, must + * not be null or the empty string. Each item in the array must + * be a simple string value. + * @param catedStr + * The string to be separated into the array items. + * @param arrayOptions Option flags to control the separation. + * @param preserveCommas Flag if commas shall be preserved + * @throws XMPException Forwards the Exceptions from the metadata processing + */ + public static void separateArrayItems(XMPMeta xmp, String schemaNS, String arrayName, + String catedStr, PropertyOptions arrayOptions, boolean preserveCommas) + throws XMPException + { + XMPUtilsImpl.separateArrayItems(xmp, schemaNS, arrayName, catedStr, arrayOptions, + preserveCommas); + } + + + /** + * Remove multiple properties from an XMP object. + * + * RemoveProperties was created to support the File Info dialog's Delete + * button, and has been been generalized somewhat from those specific needs. + * It operates in one of three main modes depending on the schemaNS and + * propName parameters: + * + * <ul> + * <li> Non-empty <code>schemaNS</code> and <code>propName</code> - The named property is + * removed if it is an external property, or if the + * flag <code>doAllProperties</code> option is true. It does not matter whether the + * named property is an actual property or an alias. + * + * <li> Non-empty <code>schemaNS</code> and empty <code>propName</code> - The all external + * properties in the named schema are removed. Internal properties are also + * removed if the flag <code>doAllProperties</code> option is set. In addition, + * aliases from the named schema will be removed if the flag <code>includeAliases</code> + * option is set. + * + * <li> Empty <code>schemaNS</code> and empty <code>propName</code> - All external properties in + * all schema are removed. Internal properties are also removed if the + * flag <code>doAllProperties</code> option is passed. Aliases are implicitly handled + * because the associated actuals are internal if the alias is. + * </ul> + * + * It is an error to pass an empty <code>schemaNS</code> and non-empty <code>propName</code>. + * + * @param xmp + * The XMP object containing the properties to be removed. + * + * @param schemaNS + * Optional schema namespace URI for the properties to be + * removed. + * + * @param propName + * Optional path expression for the property to be removed. + * + * @param doAllProperties Option flag to control the deletion: do internal properties in + * addition to external properties. + * + * @param includeAliases Option flag to control the deletion: + * Include aliases in the "named schema" case above. + * <em>Note:</em> Currently not supported. + * @throws XMPException Forwards the Exceptions from the metadata processing + */ + public static void removeProperties(XMPMeta xmp, String schemaNS, String propName, + boolean doAllProperties, boolean includeAliases) throws XMPException + { + XMPUtilsImpl.removeProperties(xmp, schemaNS, propName, doAllProperties, includeAliases); + } + + + + /** + * Alias without the new option <code>deleteEmptyValues</code>. + * @param source The source XMP object. + * @param dest The destination XMP object. + * @param doAllProperties Do internal properties in addition to external properties. + * @param replaceOldValues Replace the values of existing properties. + * @throws XMPException Forwards the Exceptions from the metadata processing + */ + public static void appendProperties(XMPMeta source, XMPMeta dest, boolean doAllProperties, + boolean replaceOldValues) throws XMPException + { + appendProperties(source, dest, doAllProperties, replaceOldValues, false); + } + + + /** + * <p>Append properties from one XMP object to another. + * + * <p>XMPUtils#appendProperties was created to support the File Info dialog's Append button, and + * has been been generalized somewhat from those specific needs. It appends information from one + * XMP object (source) to another (dest). The default operation is to append only external + * properties that do not already exist in the destination. The flag + * <code>doAllProperties</code> can be used to operate on all properties, external and internal. + * The flag <code>replaceOldValues</code> option can be used to replace the values + * of existing properties. The notion of external + * versus internal applies only to top level properties. The keep-or-replace-old notion applies + * within structs and arrays as described below. + * <ul> + * <li>If <code>replaceOldValues</code> is true then the processing is restricted to the top + * level properties. The processed properties from the source (according to + * <code>doAllProperties</code>) are propagated to the destination, + * replacing any existing values.Properties in the destination that are not in the source + * are left alone. + * + * <li>If <code>replaceOldValues</code> is not passed then the processing is more complicated. + * Top level properties are added to the destination if they do not already exist. + * If they do exist but differ in form (simple/struct/array) then the destination is left alone. + * If the forms match, simple properties are left unchanged while structs and arrays are merged. + * + * <li>If <code>deleteEmptyValues</code> is passed then an empty value in the source XMP causes + * the corresponding destination XMP property to be deleted. The default is to treat empty + * values the same as non-empty values. An empty value is any of a simple empty string, an array + * with no items, or a struct with no fields. Qualifiers are ignored. + * </ul> + * + * <p>The detailed behavior is defined by the following pseudo-code: + * <blockquote> + * <pre> + * appendProperties ( sourceXMP, destXMP, doAllProperties, + * replaceOldValues, deleteEmptyValues ): + * for all source schema (top level namespaces): + * for all top level properties in sourceSchema: + * if doAllProperties or prop is external: + * appendSubtree ( sourceNode, destSchema, replaceOldValues, deleteEmptyValues ) + * + * appendSubtree ( sourceNode, destParent, replaceOldValues, deleteEmptyValues ): + * if deleteEmptyValues and source value is empty: + * delete the corresponding child from destParent + * else if sourceNode not in destParent (by name): + * copy sourceNode's subtree to destParent + * else if replaceOld: + * delete subtree from destParent + * copy sourceNode's subtree to destParent + * else: + * // Already exists in dest and not replacing, merge structs and arrays + * if sourceNode and destNode forms differ: + * return, leave the destNode alone + * else if form is a struct: + * for each field in sourceNode: + * AppendSubtree ( sourceNode.field, destNode, replaceOldValues ) + * else if form is an alt-text array: + * copy new items by "xml:lang" value into the destination + * else if form is an array: + * copy new items by value into the destination, ignoring order and duplicates + * </pre> + * </blockquote> + * + * <p><em>Note:</em> appendProperties can be expensive if replaceOldValues is not passed and + * the XMP contains large arrays. The array item checking described above is n-squared. + * Each source item is checked to see if it already exists in the destination, + * without regard to order or duplicates. + * <p>Simple items are compared by value and "xml:lang" qualifier, other qualifiers are ignored. + * Structs are recursively compared by field names, without regard to field order. Arrays are + * compared by recursively comparing all items. + * + * @param source The source XMP object. + * @param dest The destination XMP object. + * @param doAllProperties Do internal properties in addition to external properties. + * @param replaceOldValues Replace the values of existing properties. + * @param deleteEmptyValues Delete destination values if source property is empty. + * @throws XMPException Forwards the Exceptions from the metadata processing + */ + public static void appendProperties(XMPMeta source, XMPMeta dest, boolean doAllProperties, + boolean replaceOldValues, boolean deleteEmptyValues) throws XMPException + { + XMPUtilsImpl.appendProperties(source, dest, doAllProperties, replaceOldValues, + deleteEmptyValues); + } + + + /** + * Convert from string to Boolean. + * + * @param value + * The string representation of the Boolean. + * @return The appropriate boolean value for the string. The checked values + * for <code>true</code> and <code>false</code> are: + * <ul> + * <li>{@link XMPConst#TRUESTR} and {@link XMPConst#FALSESTR} + * <li>"t" and "f" + * <li>"on" and "off" + * <li>"yes" and "no" + * <li>"value <> 0" and "value == 0" + * </ul> + * @throws XMPException If an empty string is passed. + */ + public static boolean convertToBoolean(String value) throws XMPException + { + if (value == null || value.length() == 0) + { + throw new XMPException("Empty convert-string", XMPError.BADVALUE); + } + value = value.toLowerCase(); + + try + { + // First try interpretation as Integer (anything not 0 is true) + return Integer.parseInt(value) != 0; + } + catch (NumberFormatException e) + { + return + "true".equals(value) || + "t".equals(value) || + "on".equals(value) || + "yes".equals(value); + } + } + + + /** + * Convert from boolean to string. + * + * @param value + * a boolean value + * @return The XMP string representation of the boolean. The values used are + * given by the constnts {@link XMPConst#TRUESTR} and + * {@link XMPConst#FALSESTR}. + */ + public static String convertFromBoolean(boolean value) + { + return value ? XMPConst.TRUESTR : XMPConst.FALSESTR; + } + + + /** + * Converts a string value to an <code>int</code>. + * + * @param rawValue + * the string value + * @return Returns an int. + * @throws XMPException + * If the <code>rawValue</code> is <code>null</code> or empty or the + * conversion fails. + */ + public static int convertToInteger(String rawValue) throws XMPException + { + try + { + if (rawValue == null || rawValue.length() == 0) + { + throw new XMPException("Empty convert-string", XMPError.BADVALUE); + } + if (rawValue.startsWith("0x")) + { + return Integer.parseInt(rawValue.substring(2), 16); + } + else + { + return Integer.parseInt(rawValue); + } + } + catch (NumberFormatException e) + { + throw new XMPException("Invalid integer string", XMPError.BADVALUE); + } + } + + + /** + * Convert from int to string. + * + * @param value + * an int value + * @return The string representation of the int. + */ + public static String convertFromInteger(int value) + { + return String.valueOf(value); + } + + + /** + * Converts a string value to a <code>long</code>. + * + * @param rawValue + * the string value + * @return Returns a long. + * @throws XMPException + * If the <code>rawValue</code> is <code>null</code> or empty or the + * conversion fails. + */ + public static long convertToLong(String rawValue) throws XMPException + { + try + { + if (rawValue == null || rawValue.length() == 0) + { + throw new XMPException("Empty convert-string", XMPError.BADVALUE); + } + if (rawValue.startsWith("0x")) + { + return Long.parseLong(rawValue.substring(2), 16); + } + else + { + return Long.parseLong(rawValue); + } + } + catch (NumberFormatException e) + { + throw new XMPException("Invalid long string", XMPError.BADVALUE); + } + } + + + /** + * Convert from long to string. + * + * @param value + * a long value + * @return The string representation of the long. + */ + public static String convertFromLong(long value) + { + return String.valueOf(value); + } + + + /** + * Converts a string value to a <code>double</code>. + * + * @param rawValue + * the string value + * @return Returns a double. + * @throws XMPException + * If the <code>rawValue</code> is <code>null</code> or empty or the + * conversion fails. + */ + public static double convertToDouble(String rawValue) throws XMPException + { + try + { + if (rawValue == null || rawValue.length() == 0) + { + throw new XMPException("Empty convert-string", XMPError.BADVALUE); + } + else + { + return Double.parseDouble(rawValue); + } + } + catch (NumberFormatException e) + { + throw new XMPException("Invalid double string", XMPError.BADVALUE); + } + } + + + /** + * Convert from long to string. + * + * @param value + * a long value + * @return The string representation of the long. + */ + public static String convertFromDouble(double value) + { + return String.valueOf(value); + } + + + /** + * Converts a string value to an <code>XMPDateTime</code>. + * + * @param rawValue + * the string value + * @return Returns an <code>XMPDateTime</code>-object. + * @throws XMPException + * If the <code>rawValue</code> is <code>null</code> or empty or the + * conversion fails. + */ + public static XMPDateTime convertToDate(String rawValue) throws XMPException + { + if (rawValue == null || rawValue.length() == 0) + { + throw new XMPException("Empty convert-string", XMPError.BADVALUE); + } + else + { + return ISO8601Converter.parse(rawValue); + } + } + + + /** + * Convert from <code>XMPDateTime</code> to string. + * + * @param value + * an <code>XMPDateTime</code> + * @return The string representation of the long. + */ + public static String convertFromDate(XMPDateTime value) + { + return ISO8601Converter.render(value); + } + + + /** + * Convert from a byte array to a base64 encoded string. + * + * @param buffer + * the byte array to be converted + * @return Returns the base64 string. + */ + public static String encodeBase64(byte[] buffer) + { + return new String(Base64.encode(buffer)); + } + + + /** + * Decode from Base64 encoded string to raw data. + * + * @param base64String + * a base64 encoded string + * @return Returns a byte array containg the decoded string. + * @throws XMPException Thrown if the given string is not property base64 encoded + */ + public static byte[] decodeBase64(String base64String) throws XMPException + { + try + { + return Base64.decode(base64String.getBytes()); + } + catch (Throwable e) + { + throw new XMPException("Invalid base64 string", XMPError.BADVALUE, e); + } + } +}
\ No newline at end of file |