예제 #1
0
        /// <summary>Constructor with optionsl initial values.</summary>
        /// <remarks>
        /// Constructor with optionsl initial values. If <code>propName</code> is provided,
        /// <code>schemaNS</code> has also be provided.
        /// </remarks>
        /// <param name="xmp">the iterated metadata object.</param>
        /// <param name="schemaNS">the iteration is reduced to this schema (optional)</param>
        /// <param name="propPath">the iteration is redurce to this property within the <code>schemaNS</code>
        ///     </param>
        /// <param name="options">
        /// advanced iteration options, see
        /// <see cref="iText.Kernel.XMP.Options.IteratorOptions"/>
        /// </param>
        /// <exception cref="iText.Kernel.XMP.XMPException">If the node defined by the paramters is not existing.
        ///     </exception>
        public XMPIteratorImpl(XMPMetaImpl xmp, String schemaNS, String propPath, IteratorOptions
                               options)
        {
            // make sure that options is defined at least with defaults
            this.options = options ?? new IteratorOptions();

            // the start node of the iteration depending on the schema and property filter
            XMPNode startNode;
            string  initialPath  = null;
            bool    baseSchema   = !String.IsNullOrEmpty(schemaNS);
            bool    baseProperty = !String.IsNullOrEmpty(propPath);

            if (!baseSchema && !baseProperty)
            {
                // complete tree will be iterated
                startNode = xmp.GetRoot();
            }
            else if (baseSchema && baseProperty)
            {
                // Schema and property node provided
                XMPPath path = XMPPathParser.ExpandXPath(schemaNS, propPath);

                // base path is the prop path without the property leaf
                XMPPath basePath = new XMPPath();
                for (int i = 0; i < path.Size() - 1; i++)
                {
                    basePath.Add(path.GetSegment(i));
                }

                startNode   = XMPNodeUtils.FindNode(xmp.GetRoot(), path, false, null);
                this.baseNS = schemaNS;
                initialPath = basePath.ToString();
            }
            else if (baseSchema && !baseProperty)
            {
                // Only Schema provided
                startNode = XMPNodeUtils.FindSchemaNode(xmp.GetRoot(), schemaNS, false);
            }
            else             // !baseSchema  &&  baseProperty
            {
                // No schema but property provided -> error
                throw new XMPException("Schema namespace URI is required", XMPError.BADSCHEMA);
            }


            // create iterator
            if (startNode != null)
            {
                this.nodeIterator = (!this.options.IsJustChildren())
                                        ? new NodeIterator(this, startNode, initialPath, 1)
                                        : new NodeIteratorChildren(this, startNode, initialPath);
            }
            else
            {
                // create null iterator
                this.nodeIterator = EmptyList.GetEnumerator();
            }
        }
예제 #2
0
        /// <summary>Compose the path expression to select an alternate item by a field's value.</summary>
        /// <remarks>
        /// Compose the path expression to select an alternate item by a field's value. The path syntax
        /// allows two forms of &quot;content addressing&quot; that may be used to select an item in an
        /// array of alternatives. The form used in ComposeFieldSelector lets you select an item in an
        /// array of structs based on the value of one of the fields in the structs. The other form of
        /// content addressing is shown in ComposeLangSelector. For example, consider a simple struct
        /// that has two fields, the name of a city and the URI of an FTP site in that city. Use this to
        /// create an array of download alternatives. You can show the user a popup built from the values
        /// of the city fields. You can then get the corresponding URI as follows:
        /// <p>
        /// <blockquote>
        /// <pre>
        /// String path = composeFieldSelector ( schemaNS, &quot;Downloads&quot;, fieldNS,
        /// &quot;City&quot;, chosenCity );
        /// XMPProperty prop = xmpObj.getStructField ( schemaNS, path, fieldNS, &quot;URI&quot; );
        /// </pre>
        /// </blockquote>
        /// </remarks>
        /// <param name="arrayName">
        /// The name of the array. May be a general path expression, must not be
        /// <code>null</code> or the empty string.
        /// </param>
        /// <param name="fieldNS">
        /// The namespace URI for the field used as the selector. Must not be
        /// <code>null</code> or the empty string.
        /// </param>
        /// <param name="fieldName">
        /// The name of the field used as the selector. Must be a simple XML name, must
        /// not be <code>null</code> or the empty string. It must be the name of a field that is
        /// itself simple.
        /// </param>
        /// <param name="fieldValue">The desired value of the field.</param>
        /// <returns>
        /// Returns the composed path. This will be of the form
        /// <tt>ns:arrayName[fNS:fieldName='fieldValue']</tt>, where &quot;ns&quot; is the
        /// prefix for schemaNS and &quot;fNS&quot; is the prefix for fieldNS.
        /// </returns>
        /// <exception cref="XMPException">Thrown if the path to create is not valid.</exception>
        /// <exception cref="Com.Adobe.Xmp.XMPException"/>
        public static string ComposeFieldSelector(string arrayName, string fieldNS, string fieldName, string fieldValue)
        {
            XMPPath fieldPath = XMPPathParser.ExpandXPath(fieldNS, fieldName);

            if (fieldPath.Size() != 2)
            {
                throw new XMPException("The fieldName name must be simple", XMPErrorConstants.Badxpath);
            }
            return(arrayName + '[' + fieldPath.GetSegment(XMPPath.StepRootProp).GetName() + "=\"" + fieldValue + "\"]");
        }
