コード例 #1
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public IXmpProperty GetLocalizedText(string schemaNs, string altTextName, string genericLang, string specificLang)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertArrayName(altTextName);
            ParameterAsserts.AssertSpecificLang(specificLang);
            genericLang = genericLang != null?Utils.NormalizeLangValue(genericLang) : null;

            specificLang = Utils.NormalizeLangValue(specificLang);
            var arrayPath = XmpPathParser.ExpandXPath(schemaNs, altTextName);
            var arrayNode = XmpNodeUtils.FindNode(_tree, arrayPath, false, null);

            if (arrayNode == null)
            {
                return(null);
            }
            var result   = XmpNodeUtils.ChooseLocalizedText(arrayNode, genericLang, specificLang);
            var match    = (int)result[0];
            var itemNode = (XmpNode)result[1];

            if (match != XmpNodeUtils.CltNoValues)
            {
                return(new XmpProperty407(itemNode));
            }
            return(null);
        }
コード例 #2
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public IXmpProperty GetArrayItem(string schemaNs, string arrayName, int itemIndex)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertArrayName(arrayName);
            var itemPath = XmpPathFactory.ComposeArrayItemPath(arrayName, itemIndex);

            return(GetProperty(schemaNs, itemPath));
        }
コード例 #3
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public void SetStructField(string schemaNs, string structName, string fieldNs, string fieldName, string fieldValue, PropertyOptions options)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertStructName(structName);
            var fieldPath = structName + XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);

            SetProperty(schemaNs, fieldPath, fieldValue, options);
        }
コード例 #4
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public IXmpProperty GetQualifier(string schemaNs, string propName, string qualNs, string qualName)
        {
            // qualNS and qualName are checked inside composeQualfierPath
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertPropName(propName);
            var qualPath = propName + XmpPathFactory.ComposeQualifierPath(qualNs, qualName);

            return(GetProperty(schemaNs, qualPath));
        }
コード例 #5
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public IXmpProperty GetStructField(string schemaNs, string structName, string fieldNs, string fieldName)
        {
            // fieldNS and fieldName are checked inside composeStructFieldPath
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertStructName(structName);
            var fieldPath = structName + XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);

            return(GetProperty(schemaNs, fieldPath));
        }
コード例 #6
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public void SetQualifier(string schemaNs, string propName, string qualNs, string qualName, string qualValue, PropertyOptions options)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertPropName(propName);
            if (!DoesPropertyExist(schemaNs, propName))
            {
                throw new XmpException("Specified property does not exist!", XmpErrorCode.BadXPath);
            }
            var qualPath = propName + XmpPathFactory.ComposeQualifierPath(qualNs, qualName);

            SetProperty(schemaNs, qualPath, qualValue, options);
        }
コード例 #7
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public 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", XmpErrorCode.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.
            var arrayPath = XmpPathParser.ExpandXPath(schemaNs, arrayName);
            // Just lookup, don't try to create.
            var 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.Options.IsArray)
                {
                    throw new XmpException("The named property is not an array", XmpErrorCode.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", XmpErrorCode.BadXPath);
                    }
                }
                else
                {
                    // array options missing
                    throw new XmpException("Explicit arrayOptions required to create new array", XmpErrorCode.BadOptions);
                }
            }
            DoSetArrayItem(arrayNode, XmpConstants.ArrayLastItem, itemValue, itemOptions, true);
        }
コード例 #8
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public void DeleteArrayItem(string schemaNs, string arrayName, int itemIndex)
 {
     try
     {
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertArrayName(arrayName);
         var itemPath = XmpPathFactory.ComposeArrayItemPath(arrayName, itemIndex);
         DeleteProperty(schemaNs, itemPath);
     }
     catch (XmpException)
     {
     }
 }
コード例 #9
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public bool DoesArrayItemExist(string schemaNs, string arrayName, int itemIndex)
 {
     try
     {
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertArrayName(arrayName);
         var path = XmpPathFactory.ComposeArrayItemPath(arrayName, itemIndex);
         return(DoesPropertyExist(schemaNs, path));
     }
     catch (XmpException)
     {
         return(false);
     }
 }
コード例 #10
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public void DeleteStructField(string schemaNs, string structName, string fieldNs, string fieldName)
 {
     try
     {
         // fieldNS and fieldName are checked inside composeStructFieldPath
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertStructName(structName);
         var fieldPath = structName + XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);
         DeleteProperty(schemaNs, fieldPath);
     }
     catch (XmpException)
     {
     }
 }
