/// <summary>Creates an <code>XMPNode</code> with initial values.</summary>
 /// <param name="name">the name of the node</param>
 /// <param name="value">the value of the node</param>
 /// <param name="options">the options of the node</param>
 public XMPNode(string name, string value, PropertyOptions options)
 {
     // internal processing options
     this.name = name;
     this.value = value;
     this.options = options;
 }
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.AppendArrayItem(string, string, Com.Adobe.Xmp.Options.PropertyOptions, string, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void AppendArrayItem(string schemaNS, string arrayName, PropertyOptions arrayOptions, string itemValue, PropertyOptions itemOptions)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertArrayName(arrayName);
			if (arrayOptions == null)
			{
				arrayOptions = new PropertyOptions();
			}
			if (!arrayOptions.IsOnlyArrayOptions())
			{
				throw new XMPException("Only array form flags allowed for arrayOptions", XMPErrorConstants.Badoptions);
			}
			// Check if array options are set correctly.
			arrayOptions = XMPNodeUtils.VerifySetOptions(arrayOptions, null);
			// Locate or create the array. If it already exists, make sure the array
			// form from the options
			// parameter is compatible with the current state.
			XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, arrayName);
			// Just lookup, don't try to create.
			XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, false, null);
			if (arrayNode != null)
			{
				// The array exists, make sure the form is compatible. Zero
				// arrayForm means take what exists.
				if (!arrayNode.GetOptions().IsArray())
				{
					throw new XMPException("The named property is not an array", XMPErrorConstants.Badxpath);
				}
			}
			else
			{
				// if (arrayOptions != null && !arrayOptions.equalArrayTypes(arrayNode.getOptions()))
				// {
				// throw new XMPException("Mismatch of existing and specified array form", BADOPTIONS);
				// }
				// The array does not exist, try to create it.
				if (arrayOptions.IsArray())
				{
					arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, true, arrayOptions);
					if (arrayNode == null)
					{
						throw new XMPException("Failure creating array node", XMPErrorConstants.Badxpath);
					}
				}
				else
				{
					// array options missing
					throw new XMPException("Explicit arrayOptions required to create new array", XMPErrorConstants.Badoptions);
				}
			}
			DoSetArrayItem(arrayNode, XMPConstConstants.ArrayLastItem, itemValue, itemOptions, true);
		}
 /// <summary>Performs a <b>deep clone</b> of the node and the complete subtree.</summary>
 /// <seealso cref="object.Clone()"/>
 public virtual object Clone()
 {
     PropertyOptions newOptions;
     try
     {
         newOptions = new PropertyOptions(GetOptions().GetOptions());
     }
     catch (XMPException)
     {
         // cannot happen
         newOptions = new PropertyOptions();
     }
     Com.Adobe.Xmp.Impl.XMPNode newNode = new Com.Adobe.Xmp.Impl.XMPNode(name, value, newOptions);
     CloneSubtree(newNode);
     return newNode;
 }
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetQualifier(string, string, string, string, string, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		public virtual void SetQualifier(string schemaNS, string propName, string qualNS, string qualName, string qualValue, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertPropName(propName);
			if (!DoesPropertyExist(schemaNS, propName))
			{
				throw new XMPException("Specified property does not exist!", XMPErrorConstants.Badxpath);
			}
			string qualPath = propName + XMPPathFactory.ComposeQualifierPath(qualNS, qualName);
			SetProperty(schemaNS, qualPath, qualValue, options);
		}
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.InsertArrayItem(string, string, int, string, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		public virtual void InsertArrayItem(string schemaNS, string arrayName, int itemIndex, string itemValue, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertArrayName(arrayName);
			// Just lookup, don't try to create.
			XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, arrayName);
			XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, false, null);
			if (arrayNode != null)
			{
				DoSetArrayItem(arrayNode, itemIndex, itemValue, options, true);
			}
			else
			{
				throw new XMPException("Specified array does not exist", XMPErrorConstants.Badxpath);
			}
		}
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyCalendar(string, string, Sharpen.Calendar, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetPropertyCalendar(string schemaNS, string propName, Sharpen.Calendar propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue, options);
		}
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyDouble(string, string, double, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetPropertyDouble(string schemaNS, string propName, double propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue, options);
		}
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyBoolean(string, string, bool, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		public virtual void SetPropertyBoolean(string schemaNS, string propName, bool propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue ? XMPConstConstants.Truestr : XMPConstConstants.Falsestr, options);
		}
 /// <summary>Separate a single edit string into an array of strings.</summary>
 /// <param name="xmp">The XMP object containing the array to be updated.</param>
 /// <param name="schemaNS">
 /// The schema namespace URI for the array. Must not be null or
 /// the empty string.
 /// </param>
 /// <param name="arrayName">
 /// The name of the array. May be a general path expression, must
 /// not be null or the empty string. Each item in the array must
 /// be a simple string value.
 /// </param>
 /// <param name="catedStr">The string to be separated into the array items.</param>
 /// <param name="arrayOptions">Option flags to control the separation.</param>
 /// <param name="preserveCommas">Flag if commas shall be preserved</param>
 /// <exception cref="XMPException">Forwards the Exceptions from the metadata processing</exception>
 /// <exception cref="Com.Adobe.Xmp.XMPException"/>
 public static void SeparateArrayItems(XMPMeta xmp, string schemaNS, string arrayName, string catedStr, PropertyOptions arrayOptions, bool preserveCommas)
 {
     XMPUtilsImpl.SeparateArrayItems(xmp, schemaNS, arrayName, catedStr, arrayOptions, preserveCommas);
 }
 /// <summary>Adds a child node.</summary>
 /// <param name="xmp">the xmp metadata object that is generated</param>
 /// <param name="xmpParent">the parent xmp node</param>
 /// <param name="xmlNode">the currently processed XML node</param>
 /// <param name="value">Node value</param>
 /// <param name="isTopLevel">Flag if the node is a top-level node</param>
 /// <returns>Returns the newly created child node.</returns>
 /// <exception cref="Com.Adobe.Xmp.XMPException">thown on parsing errors</exception>
 private static XMPNode AddChildNode(XMPMetaImpl xmp, XMPNode xmpParent, XmlNode xmlNode, string value, bool isTopLevel)
 {
     XMPSchemaRegistry registry = XMPMetaFactory.GetSchemaRegistry();
     string @namespace = xmlNode.NamespaceURI;
     string childName;
     if (@namespace != null)
     {
         if (XMPConstConstants.NsDcDeprecated.Equals(@namespace))
         {
             // Fix a legacy DC namespace
             @namespace = XMPConstConstants.NsDc;
         }
         string prefix = registry.GetNamespacePrefix(@namespace);
         if (prefix == null)
         {
             prefix = xmlNode.Prefix != null ? xmlNode.Prefix : DefaultPrefix;
             prefix = registry.RegisterNamespace(@namespace, prefix);
         }
         childName = prefix + xmlNode.LocalName;
     }
     else
     {
         throw new XMPException("XML namespace required for all elements and attributes", XMPErrorConstants.Badrdf);
     }
     // create schema node if not already there
     PropertyOptions childOptions = new PropertyOptions();
     bool isAlias = false;
     if (isTopLevel)
     {
         // Lookup the schema node, adjust the XMP parent pointer.
         // Incoming parent must be the tree root.
         XMPNode schemaNode = XMPNodeUtils.FindSchemaNode(xmp.GetRoot(), @namespace, DefaultPrefix, true);
         schemaNode.SetImplicit(false);
         // Clear the implicit node bit.
         // need runtime check for proper 32 bit code.
         xmpParent = schemaNode;
         // If this is an alias set the alias flag in the node
         // and the hasAliases flag in the tree.
         if (registry.FindAlias(childName) != null)
         {
             isAlias = true;
             xmp.GetRoot().SetHasAliases(true);
             schemaNode.SetHasAliases(true);
         }
     }
     // Make sure that this is not a duplicate of a named node.
     bool isArrayItem = "rdf:li".Equals(childName);
     bool isValueNode = "rdf:value".Equals(childName);
     // Create XMP node and so some checks
     XMPNode newChild = new XMPNode(childName, value, childOptions);
     newChild.SetAlias(isAlias);
     // Add the new child to the XMP parent node, a value node first.
     if (!isValueNode)
     {
         xmpParent.AddChild(newChild);
     }
     else
     {
         xmpParent.AddChild(1, newChild);
     }
     if (isValueNode)
     {
         if (isTopLevel || !xmpParent.GetOptions().IsStruct())
         {
             throw new XMPException("Misplaced rdf:value element", XMPErrorConstants.Badrdf);
         }
         xmpParent.SetHasValueChild(true);
     }
     if (isArrayItem)
     {
         if (!xmpParent.GetOptions().IsArray())
         {
             throw new XMPException("Misplaced rdf:li element", XMPErrorConstants.Badrdf);
         }
         newChild.SetName(XMPConstConstants.ArrayItemName);
     }
     return newChild;
 }
