/// <summary>
 /// The initial support for WAV files mapped a legacy ID3 audio copyright
 /// into a new xmpDM:copyright property.
 /// </summary>
 /// <remarks>
 /// The initial support for WAV files mapped a legacy ID3 audio copyright
 /// into a new xmpDM:copyright property. This is special case code to migrate
 /// that into dc:rights['x-default']. The rules:
 /// <pre>
 /// 1. If there is no dc:rights array, or an empty array -
 /// Create one with dc:rights['x-default'] set from double linefeed and xmpDM:copyright.
 /// 2. If there is a dc:rights array but it has no x-default item -
 /// Create an x-default item as a copy of the first item then apply rule #3.
 /// 3. If there is a dc:rights array with an x-default item,
 /// Look for a double linefeed in the value.
 /// A. If no double linefeed, compare the x-default value to the xmpDM:copyright value.
 /// A1. If they match then leave the x-default value alone.
 /// A2. Otherwise, append a double linefeed and
 /// the xmpDM:copyright value to the x-default value.
 /// B. If there is a double linefeed, compare the trailing text to the xmpDM:copyright value.
 /// B1. If they match then leave the x-default value alone.
 /// B2. Otherwise, replace the trailing x-default text with the xmpDM:copyright value.
 /// 4. In all cases, delete the xmpDM:copyright property.
 /// </pre>
 /// </remarks>
 /// <param name="xmp">the metadata object</param>
 /// <param name="dmCopyright">the "dm:copyright"-property</param>
 private static void MigrateAudioCopyright(XMPMeta xmp, XMPNode dmCopyright)
 {
     try
     {
         XMPNode dcSchema = XMPNodeUtils.FindSchemaNode(((XMPMetaImpl)xmp).GetRoot(), XMPConst
                                                        .NS_DC, true);
         String  dmValue       = dmCopyright.GetValue();
         String  doubleLF      = "\n\n";
         XMPNode dcRightsArray = XMPNodeUtils.FindChildNode(dcSchema, "dc:rights", false);
         if (dcRightsArray == null || !dcRightsArray.HasChildren())
         {
             // 1. No dc:rights array, create from double linefeed and xmpDM:copyright.
             dmValue = doubleLF + dmValue;
             xmp.SetLocalizedText(XMPConst.NS_DC, "rights", "", XMPConst.X_DEFAULT, dmValue, null
                                  );
         }
         else
         {
             int xdIndex = XMPNodeUtils.LookupLanguageItem(dcRightsArray, XMPConst.X_DEFAULT);
             if (xdIndex < 0)
             {
                 // 2. No x-default item, create from the first item.
                 String firstValue = dcRightsArray.GetChild(1).GetValue();
                 xmp.SetLocalizedText(XMPConst.NS_DC, "rights", "", XMPConst.X_DEFAULT, firstValue
                                      , null);
                 xdIndex = XMPNodeUtils.LookupLanguageItem(dcRightsArray, XMPConst.X_DEFAULT);
             }
             // 3. Look for a double linefeed in the x-default value.
             XMPNode defaultNode  = dcRightsArray.GetChild(xdIndex);
             String  defaultValue = defaultNode.GetValue();
             int     lfPos        = defaultValue.IndexOf(doubleLF);
             if (lfPos < 0)
             {
                 // 3A. No double LF, compare whole values.
                 if (!dmValue.Equals(defaultValue))
                 {
                     // 3A2. Append the xmpDM:copyright to the x-default
                     // item.
                     defaultNode.SetValue(defaultValue + doubleLF + dmValue);
                 }
             }
             else
             {
                 // 3B. Has double LF, compare the tail.
                 if (!defaultValue.Substring(lfPos + 2).Equals(dmValue))
                 {
                     // 3B2. Replace the x-default tail.
                     defaultNode.SetValue(defaultValue.JSubstring(0, lfPos + 2) + dmValue);
                 }
             }
         }
         // 4. Get rid of the xmpDM:copyright.
         dmCopyright.GetParent().RemoveChild(dmCopyright);
     }
     catch (XMPException)
     {
     }
 }
Exemple #2
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();
            }
        }
 /// <summary>Visit all schemas to do general fixes and handle special cases.</summary>
 /// <param name="xmp">the metadata object implementation</param>
 /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if the normalisation fails.
 ///     </exception>
 private static void TouchUpDataModel(XMPMetaImpl xmp)
 {
     // make sure the DC schema is existing, because it might be needed within the normalization
     // if not touched it will be removed by removeEmptySchemas
     XMPNodeUtils.FindSchemaNode(xmp.GetRoot(), XMPConst.NS_DC, true);
     // Do the special case fixes within each schema.
     for (IEnumerator it = xmp.GetRoot().IterateChildren(); it.MoveNext();)
     {
         XMPNode currSchema = (XMPNode)it.Current;
         if (XMPConst.NS_DC.Equals(currSchema.GetName()))
         {
             NormalizeDCArrays(currSchema);
         }
         else
         {
             if (XMPConst.NS_EXIF.Equals(currSchema.GetName()))
             {
                 // Do a special case fix for exif:GPSTimeStamp.
                 FixGPSTimeStamp(currSchema);
                 XMPNode arrayNode = XMPNodeUtils.FindChildNode(currSchema, "exif:UserComment", false
                                                                );
                 if (arrayNode != null)
                 {
                     RepairAltText(arrayNode);
                 }
             }
             else
             {
                 if (XMPConst.NS_DM.Equals(currSchema.GetName()))
                 {
                     // Do a special case migration of xmpDM:copyright to
                     // dc:rights['x-default'].
                     XMPNode dmCopyright = XMPNodeUtils.FindChildNode(currSchema, "xmpDM:copyright", false
                                                                      );
                     if (dmCopyright != null)
                     {
                         MigrateAudioCopyright(xmp, dmCopyright);
                     }
                 }
                 else
                 {
                     if (XMPConst.NS_XMP_RIGHTS.Equals(currSchema.GetName()))
                     {
                         XMPNode arrayNode = XMPNodeUtils.FindChildNode(currSchema, "xmpRights:UsageTerms"
                                                                        , false);
                         if (arrayNode != null)
                         {
                             RepairAltText(arrayNode);
                         }
                     }
                 }
             }
         }
     }
 }
        /// <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);
            }
        }