コード例 #11
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public void DeleteQualifier(string schemaNs, string propName, string qualNs, string qualName)
 {
     try
     {
         // Note: qualNS and qualName are checked inside composeQualfierPath
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertPropName(propName);
         var qualPath = propName + XmpPathFactory.ComposeQualifierPath(qualNs, qualName);
         DeleteProperty(schemaNs, qualPath);
     }
     catch (XmpException)
     {
     }
 }
コード例 #12
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public bool DoesQualifierExist(string schemaNs, string propName, string qualNs, string qualName)
 {
     try
     {
         // qualNS and qualName are checked inside composeQualifierPath()
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertPropName(propName);
         var path = XmpPathFactory.ComposeQualifierPath(qualNs, qualName);
         return(DoesPropertyExist(schemaNs, propName + path));
     }
     catch (XmpException)
     {
         return(false);
     }
 }
コード例 #13
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public bool DoesStructFieldExist(string schemaNs, string structName, string fieldNs, string fieldName)
 {
     try
     {
         // fieldNS and fieldName are checked inside composeStructFieldPath()
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertStructName(structName);
         var path = XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);
         return(DoesPropertyExist(schemaNs, structName + path));
     }
     catch (XmpException)
     {
         return(false);
     }
 }
コード例 #14
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public bool DoesPropertyExist(string schemaNs, string propName)
 {
     try
     {
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertPropName(propName);
         var expPath  = XmpPathParser.ExpandXPath(schemaNs, propName);
         var propNode = XmpNodeUtils.FindNode(_tree, expPath, false, null);
         return(propNode != null);
     }
     catch (XmpException)
     {
         return(false);
     }
 }
コード例 #15
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
        /// </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 <c>XMP_NoOptions</c>, the default value, for all direct aliases regardless of whether the actual
        /// data type is an array or not (see <see cref="AliasOptions"/>).</param>
        /// <exception cref="XmpException">for inconsistant aliases.</exception>
        private void RegisterAlias(string aliasNs, string aliasProp, string actualNs, string actualProp, AliasOptions aliasForm)
        {
            lock (_lock)
            {
                ParameterAsserts.AssertSchemaNs(aliasNs);
                ParameterAsserts.AssertPropName(aliasProp);
                ParameterAsserts.AssertSchemaNs(actualNs);
                ParameterAsserts.AssertPropName(actualProp);

                // FfF: if we need the decoration with [1] or
                // FfF: [?xml:lang="x-default"] for array forms

                // Fix the alias options
                var aliasOpts = aliasForm != null ? new AliasOptions(XmpNodeUtils.VerifySetOptions(aliasForm.ToPropertyOptions(), null).GetOptions()) : new AliasOptions();
                if (_p.IsMatch(aliasProp) || _p.IsMatch(actualProp))
                {
                    throw new XmpException("Alias and actual property names must be simple", XmpErrorCode.BadXPath);
                }

                // check if both namespaces are registered
                var aliasPrefix  = GetNamespacePrefix(aliasNs);
                var actualPrefix = GetNamespacePrefix(actualNs);

                if (aliasPrefix == null)
                {
                    throw new XmpException("Alias namespace is not registered", XmpErrorCode.BadSchema);
                }
                if (actualPrefix == null)
                {
                    throw new XmpException("Actual namespace is not registered", XmpErrorCode.BadSchema);
                }

                var key = aliasPrefix + aliasProp;

                // check if alias is already existing
                if (_aliasMap.ContainsKey(key))
                {
                    throw new XmpException("Alias is already existing", XmpErrorCode.BadParam);
                }
                if (_aliasMap.ContainsKey(actualPrefix + actualProp))
                {
                    throw new XmpException("Actual property is already an alias, use the base property", XmpErrorCode.BadParam);
                }

                _aliasMap[key] = new XmpAliasInfo(actualNs, actualPrefix, actualProp, aliasOpts);
            }
        }
コード例 #16
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
 public void DeleteProperty(string schemaNs, string propName)
 {
     try
     {
         ParameterAsserts.AssertSchemaNs(schemaNs);
         ParameterAsserts.AssertPropName(propName);
         var expPath  = XmpPathParser.ExpandXPath(schemaNs, propName);
         var propNode = XmpNodeUtils.FindNode(_tree, expPath, false, null);
         if (propNode != null)
         {
             XmpNodeUtils.DeleteNode(propNode);
         }
     }
     catch (XmpException)
     {
     }
 }
