Example #1
0
 public virtual string GetNamespace()
 {
     if (!node.GetOptions().IsSchemaNode())
     {
         // determine namespace of leaf node
         QName qname = new QName(node.GetName());
         return(XMPMetaFactory.GetSchemaRegistry().GetNamespaceURI(qname.GetPrefix()));
     }
     return(baseNs);
 }
Example #2
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);
            }
        }
Example #3
0
            /// <summary>
            /// Prepares the next node to return if not already done.
            /// </summary>
            /// <seealso cref="IEnumerator.MoveNext"/>
            public override bool MoveNext()
            {
                if (outerInstance.skipSiblings)
                {
                    return(false);
                }
                if (childrenIterator.MoveNext())
                {
                    XMPNode child = (XMPNode)childrenIterator.Current;
                    if (child != null)
                    {
                        index++;
                        string path = null;
                        if (child.GetOptions().IsSchemaNode())
                        {
                            outerInstance.SetBaseNS(child.GetName());
                        }
                        else if (child.GetParent() != null)
                        {
                            // for all but the root node and schema nodes
                            path = AccumulatePath(child, parentPath, index);
                        }

                        // report next property, skip not-leaf nodes in case options is set
                        if (!outerInstance.GetOptions().IsJustLeafnodes() || !child.HasChildren())
                        {
                            SetReturnProperty(CreatePropertyInfo(child, outerInstance.GetBaseNS(), path));
                            return(true);
                        }
                    }
                    return(MoveNext());
                }
                return(false);
            }
Example #4
0
            /// <param name="currNode"> the node that will be added to the path. </param>
            /// <param name="parentPath"> the path up to this node. </param>
            /// <param name="currentIndex"> the current array index if an arrey is traversed </param>
            /// <returns> Returns the updated path. </returns>
            protected internal virtual String AccumulatePath(XMPNode currNode, string parentPath, int currentIndex)
            {
                String separator;
                String segmentName;

                if (currNode.GetParent() == null || currNode.GetOptions().IsSchemaNode())
                {
                    return(null);
                }
                if (currNode.GetParent().GetOptions().IsArray())
                {
                    separator   = "";
                    segmentName = "[" + Convert.ToString(currentIndex) + "]";
                }
                else
                {
                    separator   = "/";
                    segmentName = currNode.GetName();
                }


                if (String.IsNullOrEmpty(parentPath))
                {
                    return(segmentName);
                }
                if (outerInstance.GetOptions().IsJustLeafname())
                {
                    return(!segmentName.StartsWith("?") ? segmentName : segmentName.Substring(1));                    // qualifier
                }
                return(parentPath + separator + segmentName);
            }
Example #5
0
        /// <summary>
        /// Searches for a field selector in a node:
        /// [fieldName="value] - an element in an array of structs, chosen by a field value.
        /// </summary>
        /// <remarks>
        /// Searches for a field selector in a node:
        /// [fieldName="value] - an element in an array of structs, chosen by a field value.
        /// No implicit nodes are created by field selectors.
        /// </remarks>
        /// <param name="arrayNode"/>
        /// <param name="fieldName"/>
        /// <param name="fieldValue"/>
        /// <returns>Returns the index of the field if found, otherwise -1.</returns>
        /// <exception cref="iText.Kernel.XMP.XMPException"></exception>
        private static int LookupFieldSelector(XMPNode arrayNode, String fieldName, String
                                               fieldValue)
        {
            int result = -1;

            for (int index = 1; index <= arrayNode.GetChildrenLength() && result < 0; index++)
            {
                XMPNode currItem = arrayNode.GetChild(index);
                if (!currItem.GetOptions().IsStruct())
                {
                    throw new XMPException("Field selector must be used on array of struct", XMPError
                                           .BADXPATH);
                }
                for (int f = 1; f <= currItem.GetChildrenLength(); f++)
                {
                    XMPNode currField = currItem.GetChild(f);
                    if (!fieldName.Equals(currField.GetName()))
                    {
                        continue;
                    }
                    if (fieldValue.Equals(currField.GetValue()))
                    {
                        result = index;
                        break;
                    }
                }
            }
            return(result);
        }