예제 #3
0
        /// <summary>Compose the path expression to select an alternate item by a field's value.</summary>
        /// <remarks>
        /// Compose the path expression to select an alternate item by a field's value. The path syntax
        /// allows two forms of &amp;quot;content addressing&amp;quot; that may be used to select an item in an
        /// array of alternatives. The form used in ComposeFieldSelector lets you select an item in an
        /// array of structs based on the value of one of the fields in the structs. The other form of
        /// content addressing is shown in ComposeLangSelector. For example, consider a simple struct
        /// that has two fields, the name of a city and the URI of an FTP site in that city. Use this to
        /// create an array of download alternatives. You can show the user a popup built from the values
        /// of the city fields. You can then get the corresponding URI as follows:
        /// <blockquote>
        /// <pre>
        /// String path = composeFieldSelector ( schemaNS, &amp;quot;Downloads&amp;quot;, fieldNS,
        /// &amp;quot;City&amp;quot;, chosenCity );
        /// XMPProperty prop = xmpObj.getStructField ( schemaNS, path, fieldNS, &amp;quot;URI&amp;quot; );
        /// </pre>
        /// </blockquote>
        /// </remarks>
        /// <param name="arrayName">
        /// The name of the array. May be a general path expression, must not be
        /// <c>null</c> or the empty string.
        /// </param>
        /// <param name="fieldNS">
        /// The namespace URI for the field used as the selector. Must not be
        /// <c>null</c> or the empty string.
        /// </param>
        /// <param name="fieldName">
        /// The name of the field used as the selector. Must be a simple XML name, must
        /// not be <c>null</c> or the empty string. It must be the name of a field that is
        /// itself simple.
        /// </param>
        /// <param name="fieldValue">The desired value of the field.</param>
        /// <returns>
        /// Returns the composed path. This will be of the form
        /// <tt>ns:arrayName[fNS:fieldName='fieldValue']</tt>, where &amp;quot;ns&amp;quot; is the
        /// prefix for schemaNS and &amp;quot;fNS&amp;quot; is the prefix for fieldNS.
        /// </returns>
        public static String ComposeFieldSelector(String arrayName, String fieldNS, String fieldName, String fieldValue
                                                  )
        {
            XMPPath fieldPath = XMPPathParser.ExpandXPath(fieldNS, fieldName);

            if (fieldPath.Size() != 2)
            {
                throw new XMPException("The fieldName name must be simple", XMPError.BADXPATH);
            }
            return(arrayName + '[' + fieldPath.GetSegment(XMPPath.STEP_ROOT_PROP).GetName() + "=\"" + fieldValue + "\"]");
        }