コード例 #17
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public void SetProperty(string schemaNs, string propName, object propValue, PropertyOptions options)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertPropName(propName);
            options = XmpNodeUtils.VerifySetOptions(options, propValue);
            var expPath  = XmpPathParser.ExpandXPath(schemaNs, propName);
            var propNode = XmpNodeUtils.FindNode(_tree, expPath, true, options);

            if (propNode != null)
            {
                SetNode(propNode, propValue, options, false);
            }
            else
            {
                throw new XmpException("Specified property does not exist", XmpErrorCode.BadXPath);
            }
        }
コード例 #18
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public 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.
            var arrayPath = XmpPathParser.ExpandXPath(schemaNs, arrayName);
            var 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", XmpErrorCode.BadXPath);
            }
        }
コード例 #19
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public int CountArrayItems(string schemaNs, string arrayName)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertArrayName(arrayName);
            var arrayPath = XmpPathParser.ExpandXPath(schemaNs, arrayName);
            var arrayNode = XmpNodeUtils.FindNode(_tree, arrayPath, false, null);

            if (arrayNode == null)
            {
                return(0);
            }
            if (arrayNode.Options.IsArray)
            {
                return(arrayNode.GetChildrenLength());
            }
            throw new XmpException("The named property is not an array", XmpErrorCode.BadXPath);
        }
コード例 #20
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <summary>Returns a property, but the result value can be requested.</summary>
        /// <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
        /// <c>valueType</c>.
        /// </returns>
        /// <exception cref="XmpException">Collects any exception that occurs.</exception>
        private object GetPropertyObject(string schemaNs, string propName, ValueType valueType)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertPropName(propName);
            var expPath  = XmpPathParser.ExpandXPath(schemaNs, propName);
            var propNode = XmpNodeUtils.FindNode(_tree, expPath, false, null);

            if (propNode != null)
            {
                if (valueType != ValueType.String && propNode.Options.IsCompositeProperty)
                {
                    throw new XmpException("Property must be simple when a value type is requested", XmpErrorCode.BadXPath);
                }
                return(EvaluateNodeValue(valueType, propNode));
            }
            return(null);
        }
コード例 #21
0
        public string RegisterNamespace(string namespaceUri, string suggestedPrefix)
        {
            lock (_lock)
            {
                ParameterAsserts.AssertSchemaNs(namespaceUri);
                ParameterAsserts.AssertPrefix(suggestedPrefix);

                if (suggestedPrefix[suggestedPrefix.Length - 1] != ':')
                {
                    suggestedPrefix += ':';
                }

                if (!Utils.IsXmlNameNs(suggestedPrefix.Substring(0, suggestedPrefix.Length - 1 - 0)))
                {
                    throw new XmpException("The prefix is a bad XML name", XmpErrorCode.BadXml);
                }

                string registeredPrefix;
                if (_namespaceToPrefixMap.TryGetValue(namespaceUri, out registeredPrefix))
                {
                    // Return the actual prefix
                    return(registeredPrefix);
                }

                if (_prefixToNamespaceMap.ContainsKey(suggestedPrefix))
                {
                    // the namespace is new, but the prefix is already engaged,
                    // we generate a new prefix out of the suggested
                    var generatedPrefix = suggestedPrefix;
                    for (var i = 1; _prefixToNamespaceMap.ContainsKey(generatedPrefix); i++)
                    {
                        generatedPrefix = suggestedPrefix.Substring(0, suggestedPrefix.Length - 1 - 0) + "_" + i + "_:";
                    }
                    suggestedPrefix = generatedPrefix;
                }

                _prefixToNamespaceMap[suggestedPrefix] = namespaceUri;
                _namespaceToPrefixMap[namespaceUri]    = suggestedPrefix;

                // Return the suggested prefix
                return(suggestedPrefix);
            }
        }