Example #11
0
 public virtual void UpdateStringArray(int tagType, string[] strings)
 {
     base.SetStringArray(tagType, strings);
     try
     {
         string schemaNS = _tagSchemaMap.Get(tagType);
         string propName = _tagPropNameMap.Get(tagType);
         GetXMPMeta().DeleteProperty(schemaNS, propName);
         PropertyOptions po = new PropertyOptions().SetArray(true);
         foreach (string item in strings)
         {
             GetXMPMeta().AppendArrayItem(schemaNS, propName, po, item, null);
         }
     }
     catch (XMPException e)
     {
         Sharpen.Runtime.PrintStackTrace(e);
     }
 }
Example #12
0
 /// <summary>Constructor for the node without value.</summary>
 /// <param name="name">the name of the node</param>
 /// <param name="options">the options of the node</param>
 public XMPNode(string name, PropertyOptions options)
     : this(name, null, options)
 {
 }
Example #13
0
 /// <summary>Updates the options of the node.</summary>
 /// <param name="options">the options to set.</param>
 public virtual void SetOptions(PropertyOptions options)
 {
     this.options = options;
 }
Example #14
0
 /// <returns>Returns the options.</returns>
 public virtual PropertyOptions GetOptions()
 {
     if (options == null)
     {
         options = new PropertyOptions();
     }
     return options;
 }
		/// <summary>
		/// The internals for SetProperty() and related calls, used after the node is
		/// found or created.
		/// </summary>
		/// <param name="node">the newly created node</param>
		/// <param name="value">the node value, can be <code>null</code></param>
		/// <param name="newOptions">options for the new node, must not be <code>null</code>.</param>
		/// <param name="deleteExisting">flag if the existing value is to be overwritten</param>
		/// <exception cref="Com.Adobe.Xmp.XMPException">thrown if options and value do not correspond</exception>
		internal virtual void SetNode(XMPNode node, object value, PropertyOptions newOptions, bool deleteExisting)
		{
			if (deleteExisting)
			{
				node.Clear();
			}
			// its checked by SetOptions(), if the merged result is a valid options set
			node.GetOptions().MergeWith(newOptions);
			if (!node.GetOptions().IsCompositeProperty())
			{
				// This is setting the value of a leaf node.
				XMPNodeUtils.SetNodeValue(node, value);
			}
			else
			{
				if (value != null && value.ToString().Length > 0)
				{
					throw new XMPException("Composite nodes can't have values", XMPErrorConstants.Badxpath);
				}
				node.RemoveChildren();
			}
		}
 /// <summary>Find or create a child node under a given parent node.</summary>
 /// <remarks>
 /// Find or create a child node under a given parent node. If the parent node is no
 /// Returns the found or created child node.
 /// </remarks>
 /// <param name="parent">the parent node</param>
 /// <param name="childName">the node name to find</param>
 /// <param name="createNodes">flag, if new nodes shall be created.</param>
 /// <returns>Returns the found or created node or <code>null</code>.</returns>
 /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown if</exception>
 internal static XMPNode FindChildNode(XMPNode parent, string childName, bool createNodes)
 {
     if (!parent.GetOptions().IsSchemaNode() && !parent.GetOptions().IsStruct())
     {
         if (!parent.IsImplicit())
         {
             throw new XMPException("Named children only allowed for schemas and structs", XMPErrorConstants.Badxpath);
         }
         else
         {
             if (parent.GetOptions().IsArray())
             {
                 throw new XMPException("Named children not allowed for arrays", XMPErrorConstants.Badxpath);
             }
             else
             {
                 if (createNodes)
                 {
                     parent.GetOptions().SetStruct(true);
                 }
             }
         }
     }
     XMPNode childNode = parent.FindChildByName(childName);
     if (childNode == null && createNodes)
     {
         PropertyOptions options = new PropertyOptions();
         childNode = new XMPNode(childName, options);
         childNode.SetImplicit(true);
         parent.AddChild(childNode);
     }
     System.Diagnostics.Debug.Assert(childNode != null || !createNodes);
     return childNode;
 }
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetLocalizedText(string, string, string, string, string, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetLocalizedText(string schemaNS, string altTextName, string genericLang, string specificLang, string itemValue, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertArrayName(altTextName);
			ParameterAsserts.AssertSpecificLang(specificLang);
			genericLang = genericLang != null ? Utils.NormalizeLangValue(genericLang) : null;
			specificLang = Utils.NormalizeLangValue(specificLang);
			XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, altTextName);
			// Find the array node and set the options if it was just created.
			XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, true, new PropertyOptions(PropertyOptions.Array | PropertyOptions.ArrayOrdered | PropertyOptions.ArrayAlternate | PropertyOptions.ArrayAltText));
			if (arrayNode == null)
			{
				throw new XMPException("Failed to find or create array node", XMPErrorConstants.Badxpath);
			}
			else
			{
				if (!arrayNode.GetOptions().IsArrayAltText())
				{
					if (!arrayNode.HasChildren() && arrayNode.GetOptions().IsArrayAlternate())
					{
						arrayNode.GetOptions().SetArrayAltText(true);
					}
					else
					{
						throw new XMPException("Specified property is no alt-text array", XMPErrorConstants.Badxpath);
					}
				}
			}
			// Make sure the x-default item, if any, is first.
			bool haveXDefault = false;
			XMPNode xdItem = null;
			for (Sharpen.Iterator it = arrayNode.IterateChildren(); it.HasNext(); )
			{
				XMPNode currItem = (XMPNode)it.Next();
				if (!currItem.HasQualifier() || !XMPConstConstants.XmlLang.Equals(currItem.GetQualifier(1).GetName()))
				{
					throw new XMPException("Language qualifier must be first", XMPErrorConstants.Badxpath);
				}
				else
				{
					if (XMPConstConstants.XDefault.Equals(currItem.GetQualifier(1).GetValue()))
					{
						xdItem = currItem;
						haveXDefault = true;
						break;
					}
				}
			}
			// Moves x-default to the beginning of the array
			if (xdItem != null && arrayNode.GetChildrenLength() > 1)
			{
				arrayNode.RemoveChild(xdItem);
				arrayNode.AddChild(1, xdItem);
			}
			// Find the appropriate item.
			// chooseLocalizedText will make sure the array is a language
			// alternative.
			object[] result = XMPNodeUtils.ChooseLocalizedText(arrayNode, genericLang, specificLang);
			int match = ((int)result[0]).IntValue();
			XMPNode itemNode = (XMPNode)result[1];
			bool specificXDefault = XMPConstConstants.XDefault.Equals(specificLang);
			switch (match)
			{
				case XMPNodeUtils.CltNoValues:
				{
					// Create the array items for the specificLang and x-default, with
					// x-default first.
					XMPNodeUtils.AppendLangItem(arrayNode, XMPConstConstants.XDefault, itemValue);
					haveXDefault = true;
					if (!specificXDefault)
					{
						XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
					}
					break;
				}

				case XMPNodeUtils.CltSpecificMatch:
				{
					if (!specificXDefault)
					{
						// Update the specific item, update x-default if it matches the
						// old value.
						if (haveXDefault && xdItem != itemNode && xdItem != null && xdItem.GetValue().Equals(itemNode.GetValue()))
						{
							xdItem.SetValue(itemValue);
						}
						// ! Do this after the x-default check!
						itemNode.SetValue(itemValue);
					}
					else
					{
						// Update all items whose values match the old x-default value.
						System.Diagnostics.Debug.Assert(haveXDefault && xdItem == itemNode);
						for (Sharpen.Iterator it_1 = arrayNode.IterateChildren(); it_1.HasNext(); )
						{
							XMPNode currItem = (XMPNode)it_1.Next();
							if (currItem == xdItem || !currItem.GetValue().Equals(xdItem != null ? xdItem.GetValue() : null))
							{
								continue;
							}
							currItem.SetValue(itemValue);
						}
						// And finally do the x-default item.
						if (xdItem != null)
						{
							xdItem.SetValue(itemValue);
						}
					}
					break;
				}

				case XMPNodeUtils.CltSingleGeneric:
				{
					// Update the generic item, update x-default if it matches the old
					// value.
					if (haveXDefault && xdItem != itemNode && xdItem != null && xdItem.GetValue().Equals(itemNode.GetValue()))
					{
						xdItem.SetValue(itemValue);
					}
					itemNode.SetValue(itemValue);
					// ! Do this after
					// the x-default
					// check!
					break;
				}

				case XMPNodeUtils.CltMultipleGeneric:
				{
					// Create the specific language, ignore x-default.
					XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
					if (specificXDefault)
					{
						haveXDefault = true;
					}
					break;
				}

				case XMPNodeUtils.CltXdefault:
				{
					// Create the specific language, update x-default if it was the only
					// item.
					if (xdItem != null && arrayNode.GetChildrenLength() == 1)
					{
						xdItem.SetValue(itemValue);
					}
					XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
					break;
				}

				case XMPNodeUtils.CltFirstItem:
				{
					// Create the specific language, don't add an x-default item.
					XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
					if (specificXDefault)
					{
						haveXDefault = true;
					}
					break;
				}

				default:
				{
					// does not happen under normal circumstances
					throw new XMPException("Unexpected result from ChooseLocalizedText", XMPErrorConstants.Internalfailure);
				}
			}
			// Add an x-default at the front if needed.
			if (!haveXDefault && arrayNode.GetChildrenLength() == 1)
			{
				XMPNodeUtils.AppendLangItem(arrayNode, XMPConstConstants.XDefault, itemValue);
			}
		}
 /// <summary>Follow an expanded path expression to find or create a node.</summary>
 /// <param name="xmpTree">the node to begin the search.</param>
 /// <param name="xpath">the complete xpath</param>
 /// <param name="createNodes">
 /// flag if nodes shall be created
 /// (when called by <code>setProperty()</code>)
 /// </param>
 /// <param name="leafOptions">
 /// the options for the created leaf nodes (only when
 /// <code>createNodes == true</code>).
 /// </param>
 /// <returns>Returns the node if found or created or <code>null</code>.</returns>
 /// <exception cref="Com.Adobe.Xmp.XMPException">
 /// An exception is only thrown if an error occurred,
 /// not if a node was not found.
 /// </exception>
 internal static XMPNode FindNode(XMPNode xmpTree, XMPPath xpath, bool createNodes, PropertyOptions leafOptions)
 {
     // check if xpath is set.
     if (xpath == null || xpath.Size() == 0)
     {
         throw new XMPException("Empty XMPPath", XMPErrorConstants.Badxpath);
     }
     // Root of implicitly created subtree to possible delete it later.
     // Valid only if leaf is new.
     XMPNode rootImplicitNode = null;
     XMPNode currNode = null;
     // resolve schema step
     currNode = FindSchemaNode(xmpTree, xpath.GetSegment(XMPPath.StepSchema).GetName(), createNodes);
     if (currNode == null)
     {
         return null;
     }
     else
     {
         if (currNode.IsImplicit())
         {
             currNode.SetImplicit(false);
             // Clear the implicit node bit.
             rootImplicitNode = currNode;
         }
     }
     // Save the top most implicit node.
     // Now follow the remaining steps of the original XMPPath.
     try
     {
         for (int i = 1; i < xpath.Size(); i++)
         {
             currNode = FollowXPathStep(currNode, xpath.GetSegment(i), createNodes);
             if (currNode == null)
             {
                 if (createNodes)
                 {
                     // delete implicitly created nodes
                     DeleteNode(rootImplicitNode);
                 }
                 return null;
             }
             else
             {
                 if (currNode.IsImplicit())
                 {
                     // clear the implicit node flag
                     currNode.SetImplicit(false);
                     // if node is an ALIAS (can be only in root step, auto-create array
                     // when the path has been resolved from a not simple alias type
                     if (i == 1 && xpath.GetSegment(i).IsAlias() && xpath.GetSegment(i).GetAliasForm() != 0)
                     {
                         currNode.GetOptions().SetOption(xpath.GetSegment(i).GetAliasForm(), true);
                     }
                     else
                     {
                         // "CheckImplicitStruct" in C++
                         if (i < xpath.Size() - 1 && xpath.GetSegment(i).GetKind() == XMPPath.StructFieldStep && !currNode.GetOptions().IsCompositeProperty())
                         {
                             currNode.GetOptions().SetStruct(true);
                         }
                     }
                     if (rootImplicitNode == null)
                     {
                         rootImplicitNode = currNode;
                     }
                 }
             }
         }
     }
     catch (XMPException e)
     {
         // Save the top most implicit node.
         // if new notes have been created prior to the error, delete them
         if (rootImplicitNode != null)
         {
             DeleteNode(rootImplicitNode);
         }
         throw;
     }
     if (rootImplicitNode != null)
     {
         // set options only if a node has been successful created
         currNode.GetOptions().MergeWith(leafOptions);
         currNode.SetOptions(currNode.GetOptions());
     }
     return currNode;
 }
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyInteger(string, string, int, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetPropertyInteger(string schemaNS, string propName, int propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue, options);
		}
 /// <summary>Verifies the PropertyOptions for consistancy and updates them as needed.</summary>
 /// <remarks>
 /// Verifies the PropertyOptions for consistancy and updates them as needed.
 /// If options are <code>null</code> they are created with default values.
 /// </remarks>
 /// <param name="options">the <code>PropertyOptions</code></param>
 /// <param name="itemValue">the node value to set</param>
 /// <returns>Returns the updated options.</returns>
 /// <exception cref="Com.Adobe.Xmp.XMPException">If the options are not consistant.</exception>
 internal static PropertyOptions VerifySetOptions(PropertyOptions options, object itemValue)
 {
     // create empty and fix existing options
     if (options == null)
     {
         // set default options
         options = new PropertyOptions();
     }
     if (options.IsArrayAltText())
     {
         options.SetArrayAlternate(true);
     }
     if (options.IsArrayAlternate())
     {
         options.SetArrayOrdered(true);
     }
     if (options.IsArrayOrdered())
     {
         options.SetArray(true);
     }
     if (options.IsCompositeProperty() && itemValue != null && itemValue.ToString().Length > 0)
     {
         throw new XMPException("Structs and arrays can't have values", XMPErrorConstants.Badoptions);
     }
     options.AssertConsistency(options.GetOptions());
     return options;
 }
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyLong(string, string, long, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetPropertyLong(string schemaNS, string propName, long propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue, options);
		}
 // Don't let failures (like a bad dc:rights form) stop other
 // cleanup.
 /// <summary>
 /// Initializes the map that contains the known arrays, that are fixed by
 /// <see cref="NormalizeDCArrays(XMPNode)"/>
 /// .
 /// </summary>
 private static void InitDCArrays()
 {
     dcArrayForms = new Hashtable();
     // Properties supposed to be a "Bag".
     PropertyOptions bagForm = new PropertyOptions();
     bagForm.SetArray(true);
     dcArrayForms.Put("dc:contributor", bagForm);
     dcArrayForms.Put("dc:language", bagForm);
     dcArrayForms.Put("dc:publisher", bagForm);
     dcArrayForms.Put("dc:relation", bagForm);
     dcArrayForms.Put("dc:subject", bagForm);
     dcArrayForms.Put("dc:type", bagForm);
     // Properties supposed to be a "Seq".
     PropertyOptions seqForm = new PropertyOptions();
     seqForm.SetArray(true);
     seqForm.SetArrayOrdered(true);
     dcArrayForms.Put("dc:creator", seqForm);
     dcArrayForms.Put("dc:date", seqForm);
     // Properties supposed to be an "Alt" in alternative-text form.
     PropertyOptions altTextForm = new PropertyOptions();
     altTextForm.SetArray(true);
     altTextForm.SetArrayOrdered(true);
     altTextForm.SetArrayAlternate(true);
     altTextForm.SetArrayAltText(true);
     dcArrayForms.Put("dc:description", altTextForm);
     dcArrayForms.Put("dc:rights", altTextForm);
     dcArrayForms.Put("dc:title", altTextForm);
 }
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyDate(string, string, Com.Adobe.Xmp.XMPDateTime, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetPropertyDate(string schemaNS, string propName, XMPDateTime propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue, options);
		}
		/// <summary>
		/// see
		/// <see cref="Com.Adobe.Xmp.XMPUtils.SeparateArrayItems(Com.Adobe.Xmp.XMPMeta, string, string, string, Com.Adobe.Xmp.Options.PropertyOptions, bool)"/>
		/// </summary>
		/// <param name="xmp">The XMP object containing the array to be updated.</param>
		/// <param name="schemaNS">
		/// The schema namespace URI for the array. Must not be null or
		/// the empty string.
		/// </param>
		/// <param name="arrayName">
		/// The name of the array. May be a general path expression, must
		/// not be null or the empty string. Each item in the array must
		/// be a simple string value.
		/// </param>
		/// <param name="catedStr">The string to be separated into the array items.</param>
		/// <param name="arrayOptions">Option flags to control the separation.</param>
		/// <param name="preserveCommas">Flag if commas shall be preserved</param>
		/// <exception cref="Com.Adobe.Xmp.XMPException">Forwards the Exceptions from the metadata processing</exception>
		public static void SeparateArrayItems(XMPMeta xmp, string schemaNS, string arrayName, string catedStr, PropertyOptions arrayOptions, bool preserveCommas)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertArrayName(arrayName);
			if (catedStr == null)
			{
				throw new XMPException("Parameter must not be null", XMPErrorConstants.Badparam);
			}
			ParameterAsserts.AssertImplementation(xmp);
			XMPMetaImpl xmpImpl = (XMPMetaImpl)xmp;
			// Keep a zero value, has special meaning below.
			XMPNode arrayNode = SeparateFindCreateArray(schemaNS, arrayName, arrayOptions, xmpImpl);
			// Extract the item values one at a time, until the whole input string is done.
			string itemValue;
			int itemStart;
			int itemEnd;
			int nextKind = UckNormal;
			int charKind = UckNormal;
			char ch = (char) 0;
			char nextChar = (char) 0;
			itemEnd = 0;
			int endPos = catedStr.Length;
			while (itemEnd < endPos)
			{
				// Skip any leading spaces and separation characters. Always skip commas here.
				// They can be kept when within a value, but not when alone between values.
				for (itemStart = itemEnd; itemStart < endPos; itemStart++)
				{
					ch = catedStr[itemStart];
					charKind = ClassifyCharacter(ch);
					if (charKind == UckNormal || charKind == UckQuote)
					{
						break;
					}
				}
				if (itemStart >= endPos)
				{
					break;
				}
				if (charKind != UckQuote)
				{
					// This is not a quoted value. Scan for the end, create an array
					// item from the substring.
					for (itemEnd = itemStart; itemEnd < endPos; itemEnd++)
					{
						ch = catedStr[itemEnd];
						charKind = ClassifyCharacter(ch);
						if (charKind == UckNormal || charKind == UckQuote || (charKind == UckComma && preserveCommas))
						{
							continue;
						}
						else
						{
							if (charKind != UckSpace)
							{
								break;
							}
							else
							{
								if ((itemEnd + 1) < endPos)
								{
									ch = catedStr[itemEnd + 1];
									nextKind = ClassifyCharacter(ch);
									if (nextKind == UckNormal || nextKind == UckQuote || (nextKind == UckComma && preserveCommas))
									{
										continue;
									}
								}
							}
						}
						// Anything left?
						break;
					}
					// Have multiple spaces, or a space followed by a
					// separator.
					itemValue = Sharpen.Runtime.Substring(catedStr, itemStart, itemEnd);
				}
				else
				{
					// Accumulate quoted values into a local string, undoubling
					// internal quotes that
					// match the surrounding quotes. Do not undouble "unmatching"
					// quotes.
					char openQuote = ch;
					char closeQuote = GetClosingQuote(openQuote);
					itemStart++;
					// Skip the opening quote;
					itemValue = string.Empty;
					for (itemEnd = itemStart; itemEnd < endPos; itemEnd++)
					{
						ch = catedStr[itemEnd];
						charKind = ClassifyCharacter(ch);
						if (charKind != UckQuote || !IsSurroundingQuote(ch, openQuote, closeQuote))
						{
							// This is not a matching quote, just append it to the
							// item value.
							itemValue += ch;
						}
						else
						{
							// This is a "matching" quote. Is it doubled, or the
							// final closing quote?
							// Tolerate various edge cases like undoubled opening
							// (non-closing) quotes,
							// or end of input.
							if ((itemEnd + 1) < endPos)
							{
								nextChar = catedStr[itemEnd + 1];
								nextKind = ClassifyCharacter(nextChar);
							}
							else
							{
								nextKind = UckSemicolon;
								nextChar = (char)unchecked((int)(0x3B));
							}
							if (ch == nextChar)
							{
								// This is doubled, copy it and skip the double.
								itemValue += ch;
								// Loop will add in charSize.
								itemEnd++;
							}
							else
							{
								if (!IsClosingingQuote(ch, openQuote, closeQuote))
								{
									// This is an undoubled, non-closing quote, copy it.
									itemValue += ch;
								}
								else
								{
									// This is an undoubled closing quote, skip it and
									// exit the loop.
									itemEnd++;
									break;
								}
							}
						}
					}
				}
				// Add the separated item to the array. 
				// Keep a matching old value in case it had separators.
				int foundIndex = -1;
				for (int oldChild = 1; oldChild <= arrayNode.GetChildrenLength(); oldChild++)
				{
					if (itemValue.Equals(arrayNode.GetChild(oldChild).GetValue()))
					{
						foundIndex = oldChild;
						break;
					}
				}
				XMPNode newItem = null;
				if (foundIndex < 0)
				{
					newItem = new XMPNode(XMPConstConstants.ArrayItemName, itemValue, null);
					arrayNode.AddChild(newItem);
				}
			}
		}
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetPropertyBase64(string, string, sbyte[], Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetPropertyBase64(string schemaNS, string propName, sbyte[] propValue, PropertyOptions options)
		{
			SetProperty(schemaNS, propName, propValue, options);
		}
		/// <summary>Utility to find or create the array used by <code>SeparateArrayItems()</code>.</summary>
		/// <param name="schemaNS">a the namespace fo the array</param>
		/// <param name="arrayName">the name of the array</param>
		/// <param name="arrayOptions">the options for the array if newly created</param>
		/// <param name="xmp">the xmp object</param>
		/// <returns>Returns the array node.</returns>
		/// <exception cref="Com.Adobe.Xmp.XMPException">Forwards exceptions</exception>
		private static XMPNode SeparateFindCreateArray(string schemaNS, string arrayName, PropertyOptions arrayOptions, XMPMetaImpl xmp)
		{
			arrayOptions = XMPNodeUtils.VerifySetOptions(arrayOptions, null);
			if (!arrayOptions.IsOnlyArrayOptions())
			{
				throw new XMPException("Options can only provide array form", XMPErrorConstants.Badoptions);
			}
			// Find the array node, make sure it is OK. Move the current children
			// aside, to be readded later if kept.
			XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, arrayName);
			XMPNode arrayNode = XMPNodeUtils.FindNode(xmp.GetRoot(), arrayPath, false, null);
			if (arrayNode != null)
			{
				// The array exists, make sure the form is compatible. Zero
				// arrayForm means take what exists.
				PropertyOptions arrayForm = arrayNode.GetOptions();
				if (!arrayForm.IsArray() || arrayForm.IsArrayAlternate())
				{
					throw new XMPException("Named property must be non-alternate array", XMPErrorConstants.Badxpath);
				}
				if (arrayOptions.EqualArrayTypes(arrayForm))
				{
					throw new XMPException("Mismatch of specified and existing array form", XMPErrorConstants.Badxpath);
				}
			}
			else
			{
				// *** Right error?
				// The array does not exist, try to create it.
				// don't modify the options handed into the method
				arrayNode = XMPNodeUtils.FindNode(xmp.GetRoot(), arrayPath, true, arrayOptions.SetArray(true));
				if (arrayNode == null)
				{
					throw new XMPException("Failed to create named array", XMPErrorConstants.Badxpath);
				}
			}
			return arrayNode;
		}
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetProperty(string, string, object, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		public virtual void SetProperty(string schemaNS, string propName, object propValue, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertPropName(propName);
			options = XMPNodeUtils.VerifySetOptions(options, propValue);
			XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName);
			XMPNode propNode = XMPNodeUtils.FindNode(tree, expPath, true, options);
			if (propNode != null)
			{
				SetNode(propNode, propValue, options, false);
			}
			else
			{
				throw new XMPException("Specified property does not exist", XMPErrorConstants.Badxpath);
			}
		}
		// -------------------------------------------------------------------------------------
		// private
		/// <summary>Locate or create the item node and set the value.</summary>
		/// <remarks>
		/// Locate or create the item node and set the value. Note the index
		/// parameter is one-based! The index can be in the range [1..size + 1] or
		/// "last()", normalize it and check the insert flags. The order of the
		/// normalization checks is important. If the array is empty we end up with
		/// an index and location to set item size + 1.
		/// </remarks>
		/// <param name="arrayNode">an array node</param>
		/// <param name="itemIndex">the index where to insert the item</param>
		/// <param name="itemValue">the item value</param>
		/// <param name="itemOptions">the options for the new item</param>
		/// <param name="insert">insert oder overwrite at index position?</param>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		private void DoSetArrayItem(XMPNode arrayNode, int itemIndex, string itemValue, PropertyOptions itemOptions, bool insert)
		{
			XMPNode itemNode = new XMPNode(XMPConstConstants.ArrayItemName, null);
			itemOptions = XMPNodeUtils.VerifySetOptions(itemOptions, itemValue);
			// in insert mode the index after the last is allowed,
			// even ArrayLastItem points to the index *after* the last.
			int maxIndex = insert ? arrayNode.GetChildrenLength() + 1 : arrayNode.GetChildrenLength();
			if (itemIndex == XMPConstConstants.ArrayLastItem)
			{
				itemIndex = maxIndex;
			}
			if (1 <= itemIndex && itemIndex <= maxIndex)
			{
				if (!insert)
				{
					arrayNode.RemoveChild(itemIndex);
				}
				arrayNode.AddChild(itemIndex, itemNode);
				SetNode(itemNode, itemValue, itemOptions, false);
			}
			else
			{
				throw new XMPException("Array index out of bounds", XMPErrorConstants.Badindex);
			}
		}
		/// <seealso cref="Com.Adobe.Xmp.XMPMeta.SetStructField(string, string, string, string, string, Com.Adobe.Xmp.Options.PropertyOptions)"/>
		/// <exception cref="Com.Adobe.Xmp.XMPException"/>
		public virtual void SetStructField(string schemaNS, string structName, string fieldNS, string fieldName, string fieldValue, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertStructName(structName);
			string fieldPath = structName + XMPPathFactory.ComposeStructFieldPath(fieldNS, fieldName);
			SetProperty(schemaNS, fieldPath, fieldValue, options);
		}
Example #30
0
 /// <summary>Resets the node.</summary>
 public virtual void Clear()
 {
     options = null;
     name = null;
     value = null;
     children = null;
     qualifier = null;
 }