Example #6
0
 /// <summary>Make sure the x-default item is first.</summary>
 /// <remarks>
 /// Make sure the x-default item is first. Touch up &quot;single value&quot;
 /// arrays that have a default plus one real language. This case should have
 /// the same value for both items. Older Adobe apps were hardwired to only
 /// use the &quot;x-default&quot; item, so we copy that value to the other
 /// item.
 /// </remarks>
 /// <param name="arrayNode">an alt text array node</param>
 internal static void NormalizeLangArray(XMPNode arrayNode)
 {
     if (!arrayNode.GetOptions().IsArrayAltText())
     {
         return;
     }
     // check if node with x-default qual is first place
     for (int i = 2; i <= arrayNode.GetChildrenLength(); i++)
     {
         XMPNode child = arrayNode.GetChild(i);
         if (child.HasQualifier() && X_DEFAULT.Equals(child.GetQualifier(1).GetValue()))
         {
             // move node to first place
             try
             {
                 arrayNode.RemoveChild(i);
                 arrayNode.AddChild(1, child);
             }
             catch (XMPException)
             {
                 // cannot occur, because same child is removed before
                 System.Diagnostics.Debug.Assert(false);
             }
             if (i == 2)
             {
                 arrayNode.GetChild(2).SetValue(child.GetValue());
             }
             break;
         }
     }
 }
Example #7
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);
            }
        }
		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", XMPError
					.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", XMPError.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", XMPError.BADXPATH);
					}
				}
				else
				{
					// array options missing
					throw new XMPException("Explicit arrayOptions required to create new array", XMPError
						.BADOPTIONS);
				}
			}
			DoSetArrayItem(arrayNode, ARRAY_LAST_ITEM, itemValue, itemOptions, true);
		}
Example #9
0
 /// <summary>
 /// Undo the denormalization performed by the XMP used in Acrobat 5.<br />
 /// If a Dublin Core array had only one item, it was serialized as a simple
 /// property.
 /// </summary>
 /// <remarks>
 /// Undo the denormalization performed by the XMP used in Acrobat 5.<br />
 /// If a Dublin Core array had only one item, it was serialized as a simple
 /// property. <br />
 /// The <code>xml:lang</code> attribute was dropped from an
 /// <code>alt-text</code> item if the language was <code>x-default</code>.
 /// </remarks>
 /// <param name="dcSchema">the DC schema node</param>
 /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if normalization fails
 ///     </exception>
 private static void NormalizeDCArrays(XMPNode dcSchema)
 {
     for (int i = 1; i <= dcSchema.GetChildrenLength(); i++)
     {
         XMPNode         currProp  = dcSchema.GetChild(i);
         PropertyOptions arrayForm = (PropertyOptions)dcArrayForms[currProp.GetName()];
         if (arrayForm == null)
         {
             continue;
         }
         else
         {
             if (currProp.GetOptions().IsSimple())
             {
                 // create a new array and add the current property as child,
                 // if it was formerly simple
                 XMPNode newArray = new XMPNode(currProp.GetName(), arrayForm);
                 currProp.SetName(XMPConst.ARRAY_ITEM_NAME);
                 newArray.AddChild(currProp);
                 dcSchema.ReplaceChild(i, newArray);
                 // fix language alternatives
                 if (arrayForm.IsArrayAltText() && !currProp.GetOptions().GetHasLanguage())
                 {
                     XMPNode newLang = new XMPNode(XMPConst.XML_LANG, XMPConst.X_DEFAULT, null);
                     currProp.AddQualifier(newLang);
                 }
             }
             else
             {
                 // clear array options and add corrected array form if it has been an array before
                 currProp.GetOptions().SetOption(PropertyOptions.ARRAY | PropertyOptions.ARRAY_ORDERED
                                                 | PropertyOptions.ARRAY_ALTERNATE | PropertyOptions.ARRAY_ALT_TEXT, false);
                 currProp.GetOptions().MergeWith(arrayForm);
                 if (arrayForm.IsArrayAltText())
                 {
                     // applying for "dc:description", "dc:rights", "dc:title"
                     RepairAltText(currProp);
                 }
             }
         }
     }
 }
Example #10
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();
 }