예제 #4
0
        /// <summary>Compose the path expression for a qualifier.</summary>
        /// <param name="qualNS">
        /// The namespace URI for the qualifier. May be <c>null</c> or the empty
        /// string if the qualifier is in the XML empty namespace.
        /// </param>
        /// <param name="qualName">
        /// The name of the qualifier. Must be a simple XML name, must not be
        /// <c>null</c> or the empty string.
        /// </param>
        /// <returns>
        /// Returns the composed path. This will be of the form
        /// <tt>ns:propName/?qNS:qualName</tt>, where &amp;quot;ns&amp;quot; is the prefix for
        /// schemaNS and &amp;quot;qNS&amp;quot; is the prefix for qualNS.
        /// </returns>
        public static String ComposeQualifierPath(String qualNS, String qualName)
        {
            AssertQualNS(qualNS);
            AssertQualName(qualName);
            XMPPath qualPath = XMPPathParser.ExpandXPath(qualNS, qualName);

            if (qualPath.Size() != 2)
            {
                throw new XMPException("The qualifier name must be simple", XMPError.BADXPATH);
            }
            return("/?" + qualPath.GetSegment(XMPPath.STEP_ROOT_PROP).GetName());
        }
예제 #5
0
        /// <summary>Compose the path expression for a field in a struct.</summary>
        /// <remarks>
        /// Compose the path expression for a field in a struct. The result can be added to the
        /// path of
        /// </remarks>
        /// <param name="fieldNS">
        /// The namespace URI for the field. Must not be <c>null</c> or the empty
        /// string.
        /// </param>
        /// <param name="fieldName">
        /// The name of the field. Must be a simple XML name, must not be
        /// <c>null</c> or the empty string.
        /// </param>
        /// <returns>
        /// Returns the composed path. This will be of the form
        /// <tt>ns:structName/fNS:fieldName</tt>, where &amp;quot;ns&amp;quot; is the prefix for
        /// schemaNS and &amp;quot;fNS&amp;quot; is the prefix for fieldNS.
        /// </returns>
        public static String ComposeStructFieldPath(String fieldNS, String fieldName)
        {
            AssertFieldNS(fieldNS);
            AssertFieldName(fieldName);
            XMPPath fieldPath = XMPPathParser.ExpandXPath(fieldNS, fieldName);

            if (fieldPath.Size() != 2)
            {
                throw new XMPException("The field name must be simple", XMPError.BADXPATH);
            }
            return('/' + fieldPath.GetSegment(XMPPath.STEP_ROOT_PROP).GetName());
        }
예제 #6
0
        /// <summary>Compose the path expression for a qualifier.</summary>
        /// <param name="qualNS">
        /// The namespace URI for the qualifier. May be <code>null</code> or the empty
        /// string if the qualifier is in the XML empty namespace.
        /// </param>
        /// <param name="qualName">
        /// The name of the qualifier. Must be a simple XML name, must not be
        /// <code>null</code> or the empty string.
        /// </param>
        /// <returns>
        /// Returns the composed path. This will be of the form
        /// <tt>ns:propName/?qNS:qualName</tt>, where &quot;ns&quot; is the prefix for
        /// schemaNS and &quot;qNS&quot; is the prefix for qualNS.
        /// </returns>
        /// <exception cref="XMPException">Thrown if the path to create is not valid.</exception>
        /// <exception cref="Com.Adobe.Xmp.XMPException"/>
        public static string ComposeQualifierPath(string qualNS, string qualName)
        {
            AssertQualNS(qualNS);
            AssertQualName(qualName);
            XMPPath qualPath = XMPPathParser.ExpandXPath(qualNS, qualName);

            if (qualPath.Size() != 2)
            {
                throw new XMPException("The qualifier name must be simple", XMPErrorConstants.Badxpath);
            }
            return("/?" + qualPath.GetSegment(XMPPath.StepRootProp).GetName());
        }