コード例 #22
0
        /// <summary>
        /// See <see cref="XmpCore.XmpUtils.SeparateArrayItems(IXmpMeta, string, string, string, PropertyOptions, bool)"/>.
        /// </summary>
        /// <param name="xmp">The XMP object containing the array to be updated.</param>
        /// <param name="schemaNs">
        /// The schema namespace URI for the array. Must not be null or the empty string.
        /// </param>
        /// <param name="arrayName">
        /// The name of the array. May be a general path expression, must
        /// not be null or the empty string. Each item in the array must
        /// be a simple string value.
        /// </param>
        /// <param name="catedStr">The string to be separated into the array items.</param>
        /// <param name="arrayOptions">Option flags to control the separation.</param>
        /// <param name="preserveCommas">Flag if commas shall be preserved</param>
        /// <exception cref="XmpException">Forwards the Exceptions from the metadata processing</exception>
        public static void SeparateArrayItems(IXmpMeta xmp, string schemaNs, string arrayName, string catedStr, PropertyOptions arrayOptions, bool preserveCommas)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertArrayName(arrayName);

            if (catedStr == null)
            {
                throw new XmpException("Parameter must not be null", XmpErrorCode.BadParam);
            }

            ParameterAsserts.AssertImplementation(xmp);
            var xmpImpl = (XmpMeta)xmp;

            // Keep a zero value, has special meaning below.
            var arrayNode = SeparateFindCreateArray(schemaNs, arrayName, arrayOptions, xmpImpl);

            // Extract the item values one at a time, until the whole input string is done.
            var charKind = UnicodeKind.Normal;
            var ch       = (char)0;
            var itemEnd  = 0;
            var endPos   = catedStr.Length;

            while (itemEnd < endPos)
            {
                // Skip any leading spaces and separation characters. Always skip commas here.
                // They can be kept when within a value, but not when alone between values.
                int itemStart;
                for (itemStart = itemEnd; itemStart < endPos; itemStart++)
                {
                    ch       = catedStr[itemStart];
                    charKind = ClassifyCharacter(ch);
                    if (charKind == UnicodeKind.Normal || charKind == UnicodeKind.Quote)
                    {
                        break;
                    }
                }

                if (itemStart >= endPos)
                {
                    break;
                }

                string itemValue;
                if (charKind != UnicodeKind.Quote)
                {
                    // This is not a quoted value. Scan for the end, create an array
                    // item from the substring.
                    for (itemEnd = itemStart; itemEnd < endPos; itemEnd++)
                    {
                        ch       = catedStr[itemEnd];
                        charKind = ClassifyCharacter(ch);

                        if (charKind == UnicodeKind.Normal || charKind == UnicodeKind.Quote || (charKind == UnicodeKind.Comma && preserveCommas))
                        {
                            continue;
                        }

                        if (charKind != UnicodeKind.Space)
                        {
                            break;
                        }

                        if ((itemEnd + 1) < endPos)
                        {
                            ch = catedStr[itemEnd + 1];
                            var nextKind = ClassifyCharacter(ch);
                            if (nextKind == UnicodeKind.Normal || nextKind == UnicodeKind.Quote || (nextKind == UnicodeKind.Comma && preserveCommas))
                            {
                                continue;
                            }
                        }
                        // Anything left?
                        break;
                    }
                    // Have multiple spaces, or a space followed by a
                    // separator.
                    itemValue = catedStr.Substring(itemStart, itemEnd - itemStart);
                }
                else
                {
                    // Accumulate quoted values into a local string, undoubling
                    // internal quotes that
                    // match the surrounding quotes. Do not undouble "unmatching"
                    // quotes.
                    var openQuote  = ch;
                    var closeQuote = GetClosingQuote(openQuote);
                    itemStart++;
                    // Skip the opening quote;
                    itemValue = string.Empty;
                    for (itemEnd = itemStart; itemEnd < endPos; itemEnd++)
                    {
                        ch       = catedStr[itemEnd];
                        charKind = ClassifyCharacter(ch);
                        if (charKind != UnicodeKind.Quote || !IsSurroundingQuote(ch, openQuote, closeQuote))
                        {
                            // This is not a matching quote, just append it to the
                            // item value.
                            itemValue += ch;
                        }
                        else
                        {
                            // This is a "matching" quote. Is it doubled, or the
                            // final closing quote?
                            // Tolerate various edge cases like undoubled opening
                            // (non-closing) quotes,
                            // or end of input.
                            char nextChar;
                            if ((itemEnd + 1) < endPos)
                            {
                                nextChar = catedStr[itemEnd + 1];
                            }
                            else
                            {
                                nextChar = (char)0x3B;
                            }

                            if (ch == nextChar)
                            {
                                // This is doubled, copy it and skip the double.
                                itemValue += ch;
                                // Loop will add in charSize.
                                itemEnd++;
                            }
                            else
                            {
                                if (!IsClosingQuote(ch, openQuote, closeQuote))
                                {
                                    // This is an undoubled, non-closing quote, copy it.
                                    itemValue += ch;
                                }
                                else
                                {
                                    // This is an undoubled closing quote, skip it and
                                    // exit the loop.
                                    itemEnd++;
                                    break;
                                }
                            }
                        }
                    }
                }

                // Add the separated item to the array.
                // Keep a matching old value in case it had separators.
                var foundIndex = -1;
                for (var oldChild = 1; oldChild <= arrayNode.GetChildrenLength(); oldChild++)
                {
                    if (itemValue.Equals(arrayNode.GetChild(oldChild).Value))
                    {
                        foundIndex = oldChild;
                        break;
                    }
                }

                if (foundIndex < 0)
                {
                    arrayNode.AddChild(new XmpNode(XmpConstants.ArrayItemName, itemValue, null));
                }
            }
        }
