예제 #1
0
		public virtual XMPProperty GetLocalizedText(String schemaNS, String altTextName, 
			String genericLang, String specificLang)
		{
			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);
			XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, false, null);
			if (arrayNode == null)
			{
				return null;
			}
			Object[] result = XMPNodeUtils.ChooseLocalizedText(arrayNode, genericLang, specificLang
				);
			int match = (int)result[0];
			XMPNode itemNode = (XMPNode)result[1];
			if (match != XMPNodeUtils.CLT_NO_VALUES)
			{
				return new _XMPProperty_428(itemNode);
			}
			else
			{
				return null;
			}
		}
예제 #2
0
        /// <summary>Fixes the GPS Timestamp in EXIF.</summary>
        /// <param name="exifSchema">the EXIF schema node</param>
        /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if the date conversion fails.
        ///     </exception>
        private static void FixGPSTimeStamp(XMPNode exifSchema)
        {
            // Note: if dates are not found the convert-methods throws an exceptions,
            //       and this methods returns.
            XMPNode gpsDateTime = XMPNodeUtils.FindChildNode(exifSchema, "exif:GPSTimeStamp", false);

            if (gpsDateTime == null)
            {
                return;
            }

            try {
                XMPDateTime binGpsStamp = XMPUtils.ConvertToDate(gpsDateTime.GetValue());
                if (binGpsStamp.GetYear() != 0 || binGpsStamp.GetMonth() != 0 || binGpsStamp.GetDay() != 0)
                {
                    return;
                }

                XMPNode otherDate = XMPNodeUtils.FindChildNode(exifSchema, "exif:DateTimeOriginal", false);
                otherDate = otherDate ?? XMPNodeUtils.FindChildNode(exifSchema, "exif:DateTimeDigitized", false);

                XMPDateTime binOtherDate = XMPUtils.ConvertToDate(otherDate.GetValue());
                XMPCalendar cal          = binGpsStamp.GetCalendar();
                DateTime    dt           = new DateTime(binOtherDate.GetYear(), binOtherDate.GetMonth(), binOtherDate.GetDay(),
                                                        cal.GetDateTime().Hour, cal.GetDateTime().Minute, cal.GetDateTime().Second, cal.GetDateTime().Millisecond);
                cal.SetDateTime(dt);
                binGpsStamp = new XMPDateTimeImpl(cal);
                gpsDateTime.SetValue(XMPUtils.ConvertFromDate(binGpsStamp));
            }
            catch (XMPException) {
            }
        }
예제 #3
0
 /// <summary>
 /// Tweak old XMP: Move an instance ID from rdf:about to the
 /// <em>xmpMM:InstanceID</em> property.
 /// </summary>
 /// <remarks>
 /// Tweak old XMP: Move an instance ID from rdf:about to the
 /// <em>xmpMM:InstanceID</em> property. An old instance ID usually looks
 /// like &quot;uuid:bac965c4-9d87-11d9-9a30-000d936b79c4&quot;, plus InDesign
 /// 3.0 wrote them like &quot;bac965c4-9d87-11d9-9a30-000d936b79c4&quot;. If
 /// the name looks like a UUID simply move it to <em>xmpMM:InstanceID</em>,
 /// don't worry about any existing <em>xmpMM:InstanceID</em>. Both will
 /// only be present when a newer file with the <em>xmpMM:InstanceID</em>
 /// property is updated by an old app that uses <em>rdf:about</em>.
 /// </remarks>
 /// <param name="tree">the root of the metadata tree</param>
 /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if tweaking fails.</exception>
 private static void TweakOldXMP(XMPNode tree)
 {
     if (tree.GetName() != null && tree.GetName().Length >= Utils.UUID_LENGTH)
     {
         String nameStr = tree.GetName().ToLower();
         if (nameStr.StartsWith("uuid:"))
         {
             nameStr = nameStr.Substring(5);
         }
         if (Utils.CheckUUIDFormat(nameStr))
         {
             // move UUID to xmpMM:InstanceID and remove it from the root node
             XMPPath path   = XMPPathParser.ExpandXPath(XMPConst.NS_XMP_MM, "InstanceID");
             XMPNode idNode = XMPNodeUtils.FindNode(tree, path, true, null);
             if (idNode != null)
             {
                 idNode.SetOptions(null);
                 // Clobber any existing xmpMM:InstanceID.
                 idNode.SetValue("uuid:" + nameStr);
                 idNode.RemoveChildren();
                 idNode.RemoveQualifiers();
                 tree.SetName(null);
             }
             else
             {
                 throw new XMPException("Failure creating xmpMM:InstanceID", XMPError.INTERNALFAILURE
                                        );
             }
         }
     }
 }
