Beispiel #1
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;
         }
     }
 }
 /// <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)
     {
     }
 }
Beispiel #3
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);
        }
 /// <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);
                 }
             }
         }
     }
 }
Beispiel #5
0
 /// <summary>
 /// Searches for a qualifier selector in a node:
 /// [?qualName="value"] - an element in an array, chosen by a qualifier value.
 /// </summary>
 /// <remarks>
 /// Searches for a qualifier selector in a node:
 /// [?qualName="value"] - an element in an array, chosen by a qualifier value.
 /// No implicit nodes are created for qualifier selectors,
 /// except for an alias to an x-default item.
 /// </remarks>
 /// <param name="arrayNode">an array node</param>
 /// <param name="qualName">the qualifier name</param>
 /// <param name="qualValue">the qualifier value</param>
 /// <param name="aliasForm">
 /// in case the qual selector results from an alias,
 /// an x-default node is created if there has not been one.
 /// </param>
 /// <returns>Returns the index of th</returns>
 /// <exception cref="iText.Kernel.XMP.XMPException"></exception>
 private static int LookupQualSelector(XMPNode arrayNode, String qualName, String
                                       qualValue, int aliasForm)
 {
     if (XML_LANG.Equals(qualName))
     {
         qualValue = iText.Kernel.XMP.Impl.Utils.NormalizeLangValue(qualValue);
         int index = XMPNodeUtils.LookupLanguageItem(arrayNode, qualValue);
         if (index < 0 && (aliasForm & AliasOptions.PROP_ARRAY_ALT_TEXT) > 0)
         {
             XMPNode langNode = new XMPNode(ARRAY_ITEM_NAME, null);
             XMPNode xdefault = new XMPNode(XML_LANG, X_DEFAULT, null);
             langNode.AddQualifier(xdefault);
             arrayNode.AddChild(1, langNode);
             return(1);
         }
         else
         {
             return(index);
         }
     }
     else
     {
         for (int index = 1; index < arrayNode.GetChildrenLength(); index++)
         {
             XMPNode currItem = arrayNode.GetChild(index);
             for (IEnumerator it = currItem.IterateQualifier(); it.MoveNext();)
             {
                 XMPNode qualifier = (XMPNode)it.Current;
                 if (qualName.Equals(qualifier.GetName()) && qualValue.Equals(qualifier.GetValue()
                                                                              ))
                 {
                     return(index);
                 }
             }
         }
         return(-1);
     }
 }
Beispiel #6
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);
 }
Beispiel #7
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) });
                    }
                }
            }
        }
Beispiel #8
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);
        }