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.impl;
11f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
12f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.Calendar;
13f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.Iterator;
14f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
15f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPConst;
16f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPDateTime;
17f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPError;
18f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPException;
19f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPIterator;
20f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPMeta;
21f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPPathFactory;
22f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPUtils;
23f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.impl.xpath.XMPPath;
24f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.impl.xpath.XMPPathParser;
25f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.options.IteratorOptions;
26f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.options.ParseOptions;
27f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.options.PropertyOptions;
28f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.properties.XMPProperty;
29f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
30f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
31f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling/**
32f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Implementation for {@link XMPMeta}.
33f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling *
34f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @since 17.02.2006
35f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */
36f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingpublic class XMPMetaImpl implements XMPMeta, XMPConst
37f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling{
38f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** Property values are Strings by default */
39f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_STRING = 0;
40f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
41f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_BOOLEAN = 1;
42f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
43f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_INTEGER = 2;
44f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
45f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_LONG = 3;
46f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
47f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_DOUBLE = 4;
48f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
49f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_DATE = 5;
50f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
51f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_CALENDAR = 6;
52f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** */
53f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private static final int VALUE_BASE64 = 7;
54f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
55f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** root of the metadata tree */
56f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private XMPNode tree;
57f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/** the xpacket processing instructions content */
58f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private String packetHeader = null;
59f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
60f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
61f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
62f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Constructor for an empty metadata object.
63f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
64f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPMetaImpl()
65f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
66f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// create root node
67f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		tree = new XMPNode(null, null, null);
68f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
69f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
70f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
71f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
72f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Constructor for a cloned metadata tree.
73f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
74f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param tree
75f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            an prefilled metadata tree which fulfills all
76f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            <code>XMPNode</code> contracts.
77f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
78f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPMetaImpl(XMPNode tree)
79f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
80f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		this.tree = tree;
81f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
82f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
83f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
84f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
85f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#appendArrayItem(String, String, PropertyOptions, String,
86f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
87f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
88f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void appendArrayItem(String schemaNS, String arrayName, PropertyOptions arrayOptions,
89f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String itemValue, PropertyOptions itemOptions) throws XMPException
90f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
91f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
92f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(arrayName);
93f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
94f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayOptions == null)
95f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
96f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			arrayOptions = new PropertyOptions();
97f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
98f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (!arrayOptions.isOnlyArrayOptions())
99f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
100f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Only array form flags allowed for arrayOptions",
101f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					XMPError.BADOPTIONS);
102f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
103f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
104f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Check if array options are set correctly.
105f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		arrayOptions = XMPNodeUtils.verifySetOptions(arrayOptions, null);
106f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
107f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
108f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Locate or create the array. If it already exists, make sure the array
109f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// form from the options
110f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// parameter is compatible with the current state.
111f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath arrayPath = XMPPathParser.expandXPath(schemaNS, arrayName);
112f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
113f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
114f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Just lookup, don't try to create.
115f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode arrayNode = XMPNodeUtils.findNode(tree, arrayPath, false, null);
116f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
117f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode != null)
118f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
119f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// The array exists, make sure the form is compatible. Zero
120f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// arrayForm means take what exists.
121f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (!arrayNode.getOptions().isArray())
122f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
123f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("The named property is not an array", XMPError.BADXPATH);
124f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
125f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// if (arrayOptions != null && !arrayOptions.equalArrayTypes(arrayNode.getOptions()))
126f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// {
127f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// throw new XMPException("Mismatch of existing and specified array form", BADOPTIONS);
128f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// }
129f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
130f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
131f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
132f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// The array does not exist, try to create it.
133f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (arrayOptions.isArray())
134f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
135f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				arrayNode = XMPNodeUtils.findNode(tree, arrayPath, true, arrayOptions);
136f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				if (arrayNode == null)
137f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
138f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					throw new XMPException("Failure creating array node", XMPError.BADXPATH);
139f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
140f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
141f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else
142f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
143f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				// array options missing
144f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Explicit arrayOptions required to create new array",
145f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling						XMPError.BADOPTIONS);
146f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
147f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
148f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
149f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		doSetArrayItem(arrayNode, ARRAY_LAST_ITEM, itemValue, itemOptions, true);
150f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
151f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
152f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
153f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
154f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#appendArrayItem(String, String, String)
155f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
156f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void appendArrayItem(String schemaNS, String arrayName, String itemValue)
157f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
158f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
159f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		appendArrayItem(schemaNS, arrayName, null, itemValue, null);
160f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
161f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
162f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
163f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
164f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
165f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#countArrayItems(String, String)
166f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
167f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public int countArrayItems(String schemaNS, String arrayName) throws XMPException
168f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
169f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
170f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(arrayName);
171f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
172f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath arrayPath = XMPPathParser.expandXPath(schemaNS, arrayName);
173f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode arrayNode = XMPNodeUtils.findNode(tree, arrayPath, false, null);
174f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
175f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode == null)
176f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
177f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return 0;
178f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
179f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
180f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode.getOptions().isArray())
181f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
182f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return arrayNode.getChildrenLength();
183f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
184f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
185f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
186f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("The named property is not an array", XMPError.BADXPATH);
187f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
188f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
189f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
190f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
191f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
192f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#deleteArrayItem(String, String, int)
193f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
194f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void deleteArrayItem(String schemaNS, String arrayName, int itemIndex)
195f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
196f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
197f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
198f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
199f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertArrayName(arrayName);
200f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
201f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String itemPath = XMPPathFactory.composeArrayItemPath(arrayName, itemIndex);
202f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			deleteProperty(schemaNS, itemPath);
203f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
204f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
205f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
206f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// EMPTY, exceptions are ignored within delete
207f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
208f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
209f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
210f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
211f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
212f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#deleteProperty(String, String)
213f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
214f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void deleteProperty(String schemaNS, String propName)
215f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
216f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
217f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
218f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
219f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertPropName(propName);
220f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
221f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPPath expPath = XMPPathParser.expandXPath(schemaNS, propName);
222f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
223f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNode propNode = XMPNodeUtils.findNode(tree, expPath, false, null);
224f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (propNode != null)
225f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
226f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				XMPNodeUtils.deleteNode(propNode);
227f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
228f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
229f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
230f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
231f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// EMPTY, exceptions are ignored within delete
232f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
233f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
234f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
235f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
236f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
237f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#deleteQualifier(String, String, String, String)
238f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
239f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void deleteQualifier(String schemaNS, String propName, String qualNS, String qualName)
240f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
241f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
242f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
243f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// Note: qualNS and qualName are checked inside composeQualfierPath
244f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
245f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertPropName(propName);
246f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
247f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String qualPath = propName + XMPPathFactory.composeQualifierPath(qualNS, qualName);
248f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			deleteProperty(schemaNS, qualPath);
249f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
250f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
251f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
252f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// EMPTY, exceptions within delete are ignored
253f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
254f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
255f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
256f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
257f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
258f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#deleteStructField(String, String, String, String)
259f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
260f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void deleteStructField(String schemaNS, String structName, String fieldNS,
261f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String fieldName)
262f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
263f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
264f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
265f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// fieldNS and fieldName are checked inside composeStructFieldPath
266f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
267f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertStructName(structName);
268f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
269f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String fieldPath = structName
270f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					+ XMPPathFactory.composeStructFieldPath(fieldNS, fieldName);
271f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			deleteProperty(schemaNS, fieldPath);
272f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
273f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
274f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
275f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// EMPTY, exceptions within delete are ignored
276f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
277f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
278f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
279f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
280f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
281f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#doesPropertyExist(String, String)
282f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
283f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public boolean doesPropertyExist(String schemaNS, String propName)
284f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
285f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
286f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
287f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
288f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertPropName(propName);
289f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
290f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPPath expPath = XMPPathParser.expandXPath(schemaNS, propName);
291f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			final XMPNode propNode = XMPNodeUtils.findNode(tree, expPath, false, null);
292f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return propNode != null;
293f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
294f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
295f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
296f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return false;
297f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
298f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
299f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
300f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
301f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
302f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#doesArrayItemExist(String, String, int)
303f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
304f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public boolean doesArrayItemExist(String schemaNS, String arrayName, int itemIndex)
305f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
306f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
307f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
308f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
309f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertArrayName(arrayName);
310f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
311f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String path = XMPPathFactory.composeArrayItemPath(arrayName, itemIndex);
312f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return doesPropertyExist(schemaNS, path);
313f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
314f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
315f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
316f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return false;
317f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
318f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
319f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
320f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
321f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
322f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#doesStructFieldExist(String, String, String, String)
323f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
324f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public boolean doesStructFieldExist(String schemaNS, String structName, String fieldNS,
325f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String fieldName)
326f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
327f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
328f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
329f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// fieldNS and fieldName are checked inside composeStructFieldPath()
330f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
331f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertStructName(structName);
332f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
333f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String path = XMPPathFactory.composeStructFieldPath(fieldNS, fieldName);
334f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return doesPropertyExist(schemaNS, structName + path);
335f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
336f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
337f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
338f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return false;
339f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
340f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
341f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
342f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
343f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
344f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#doesQualifierExist(String, String, String, String)
345f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
346f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public boolean doesQualifierExist(String schemaNS, String propName, String qualNS,
347f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String qualName)
348f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
349f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		try
350f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
351f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// qualNS and qualName are checked inside composeQualifierPath()
352f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertSchemaNS(schemaNS);
353f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			ParameterAsserts.assertPropName(propName);
354f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
355f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String path = XMPPathFactory.composeQualifierPath(qualNS, qualName);
356f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return doesPropertyExist(schemaNS, propName + path);
357f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
358f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		catch (XMPException e)
359f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
360f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return false;
361f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
362f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
363f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
364f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
365f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
366f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getArrayItem(String, String, int)
367f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
368f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPProperty getArrayItem(String schemaNS, String arrayName, int itemIndex)
369f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
370f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
371f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
372f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(arrayName);
373f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
374f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String itemPath = XMPPathFactory.composeArrayItemPath(arrayName, itemIndex);
375f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return getProperty(schemaNS, itemPath);
376f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
377f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
378f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
379f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
380f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
381f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getLocalizedText(String, String, String, String)
382f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
383f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPProperty getLocalizedText(String schemaNS, String altTextName, String genericLang,
384f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String specificLang) throws XMPException
385f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
386f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
387f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(altTextName);
388f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSpecificLang(specificLang);
389f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
390f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		genericLang = genericLang != null ? Utils.normalizeLangValue(genericLang) : null;
391f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		specificLang = Utils.normalizeLangValue(specificLang);
392f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
393f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath arrayPath = XMPPathParser.expandXPath(schemaNS, altTextName);
394f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode arrayNode = XMPNodeUtils.findNode(tree, arrayPath, false, null);
395f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode == null)
396f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
397f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return null;
398f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
399f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
400f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		Object[] result = XMPNodeUtils.chooseLocalizedText(arrayNode, genericLang, specificLang);
401f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		int match = ((Integer) result[0]).intValue();
402f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		final XMPNode itemNode = (XMPNode) result[1];
403f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
404f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (match != XMPNodeUtils.CLT_NO_VALUES)
405f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
406f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return new XMPProperty()
407f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
408f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public Object getValue()
409f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
410f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return itemNode.getValue();
411f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
412f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
413f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
414f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public PropertyOptions getOptions()
415f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
416f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return itemNode.getOptions();
417f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
418f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
419f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
420f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public String getLanguage()
421f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
422f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return itemNode.getQualifier(1).getValue();
423f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
424f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
425f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
426f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public String toString()
427f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
428f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return itemNode.getValue().toString();
429f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
430f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			};
431f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
432f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
433f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
434f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return null;
435f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
436f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
437f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
438f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
439f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
440f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setLocalizedText(String, String, String, String, String,
441f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
442f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
443f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setLocalizedText(String schemaNS, String altTextName, String genericLang,
444f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String specificLang, String itemValue, PropertyOptions options) throws XMPException
445f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
446f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
447f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(altTextName);
448f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSpecificLang(specificLang);
449f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
450f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		genericLang = genericLang != null ? Utils.normalizeLangValue(genericLang) : null;
451f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		specificLang = Utils.normalizeLangValue(specificLang);
452f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
453f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath arrayPath = XMPPathParser.expandXPath(schemaNS, altTextName);
454f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
455f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Find the array node and set the options if it was just created.
456f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode arrayNode = XMPNodeUtils.findNode(tree, arrayPath, true, new PropertyOptions(
457f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				PropertyOptions.ARRAY | PropertyOptions.ARRAY_ORDERED
458f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling						| PropertyOptions.ARRAY_ALTERNATE | PropertyOptions.ARRAY_ALT_TEXT));
459f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
460f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode == null)
461f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
462f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Failed to find or create array node", XMPError.BADXPATH);
463f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
464f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else if (!arrayNode.getOptions().isArrayAltText())
465f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
466f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (!arrayNode.hasChildren() && arrayNode.getOptions().isArrayAlternate())
467f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
468f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				arrayNode.getOptions().setArrayAltText(true);
469f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
470f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else
471f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
472f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException(
473f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					"Specified property is no alt-text array", XMPError.BADXPATH);
474f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
475f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
476f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
477f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Make sure the x-default item, if any, is first.
478f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		boolean haveXDefault = false;
479f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode xdItem = null;
480f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
481f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		for (Iterator it = arrayNode.iterateChildren(); it.hasNext();)
482f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
483f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNode currItem = (XMPNode) it.next();
484f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (!currItem.hasQualifier()
485f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					|| !XMPConst.XML_LANG.equals(currItem.getQualifier(1).getName()))
486f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
487f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Language qualifier must be first", XMPError.BADXPATH);
488f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
489f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else if (XMPConst.X_DEFAULT.equals(currItem.getQualifier(1).getValue()))
490f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
491f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				xdItem = currItem;
492f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				haveXDefault = true;
493f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				break;
494f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
495f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
496f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
497f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Moves x-default to the beginning of the array
498f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (xdItem != null  &&  arrayNode.getChildrenLength() > 1)
499f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
500f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			arrayNode.removeChild(xdItem);
501f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			arrayNode.addChild(1, xdItem);
502f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
503f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
504f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Find the appropriate item.
505f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// chooseLocalizedText will make sure the array is a language
506f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// alternative.
507f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		Object[] result = XMPNodeUtils.chooseLocalizedText(arrayNode, genericLang, specificLang);
508f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		int match = ((Integer) result[0]).intValue();
509f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode itemNode = (XMPNode) result[1];
510f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
511f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		boolean specificXDefault = XMPConst.X_DEFAULT.equals(specificLang);
512f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
513f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		switch (match)
514f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
515f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case XMPNodeUtils.CLT_NO_VALUES:
516f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
517f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// Create the array items for the specificLang and x-default, with
518f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// x-default first.
519f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNodeUtils.appendLangItem(arrayNode, XMPConst.X_DEFAULT, itemValue);
520f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			haveXDefault = true;
521f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (!specificXDefault)
522f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
523f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				XMPNodeUtils.appendLangItem(arrayNode, specificLang, itemValue);
524f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
525f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
526f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
527f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case XMPNodeUtils.CLT_SPECIFIC_MATCH:
528f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
529f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (!specificXDefault)
530f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
531f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				// Update the specific item, update x-default if it matches the
532f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				// old value.
533f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				if (haveXDefault && xdItem != itemNode && xdItem != null
534f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling						&& xdItem.getValue().equals(itemNode.getValue()))
535f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
536f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					xdItem.setValue(itemValue);
537f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
538f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				// ! Do this after the x-default check!
539f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				itemNode.setValue(itemValue);
540f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
541f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			else
542f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
543f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				// Update all items whose values match the old x-default value.
544f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				assert  haveXDefault  &&  xdItem == itemNode;
545f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				for (Iterator it = arrayNode.iterateChildren(); it.hasNext();)
546f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
547f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					XMPNode currItem = (XMPNode) it.next();
548f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					if (currItem == xdItem
549f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling							|| !currItem.getValue().equals(
550f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling									xdItem != null ? xdItem.getValue() : null))
551f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					{
552f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling						continue;
553f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					}
554f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					currItem.setValue(itemValue);
555f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
556f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				// And finally do the x-default item.
557f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				if (xdItem != null)
558f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
559f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					xdItem.setValue(itemValue);
560f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
561f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
562f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
563f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
564f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case XMPNodeUtils.CLT_SINGLE_GENERIC:
565f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
566f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// Update the generic item, update x-default if it matches the old
567f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// value.
568f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (haveXDefault && xdItem != itemNode && xdItem != null
569f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					&& xdItem.getValue().equals(itemNode.getValue()))
570f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
571f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				xdItem.setValue(itemValue);
572f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
573f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			itemNode.setValue(itemValue); // ! Do this after
574f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// the x-default
575f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// check!
576f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
577f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
578f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case XMPNodeUtils.CLT_MULTIPLE_GENERIC:
579f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
580f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// Create the specific language, ignore x-default.
581f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNodeUtils.appendLangItem(arrayNode, specificLang, itemValue);
582f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (specificXDefault)
583f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
584f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				haveXDefault = true;
585f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
586f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
587f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
588f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case XMPNodeUtils.CLT_XDEFAULT:
589f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
590f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// Create the specific language, update x-default if it was the only
591f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// item.
592f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (xdItem != null  &&  arrayNode.getChildrenLength() == 1)
593f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
594f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				xdItem.setValue(itemValue);
595f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
596f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNodeUtils.appendLangItem(arrayNode, specificLang, itemValue);
597f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
598f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
599f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case XMPNodeUtils.CLT_FIRST_ITEM:
600f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
601f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// Create the specific language, don't add an x-default item.
602f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNodeUtils.appendLangItem(arrayNode, specificLang, itemValue);
603f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (specificXDefault)
604f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
605f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				haveXDefault = true;
606f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
607f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
608f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
609f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		default:
610f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// does not happen under normal circumstances
611f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Unexpected result from ChooseLocalizedText",
612f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					XMPError.INTERNALFAILURE);
613f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
614f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
615f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
616f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Add an x-default at the front if needed.
617f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (!haveXDefault && arrayNode.getChildrenLength() == 1)
618f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
619f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNodeUtils.appendLangItem(arrayNode, XMPConst.X_DEFAULT, itemValue);
620f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
621f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
622f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
623f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
624f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
625f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setLocalizedText(String, String, String, String, String)
626f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
627f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setLocalizedText(String schemaNS, String altTextName, String genericLang,
628f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String specificLang, String itemValue) throws XMPException
629f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
630f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setLocalizedText(schemaNS, altTextName, genericLang, specificLang, itemValue, null);
631f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
632f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
633f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
634f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
635f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
636f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getProperty(String, String)
637f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
638f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPProperty getProperty(String schemaNS, String propName) throws XMPException
639f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
640f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return getProperty(schemaNS, propName, VALUE_STRING);
641f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
642f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
643f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
644f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
645f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Returns a property, but the result value can be requested. It can be one
646f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * of {@link XMPMetaImpl#VALUE_STRING}, {@link XMPMetaImpl#VALUE_BOOLEAN},
647f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * {@link XMPMetaImpl#VALUE_INTEGER}, {@link XMPMetaImpl#VALUE_LONG},
648f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * {@link XMPMetaImpl#VALUE_DOUBLE}, {@link XMPMetaImpl#VALUE_DATE},
649f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * {@link XMPMetaImpl#VALUE_CALENDAR}, {@link XMPMetaImpl#VALUE_BASE64}.
650f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
651f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getProperty(String, String)
652f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param schemaNS
653f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a schema namespace
654f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param propName
655f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a property name or path
656f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param valueType
657f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the type of the value, see VALUE_...
658f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns an <code>XMPProperty</code>
659f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
660f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             Collects any exception that occurs.
661f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
662f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	protected XMPProperty getProperty(String schemaNS, String propName, int valueType)
663f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
664f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
665f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
666f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertPropName(propName);
667f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
668f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		final XMPPath expPath = XMPPathParser.expandXPath(schemaNS, propName);
669f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		final XMPNode propNode = XMPNodeUtils.findNode(tree, expPath, false, null);
670f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
671f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (propNode != null)
672f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
673f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (valueType != VALUE_STRING && propNode.getOptions().isCompositeProperty())
674f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
675f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Property must be simple when a value type is requested",
676f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling						XMPError.BADXPATH);
677f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
678f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
679f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			final Object value = evaluateNodeValue(valueType, propNode);
680f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
681f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return new XMPProperty()
682f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
683f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public Object getValue()
684f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
685f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return value;
686f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
687f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
688f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
689f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public PropertyOptions getOptions()
690f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
691f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return propNode.getOptions();
692f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
693f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
694f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
695f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public String getLanguage()
696f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
697f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return null;
698f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
699f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
700f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
701f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				public String toString()
702f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				{
703f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling					return value.toString();
704f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				}
705f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			};
706f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
707f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
708f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
709f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return null;
710f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
711f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
712f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
713f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
714f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
715f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Returns a property, but the result value can be requested.
716f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
717f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getProperty(String, String)
718f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param schemaNS
719f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a schema namespace
720f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param propName
721f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            a property name or path
722f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param valueType
723f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the type of the value, see VALUE_...
724f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns the node value as an object according to the
725f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *         <code>valueType</code>.
726f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
727f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *             Collects any exception that occurs.
728f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
729f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	protected Object getPropertyObject(String schemaNS, String propName, int valueType)
730f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
731f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
732f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
733f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertPropName(propName);
734f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
735f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		final XMPPath expPath = XMPPathParser.expandXPath(schemaNS, propName);
736f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		final XMPNode propNode = XMPNodeUtils.findNode(tree, expPath, false, null);
737f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
738f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (propNode != null)
739f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
740f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (valueType != VALUE_STRING && propNode.getOptions().isCompositeProperty())
741f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
742f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Property must be simple when a value type is requested",
743f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling						XMPError.BADXPATH);
744f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
745f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
746f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return evaluateNodeValue(valueType, propNode);
747f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
748f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
749f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
750f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			return null;
751f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
752f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
753f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
754f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
755f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
756f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyBoolean(String, String)
757f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
758f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public Boolean getPropertyBoolean(String schemaNS, String propName) throws XMPException
759f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
760f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (Boolean) getPropertyObject(schemaNS, propName, VALUE_BOOLEAN);
761f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
762f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
763f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
764f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
765f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
766f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyBoolean(String, String, boolean, PropertyOptions)
767f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
768f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyBoolean(String schemaNS, String propName, boolean propValue,
769f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
770f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
771f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue ? TRUESTR : FALSESTR, options);
772f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
773f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
774f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
775f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
776f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyBoolean(String, String, boolean)
777f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
778f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyBoolean(String schemaNS, String propName, boolean propValue)
779f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
780f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
781f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue ? TRUESTR : FALSESTR, null);
782f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
783f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
784f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
785f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
786f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyInteger(String, String)
787f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
788f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public Integer getPropertyInteger(String schemaNS, String propName) throws XMPException
789f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
790f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (Integer) getPropertyObject(schemaNS, propName, VALUE_INTEGER);
791f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
792f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
793f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
794f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
795f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyInteger(String, String, int, PropertyOptions)
796f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
797f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyInteger(String schemaNS, String propName, int propValue,
798f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
799f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
800f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, new Integer(propValue), options);
801f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
802f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
803f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
804f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
805f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyInteger(String, String, int)
806f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
807f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyInteger(String schemaNS, String propName, int propValue)
808f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
809f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
810f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, new Integer(propValue), null);
811f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
812f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
813f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
814f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
815f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyLong(String, String)
816f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
817f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public Long getPropertyLong(String schemaNS, String propName) throws XMPException
818f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
819f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (Long) getPropertyObject(schemaNS, propName, VALUE_LONG);
820f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
821f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
822f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
823f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
824f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyLong(String, String, long, PropertyOptions)
825f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
826f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyLong(String schemaNS, String propName, long propValue,
827f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
828f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
829f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, new Long(propValue), options);
830f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
831f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
832f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
833f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
834f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyLong(String, String, long)
835f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
836f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyLong(String schemaNS, String propName, long propValue)
837f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
838f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
839f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, new Long(propValue), null);
840f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
841f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
842f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
843f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
844f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyDouble(String, String)
845f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
846f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public Double getPropertyDouble(String schemaNS, String propName) throws XMPException
847f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
848f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (Double) getPropertyObject(schemaNS, propName, VALUE_DOUBLE);
849f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
850f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
851f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
852f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
853f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyDouble(String, String, double, PropertyOptions)
854f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
855f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyDouble(String schemaNS, String propName, double propValue,
856f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
857f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
858f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, new Double(propValue), options);
859f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
860f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
861f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
862f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
863f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyDouble(String, String, double)
864f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
865f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyDouble(String schemaNS, String propName, double propValue)
866f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
867f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
868f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, new Double(propValue), null);
869f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
870f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
871f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
872f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
873f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyDate(String, String)
874f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
875f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPDateTime getPropertyDate(String schemaNS, String propName) throws XMPException
876f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
877f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (XMPDateTime) getPropertyObject(schemaNS, propName, VALUE_DATE);
878f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
879f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
880f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
881f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
882f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyDate(String, String, XMPDateTime,
883f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
884f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
885f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyDate(String schemaNS, String propName, XMPDateTime propValue,
886f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
887f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
888f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, options);
889f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
890f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
891f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
892f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
893f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyDate(String, String, XMPDateTime)
894f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
895f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyDate(String schemaNS, String propName, XMPDateTime propValue)
896f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
897f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
898f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, null);
899f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
900f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
901f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
902f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
903f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyCalendar(String, String)
904f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
905f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public Calendar getPropertyCalendar(String schemaNS, String propName) throws XMPException
906f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
907f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (Calendar) getPropertyObject(schemaNS, propName, VALUE_CALENDAR);
908f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
909f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
910f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
911f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
912f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyCalendar(String, String, Calendar,
913f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
914f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
915f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyCalendar(String schemaNS, String propName, Calendar propValue,
916f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
917f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
918f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, options);
919f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
920f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
921f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
922f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
923f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyCalendar(String, String, Calendar)
924f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
925f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyCalendar(String schemaNS, String propName, Calendar propValue)
926f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
927f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
928f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, null);
929f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
930f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
931f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
932f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
933f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyBase64(String, String)
934f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
935f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public byte[] getPropertyBase64(String schemaNS, String propName) throws XMPException
936f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
937f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (byte[]) getPropertyObject(schemaNS, propName, VALUE_BASE64);
938f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
939f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
940f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
941f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
942f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPropertyString(String, String)
943f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
944f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public String getPropertyString(String schemaNS, String propName) throws XMPException
945f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
946f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return (String) getPropertyObject(schemaNS, propName, VALUE_STRING);
947f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
948f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
949f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
950f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
951f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyBase64(String, String, byte[], PropertyOptions)
952f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
953f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyBase64(String schemaNS, String propName, byte[] propValue,
954f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
955f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
956f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, options);
957f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
958f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
959f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
960f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
961f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setPropertyBase64(String, String, byte[])
962f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
963f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPropertyBase64(String schemaNS, String propName, byte[] propValue)
964f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
965f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
966f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, null);
967f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
968f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
969f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
970f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
971f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
972f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getQualifier(String, String, String, String)
973f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
974f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPProperty getQualifier(String schemaNS, String propName, String qualNS,
975f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String qualName) throws XMPException
976f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
977f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// qualNS and qualName are checked inside composeQualfierPath
978f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
979f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertPropName(propName);
980f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
981f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String qualPath = propName + XMPPathFactory.composeQualifierPath(qualNS, qualName);
982f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return getProperty(schemaNS, qualPath);
983f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
984f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
985f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
986f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
987f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getStructField(String, String, String, String)
988f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
989f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPProperty getStructField(String schemaNS, String structName, String fieldNS,
990f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String fieldName) throws XMPException
991f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
992f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// fieldNS and fieldName are checked inside composeStructFieldPath
993f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
994f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertStructName(structName);
995f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
996f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String fieldPath = structName + XMPPathFactory.composeStructFieldPath(fieldNS, fieldName);
997f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return getProperty(schemaNS, fieldPath);
998f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
999f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1000f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1001f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1002f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1003f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#iterator()
1004f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1005f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPIterator iterator() throws XMPException
1006f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1007f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return iterator(null, null, null);
1008f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1009f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1010f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1011f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1012f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#iterator(IteratorOptions)
1013f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1014f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPIterator iterator(IteratorOptions options) throws XMPException
1015f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1016f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return iterator(null, null, options);
1017f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1018f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1019f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1020f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1021f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#iterator(String, String, IteratorOptions)
1022f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1023f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPIterator iterator(String schemaNS, String propName, IteratorOptions options)
1024f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
1025f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1026f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return new XMPIteratorImpl(this, schemaNS, propName, options);
1027f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1028f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1029f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1030f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1031f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1032f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setArrayItem(String, String, int, String, PropertyOptions)
1033f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1034f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setArrayItem(String schemaNS, String arrayName, int itemIndex, String itemValue,
1035f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
1036f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1037f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
1038f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(arrayName);
1039f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1040f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Just lookup, don't try to create.
1041f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath arrayPath = XMPPathParser.expandXPath(schemaNS, arrayName);
1042f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode arrayNode = XMPNodeUtils.findNode(tree, arrayPath, false, null);
1043f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1044f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode != null)
1045f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1046f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			doSetArrayItem(arrayNode, itemIndex, itemValue, options, false);
1047f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1048f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
1049f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1050f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Specified array does not exist", XMPError.BADXPATH);
1051f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1052f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1053f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1054f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1055f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1056f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setArrayItem(String, String, int, String)
1057f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1058f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setArrayItem(String schemaNS, String arrayName, int itemIndex, String itemValue)
1059f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
1060f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1061f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setArrayItem(schemaNS, arrayName, itemIndex, itemValue, null);
1062f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1063f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1064f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1065f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1066f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1067f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#insertArrayItem(String, String, int, String,
1068f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
1069f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1070f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void insertArrayItem(String schemaNS, String arrayName, int itemIndex, String itemValue,
1071f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
1072f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1073f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
1074f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertArrayName(arrayName);
1075f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1076f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// Just lookup, don't try to create.
1077f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath arrayPath = XMPPathParser.expandXPath(schemaNS, arrayName);
1078f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode arrayNode = XMPNodeUtils.findNode(tree, arrayPath, false, null);
1079f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1080f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (arrayNode != null)
1081f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1082f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			doSetArrayItem(arrayNode, itemIndex, itemValue, options, true);
1083f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1084f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
1085f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1086f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Specified array does not exist", XMPError.BADXPATH);
1087f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1088f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1089f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1090f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1091f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1092f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#insertArrayItem(String, String, int, String)
1093f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1094f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void insertArrayItem(String schemaNS, String arrayName, int itemIndex, String itemValue)
1095f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
1096f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1097f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		insertArrayItem(schemaNS, arrayName, itemIndex, itemValue, null);
1098f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1099f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1100f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1101f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1102f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1103f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setProperty(String, String, Object, PropertyOptions)
1104f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1105f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setProperty(String schemaNS, String propName, Object propValue,
1106f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions options) throws XMPException
1107f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1108f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
1109f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertPropName(propName);
1110f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1111f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		options = XMPNodeUtils.verifySetOptions(options, propValue);
1112f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1113f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPPath expPath = XMPPathParser.expandXPath(schemaNS, propName);
1114f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1115f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode propNode = XMPNodeUtils.findNode(tree, expPath, true, options);
1116f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (propNode != null)
1117f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1118f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			setNode(propNode, propValue, options, false);
1119f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1120f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
1121f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1122f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Specified property does not exist", XMPError.BADXPATH);
1123f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1124f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1125f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1126f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1127f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1128f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setProperty(String, String, Object)
1129f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1130f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setProperty(String schemaNS, String propName, Object propValue) throws XMPException
1131f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1132f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, propName, propValue, null);
1133f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1134f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1135f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1136f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1137f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1138f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setQualifier(String, String, String, String, String,
1139f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
1140f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1141f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setQualifier(String schemaNS, String propName, String qualNS, String qualName,
1142f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String qualValue, PropertyOptions options) throws XMPException
1143f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1144f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
1145f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertPropName(propName);
1146f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1147f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (!doesPropertyExist(schemaNS, propName))
1148f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1149f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Specified property does not exist!", XMPError.BADXPATH);
1150f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1151f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1152f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String qualPath = propName + XMPPathFactory.composeQualifierPath(qualNS, qualName);
1153f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, qualPath, qualValue, options);
1154f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1155f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1156f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1157f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1158f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setQualifier(String, String, String, String, String)
1159f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1160f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setQualifier(String schemaNS, String propName, String qualNS, String qualName,
1161f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String qualValue) throws XMPException
1162f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1163f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setQualifier(schemaNS, propName, qualNS, qualName, qualValue, null);
1164f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1165f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1166f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1167f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1168f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1169f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setStructField(String, String, String, String, String,
1170f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *      PropertyOptions)
1171f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1172f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setStructField(String schemaNS, String structName, String fieldNS,
1173f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String fieldName, String fieldValue, PropertyOptions options) throws XMPException
1174f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1175f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertSchemaNS(schemaNS);
1176f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		ParameterAsserts.assertStructName(structName);
1177f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1178f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String fieldPath = structName + XMPPathFactory.composeStructFieldPath(fieldNS, fieldName);
1179f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setProperty(schemaNS, fieldPath, fieldValue, options);
1180f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1181f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1182f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1183f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1184f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setStructField(String, String, String, String, String)
1185f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1186f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setStructField(String schemaNS, String structName, String fieldNS,
1187f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			String fieldName, String fieldValue) throws XMPException
1188f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1189f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		setStructField(schemaNS, structName, fieldNS, fieldName, fieldValue, null);
1190f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1191f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1192f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1193f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1194f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getObjectName()
1195f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1196f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public String getObjectName()
1197f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1198f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return tree.getName() != null ? tree.getName() : "";
1199f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1200f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1201f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1202f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1203f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#setObjectName(String)
1204f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1205f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setObjectName(String name)
1206f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1207f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		tree.setName(name);
1208f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1209f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1210f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1211f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1212f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#getPacketHeader()
1213f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1214f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public String getPacketHeader()
1215f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1216f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return packetHeader;
1217f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1218f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1219f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1220f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1221f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Sets the packetHeader attributes, only used by the parser.
1222f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param packetHeader the processing instruction content
1223f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1224f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void setPacketHeader(String packetHeader)
1225f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1226f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		this.packetHeader = packetHeader;
1227f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1228f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1229f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1230f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1231f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Performs a deep clone of the XMPMeta-object
1232f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
1233f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see java.lang.Object#clone()
1234f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1235f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public Object clone()
1236f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1237f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode clonedTree = (XMPNode) tree.clone();
1238f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return new XMPMetaImpl(clonedTree);
1239f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1240f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1241f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1242f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1243f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#dumpObject()
1244f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1245f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public String dumpObject()
1246f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1247f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// renders tree recursively
1248f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return getRoot().dumpNode(true);
1249f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1250f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1251f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1252f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1253f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#sort()
1254f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1255f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void sort()
1256f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1257f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		this.tree.sort();
1258f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1259f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1260f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1261f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1262f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @see XMPMeta#normalize(ParseOptions)
1263f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1264f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public void normalize(ParseOptions options) throws XMPException
1265f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1266f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (options == null)
1267f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1268f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			options = new ParseOptions();
1269f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1270f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNormalizer.process(this, options);
1271f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1272f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1273f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1274f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1275f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns the root node of the XMP tree.
1276f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1277f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	public XMPNode getRoot()
1278f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1279f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return tree;
1280f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1281f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1282f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1283f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1284f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	// -------------------------------------------------------------------------------------
1285f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	// private
1286f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1287f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1288f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1289f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Locate or create the item node and set the value. Note the index
1290f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * parameter is one-based! The index can be in the range [1..size + 1] or
1291f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * "last()", normalize it and check the insert flags. The order of the
1292f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * normalization checks is important. If the array is empty we end up with
1293f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * an index and location to set item size + 1.
1294f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
1295f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param arrayNode an array node
1296f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param itemIndex the index where to insert the item
1297f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param itemValue the item value
1298f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param itemOptions the options for the new item
1299f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param insert insert oder overwrite at index position?
1300f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1301f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1302f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private void doSetArrayItem(XMPNode arrayNode, int itemIndex, String itemValue,
1303f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			PropertyOptions itemOptions, boolean insert) throws XMPException
1304f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1305f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		XMPNode itemNode = new XMPNode(ARRAY_ITEM_NAME, null);
1306f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		itemOptions = XMPNodeUtils.verifySetOptions(itemOptions, itemValue);
1307f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1308f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// in insert mode the index after the last is allowed,
1309f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// even ARRAY_LAST_ITEM points to the index *after* the last.
1310f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		int maxIndex = insert ? arrayNode.getChildrenLength() + 1 : arrayNode.getChildrenLength();
1311f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (itemIndex == ARRAY_LAST_ITEM)
1312f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1313f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			itemIndex = maxIndex;
1314f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1315f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1316f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (1 <= itemIndex && itemIndex <= maxIndex)
1317f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1318f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (!insert)
1319f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
1320f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				arrayNode.removeChild(itemIndex);
1321f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
1322f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			arrayNode.addChild(itemIndex, itemNode);
1323f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			setNode(itemNode, itemValue, itemOptions, false);
1324f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1325f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
1326f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1327f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throw new XMPException("Array index out of bounds", XMPError.BADINDEX);
1328f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1329f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1330f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1331f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1332f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1333f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * The internals for setProperty() and related calls, used after the node is
1334f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * found or created.
1335f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
1336f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param node
1337f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the newly created node
1338f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param value
1339f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the node value, can be <code>null</code>
1340f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param newOptions
1341f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            options for the new node, must not be <code>null</code>.
1342f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param deleteExisting flag if the existing value is to be overwritten
1343f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException thrown if options and value do not correspond
1344f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1345f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	void setNode(XMPNode node, Object value, PropertyOptions newOptions, boolean deleteExisting)
1346f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			throws XMPException
1347f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1348f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (deleteExisting)
1349f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1350f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			node.clear();
1351f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1352f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1353f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		// its checked by setOptions(), if the merged result is a valid options set
1354f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		node.getOptions().mergeWith(newOptions);
1355f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1356f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		if (!node.getOptions().isCompositeProperty())
1357f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1358f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// This is setting the value of a leaf node.
1359f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPNodeUtils.setNodeValue(node, value);
1360f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1361f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		else
1362f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1363f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			if (value != null && value.toString().length() > 0)
1364f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			{
1365f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling				throw new XMPException("Composite nodes can't have values", XMPError.BADXPATH);
1366f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			}
1367f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1368f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			node.removeChildren();
1369f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1370f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1371f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1372f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1373f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling
1374f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	/**
1375f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * Evaluates a raw node value to the given value type, apply special
1376f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * conversions for defined types in XMP.
1377f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *
1378f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param valueType
1379f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            an int indicating the value type
1380f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @param propNode
1381f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 *            the node containing the value
1382f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @return Returns a literal value for the node.
1383f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 * @throws XMPException
1384f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	 */
1385f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	private Object evaluateNodeValue(int valueType, final XMPNode propNode) throws XMPException
1386f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	{
1387f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		final Object value;
1388f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		String rawValue = propNode.getValue();
1389f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		switch (valueType)
1390f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		{
1391f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_BOOLEAN:
1392f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = new Boolean(XMPUtils.convertToBoolean(rawValue));
1393f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1394f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_INTEGER:
1395f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = new Integer(XMPUtils.convertToInteger(rawValue));
1396f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1397f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_LONG:
1398f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = new Long(XMPUtils.convertToLong(rawValue));
1399f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1400f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_DOUBLE:
1401f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = new Double(XMPUtils.convertToDouble(rawValue));
1402f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1403f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_DATE:
1404f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = XMPUtils.convertToDate(rawValue);
1405f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1406f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_CALENDAR:
1407f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			XMPDateTime dt = XMPUtils.convertToDate(rawValue);
1408f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = dt.getCalendar();
1409f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1410f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_BASE64:
1411f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = XMPUtils.decodeBase64(rawValue);
1412f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1413f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		case VALUE_STRING:
1414f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		default:
1415f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// leaf values return empty string instead of null
1416f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// for the other cases the converter methods provides a "null"
1417f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// value.
1418f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			// a default value can only occur if this method is made public.
1419f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			value = rawValue != null || propNode.getOptions().isCompositeProperty() ? rawValue : "";
1420f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling			break;
1421f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		}
1422f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling		return value;
1423f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling	}
1424f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling}
1425