コード例 #23
0
        /// <param name="xmp">The XMP object containing the array to be catenated.</param>
        /// <param name="schemaNs">
        /// The schema namespace URI for the array. Must not be null or
        /// the empty string.
        /// </param>
        /// <param name="arrayName">
        /// The name of the array. May be a general path expression, must
        /// not be null or the empty string. Each item in the array must
        /// be a simple string value.
        /// </param>
        /// <param name="separator">
        /// The string to be used to separate the items in the catenated
        /// string. Defaults to &quot;; &quot;, ASCII semicolon and space
        /// (U+003B, U+0020).
        /// </param>
        /// <param name="quotes">
        /// The characters to be used as quotes around array items that
        /// contain a separator. Defaults to &apos;&quot;&apos;
        /// </param>
        /// <param name="allowCommas">Option flag to control the catenation.</param>
        /// <returns>Returns the string containing the catenated array items.</returns>
        /// <exception cref="XmpException">Forwards the Exceptions from the metadata processing</exception>
        public static string CatenateArrayItems(IXmpMeta xmp, string schemaNs, string arrayName, string separator, string quotes, bool allowCommas)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertArrayName(arrayName);
            ParameterAsserts.AssertImplementation(xmp);

            if (string.IsNullOrEmpty(separator))
            {
                separator = "; ";
            }
            if (string.IsNullOrEmpty(quotes))
            {
                quotes = "\"";
            }

            var xmpImpl = (XmpMeta)xmp;

            // Return an empty result if the array does not exist,
            // hurl if it isn't the right form.
            var arrayPath = XmpPathParser.ExpandXPath(schemaNs, arrayName);
            var arrayNode = XmpNodeUtils.FindNode(xmpImpl.GetRoot(), arrayPath, false, null);

            if (arrayNode == null)
            {
                return(string.Empty);
            }
            if (!arrayNode.Options.IsArray || arrayNode.Options.IsArrayAlternate)
            {
                throw new XmpException("Named property must be non-alternate array", XmpErrorCode.BadParam);
            }

            // Make sure the separator is OK.
            CheckSeparator(separator);

            // Make sure the open and close quotes are a legitimate pair.
            var openQuote  = quotes[0];
            var closeQuote = CheckQuotes(quotes, openQuote);

            // Build the result, quoting the array items, adding separators.
            // Hurl if any item isn't simple.
            var catenatedString = new StringBuilder();

            for (var it = arrayNode.IterateChildren(); it.HasNext();)
            {
                var currItem = (XmpNode)it.Next();

                if (currItem.Options.IsCompositeProperty)
                {
                    throw new XmpException("Array items must be simple", XmpErrorCode.BadParam);
                }

                var str = ApplyQuotes(currItem.Value, openQuote, closeQuote, allowCommas);
                catenatedString.Append(str);

                if (it.HasNext())
                {
                    catenatedString.Append(separator);
                }
            }
            return(catenatedString.ToString());
        }
コード例 #24
0
ファイル: XmpMeta.cs プロジェクト: wwwlicious/xmp-core-dotnet
        /// <exception cref="XmpException"/>
        public 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?Utils.NormalizeLangValue(genericLang) : null;

            specificLang = Utils.NormalizeLangValue(specificLang);
            var arrayPath = XmpPathParser.ExpandXPath(schemaNs, altTextName);
            // Find the array node and set the options if it was just created.
            var arrayNode = XmpNodeUtils.FindNode(_tree, arrayPath, true, new PropertyOptions(PropertyOptions.ArrayFlag | PropertyOptions.ArrayOrderedFlag | PropertyOptions.ArrayAlternateFlag | PropertyOptions.ArrayAltTextFlag));

            if (arrayNode == null)
            {
                throw new XmpException("Failed to find or create array node", XmpErrorCode.BadXPath);
            }
            if (!arrayNode.Options.IsArrayAltText)
            {
                if (!arrayNode.HasChildren && arrayNode.Options.IsArrayAlternate)
                {
                    arrayNode.Options.IsArrayAltText = true;
                }
                else
                {
                    throw new XmpException("Specified property is no alt-text array", XmpErrorCode.BadXPath);
                }
            }
            // Make sure the x-default item, if any, is first.
            var     haveXDefault = false;
            XmpNode xdItem       = null;

            for (var it = arrayNode.IterateChildren(); it.HasNext();)
            {
                var currItem = (XmpNode)it.Next();
                if (!currItem.HasQualifier || !XmpConstants.XmlLang.Equals(currItem.GetQualifier(1).Name))
                {
                    throw new XmpException("Language qualifier must be first", XmpErrorCode.BadXPath);
                }
                if (XmpConstants.XDefault.Equals(currItem.GetQualifier(1).Value))
                {
                    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.
            var result           = XmpNodeUtils.ChooseLocalizedText(arrayNode, genericLang, specificLang);
            var match            = (int)result[0];
            var itemNode         = (XmpNode)result[1];
            var specificXDefault = XmpConstants.XDefault.Equals(specificLang);

            switch (match)
            {
            case XmpNodeUtils.CltNoValues:
            {
                // Create the array items for the specificLang and x-default, with
                // x-default first.
                XmpNodeUtils.AppendLangItem(arrayNode, XmpConstants.XDefault, itemValue);
                haveXDefault = true;
                if (!specificXDefault)
                {
                    XmpNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
                }
                break;
            }

            case XmpNodeUtils.CltSpecificMatch:
            {
                if (!specificXDefault)
                {
                    // Update the specific item, update x-default if it matches the
                    // old value.
                    if (haveXDefault && xdItem != itemNode && xdItem != null && xdItem.Value.Equals(itemNode.Value))
                    {
                        xdItem.Value = itemValue;
                    }
                    // ! Do this after the x-default check!
                    itemNode.Value = itemValue;
                }
                else
                {
                    // Update all items whose values match the old x-default value.
                    Debug.Assert(haveXDefault && xdItem == itemNode);
                    for (var it1 = arrayNode.IterateChildren(); it1.HasNext();)
                    {
                        var currItem = (XmpNode)it1.Next();
                        if (currItem == xdItem || !currItem.Value.Equals(xdItem != null ? xdItem.Value : null))
                        {
                            continue;
                        }
                        currItem.Value = itemValue;
                    }
                    // And finally do the x-default item.
                    if (xdItem != null)
                    {
                        xdItem.Value = itemValue;
                    }
                }
                break;
            }

            case XmpNodeUtils.CltSingleGeneric:
            {
                // Update the generic item, update x-default if it matches the old
                // value.
                if (haveXDefault && xdItem != itemNode && xdItem != null && xdItem.Value.Equals(itemNode.Value))
                {
                    xdItem.Value = itemValue;
                }
                itemNode.Value = itemValue;
                // ! Do this after
                // the x-default
                // check!
                break;
            }

            case XmpNodeUtils.CltMultipleGeneric:
            {
                // Create the specific language, ignore x-default.
                XmpNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
                if (specificXDefault)
                {
                    haveXDefault = true;
                }
                break;
            }

            case XmpNodeUtils.CltXdefault:
            {
                // Create the specific language, update x-default if it was the only
                // item.
                if (xdItem != null && arrayNode.GetChildrenLength() == 1)
                {
                    xdItem.Value = itemValue;
                }
                XmpNodeUtils.AppendLangItem(arrayNode, specificLang, itemValue);
                break;
            }

            case XmpNodeUtils.CltFirstItem:
            {
                // 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", XmpErrorCode.InternalFailure);
            }
            }
            // Add an x-default at the front if needed.
            if (!haveXDefault && arrayNode.GetChildrenLength() == 1)
            {
                XmpNodeUtils.AppendLangItem(arrayNode, XmpConstants.XDefault, itemValue);
            }
        }