예제 #7
0
        /// <summary>Compose the path expression for a field in a struct.</summary>
        /// <remarks>
        /// Compose the path expression for a field in a struct. The result can be added to the
        /// path of
        /// </remarks>
        /// <param name="fieldNS">
        /// The namespace URI for the field. Must not be <code>null</code> or the empty
        /// string.
        /// </param>
        /// <param name="fieldName">
        /// The name of the field. Must be a simple XML name, must not be
        /// <code>null</code> or the empty string.
        /// </param>
        /// <returns>
        /// Returns the composed path. This will be of the form
        /// <tt>ns:structName/fNS:fieldName</tt>, where &quot;ns&quot; is the prefix for
        /// schemaNS and &quot;fNS&quot; is the prefix for fieldNS.
        /// </returns>
        /// <exception cref="XMPException">Thrown if the path to create is not valid.</exception>
        /// <exception cref="Com.Adobe.Xmp.XMPException"/>
        public static string ComposeStructFieldPath(string fieldNS, string fieldName)
        {
            AssertFieldNS(fieldNS);
            AssertFieldName(fieldName);
            XMPPath fieldPath = XMPPathParser.ExpandXPath(fieldNS, fieldName);

            if (fieldPath.Size() != 2)
            {
                throw new XMPException("The field name must be simple", XMPErrorConstants.Badxpath);
            }
            return('/' + fieldPath.GetSegment(XMPPath.StepRootProp).GetName());
        }
예제 #8
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="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);
        }
예제 #9
0
        /// <seealso cref="Com.Adobe.Xmp.XMPUtils.RemoveProperties(Com.Adobe.Xmp.XMPMeta, string, string, bool, bool)"/>
        /// <param name="xmp">The XMP object containing the properties to be removed.</param>
        /// <param name="schemaNS">
        /// Optional schema namespace URI for the properties to be
        /// removed.
        /// </param>
        /// <param name="propName">Optional path expression for the property to be removed.</param>
        /// <param name="doAllProperties">
        /// Option flag to control the deletion: do internal properties in
        /// addition to external properties.
        /// </param>
        /// <param name="includeAliases">
        /// Option flag to control the deletion: Include aliases in the
        /// "named schema" case above.
        /// </param>
        /// <exception cref="Com.Adobe.Xmp.XMPException">If metadata processing fails</exception>
        public static void RemoveProperties(XMPMeta xmp, string schemaNS, string propName, bool doAllProperties, bool includeAliases)
        {
            ParameterAsserts.AssertImplementation(xmp);
            XMPMetaImpl xmpImpl = (XMPMetaImpl)xmp;

            if (propName != null && propName.Length > 0)
            {
                // Remove just the one indicated property. This might be an alias,
                // the named schema might not actually exist. So don't lookup the
                // schema node.
                if (schemaNS == null || schemaNS.Length == 0)
                {
                    throw new XMPException("Property name requires schema namespace", XMPErrorConstants.Badparam);
                }
                XMPPath expPath  = XMPPathParser.ExpandXPath(schemaNS, propName);
                XMPNode propNode = XMPNodeUtils.FindNode(xmpImpl.GetRoot(), expPath, false, null);
                if (propNode != null)
                {
                    if (doAllProperties || !Utils.IsInternalProperty(expPath.GetSegment(XMPPath.StepSchema).GetName(), expPath.GetSegment(XMPPath.StepRootProp).GetName()))
                    {
                        XMPNode parent = propNode.GetParent();
                        parent.RemoveChild(propNode);
                        if (parent.GetOptions().IsSchemaNode() && !parent.HasChildren())
                        {
                            // remove empty schema node
                            parent.GetParent().RemoveChild(parent);
                        }
                    }
                }
            }
            else
            {
                if (schemaNS != null && schemaNS.Length > 0)
                {
                    // Remove all properties from the named schema. Optionally include
                    // aliases, in which case
                    // there might not be an actual schema node.
                    // XMP_NodePtrPos schemaPos;
                    XMPNode schemaNode = XMPNodeUtils.FindSchemaNode(xmpImpl.GetRoot(), schemaNS, false);
                    if (schemaNode != null)
                    {
                        if (RemoveSchemaChildren(schemaNode, doAllProperties))
                        {
                            xmpImpl.GetRoot().RemoveChild(schemaNode);
                        }
                    }
                    if (includeAliases)
                    {
                        // We're removing the aliases also. Look them up by their
                        // namespace prefix.
                        // But that takes more code and the extra speed isn't worth it.
                        // Lookup the XMP node
                        // from the alias, to make sure the actual exists.
                        XMPAliasInfo[] aliases = XMPMetaFactory.GetSchemaRegistry().FindAliases(schemaNS);
                        for (int i = 0; i < aliases.Length; i++)
                        {
                            XMPAliasInfo info       = aliases[i];
                            XMPPath      path       = XMPPathParser.ExpandXPath(info.GetNamespace(), info.GetPropName());
                            XMPNode      actualProp = XMPNodeUtils.FindNode(xmpImpl.GetRoot(), path, false, null);
                            if (actualProp != null)
                            {
                                XMPNode parent = actualProp.GetParent();
                                parent.RemoveChild(actualProp);
                            }
                        }
                    }
                }
                else
                {
                    // Remove all appropriate properties from all schema. In this case
                    // we don't have to be
                    // concerned with aliases, they are handled implicitly from the
                    // actual properties.
                    for (Iterator it = xmpImpl.GetRoot().IterateChildren(); it.HasNext();)
                    {
                        XMPNode schema = (XMPNode)it.Next();
                        if (RemoveSchemaChildren(schema, doAllProperties))
                        {
                            it.Remove();
                        }
                    }
                }
            }
        }
