Пример #1
0
        /// <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="iText.Kernel.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", XMPError.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", XMPError.BADXMP);
            }

            for (IEnumerator an = aliasNode.IterateChildren(), bn = baseNode.IterateChildren();
                 an.MoveNext() && bn.MoveNext();)
            {
                XMPNode aliasChild = (XMPNode)an.Current;
                XMPNode baseChild  = (XMPNode)bn.Current;
                CompareAliasedSubtrees(aliasChild, baseChild, false);
            }


            for (IEnumerator an = aliasNode.IterateQualifier(), bn = baseNode.IterateQualifier();
                 an.MoveNext() && bn.MoveNext();)
            {
                XMPNode aliasQual = (XMPNode)an.Current;
                XMPNode baseQual  = (XMPNode)bn.Current;
                CompareAliasedSubtrees(aliasQual, baseQual, false);
            }
        }
Пример #2
0
 /// <summary>
 /// Constructor </summary>
 /// <param name="parentNode"> the node which children shall be iterated. </param>
 /// <param name="parentPath"> the full path of the former node without the leaf node. </param>
 public NodeIteratorChildren(XMPIteratorImpl outerInstance, XMPNode parentNode, string parentPath)
     : base(outerInstance, parentNode, parentPath, 0)
 {
     this.outerInstance = outerInstance;
     if (parentNode.GetOptions().IsSchemaNode())
     {
         outerInstance.SetBaseNS(parentNode.GetName());
     }
     this.parentPath       = AccumulatePath(parentNode, parentPath, 1);
     this.childrenIterator = parentNode.IterateChildren();
 }
Пример #3
0
        /// <summary>Make sure that the array is well-formed AltText.</summary>
        /// <remarks>
        /// Make sure that the array is well-formed AltText. Each item must be simple
        /// and have an "xml:lang" qualifier. If repairs are needed, keep simple
        /// non-empty items by adding the "xml:lang" with value "x-repair".
        /// </remarks>
        /// <param name="arrayNode">the property node of the array to repair.</param>
        /// <exception cref="iText.Kernel.XMP.XMPException">Forwards unexpected exceptions.
        ///     </exception>
        private static void RepairAltText(XMPNode arrayNode)
        {
            if (arrayNode == null || !arrayNode.GetOptions().IsArray())
            {
                // Already OK or not even an array.
                return;
            }

            // fix options
            arrayNode.GetOptions().SetArrayOrdered(true);
            arrayNode.GetOptions().SetArrayAlternate(true);
            arrayNode.GetOptions().SetArrayAltText(true);
            ArrayList   currChildsToRemove = new ArrayList();
            IEnumerator it = arrayNode.IterateChildren();

            while (it.MoveNext())
            {
                XMPNode currChild = (XMPNode)it.Current;
                if (currChild == null)
                {
                    continue;
                }
                if (currChild.GetOptions().IsCompositeProperty())
                {
                    // Delete non-simple children.
                    currChildsToRemove.Add(currChild);
                }
                else if (!currChild.GetOptions().GetHasLanguage())
                {
                    string childValue = currChild.GetValue();
                    if (String.IsNullOrEmpty(childValue))
                    {
                        // Delete empty valued children that have no xml:lang.
                        currChildsToRemove.Add(currChild);
                    }
                    else
                    {
                        // Add an xml:lang qualifier with the value "x-repair".
                        XMPNode repairLang = new XMPNode(XMPConst.XML_LANG, "x-repair", null);
                        currChild.AddQualifier(repairLang);
                    }
                }
            }
            foreach (object o in currChildsToRemove)
            {
                arrayNode.GetChildren().Remove(o);
            }
        }
Пример #4
0
 /// <summary>See if an array is an alt-text array.</summary>
 /// <remarks>
 /// See if an array is an alt-text array. If so, make sure the x-default item
 /// is first.
 /// </remarks>
 /// <param name="arrayNode">the array node to check if its an alt-text array</param>
 internal static void DetectAltText(XMPNode arrayNode)
 {
     if (arrayNode.GetOptions().IsArrayAlternate() && arrayNode.HasChildren())
     {
         bool isAltText = false;
         for (IEnumerator it = arrayNode.IterateChildren(); it.MoveNext();)
         {
             XMPNode child = (XMPNode)it.Current;
             if (child.GetOptions().GetHasLanguage())
             {
                 isAltText = true;
                 break;
             }
         }
         if (isAltText)
         {
             arrayNode.GetOptions().SetArrayAltText(true);
             NormalizeLangArray(arrayNode);
         }
     }
 }