Example #11
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);
         }
     }
 }
Example #12
0
        /// <summary>This is setting the value of a leaf node.</summary>
        /// <param name="node">an XMPNode</param>
        /// <param name="value">a value</param>
        internal static void SetNodeValue(XMPNode node, Object value)
        {
            String strValue = SerializeNodeValue(value);

            if (!(node.GetOptions().IsQualifier() && XML_LANG.Equals(node.GetName())))
            {
                node.SetValue(strValue);
            }
            else
            {
                node.SetValue(iText.Kernel.XMP.Impl.Utils.NormalizeLangValue(strValue));
            }
        }
Example #13
0
            /// <summary>
            /// Constructor for the node iterator. </summary>
            /// <param name="visitedNode"> the currently visited node </param>
            /// <param name="parentPath"> the accumulated path of the node </param>
            /// <param name="index"> the index within the parent node (only for arrays) </param>
            public NodeIterator(XMPIteratorImpl outerInstance, XMPNode visitedNode, string parentPath, int index)
            {
                this.outerInstance = outerInstance;
                this.visitedNode   = visitedNode;
                this.state         = ITERATE_NODE;
                if (visitedNode.GetOptions().IsSchemaNode())
                {
                    outerInstance.SetBaseNS(visitedNode.GetName());
                }

                // for all but the root node and schema nodes
                this.path = AccumulatePath(visitedNode, parentPath, index);
            }
Example #14
0
        /// <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="iText.Kernel.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", XMPError
                                           .BADXPATH);
                }
                else
                {
                    if (parent.GetOptions().IsArray())
                    {
                        throw new XMPException("Named children not allowed for arrays", XMPError.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);
        }
Example #15
0
		/// <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="iText.Kernel.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", XMPError.BADXPATH);
				}
				node.RemoveChildren();
			}
		}
Example #16
0
        /// <summary>
        /// Moves an alias node of array form to another schema into an array </summary>
        /// <param name="childNode"> the node to be moved </param>
        /// <param name="baseArray"> the base array for the array item </param>
        /// <exception cref="XMPException"> Forwards XMP errors </exception>
        private static void TransplantArrayItemAlias(XMPNode childNode, XMPNode baseArray)
        {
            if (baseArray.GetOptions().IsArrayAltText())
            {
                if (childNode.GetOptions().GetHasLanguage())
                {
                    throw new XMPException("Alias to x-default already has a language qualifier",
                                           XMPError.BADXMP);
                }

                XMPNode langQual = new XMPNode(XMPConst.XML_LANG, XMPConst.X_DEFAULT, null);
                childNode.AddQualifier(langQual);
            }

            childNode.SetName(XMPConst.ARRAY_ITEM_NAME);
            baseArray.AddChild(childNode);
        }
Example #17
0
		public virtual int CountArrayItems(String schemaNS, String arrayName)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertArrayName(arrayName);
			XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, arrayName);
			XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, false, null);
			if (arrayNode == null)
			{
				return 0;
			}
			if (arrayNode.GetOptions().IsArray())
			{
				return arrayNode.GetChildrenLength();
			}
			else
			{
				throw new XMPException("The named property is not an array", XMPError.BADXPATH);
			}
		}
Example #18
0
        /// <summary>Deletes the the given node and its children from its parent.</summary>
        /// <remarks>
        /// Deletes the the given node and its children from its parent.
        /// Takes care about adjusting the flags.
        /// </remarks>
        /// <param name="node">the top-most node to delete.</param>
        internal static void DeleteNode(XMPNode node)
        {
            XMPNode parent = node.GetParent();

            if (node.GetOptions().IsQualifier())
            {
                // root is qualifier
                parent.RemoveQualifier(node);
            }
            else
            {
                // root is NO qualifier
                parent.RemoveChild(node);
            }
            // delete empty Schema nodes
            if (!parent.HasChildren() && parent.GetOptions().IsSchemaNode())
            {
                parent.GetParent().RemoveChild(parent);
            }
        }
