1f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// =================================================================================================
2f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// ADOBE SYSTEMS INCORPORATED
3f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// Copyright 2006 Adobe Systems Incorporated
4f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// All Rights Reserved
5f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling//
6f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
7f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// of the Adobe license agreement accompanying it.
8f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// =================================================================================================
9f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
10f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingpackage com.adobe.xmp;
11f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
12f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.impl.Base64;
13f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.impl.ISO8601Converter;
14f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.impl.XMPUtilsImpl;
15f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.options.PropertyOptions;
16f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
17f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
18f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling/**
19f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Utility methods for XMP. I included only those that are different from the
20f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Java default conversion utilities.
21f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling *
22f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @since 21.02.2006
23f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */
24f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingpublic class XMPUtils
25f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling{
26f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** Private constructor */
27f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private XMPUtils()
28f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
29f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// EMPTY
30f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
31f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
32f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
33f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
34f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Create a single edit string from an array of strings.
35f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
36f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param xmp
37f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The XMP object containing the array to be catenated.
38f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param schemaNS
39f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The schema namespace URI for the array. Must not be null or
40f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the empty string.
41f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param arrayName
42f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The name of the array. May be a general path expression, must
43f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            not be null or the empty string. Each item in the array must
44f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            be a simple string value.
45f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param separator
46f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The string to be used to separate the items in the catenated
47f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            string. Defaults to "; ", ASCII semicolon and space
48f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            (U+003B, U+0020).
49f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param quotes
50f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The characters to be used as quotes around array items that
51f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            contain a separator. Defaults to '"'
52f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param allowCommas
53f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            Option flag to control the catenation.
54f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns the string containing the catenated array items.
55f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException Forwards the Exceptions from the metadata processing
56f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
57f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String catenateArrayItems(XMPMeta xmp, String schemaNS, String arrayName,
58f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String separator, String quotes, boolean allowCommas) throws XMPException
59f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
60f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return XMPUtilsImpl
61f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				.catenateArrayItems(xmp, schemaNS, arrayName, separator, quotes, allowCommas);
62f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
63f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
64f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
65f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
66f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Separate a single edit string into an array of strings.
67f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
68f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param xmp
69f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The XMP object containing the array to be updated.
70f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param schemaNS
71f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The schema namespace URI for the array. Must not be null or
72f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the empty string.
73f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param arrayName
74f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The name of the array. May be a general path expression, must
75f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            not be null or the empty string. Each item in the array must
76f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            be a simple string value.
77f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param catedStr
78f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The string to be separated into the array items.
79f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param arrayOptions Option flags to control the separation.
80f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param preserveCommas Flag if commas shall be preserved
81f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException Forwards the Exceptions from the metadata processing
82f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
83f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static void separateArrayItems(XMPMeta xmp, String schemaNS, String arrayName,
84f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String catedStr, PropertyOptions arrayOptions, boolean preserveCommas)
85f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throws XMPException
86f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
87f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPUtilsImpl.separateArrayItems(xmp, schemaNS, arrayName, catedStr, arrayOptions,
88f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				preserveCommas);
89f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
90f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
91f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
92f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
93f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Remove multiple properties from an XMP object.
94f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
95f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * RemoveProperties was created to support the File Info dialog's Delete
96f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * button, and has been been generalized somewhat from those specific needs.
97f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * It operates in one of three main modes depending on the schemaNS and
98f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * propName parameters:
99f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
100f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <ul>
101f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <li> Non-empty <code>schemaNS</code> and <code>propName</code> - The named property is
102f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * removed if it is an external property, or if the
103f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * flag <code>doAllProperties</code> option is true. It does not matter whether the
104f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * named property is an actual property or an alias.
105f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
106f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <li> Non-empty <code>schemaNS</code> and empty <code>propName</code> - The all external
107f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * properties in the named schema are removed. Internal properties are also
108f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * removed if the flag <code>doAllProperties</code> option is set. In addition,
109f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * aliases from the named schema will be removed if the flag <code>includeAliases</code>
110f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * option is set.
111f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
112f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <li> Empty <code>schemaNS</code> and empty <code>propName</code> - All external properties in
113f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * all schema are removed. Internal properties are also removed if the
114f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * flag <code>doAllProperties</code> option is passed. Aliases are implicitly handled
115f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * because the associated actuals are internal if the alias is.
116f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * </ul>
117f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
118f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * It is an error to pass an empty <code>schemaNS</code> and non-empty <code>propName</code>.
119f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
120f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param xmp
121f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The XMP object containing the properties to be removed.
122f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
123f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param schemaNS
124f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            Optional schema namespace URI for the properties to be
125f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            removed.
126f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
127f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param propName
128f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            Optional path expression for the property to be removed.
129f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
130f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param doAllProperties Option flag to control the deletion: do internal properties in
131f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *          addition to external properties.
132f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
133f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param includeAliases Option flag to control the deletion:
134f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * 			Include aliases in the "named schema" case above.
135f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * 			<em>Note:</em> Currently not supported.
136f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException Forwards the Exceptions from the metadata processing
137f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
138f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static void removeProperties(XMPMeta xmp, String schemaNS, String propName,
139f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			boolean doAllProperties, boolean includeAliases) throws XMPException
140f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
141f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPUtilsImpl.removeProperties(xmp, schemaNS, propName, doAllProperties, includeAliases);
142f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
143f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
144f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
145f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
146f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
147f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Alias without the new option <code>deleteEmptyValues</code>.
148f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param source The source XMP object.
149f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param dest The destination XMP object.
150f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param doAllProperties Do internal properties in addition to external properties.
151f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param replaceOldValues Replace the values of existing properties.
152f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException Forwards the Exceptions from the metadata processing
153f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
154f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static void appendProperties(XMPMeta source, XMPMeta dest, boolean doAllProperties,
155f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			boolean replaceOldValues) throws XMPException
156f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
157f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		appendProperties(source, dest, doAllProperties, replaceOldValues, false);
158f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
159f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
160f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
161f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
162f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <p>Append properties from one XMP object to another.
163f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
164f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <p>XMPUtils#appendProperties was created to support the File Info dialog's Append button, and
165f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * has been been generalized somewhat from those specific needs. It appends information from one
166f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * XMP object (source) to another (dest). The default operation is to append only external
167f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * properties that do not already exist in the destination. The flag
168f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <code>doAllProperties</code> can be used to operate on all properties, external and internal.
169f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * The flag <code>replaceOldValues</code> option can be used to replace the values
170f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * of existing properties. The notion of external
171f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * versus internal applies only to top level properties. The keep-or-replace-old notion applies
172f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * within structs and arrays as described below.
173f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <ul>
174f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <li>If <code>replaceOldValues</code> is true then the processing is restricted to the top
175f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * level properties. The processed properties from the source (according to
176f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <code>doAllProperties</code>) are propagated to the destination,
177f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * replacing any existing values.Properties in the destination that are not in the source
178f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * are left alone.
179f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
180f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <li>If <code>replaceOldValues</code> is not passed then the processing is more complicated.
181f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Top level properties are added to the destination if they do not already exist.
182f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * If they do exist but differ in form (simple/struct/array) then the destination is left alone.
183f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * If the forms match, simple properties are left unchanged while structs and arrays are merged.
184f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
185f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <li>If <code>deleteEmptyValues</code> is passed then an empty value in the source XMP causes
186f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * the corresponding destination XMP property to be deleted. The default is to treat empty
187f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * values the same as non-empty values. An empty value is any of a simple empty string, an array
188f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * with no items, or a struct with no fields. Qualifiers are ignored.
189f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * </ul>
190f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
191f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <p>The detailed behavior is defined by the following pseudo-code:
192f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <blockquote>
193f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <pre>
194f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *    appendProperties ( sourceXMP, destXMP, doAllProperties,
195f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *    			replaceOldValues, deleteEmptyValues ):
196f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *       for all source schema (top level namespaces):
197f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *          for all top level properties in sourceSchema:
198f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *             if doAllProperties or prop is external:
199f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *                appendSubtree ( sourceNode, destSchema, replaceOldValues, deleteEmptyValues )
200f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *
201f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *    appendSubtree ( sourceNode, destParent, replaceOldValues, deleteEmptyValues ):
202f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *        if deleteEmptyValues and source value is empty:
203f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            delete the corresponding child from destParent
204f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *        else if sourceNode not in destParent (by name):
205f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *           copy sourceNode's subtree to destParent
206f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *        else if replaceOld:
207f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            delete subtree from destParent
208f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            copy sourceNode's subtree to destParent
209f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *        else:
210f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            // Already exists in dest and not replacing, merge structs and arrays
211f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            if sourceNode and destNode forms differ:
212f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *                return, leave the destNode alone
213f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            else if form is a struct:
214f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *                for each field in sourceNode:
215f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *                    AppendSubtree ( sourceNode.field, destNode, replaceOldValues )
216f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            else if form is an alt-text array:
217f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *                copy new items by "xml:lang" value into the destination
218f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *            else if form is an array:
219f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     *                copy new items by value into the destination, ignoring order and duplicates
220f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling     * </pre>
221f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * </blockquote>
222f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
223f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <p><em>Note:</em> appendProperties can be expensive if replaceOldValues is not passed and
224f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * the XMP contains large arrays. The array item checking described above is n-squared.
225f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Each source item is checked to see if it already exists in the destination,
226f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * without regard to order or duplicates.
227f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * <p>Simple items are compared by value and "xml:lang" qualifier, other qualifiers are ignored.
228f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Structs are recursively compared by field names, without regard to field order. Arrays are
229f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * compared by recursively comparing all items.
230f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
231f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param source The source XMP object.
232f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param dest The destination XMP object.
233f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param doAllProperties Do internal properties in addition to external properties.
234f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param replaceOldValues Replace the values of existing properties.
235f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param deleteEmptyValues Delete destination values if source property is empty.
236f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException Forwards the Exceptions from the metadata processing
237f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
238f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static void appendProperties(XMPMeta source, XMPMeta dest, boolean doAllProperties,
239f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			boolean replaceOldValues, boolean deleteEmptyValues) throws XMPException
240f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
241f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPUtilsImpl.appendProperties(source, dest, doAllProperties, replaceOldValues,
242f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			deleteEmptyValues);
243f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
244f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
245f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
246f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
247f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Convert from string to Boolean.
248f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
249f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
250f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            The string representation of the Boolean.
251f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return The appropriate boolean value for the string. The checked values
252f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *         for <code>true</code> and <code>false</code> are:
253f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *         <ul>
254f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *    	    	<li>{@link XMPConst#TRUESTR} and {@link XMPConst#FALSESTR}
255f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *    		    <li>&quot;t&quot; and &quot;f&quot;
256f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *    		    <li>&quot;on&quot; and &quot;off&quot;
257f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *    		    <li>&quot;yes&quot; and &quot;no&quot;
258f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *   		  	<li>&quot;value <> 0&quot; and &quot;value == 0&quot;
259f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *         </ul>
260f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException If an empty string is passed.
261f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
262f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static boolean convertToBoolean(String value) throws XMPException
263f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
264f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (value == null  ||  value.length() == 0)
265f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
266f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Empty convert-string", XMPError.BADVALUE);
267f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
268f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		value = value.toLowerCase();
269f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
270f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
271f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
272f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// First try interpretation as Integer (anything not 0 is true)
273f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return Integer.parseInt(value) != 0;
274f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
275f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (NumberFormatException e)
276f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
277f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return
278f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				"true".equals(value)  ||
279f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				"t".equals(value)  ||
280f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				"on".equals(value)  ||
281f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				"yes".equals(value);
282f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
283f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
284f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
285f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
286f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
287f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Convert from boolean to string.
288f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
289f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
290f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a boolean value
291f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return The XMP string representation of the boolean. The values used are
292f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *         given by the constnts {@link XMPConst#TRUESTR} and
293f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *         {@link XMPConst#FALSESTR}.
294f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
295f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String convertFromBoolean(boolean value)
296f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
297f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return value ? XMPConst.TRUESTR : XMPConst.FALSESTR;
298f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
299f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
300f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
301f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
302f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Converts a string value to an <code>int</code>.
303f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
304f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param rawValue
305f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the string value
306f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns an int.
307f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
308f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             If the <code>rawValue</code> is <code>null</code> or empty or the
309f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             conversion fails.
310f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
311f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static int convertToInteger(String rawValue) throws XMPException
312f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
313f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
314f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
315f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (rawValue == null  ||  rawValue.length() == 0)
316f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
317f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Empty convert-string", XMPError.BADVALUE);
318f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
319f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (rawValue.startsWith("0x"))
320f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
321f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				return Integer.parseInt(rawValue.substring(2), 16);
322f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
323f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else
324f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
325f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				return Integer.parseInt(rawValue);
326f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
327f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
328f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (NumberFormatException e)
329f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
330f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Invalid integer string", XMPError.BADVALUE);
331f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
332f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
333f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
334f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
335f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
336f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Convert from int to string.
337f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
338f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
339f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            an int value
340f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return The string representation of the int.
341f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
342f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String convertFromInteger(int value)
343f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
344f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return String.valueOf(value);
345f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
346f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
347f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
348f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
349f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Converts a string value to a <code>long</code>.
350f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
351f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param rawValue
352f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the string value
353f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns a long.
354f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
355f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             If the <code>rawValue</code> is <code>null</code> or empty or the
356f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             conversion fails.
357f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
358f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static long convertToLong(String rawValue) throws XMPException
359f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
360f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
361f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
362f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (rawValue == null  ||  rawValue.length() == 0)
363f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
364f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Empty convert-string", XMPError.BADVALUE);
365f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
366f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (rawValue.startsWith("0x"))
367f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
368f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				return Long.parseLong(rawValue.substring(2), 16);
369f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
370f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else
371f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
372f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				return Long.parseLong(rawValue);
373f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
374f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
375f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (NumberFormatException e)
376f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
377f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Invalid long string", XMPError.BADVALUE);
378f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
379f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
380f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
381f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
382f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
383f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Convert from long to string.
384f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
385f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
386f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a long value
387f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return The string representation of the long.
388f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
389f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String convertFromLong(long value)
390f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
391f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return String.valueOf(value);
392f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
393f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
394f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
395f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
396f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Converts a string value to a <code>double</code>.
397f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
398f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param rawValue
399f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the string value
400f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns a double.
401f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
402f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             If the <code>rawValue</code> is <code>null</code> or empty or the
403f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             conversion fails.
404f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
405f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static double convertToDouble(String rawValue) throws XMPException
406f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
407f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
408f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
409f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (rawValue == null  ||  rawValue.length() == 0)
410f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
411f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Empty convert-string", XMPError.BADVALUE);
412f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
413f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else
414f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
415f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				return Double.parseDouble(rawValue);
416f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
417f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
418f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (NumberFormatException e)
419f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
420f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Invalid double string", XMPError.BADVALUE);
421f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
422f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
423f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
424f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
425f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
426f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Convert from long to string.
427f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
428f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
429f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a long value
430f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return The string representation of the long.
431f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
432f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String convertFromDouble(double value)
433f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
434f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return String.valueOf(value);
435f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
436f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
437f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
438f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
439f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Converts a string value to an <code>XMPDateTime</code>.
440f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
441f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param rawValue
442f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the string value
443f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns an <code>XMPDateTime</code>-object.
444f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
445f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             If the <code>rawValue</code> is <code>null</code> or empty or the
446f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             conversion fails.
447f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
448f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static XMPDateTime convertToDate(String rawValue) throws XMPException
449f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
450f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (rawValue == null  ||  rawValue.length() == 0)
451f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
452f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Empty convert-string", XMPError.BADVALUE);
453f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
454f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
455f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
456f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return ISO8601Converter.parse(rawValue);
457f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
458f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
459f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
460f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
461f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
462f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Convert from <code>XMPDateTime</code> to string.
463f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
464f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
465f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            an <code>XMPDateTime</code>
466f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return The string representation of the long.
467f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
468f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String convertFromDate(XMPDateTime value)
469f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
470f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return ISO8601Converter.render(value);
471f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
472f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
473f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
474f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 /**
475f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	  * Convert from a byte array to a base64 encoded string.
476f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	  *
477f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	  * @param buffer
478f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	  *            the byte array to be converted
479f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	  * @return Returns the base64 string.
480f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	  */
481f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static String encodeBase64(byte[] buffer)
482f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
483f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return new String(Base64.encode(buffer));
484f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
485f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
486f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
487f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
488f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Decode from Base64 encoded string to raw data.
489f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
490f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param base64String
491f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a base64 encoded string
492f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns a byte array containg the decoded string.
493f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException Thrown if the given string is not property base64 encoded
494f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
495f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public static byte[] decodeBase64(String base64String) throws XMPException
496f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
497f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
498f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
499f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return Base64.decode(base64String.getBytes());
500f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
501f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (Throwable e)
502f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
503f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Invalid base64 string", XMPError.BADVALUE, e);
504f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
505f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
506f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling}