/// <summary>The outermost call is special.</summary>
 /// <remarks>
 /// The outermost call is special. The names almost certainly differ. The
 /// qualifiers (and hence options) will differ for an alias to the x-default
 /// item of a langAlt array.
 /// </remarks>
 /// <param name="aliasNode">the alias node</param>
 /// <param name="baseNode">the base node of the alias</param>
 /// <param name="outerCall">marks the outer call of the recursion</param>
 /// <exception cref="Com.Adobe.Xmp.XMPException">Forwards XMP errors</exception>
 private static void CompareAliasedSubtrees(XMPNode aliasNode, XMPNode baseNode, bool outerCall)
 {
     if (!aliasNode.GetValue().Equals(baseNode.GetValue()) || aliasNode.GetChildrenLength() != baseNode.GetChildrenLength())
     {
         throw new XMPException("Mismatch between alias and base nodes", XMPErrorConstants.Badxmp);
     }
     if (!outerCall && (!aliasNode.GetName().Equals(baseNode.GetName()) || !aliasNode.GetOptions().Equals(baseNode.GetOptions()) || aliasNode.GetQualifierLength() != baseNode.GetQualifierLength()))
     {
         throw new XMPException("Mismatch between alias and base nodes", XMPErrorConstants.Badxmp);
     }
     for (Iterator an = aliasNode.IterateChildren(), bn = baseNode.IterateChildren(); an.HasNext() && bn.HasNext();)
     {
         XMPNode aliasChild = (XMPNode)an.Next();
         XMPNode baseChild  = (XMPNode)bn.Next();
         CompareAliasedSubtrees(aliasChild, baseChild, false);
     }
     for (Iterator an_1 = aliasNode.IterateQualifier(), bn_1 = baseNode.IterateQualifier(); an_1.HasNext() && bn_1.HasNext();)
     {
         XMPNode aliasQual = (XMPNode)an_1.Next();
         XMPNode baseQual  = (XMPNode)bn_1.Next();
         CompareAliasedSubtrees(aliasQual, baseQual, false);
     }
 }