Example #19
0
		/// <summary>Returns a property, but the result value can be requested.</summary>
		/// <seealso cref="iText.Kernel.XMP.XMPMeta.GetProperty(System.String, System.String)
		/// 	"/>
		/// <param name="schemaNS">a schema namespace</param>
		/// <param name="propName">a property name or path</param>
		/// <param name="valueType">the type of the value, see VALUE_...</param>
		/// <returns>
		/// Returns the node value as an object according to the
		/// <code>valueType</code>.
		/// </returns>
		/// <exception cref="iText.Kernel.XMP.XMPException">Collects any exception that occurs.</exception>
		protected internal virtual Object GetPropertyObject(String schemaNS, String propName
			, int valueType)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertPropName(propName);
			XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName);
			XMPNode propNode = XMPNodeUtils.FindNode(tree, expPath, false, null);
			if (propNode != null)
			{
				if (valueType != VALUE_STRING && propNode.GetOptions().IsCompositeProperty())
				{
					throw new XMPException("Property must be simple when a value type is requested", 
						XMPError.BADXPATH);
				}
				return EvaluateNodeValue(valueType, propNode);
			}
			else
			{
				return null;
			}
		}
Example #20
0
 /// <summary>Looks for the appropriate language item in a text alternative array.item
 ///     </summary>
 /// <param name="arrayNode">an array node</param>
 /// <param name="language">the requested language</param>
 /// <returns>Returns the index if the language has been found, -1 otherwise.</returns>
 /// <exception cref="iText.Kernel.XMP.XMPException"/>
 internal static int LookupLanguageItem(XMPNode arrayNode, String language)
 {
     if (!arrayNode.GetOptions().IsArray())
     {
         throw new XMPException("Language item must be used on array", XMPError.BADXPATH);
     }
     for (int index = 1; index <= arrayNode.GetChildrenLength(); index++)
     {
         XMPNode child = arrayNode.GetChild(index);
         if (!child.HasQualifier() || !XML_LANG.Equals(child.GetQualifier(1).GetName()))
         {
             continue;
         }
         else
         {
             if (language.Equals(child.GetQualifier(1).GetValue()))
             {
                 return(index);
             }
         }
     }
     return(-1);
 }
Example #21
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) });
                    }
                }
            }
        }
Example #22
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);
			}
		}
Example #23
0
        /// <summary>
        /// After processing by ExpandXPath, a step can be of these forms:
        /// <ul>
        /// <li>qualName - A top level property or struct field.
        /// </summary>
        /// <remarks>
        /// After processing by ExpandXPath, a step can be of these forms:
        /// <ul>
        /// <li>qualName - A top level property or struct field.
        /// <li>[index] - An element of an array.
        /// <li>[last()] - The last element of an array.
        /// <li>[qualName="value"] - An element in an array of structs, chosen by a field value.
        /// <li>[?qualName="value"] - An element in an array, chosen by a qualifier value.
        /// <li>?qualName - A general qualifier.
        /// </ul>
        /// Find the appropriate child node, resolving aliases, and optionally creating nodes.
        /// </remarks>
        /// <param name="parentNode">the node to start to start from</param>
        /// <param name="nextStep">the xpath segment</param>
        /// <param name="createNodes"></param>
        /// <returns>returns the found or created XMPPath node</returns>
        /// <exception cref="iText.Kernel.XMP.XMPException"></exception>
        private static XMPNode FollowXPathStep(XMPNode parentNode, XMPPathSegment nextStep
                                               , bool createNodes)
        {
            XMPNode nextNode = null;
            int     index    = 0;
            int     stepKind = nextStep.GetKind();

            if (stepKind == XMPPath.STRUCT_FIELD_STEP)
            {
                nextNode = FindChildNode(parentNode, nextStep.GetName(), createNodes);
            }
            else
            {
                if (stepKind == XMPPath.QUALIFIER_STEP)
                {
                    nextNode = FindQualifierNode(parentNode, nextStep.GetName().Substring(1), createNodes
                                                 );
                }
                else
                {
                    // This is an array indexing step. First get the index, then get the node.
                    if (!parentNode.GetOptions().IsArray())
                    {
                        throw new XMPException("Indexing applied to non-array", XMPError.BADXPATH);
                    }
                    if (stepKind == XMPPath.ARRAY_INDEX_STEP)
                    {
                        index = FindIndexedItem(parentNode, nextStep.GetName(), createNodes);
                    }
                    else
                    {
                        if (stepKind == XMPPath.ARRAY_LAST_STEP)
                        {
                            index = parentNode.GetChildrenLength();
                        }
                        else
                        {
                            if (stepKind == XMPPath.FIELD_SELECTOR_STEP)
                            {
                                String[] result     = Utils.SplitNameAndValue(nextStep.GetName());
                                String   fieldName  = result[0];
                                String   fieldValue = result[1];
                                index = LookupFieldSelector(parentNode, fieldName, fieldValue);
                            }
                            else
                            {
                                if (stepKind == XMPPath.QUAL_SELECTOR_STEP)
                                {
                                    String[] result    = Utils.SplitNameAndValue(nextStep.GetName());
                                    String   qualName  = result[0];
                                    String   qualValue = result[1];
                                    index = LookupQualSelector(parentNode, qualName, qualValue, nextStep.GetAliasForm
                                                                   ());
                                }
                                else
                                {
                                    throw new XMPException("Unknown array indexing step in FollowXPathStep", XMPError
                                                           .INTERNALFAILURE);
                                }
                            }
                        }
                    }
                    if (1 <= index && index <= parentNode.GetChildrenLength())
                    {
                        nextNode = parentNode.GetChild(index);
                    }
                }
            }
            return(nextNode);
        }