예제 #10
0
        /// <summary>Constructor with optionsl initial values.</summary>
        /// <remarks>
        /// Constructor with optionsl initial values. If <code>propName</code> is provided,
        /// <code>schemaNS</code> has also be provided.
        /// </remarks>
        /// <param name="xmp">the iterated metadata object.</param>
        /// <param name="schemaNS">the iteration is reduced to this schema (optional)</param>
        /// <param name="propPath">the iteration is redurce to this property within the <code>schemaNS</code></param>
        /// <param name="options">
        /// advanced iteration options, see
        /// <see cref="Com.Adobe.Xmp.Options.IteratorOptions"/>
        /// </param>
        /// <exception cref="Com.Adobe.Xmp.XMPException">If the node defined by the paramters is not existing.</exception>
        public XMPIteratorImpl(XMPMetaImpl xmp, string schemaNS, string propPath, IteratorOptions options)
        {
            // make sure that options is defined at least with defaults
            this.options = options != null ? options : new IteratorOptions();
            // the start node of the iteration depending on the schema and property filter
            XMPNode startNode    = null;
            string  initialPath  = null;
            bool    baseSchema   = schemaNS != null && schemaNS.Length > 0;
            bool    baseProperty = propPath != null && propPath.Length > 0;

            if (!baseSchema && !baseProperty)
            {
                // complete tree will be iterated
                startNode = xmp.GetRoot();
            }
            else
            {
                if (baseSchema && baseProperty)
                {
                    // Schema and property node provided
                    XMPPath path = XMPPathParser.ExpandXPath(schemaNS, propPath);
                    // base path is the prop path without the property leaf
                    XMPPath basePath = new XMPPath();
                    for (int i = 0; i < path.Size() - 1; i++)
                    {
                        basePath.Add(path.GetSegment(i));
                    }
                    startNode   = XMPNodeUtils.FindNode(xmp.GetRoot(), path, false, null);
                    baseNS      = schemaNS;
                    initialPath = basePath.ToString();
                }
                else
                {
                    if (baseSchema && !baseProperty)
                    {
                        // Only Schema provided
                        startNode = XMPNodeUtils.FindSchemaNode(xmp.GetRoot(), schemaNS, false);
                    }
                    else
                    {
                        // !baseSchema  &&  baseProperty
                        // No schema but property provided -> error
                        throw new XMPException("Schema namespace URI is required", XMPErrorConstants.Badschema);
                    }
                }
            }
            // create iterator
            if (startNode != null)
            {
                if (!this.options.IsJustChildren())
                {
                    nodeIterator = new XMPIteratorImpl.NodeIterator(this, startNode, initialPath, 1);
                }
                else
                {
                    nodeIterator = new XMPIteratorImpl.NodeIteratorChildren(this, startNode, initialPath);
                }
            }
            else
            {
                // create null iterator
                nodeIterator = Collections.EmptyList().ListIterator();
            }
        }