Пример #5
0
        /// <summary>
        /// <ol>
        /// <li>Look for an exact match with the specific language.
        /// </summary>
        /// <remarks>
        /// <ol>
        /// <li>Look for an exact match with the specific language.
        /// <li>If a generic language is given, look for partial matches.
        /// <li>Look for an "x-default"-item.
        /// <li>Choose the first item.
        /// </ol>
        /// </remarks>
        /// <param name="arrayNode">the alt text array node</param>
        /// <param name="genericLang">the generic language</param>
        /// <param name="specificLang">the specific language</param>
        /// <returns>
        /// Returns the kind of match as an Integer and the found node in an
        /// array.
        /// </returns>
        /// <exception cref="iText.Kernel.XMP.XMPException"/>
        internal static Object[] ChooseLocalizedText(XMPNode arrayNode, String genericLang
                                                     , String specificLang)
        {
            // See if the array has the right form. Allow empty alt arrays,
            // that is what parsing returns.
            if (!arrayNode.GetOptions().IsArrayAltText())
            {
                throw new XMPException("Localized text array is not alt-text", XMPError.BADXPATH);
            }
            else
            {
                if (!arrayNode.HasChildren())
                {
                    return(new Object[] { XMPNodeUtils.CLT_NO_VALUES, null });
                }
            }
            int     foundGenericMatches = 0;
            XMPNode resultNode          = null;
            XMPNode xDefault            = null;

            // Look for the first partial match with the generic language.
            for (IEnumerator it = arrayNode.IterateChildren(); it.MoveNext();)
            {
                XMPNode currItem = (XMPNode)it.Current;
                // perform some checks on the current item
                if (currItem.GetOptions().IsCompositeProperty())
                {
                    throw new XMPException("Alt-text array item is not simple", XMPError.BADXPATH);
                }
                else
                {
                    if (!currItem.HasQualifier() || !XML_LANG.Equals(currItem.GetQualifier(1).GetName
                                                                         ()))
                    {
                        throw new XMPException("Alt-text array item has no language qualifier", XMPError.
                                               BADXPATH);
                    }
                }
                String currLang = currItem.GetQualifier(1).GetValue();
                // Look for an exact match with the specific language.
                if (specificLang.Equals(currLang))
                {
                    return(new Object[] { XMPNodeUtils.CLT_SPECIFIC_MATCH, currItem });
                }
                else
                {
                    if (genericLang != null && currLang.StartsWith(genericLang))
                    {
                        if (resultNode == null)
                        {
                            resultNode = currItem;
                        }
                        // ! Don't return/break, need to look for other matches.
                        foundGenericMatches++;
                    }
                    else
                    {
                        if (X_DEFAULT.Equals(currLang))
                        {
                            xDefault = currItem;
                        }
                    }
                }
            }
            // evaluate loop
            if (foundGenericMatches == 1)
            {
                return(new Object[] { XMPNodeUtils.CLT_SINGLE_GENERIC, resultNode });
            }
            else
            {
                if (foundGenericMatches > 1)
                {
                    return(new Object[] { XMPNodeUtils.CLT_MULTIPLE_GENERIC, resultNode });
                }
                else
                {
                    if (xDefault != null)
                    {
                        return(new Object[] { XMPNodeUtils.CLT_XDEFAULT, xDefault });
                    }
                    else
                    {
                        // Everything failed, choose the first item.
                        return(new Object[] { XMPNodeUtils.CLT_FIRST_ITEM, arrayNode.GetChild(1) });
                    }
                }
            }
        }