Example #24
0
            /// <summary>
            /// Creates a property info object from an <code>XMPNode</code>. </summary>
            /// <param name="node"> an <code>XMPNode</code> </param>
            /// <param name="baseNs"> the base namespace to report </param>
            /// <param name="path"> the full property path </param>
            /// <returns> Returns a <code>XMPProperty</code>-object that serves representation of the node. </returns>
            protected internal virtual XMPPropertyInfo CreatePropertyInfo(XMPNode node, String baseNS, String path)
            {
                String value = node.GetOptions().IsSchemaNode() ? null : node.GetValue();

                return(new XMPPropertyInfoImpl(node, baseNS, path, value));
            }
Example #25
0
        /// <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="iText.Kernel.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", XMPError.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.STEP_SCHEMA).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.STRUCT_FIELD_STEP &&
                                    !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);
        }
Example #26
0
		/// <summary>
		/// Evaluates a raw node value to the given value type, apply special
		/// conversions for defined types in XMP.
		/// </summary>
		/// <param name="valueType">an int indicating the value type</param>
		/// <param name="propNode">the node containing the value</param>
		/// <returns>Returns a literal value for the node.</returns>
		/// <exception cref="iText.Kernel.XMP.XMPException">
		/// if the value of <code>propNode</code> is <code>null</code> or empty or the conversion fails.
		/// </exception>
		private Object EvaluateNodeValue(int valueType, XMPNode propNode)
		{
			Object value;
			String rawValue = propNode.GetValue();
			switch (valueType)
			{
				case VALUE_BOOLEAN:
				{
					value = XMPUtils.ConvertToBoolean(rawValue);
					break;
				}

				case VALUE_INTEGER:
				{
					value = XMPUtils.ConvertToInteger(rawValue);
					break;
				}

				case VALUE_LONG:
				{
					value = XMPUtils.ConvertToLong(rawValue);
					break;
				}

				case VALUE_DOUBLE:
				{
					value = XMPUtils.ConvertToDouble(rawValue);
					break;
				}

				case VALUE_DATE:
				{
					value = XMPUtils.ConvertToDate(rawValue);
					break;
				}

				case VALUE_CALENDAR:
				{
					XMPDateTime dt = XMPUtils.ConvertToDate(rawValue);
					value = dt.GetCalendar();
					break;
				}

				case VALUE_BASE64:
				{
					value = XMPUtils.DecodeBase64(rawValue);
					break;
				}

				case VALUE_STRING:
				default:
				{
					// leaf values return empty string instead of null
					// for the other cases the converter methods provides a "null"
					// value.
					// a default value can only occur if this method is made public.
					value = rawValue != null || propNode.GetOptions().IsCompositeProperty() ? rawValue
						 : "";
					break;
				}
			}
			return value;
		}