示例#2
0
 /// <summary>
 /// Searches for a qualifier selector in a node:
 /// [?qualName="value"] - an element in an array, chosen by a qualifier value.
 /// </summary>
 /// <remarks>
 /// Searches for a qualifier selector in a node:
 /// [?qualName="value"] - an element in an array, chosen by a qualifier value.
 /// No implicit nodes are created for qualifier selectors,
 /// except for an alias to an x-default item.
 /// </remarks>
 /// <param name="arrayNode">an array node</param>
 /// <param name="qualName">the qualifier name</param>
 /// <param name="qualValue">the qualifier value</param>
 /// <param name="aliasForm">
 /// in case the qual selector results from an alias,
 /// an x-default node is created if there has not been one.
 /// </param>
 /// <returns>Returns the index of th</returns>
 /// <exception cref="Com.Adobe.Xmp.XMPException"></exception>
 private static int LookupQualSelector(XMPNode arrayNode, string qualName, string qualValue, int aliasForm)
 {
     if (XMPConstConstants.XmlLang.Equals(qualName))
     {
         qualValue = Utils.NormalizeLangValue(qualValue);
         int index = Com.Adobe.Xmp.Impl.XMPNodeUtils.LookupLanguageItem(arrayNode, qualValue);
         if (index < 0 && (aliasForm & AliasOptions.PropArrayAltText) > 0)
         {
             XMPNode langNode = new XMPNode(XMPConstConstants.ArrayItemName, null);
             XMPNode xdefault = new XMPNode(XMPConstConstants.XmlLang, XMPConstConstants.XDefault, null);
             langNode.AddQualifier(xdefault);
             arrayNode.AddChild(1, langNode);
             return(1);
         }
         else
         {
             return(index);
         }
     }
     else
     {
         for (int index = 1; index < arrayNode.GetChildrenLength(); index++)
         {
             XMPNode currItem = arrayNode.GetChild(index);
             for (Iterator it = currItem.IterateQualifier(); it.HasNext();)
             {
                 XMPNode qualifier = (XMPNode)it.Next();
                 if (qualName.Equals(qualifier.GetName()) && qualValue.Equals(qualifier.GetValue()))
                 {
                     return(index);
                 }
             }
         }
         return(-1);
     }
 }
 /// <summary>The outermost call is special.</summary>
 /// <remarks>
 /// The outermost call is special. The names almost certainly differ. The
 /// qualifiers (and hence options) will differ for an alias to the x-default
 /// item of a langAlt array.
 /// </remarks>
 /// <param name="aliasNode">the alias node</param>
 /// <param name="baseNode">the base node of the alias</param>
 /// <param name="outerCall">marks the outer call of the recursion</param>
 /// <exception cref="Com.Adobe.Xmp.XMPException">Forwards XMP errors</exception>
 private static void CompareAliasedSubtrees(XMPNode aliasNode, XMPNode baseNode, bool outerCall)
 {
     if (!aliasNode.GetValue().Equals(baseNode.GetValue()) || aliasNode.GetChildrenLength() != baseNode.GetChildrenLength())
     {
         throw new XMPException("Mismatch between alias and base nodes", XMPErrorConstants.Badxmp);
     }
     if (!outerCall && (!aliasNode.GetName().Equals(baseNode.GetName()) || !aliasNode.GetOptions().Equals(baseNode.GetOptions()) || aliasNode.GetQualifierLength() != baseNode.GetQualifierLength()))
     {
         throw new XMPException("Mismatch between alias and base nodes", XMPErrorConstants.Badxmp);
     }
     for (Iterator an = aliasNode.IterateChildren(), bn = baseNode.IterateChildren(); an.HasNext() && bn.HasNext(); )
     {
         XMPNode aliasChild = (XMPNode)an.Next();
         XMPNode baseChild = (XMPNode)bn.Next();
         CompareAliasedSubtrees(aliasChild, baseChild, false);
     }
     for (Iterator an_1 = aliasNode.IterateQualifier(), bn_1 = baseNode.IterateQualifier(); an_1.HasNext() && bn_1.HasNext(); )
     {
         XMPNode aliasQual = (XMPNode)an_1.Next();
         XMPNode baseQual = (XMPNode)bn_1.Next();
         CompareAliasedSubtrees(aliasQual, baseQual, false);
     }
 }
		/// <summary>Recursively handles the "value" for a node.</summary>
		/// <remarks>
		/// Recursively handles the "value" for a node. It does not matter if it is a
		/// top level property, a field of a struct, or an item of an array. The
		/// indent is that for the property element. An xml:lang qualifier is written
		/// as an attribute of the property start tag, not by itself forcing the
		/// qualified property form. The patterns below mostly ignore attribute
		/// qualifiers like xml:lang. Except for the one struct case, attribute
		/// qualifiers don't affect the output form.
		/// <blockquote>
		/// <pre>
		/// &lt;ns:UnqualifiedSimpleProperty&gt;value&lt;/ns:UnqualifiedSimpleProperty&gt;
		/// &lt;ns:UnqualifiedStructProperty&gt; (If no rdf:resource qualifier)
		/// &lt;rdf:Description&gt;
		/// ... Fields, same forms as top level properties
		/// &lt;/rdf:Description&gt;
		/// &lt;/ns:UnqualifiedStructProperty&gt;
		/// &lt;ns:ResourceStructProperty rdf:resource=&quot;URI&quot;
		/// ... Fields as attributes
		/// &gt;
		/// &lt;ns:UnqualifiedArrayProperty&gt;
		/// &lt;rdf:Bag&gt; or Seq or Alt
		/// ... Array items as rdf:li elements, same forms as top level properties
		/// &lt;/rdf:Bag&gt;
		/// &lt;/ns:UnqualifiedArrayProperty&gt;
		/// &lt;ns:QualifiedProperty&gt;
		/// &lt;rdf:Description&gt;
		/// &lt;rdf:value&gt; ... Property &quot;value&quot; following the unqualified
		/// forms ... &lt;/rdf:value&gt;
		/// ... Qualifiers looking like named struct fields
		/// &lt;/rdf:Description&gt;
		/// &lt;/ns:QualifiedProperty&gt;
		/// </pre>
		/// </blockquote>
		/// </remarks>
		/// <param name="node">the property node</param>
		/// <param name="emitAsRDFValue">property shall be rendered as attribute rather than tag</param>
		/// <param name="useCanonicalRDF">
		/// use canonical form with inner description tag or
		/// the compact form with rdf:ParseType=&quot;resource&quot; attribute.
		/// </param>
		/// <param name="indent">the current indent level</param>
		/// <exception cref="System.IO.IOException">Forwards all writer exceptions.</exception>
		/// <exception cref="Com.Adobe.Xmp.XMPException">If &quot;rdf:resource&quot; and general qualifiers are mixed.</exception>
		private void SerializeCanonicalRDFProperty(XMPNode node, bool useCanonicalRDF, bool emitAsRDFValue, int indent)
		{
			bool emitEndTag = true;
			bool indentEndTag = true;
			// Determine the XML element name. Open the start tag with the name and
			// attribute qualifiers.
			string elemName = node.GetName();
			if (emitAsRDFValue)
			{
				elemName = "rdf:value";
			}
			else
			{
				if (XMPConstConstants.ArrayItemName.Equals(elemName))
				{
					elemName = "rdf:li";
				}
			}
			WriteIndent(indent);
			Write('<');
			Write(elemName);
			bool hasGeneralQualifiers = false;
			bool hasRDFResourceQual = false;
			for (Iterator it = node.IterateQualifier(); it.HasNext(); )
			{
				XMPNode qualifier = (XMPNode)it.Next();
				if (!RdfAttrQualifier.Contains(qualifier.GetName()))
				{
					hasGeneralQualifiers = true;
				}
				else
				{
					hasRDFResourceQual = "rdf:resource".Equals(qualifier.GetName());
					if (!emitAsRDFValue)
					{
						Write(' ');
						Write(qualifier.GetName());
						Write("=\"");
						AppendNodeValue(qualifier.GetValue(), true);
						Write('"');
					}
				}
			}
			// Process the property according to the standard patterns.
			if (hasGeneralQualifiers && !emitAsRDFValue)
			{
				// This node has general, non-attribute, qualifiers. Emit using the
				// qualified property form.
				// ! The value is output by a recursive call ON THE SAME NODE with
				// emitAsRDFValue set.
				if (hasRDFResourceQual)
				{
					throw new XMPException("Can't mix rdf:resource and general qualifiers", XMPErrorConstants.Badrdf);
				}
				// Change serialization to canonical format with inner rdf:Description-tag
				// depending on option
				if (useCanonicalRDF)
				{
					Write(">");
					WriteNewline();
					indent++;
					WriteIndent(indent);
					Write(RdfStructStart);
					Write(">");
				}
				else
				{
					Write(" rdf:parseType=\"Resource\">");
				}
				WriteNewline();
				SerializeCanonicalRDFProperty(node, useCanonicalRDF, true, indent + 1);
				for (Iterator it_1 = node.IterateQualifier(); it_1.HasNext(); )
				{
					XMPNode qualifier = (XMPNode)it_1.Next();
					if (!RdfAttrQualifier.Contains(qualifier.GetName()))
					{
						SerializeCanonicalRDFProperty(qualifier, useCanonicalRDF, false, indent + 1);
					}
				}
				if (useCanonicalRDF)
				{
					WriteIndent(indent);
					Write(RdfStructEnd);
					WriteNewline();
					indent--;
				}
			}
			else
			{
				// This node has no general qualifiers. Emit using an unqualified form.
				if (!node.GetOptions().IsCompositeProperty())
				{
					// This is a simple property.
					if (node.GetOptions().IsURI())
					{
						Write(" rdf:resource=\"");
						AppendNodeValue(node.GetValue(), true);
						Write("\"/>");
						WriteNewline();
						emitEndTag = false;
					}
					else
					{
						if (node.GetValue() == null || string.Empty.Equals(node.GetValue()))
						{
							Write("/>");
							WriteNewline();
							emitEndTag = false;
						}
						else
						{
							Write('>');
							AppendNodeValue(node.GetValue(), false);
							indentEndTag = false;
						}
					}
				}
				else
				{
					if (node.GetOptions().IsArray())
					{
						// This is an array.
						Write('>');
						WriteNewline();
						EmitRDFArrayTag(node, true, indent + 1);
						if (node.GetOptions().IsArrayAltText())
						{
							XMPNodeUtils.NormalizeLangArray(node);
						}
						for (Iterator it_1 = node.IterateChildren(); it_1.HasNext(); )
						{
							XMPNode child = (XMPNode)it_1.Next();
							SerializeCanonicalRDFProperty(child, useCanonicalRDF, false, indent + 2);
						}
						EmitRDFArrayTag(node, false, indent + 1);
					}
					else
					{
						if (!hasRDFResourceQual)
						{
							// This is a "normal" struct, use the rdf:parseType="Resource" form.
							if (!node.HasChildren())
							{
								// Change serialization to canonical format with inner rdf:Description-tag
								// if option is set
								if (useCanonicalRDF)
								{
									Write(">");
									WriteNewline();
									WriteIndent(indent + 1);
									Write(RdfEmptyStruct);
								}
								else
								{
									Write(" rdf:parseType=\"Resource\"/>");
									emitEndTag = false;
								}
								WriteNewline();
							}
							else
							{
								// Change serialization to canonical format with inner rdf:Description-tag
								// if option is set
								if (useCanonicalRDF)
								{
									Write(">");
									WriteNewline();
									indent++;
									WriteIndent(indent);
									Write(RdfStructStart);
									Write(">");
								}
								else
								{
									Write(" rdf:parseType=\"Resource\">");
								}
								WriteNewline();
								for (Iterator it_1 = node.IterateChildren(); it_1.HasNext(); )
								{
									XMPNode child = (XMPNode)it_1.Next();
									SerializeCanonicalRDFProperty(child, useCanonicalRDF, false, indent + 1);
								}
								if (useCanonicalRDF)
								{
									WriteIndent(indent);
									Write(RdfStructEnd);
									WriteNewline();
									indent--;
								}
							}
						}
						else
						{
							// This is a struct with an rdf:resource attribute, use the
							// "empty property element" form.
							for (Iterator it_1 = node.IterateChildren(); it_1.HasNext(); )
							{
								XMPNode child = (XMPNode)it_1.Next();
								if (!CanBeRDFAttrProp(child))
								{
									throw new XMPException("Can't mix rdf:resource and complex fields", XMPErrorConstants.Badrdf);
								}
								WriteNewline();
								WriteIndent(indent + 1);
								Write(' ');
								Write(child.GetName());
								Write("=\"");
								AppendNodeValue(child.GetValue(), true);
								Write('"');
							}
							Write("/>");
							WriteNewline();
							emitEndTag = false;
						}
					}
				}
			}
			// Emit the property element end tag.
			if (emitEndTag)
			{
				if (indentEndTag)
				{
					WriteIndent(indent);
				}
				Write("</");
				Write(elemName);
				Write('>');
				WriteNewline();
			}
		}
		/// <summary>Writes all used namespaces of the subtree in node to the output.</summary>
		/// <remarks>
		/// Writes all used namespaces of the subtree in node to the output.
		/// The subtree is recursivly traversed.
		/// </remarks>
		/// <param name="node">the root node of the subtree</param>
		/// <param name="usedPrefixes">a set containing currently used prefixes</param>
		/// <param name="indent">the current indent level</param>
		/// <exception cref="System.IO.IOException">Forwards all writer exceptions.</exception>
        private void DeclareUsedNamespaces(XMPNode node, HashSet<string> usedPrefixes, int indent)
		{
			if (node.GetOptions().IsSchemaNode())
			{
				// The schema node name is the URI, the value is the prefix.
				string prefix = Sharpen.Runtime.Substring(node.GetValue(), 0, node.GetValue().Length - 1);
				DeclareNamespace(prefix, node.GetName(), usedPrefixes, indent);
			}
			else
			{
				if (node.GetOptions().IsStruct())
				{
					for (Iterator it = node.IterateChildren(); it.HasNext(); )
					{
						XMPNode field = (XMPNode)it.Next();
						DeclareNamespace(field.GetName(), null, usedPrefixes, indent);
					}
				}
			}
			for (Iterator it_1 = node.IterateChildren(); it_1.HasNext(); )
			{
				XMPNode child = (XMPNode)it_1.Next();
				DeclareUsedNamespaces(child, usedPrefixes, indent);
			}
			for (Iterator it_2 = node.IterateQualifier(); it_2.HasNext(); )
			{
				XMPNode qualifier = (XMPNode)it_2.Next();
				DeclareNamespace(qualifier.GetName(), null, usedPrefixes, indent);
				DeclareUsedNamespaces(qualifier, usedPrefixes, indent);
			}
		}
		/// <summary>Serializes the general qualifier.</summary>
		/// <param name="node">the root node of the subtree</param>
		/// <param name="indent">the current indent level</param>
		/// <exception cref="System.IO.IOException">Forwards all writer exceptions.</exception>
		/// <exception cref="Com.Adobe.Xmp.XMPException">If qualifier and element fields are mixed.</exception>
		private void SerializeCompactRDFGeneralQualifier(int indent, XMPNode node)
		{
			// The node has general qualifiers, ones that can't be
			// attributes on a property element.
			// Emit using the qualified property pseudo-struct form. The
			// value is output by a call
			// to SerializePrettyRDFProperty with emitAsRDFValue set.
			Write(" rdf:parseType=\"Resource\">");
			WriteNewline();
			SerializeCanonicalRDFProperty(node, false, true, indent + 1);
			for (Iterator iq = node.IterateQualifier(); iq.HasNext(); )
			{
				XMPNode qualifier = (XMPNode)iq.Next();
				SerializeCanonicalRDFProperty(qualifier, false, false, indent + 1);
			}
		}