예제 #4
0
		// -------------------------------------------------------------------------------------
		// private
		/// <summary>Locate or create the item node and set the value.</summary>
		/// <remarks>
		/// Locate or create the item node and set the value. Note the index
		/// parameter is one-based! The index can be in the range [1..size + 1] or
		/// "last()", normalize it and check the insert flags. The order of the
		/// normalization checks is important. If the array is empty we end up with
		/// an index and location to set item size + 1.
		/// </remarks>
		/// <param name="arrayNode">an array node</param>
		/// <param name="itemIndex">the index where to insert the item</param>
		/// <param name="itemValue">the item value</param>
		/// <param name="itemOptions">the options for the new item</param>
		/// <param name="insert">insert oder overwrite at index position?</param>
		/// <exception cref="iText.Kernel.XMP.XMPException">array item cannot be set</exception>
		private void DoSetArrayItem(XMPNode arrayNode, int itemIndex, String itemValue, PropertyOptions
			 itemOptions, bool insert)
		{
			XMPNode itemNode = new XMPNode(ARRAY_ITEM_NAME, null);
			itemOptions = XMPNodeUtils.VerifySetOptions(itemOptions, itemValue);
			// in insert mode the index after the last is allowed,
			// even ARRAY_LAST_ITEM points to the index *after* the last.
			int maxIndex = insert ? arrayNode.GetChildrenLength() + 1 : arrayNode.GetChildrenLength
				();
			if (itemIndex == ARRAY_LAST_ITEM)
			{
				itemIndex = maxIndex;
			}
			if (1 <= itemIndex && itemIndex <= maxIndex)
			{
				if (!insert)
				{
					arrayNode.RemoveChild(itemIndex);
				}
				arrayNode.AddChild(itemIndex, itemNode);
				SetNode(itemNode, itemValue, itemOptions, false);
			}
			else
			{
				throw new XMPException("Array index out of bounds", XMPError.BADINDEX);
			}
		}
예제 #5
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();
            }
        }
예제 #6
0
 /// <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)
     {
     }
 }
예제 #7
0
		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);
		}
예제 #8
0
 /// <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);
                         }
                     }
                 }
             }
         }
     }
 }
예제 #9
0
 /// <summary>Associates an alias name with an actual name.</summary>
 /// <remarks>
 /// Associates an alias name with an actual name.
 /// <para>
 /// Define a alias mapping from one namespace/property to another. Both
 /// property names must be simple names. An alias can be a direct mapping,
 /// where the alias and actual have the same data type. It is also possible
 /// to map a simple alias to an item in an array. This can either be to the
 /// first item in the array, or to the 'x-default' item in an alt-text array.
 /// Multiple alias names may map to the same actual, as long as the forms
 /// match. It is a no-op to reregister an alias in an identical fashion.
 /// Note: This method is not locking because only called by registerStandardAliases
 /// which is only called by the constructor.
 /// Note2: The method is only package-private so that it can be tested with unittests
 /// </para>
 /// </remarks>
 /// <param name="aliasNS">
 /// The namespace URI for the alias. Must not be null or the empty
 /// string.
 /// </param>
 /// <param name="aliasProp">
 /// The name of the alias. Must be a simple name, not null or the
 /// empty string and not a general path expression.
 /// </param>
 /// <param name="actualNS">
 /// The namespace URI for the actual. Must not be null or the
 /// empty string.
 /// </param>
 /// <param name="actualProp">
 /// The name of the actual. Must be a simple name, not null or the
 /// empty string and not a general path expression.
 /// </param>
 /// <param name="aliasForm">
 /// Provides options for aliases for simple aliases to array
 /// items. This is needed to know what kind of array to create if
 /// set for the first time via the simple alias. Pass
 /// <code>XMP_NoOptions</code>, the default value, for all
 /// direct aliases regardless of whether the actual data type is
 /// an array or not (see
 /// <see cref="iText.Kernel.XMP.Options.AliasOptions"/>
 /// ).
 /// </param>
 /// <exception cref="iText.Kernel.XMP.XMPException">for inconsistant aliases.</exception>
 internal void RegisterAlias(String aliasNS, String aliasProp, String actualNS, String
                             actualProp, AliasOptions aliasForm)
 {
     lock (this)
     {
         ParameterAsserts.AssertSchemaNS(aliasNS);
         ParameterAsserts.AssertPropName(aliasProp);
         ParameterAsserts.AssertSchemaNS(actualNS);
         ParameterAsserts.AssertPropName(actualProp);
         // Fix the alias options
         AliasOptions aliasOpts = aliasForm != null ? new AliasOptions(XMPNodeUtils.VerifySetOptions
                                                                           (aliasForm.ToPropertyOptions(), null).GetOptions()) : new AliasOptions();
         if (_regex.IsMatch(aliasProp) || _regex.IsMatch(actualProp))
         {
             throw new XMPException("Alias and actual property names must be simple", XMPError.BADXPATH);
         }
         // check if both namespaces are registered
         String aliasPrefix  = GetNamespacePrefix(aliasNS);
         String actualPrefix = GetNamespacePrefix(actualNS);
         if (aliasPrefix == null)
         {
             throw new XMPException("Alias namespace is not registered", XMPError.BADSCHEMA);
         }
         else
         {
             if (actualPrefix == null)
             {
                 throw new XMPException("Actual namespace is not registered", XMPError.BADSCHEMA);
             }
         }
         String key = aliasPrefix + aliasProp;
         // check if alias is already existing
         if (aliasMap.Contains(key))
         {
             throw new XMPException("Alias is already existing", XMPError.BADPARAM);
         }
         else
         {
             if (aliasMap.Contains(actualPrefix + actualProp))
             {
                 throw new XMPException("Actual property is already an alias, use the base property"
                                        , XMPError.BADPARAM);
             }
         }
         XMPAliasInfo aliasInfo = new _XMPAliasInfo_409(actualNS, actualPrefix, actualProp
                                                        , aliasOpts);
         aliasMap[key] = aliasInfo;
     }
 }