Пример #6
0
        /// <summary>Visit all of the top level nodes looking for aliases.</summary>
        /// <remarks>
        /// Visit all of the top level nodes looking for aliases. If there is
        /// no base, transplant the alias subtree. If there is a base and strict
        /// aliasing is on, make sure the alias and base subtrees match.
        /// </remarks>
        /// <param name="tree">the root of the metadata tree</param>
        /// <param name="options">th parsing options</param>
        /// <exception cref="iText.Kernel.XMP.XMPException">Forwards XMP errors</exception>
        private static void MoveExplicitAliases(XMPNode tree, ParseOptions options)
        {
            if (!tree.GetHasAliases())
            {
                return;
            }
            tree.SetHasAliases(false);

            bool        strictAliasing = options.GetStrictAliasing();
            IEnumerator schemaIt       = tree.GetUnmodifiableChildren().GetEnumerator();

            while (schemaIt.MoveNext())
            {
                XMPNode currSchema = (XMPNode)schemaIt.Current;
                if (currSchema == null)
                {
                    continue;
                }
                if (!currSchema.GetHasAliases())
                {
                    continue;
                }

                List <XMPNode> currPropsToRemove = new List <XMPNode>();
                IEnumerator    propertyIt        = currSchema.IterateChildren();
                while (propertyIt.MoveNext())
                {
                    XMPNode currProp = (XMPNode)propertyIt.Current;
                    if (currProp == null)
                    {
                        continue;
                    }

                    if (!currProp.IsAlias())
                    {
                        continue;
                    }

                    currProp.SetAlias(false);

                    // Find the base path, look for the base schema and root node.
                    XMPAliasInfo info = XMPMetaFactory.GetSchemaRegistry().FindAlias(currProp.GetName());
                    if (info != null)
                    {
                        // find or create schema
                        XMPNode baseSchema = XMPNodeUtils.FindSchemaNode(tree, info.GetNamespace(), null, true);
                        baseSchema.SetImplicit(false);

                        XMPNode baseNode = XMPNodeUtils.FindChildNode(baseSchema, info.GetPrefix() + info.GetPropName(), false);
                        if (baseNode == null)
                        {
                            if (info.GetAliasForm().IsSimple())
                            {
                                // A top-to-top alias, transplant the property.
                                // change the alias property name to the base name
                                string qname = info.GetPrefix() + info.GetPropName();
                                currProp.SetName(qname);
                                baseSchema.AddChild(currProp);
                            }
                            else
                            {
                                // An alias to an array item,
                                // create the array and transplant the property.
                                baseNode = new XMPNode(info.GetPrefix() + info.GetPropName(),
                                                       info.GetAliasForm().ToPropertyOptions());
                                baseSchema.AddChild(baseNode);
                                TransplantArrayItemAlias(currProp, baseNode);
                            }
                            currPropsToRemove.Add(currProp);
                        }
                        else if (info.GetAliasForm().IsSimple())
                        {
                            // The base node does exist and this is a top-to-top alias.
                            // Check for conflicts if strict aliasing is on.
                            // Remove and delete the alias subtree.
                            if (strictAliasing)
                            {
                                CompareAliasedSubtrees(currProp, baseNode, true);
                            }
                            currPropsToRemove.Add(currProp);
                        }
                        else
                        {
                            // This is an alias to an array item and the array exists.
                            // Look for the aliased item.
                            // Then transplant or check & delete as appropriate.

                            XMPNode itemNode = null;
                            if (info.GetAliasForm().IsArrayAltText())
                            {
                                int xdIndex = XMPNodeUtils.LookupLanguageItem(baseNode, XMPConst.X_DEFAULT);
                                if (xdIndex != -1)
                                {
                                    itemNode = baseNode.GetChild(xdIndex);
                                }
                            }
                            else if (baseNode.HasChildren())
                            {
                                itemNode = baseNode.GetChild(1);
                            }

                            if (itemNode == null)
                            {
                                TransplantArrayItemAlias(currProp, baseNode);
                            }
                            else
                            {
                                if (strictAliasing)
                                {
                                    CompareAliasedSubtrees(currProp, itemNode, true);
                                }
                            }
                            currPropsToRemove.Add(currProp);
                        }
                    }
                }
                foreach (XMPNode o in currPropsToRemove)
                {
                    currSchema.RemoveChild(o);
                }
                currPropsToRemove.Clear();
                currSchema.SetHasAliases(false);
            }
        }
Пример #7
0
		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 ? iText.Kernel.XMP.Impl.Utils.NormalizeLangValue
				(genericLang) : null;
			specificLang = iText.Kernel.XMP.Impl.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.ARRAY_ORDERED | PropertyOptions.ARRAY_ALTERNATE
				 | PropertyOptions.ARRAY_ALT_TEXT));
			if (arrayNode == null)
			{
				throw new XMPException("Failed to find or create array node", XMPError.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", XMPError.BADXPATH
							);
					}
				}
			}
			// Make sure the x-default item, if any, is first.
			bool haveXDefault = false;
			XMPNode xdItem = null;
			foreach (XMPNode currItem in arrayNode.GetChildren())
			{
				if (!currItem.HasQualifier() || !XMPConst.XML_LANG.Equals(currItem.GetQualifier(1
					).GetName()))
				{
					throw new XMPException("Language qualifier must be first", XMPError.BADXPATH);
				}
				else
				{
					if (XMPConst.X_DEFAULT.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];
			XMPNode itemNode = (XMPNode)result[1];
			bool specificXDefault = XMPConst.X_DEFAULT.Equals(specificLang);
			switch (match)
			{
				case XMPNodeUtils.CLT_NO_VALUES:
				{
					// Create the array items for the specificLang and x-default, with
					// x-default first.
					XMPNodeUtils.AppendLangItem(arrayNode, XMPConst.X_DEFAULT, itemValue);
					haveXDefault = true;
					if (!specificXDefault)
					{
						XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
					}
					break;
				}

				case XMPNodeUtils.CLT_SPECIFIC_MATCH:
				{
					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 (IEnumerator it_1 = arrayNode.IterateChildren(); it_1.MoveNext(); )
						{
							XMPNode currItem = (XMPNode)it_1.Current;
							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.CLT_SINGLE_GENERIC:
				{
					// 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.CLT_MULTIPLE_GENERIC:
				{
					// Create the specific language, ignore x-default.
					XMPNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
					if (specificXDefault)
					{
						haveXDefault = true;
					}
					break;
				}

				case XMPNodeUtils.CLT_XDEFAULT:
				{
					// 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.CLT_FIRST_ITEM:
				{
					// 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", XMPError.INTERNALFAILURE
						);
				}
			}
			// Add an x-default at the front if needed.
			if (!haveXDefault && arrayNode.GetChildrenLength() == 1)
			{
				XMPNodeUtils.AppendLangItem(arrayNode, XMPConst.X_DEFAULT, itemValue);
			}
		}