예제 #10
0
		public virtual bool DoesPropertyExist(String schemaNS, String propName)
		{
			try
			{
				ParameterAsserts.AssertSchemaNS(schemaNS);
				ParameterAsserts.AssertPropName(propName);
				XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName);
				XMPNode propNode = XMPNodeUtils.FindNode(tree, expPath, false, null);
				return propNode != null;
			}
			catch (XMPException)
			{
				return false;
			}
		}
예제 #11
0
		public virtual void SetProperty(String schemaNS, String propName, Object propValue
			, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertPropName(propName);
			options = XMPNodeUtils.VerifySetOptions(options, propValue);
			XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName);
			XMPNode propNode = XMPNodeUtils.FindNode(tree, expPath, true, options);
			if (propNode != null)
			{
				SetNode(propNode, propValue, options, false);
			}
			else
			{
				throw new XMPException("Specified property does not exist", XMPError.BADXPATH);
			}
		}
예제 #12
0
		public virtual void InsertArrayItem(String schemaNS, String arrayName, int itemIndex
			, String itemValue, PropertyOptions options)
		{
			ParameterAsserts.AssertSchemaNS(schemaNS);
			ParameterAsserts.AssertArrayName(arrayName);
			// Just lookup, don't try to create.
			XMPPath arrayPath = XMPPathParser.ExpandXPath(schemaNS, arrayName);
			XMPNode arrayNode = XMPNodeUtils.FindNode(tree, arrayPath, false, null);
			if (arrayNode != null)
			{
				DoSetArrayItem(arrayNode, itemIndex, itemValue, options, true);
			}
			else
			{
				throw new XMPException("Specified array does not exist", XMPError.BADXPATH);
			}
		}
예제 #13
0
		public virtual void DeleteProperty(String schemaNS, String propName)
		{
			try
			{
				ParameterAsserts.AssertSchemaNS(schemaNS);
				ParameterAsserts.AssertPropName(propName);
				XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName);
				XMPNode propNode = XMPNodeUtils.FindNode(tree, expPath, false, null);
				if (propNode != null)
				{
					XMPNodeUtils.DeleteNode(propNode);
				}
			}
			catch (XMPException)
			{
				// EMPTY, exceptions are ignored within delete
			}
		}
예제 #14
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);
			}
		}
예제 #15
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;
			}
		}
예제 #16
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);
     }
 }
예제 #17
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();
			}
		}
예제 #18
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);
			}
		}
예제 #19
0
        /// <summary>Visit all of the top level nodes looking for aliases.</summary>
        /// <remarks>
        /// Visit all of the top level nodes looking for aliases. If there is
        /// no base, transplant the alias subtree. If there is a base and strict
        /// aliasing is on, make sure the alias and base subtrees match.
        /// </remarks>
        /// <param name="tree">the root of the metadata tree</param>
        /// <param name="options">th parsing options</param>
        /// <exception cref="iText.Kernel.XMP.XMPException">Forwards XMP errors</exception>
        private static void MoveExplicitAliases(XMPNode tree, ParseOptions options)
        {
            if (!tree.GetHasAliases())
            {
                return;
            }
            tree.SetHasAliases(false);

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

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

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

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

                    currProp.SetAlias(false);

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

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

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

                            if (itemNode == null)
                            {
                                TransplantArrayItemAlias(currProp, baseNode);
                            }
                            else
                            {
                                if (strictAliasing)
                                {
                                    CompareAliasedSubtrees(currProp, itemNode, true);
                                }
                            }
                            currPropsToRemove.Add(currProp);
                        }
                    }
                }
                foreach (XMPNode o in currPropsToRemove)
                {
                    currSchema.RemoveChild(o);
                }
                currPropsToRemove.Clear();
                currSchema.SetHasAliases(false);
            }
        }