@since 11.08.2006
상속: XmpConst
예제 #1
0
        /// <exception cref="XmpException"> </exception>
        /// <seealso cref= XMPMeta#getLocalizedText(String, String, String, String) </seealso>
        public virtual 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);

            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)((int?)result[0]);
            XmpNode  itemNode = (XmpNode)result[1];

            if (match != XmpNodeUtils.CLT_NO_VALUES)
            {
                return(new XmpPropertyImpl1(itemNode));
            }
            return(null);
        }
예제 #2
0
        /// <summary>
        /// Parses the input source into an XMP metadata object, including
        /// de-aliasing and normalisation.
        /// </summary>
        /// <param name="input"> the input can be an <code>InputStream</code>, a <code>String</code> or
        ///             a byte buffer containing the XMP packet. </param>
        /// <param name="options"> the parse options </param>
        /// <returns> Returns the resulting XMP metadata object </returns>
        /// <exception cref="XmpException"> Thrown if parsing or normalisation fails. </exception>
        public static XMPMeta Parse(object input, ParseOptions options)
        {
            ParameterAsserts.AssertNotNull(input);
            options = options ?? new ParseOptions();

            XmlDocument document = ParseXml(input, options);

            bool xmpmetaRequired = options.RequireXmpMeta;

            object[] result = new object[3];
            result = FindRootNode(document, xmpmetaRequired, result);

            if (result != null && result[1] == XmpRdf)
            {
                XmpMetaImpl xmp = ParseRdf.Parse((XmlNode)result[0]);
                xmp.PacketHeader = (string)result[2];

                // Check if the XMP object shall be normalized
                if (!options.OmitNormalization)
                {
                    return(XmpNormalizer.Process(xmp, options));
                }
                return(xmp);
            }
            // no appropriate root node found, return empty metadata object
            return(new XmpMetaImpl());
        }
예제 #3
0
        /// <seealso cref= XMPMeta#getArrayItem(String, String, int) </seealso>
        public virtual IXmpProperty GetArrayItem(string schemaNs, string arrayName, int itemIndex)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertArrayName(arrayName);

            string itemPath = XmpPathFactory.ComposeArrayItemPath(arrayName, itemIndex);

            return(GetProperty(schemaNs, itemPath));
        }
예제 #4
0
        /// <seealso cref= XMPMeta#setStructField(String, String, String, String, String,
        ///      PropertyOptions) </seealso>
        public virtual void SetStructField(string schemaNs, string structName, string fieldNs, string fieldName,
                                           string fieldValue, PropertyOptions options)
        {
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertStructName(structName);

            string fieldPath = structName + XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);

            SetProperty(schemaNs, fieldPath, fieldValue, options);
        }
예제 #5
0
        /// <seealso cref= XMPMeta#getStructField(String, String, String, String) </seealso>
        public virtual IXmpProperty GetStructField(string schemaNs, string structName, string fieldNs, string fieldName)
        {
            // fieldNs and fieldName are checked inside composeStructFieldPath
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertStructName(structName);

            string fieldPath = structName + XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);

            return(GetProperty(schemaNs, fieldPath));
        }
예제 #6
0
        /// <exception cref="XmpException"> </exception>
        /// <seealso cref= XMPMeta#getQualifier(String, String, String, String) </seealso>
        public virtual IXmpProperty GetQualifier(string schemaNs, string propName, string qualNs, string qualName)
        {
            // qualNs and qualName are checked inside composeQualfierPath
            ParameterAsserts.AssertSchemaNs(schemaNs);
            ParameterAsserts.AssertPropName(propName);

            string qualPath = propName + XmpPathFactory.ComposeQualifierPath(qualNs, qualName);

            return(GetProperty(schemaNs, qualPath));
        }
예제 #7
0
        /// <seealso cref= XMPMeta#doesArrayItemExist(String, String, int) </seealso>
        public virtual bool DoesArrayItemExist(string schemaNs, string arrayName, int itemIndex)
        {
            try {
                ParameterAsserts.AssertSchemaNs(schemaNs);
                ParameterAsserts.AssertArrayName(arrayName);

                string path = XmpPathFactory.ComposeArrayItemPath(arrayName, itemIndex);
                return(DoesPropertyExist(schemaNs, path));
            }
            catch (XmpException) {
                return(false);
            }
        }
예제 #8
0
        /// <seealso cref= XMPMeta#deleteArrayItem(String, String, int) </seealso>
        public virtual void DeleteArrayItem(string schemaNs, string arrayName, int itemIndex)
        {
            try {
                ParameterAsserts.AssertSchemaNs(schemaNs);
                ParameterAsserts.AssertArrayName(arrayName);

                string itemPath = XmpPathFactory.ComposeArrayItemPath(arrayName, itemIndex);
                DeleteProperty(schemaNs, itemPath);
            }
            catch (XmpException) {
                // EMPTY, exceptions are ignored within delete
            }
        }
예제 #9
0
        /// <seealso cref= XMPMeta#doesQualifierExist(String, String, String, String) </seealso>
        public virtual bool DoesQualifierExist(string schemaNs, string propName, string qualNs, string qualName)
        {
            try {
                // qualNs and qualName are checked inside composeQualifierPath()
                ParameterAsserts.AssertSchemaNs(schemaNs);
                ParameterAsserts.AssertPropName(propName);

                string path = XmpPathFactory.ComposeQualifierPath(qualNs, qualName);
                return(DoesPropertyExist(schemaNs, propName + path));
            }
            catch (XmpException) {
                return(false);
            }
        }
예제 #10
0
        /// <seealso cref= XMPMeta#doesStructFieldExist(String, String, String, String) </seealso>
        public virtual bool DoesStructFieldExist(string schemaNs, string structName, string fieldNs, string fieldName)
        {
            try {
                // fieldNs and fieldName are checked inside composeStructFieldPath()
                ParameterAsserts.AssertSchemaNs(schemaNs);
                ParameterAsserts.AssertStructName(structName);

                string path = XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);
                return(DoesPropertyExist(schemaNs, structName + path));
            }
            catch (XmpException) {
                return(false);
            }
        }
예제 #11
0
        /// <seealso cref= XMPMeta#doesPropertyExist(String, String) </seealso>
        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);
            }
        }
예제 #12
0
        /// <seealso cref= XMPMeta#deleteStructField(String, String, String, String) </seealso>
        public virtual void DeleteStructField(string schemaNs, string structName, string fieldNs, string fieldName)
        {
            try {
                // fieldNs and fieldName are checked inside composeStructFieldPath
                ParameterAsserts.AssertSchemaNs(schemaNs);
                ParameterAsserts.AssertStructName(structName);

                string fieldPath = structName + XmpPathFactory.ComposeStructFieldPath(fieldNs, fieldName);
                DeleteProperty(schemaNs, fieldPath);
            }
            catch (XmpException) {
                // EMPTY, exceptions within delete are ignored
            }
        }
예제 #13
0
        /// <seealso cref= XMPMeta#deleteQualifier(String, String, String, String) </seealso>
        public virtual 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);

                string qualPath = propName + XmpPathFactory.ComposeQualifierPath(qualNs, qualName);
                DeleteProperty(schemaNs, qualPath);
            }
            catch (XmpException) {
                // EMPTY, exceptions within delete are ignored
            }
        }
        private void RegisterAlias(string aliasNs, string aliasProp, string actualNs, string actualProp,
                                   AliasOptions aliasForm)
        {
            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).
                Options)
                                         : 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);
            }
            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);
            }
            if (_aliasMap.Contains(actualPrefix + actualProp))
            {
                throw new XmpException("Actual property is already an alias, use the base property",
                                       XmpError.BADPARAM);
            }

            IXmpAliasInfo aliasInfo = new XmpAliasInfoImpl(actualNs, actualPrefix, actualProp, aliasOpts);

            _aliasMap[key] = aliasInfo;
        }
예제 #15
0
        /// <seealso cref= XMPUtils#appendProperties(XMPMeta, XMPMeta, boolean, boolean) </seealso>
        /// <param name="source"> The source XMP object. </param>
        /// <param name="destination"> The destination XMP object. </param>
        /// <param name="doAllProperties"> Do internal properties in addition to external properties. </param>
        /// <param name="replaceOldValues"> Replace the values of existing properties. </param>
        /// <param name="deleteEmptyValues"> Delete destination values if source property is empty. </param>
        /// <exception cref="XmpException"> Forwards the Exceptions from the metadata processing </exception>
        public static void AppendProperties(IXmpMeta source, IXmpMeta destination, bool doAllProperties,
                                            bool replaceOldValues, bool deleteEmptyValues)
        {
            ParameterAsserts.AssertImplementation(source);
            ParameterAsserts.AssertImplementation(destination);

            XmpMetaImpl src  = (XmpMetaImpl)source;
            XmpMetaImpl dest = (XmpMetaImpl)destination;

            for (IEnumerator it = src.Root.IterateChildren(); it.MoveNext();)
            {
                XmpNode sourceSchema = (XmpNode)it.Current;
                if (sourceSchema == null)
                {
                    continue;
                }
                // Make sure we have a destination schema node
                XmpNode destSchema    = XmpNodeUtils.FindSchemaNode(dest.Root, sourceSchema.Name, false);
                bool    createdSchema = false;
                if (destSchema == null)
                {
                    PropertyOptions propertyOptions = new PropertyOptions();
                    propertyOptions.SchemaNode = true;
                    destSchema = new XmpNode(sourceSchema.Name, sourceSchema.Value,
                                             propertyOptions);
                    dest.Root.AddChild(destSchema);
                    createdSchema = true;
                }

                // Process the source schema's children.
                for (IEnumerator ic = sourceSchema.IterateChildren(); ic.MoveNext();)
                {
                    XmpNode sourceProp = (XmpNode)ic.Current;
                    if (sourceProp == null)
                    {
                        continue;
                    }
                    if (doAllProperties || !Utils.IsInternalProperty(sourceSchema.Name, sourceProp.Name))
                    {
                        AppendSubtree(dest, sourceProp, destSchema, replaceOldValues, deleteEmptyValues);
                    }
                }

                if (!destSchema.HasChildren() && (createdSchema || deleteEmptyValues))
                {
                    // Don't create an empty schema / remove empty schema.
                    dest.Root.RemoveChild(destSchema);
                }
            }
        }
예제 #16
0
        /// <exception cref="XmpException"> </exception>
        /// <seealso cref= XMPMeta#setQualifier(String, String, String, String, String,
        ///      PropertyOptions) </seealso>
        public virtual 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!", XmpError.BADXPATH);
            }

            string qualPath = propName + XmpPathFactory.ComposeQualifierPath(qualNs, qualName);

            SetProperty(schemaNs, qualPath, qualValue, options);
        }
예제 #17
0
        /// <seealso cref= XMPMeta#deleteProperty(String, String) </seealso>
        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
            }
        }
예제 #18
0
        /// <exception cref="XmpException"> </exception>
        /// <seealso cref= XMPMeta#insertArrayItem(String, String, int, String,
        ///      PropertyOptions) </seealso>
        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);
            }
        }
예제 #19
0
        /// <exception cref="XmpException"> </exception>
        /// <seealso cref= XMPMeta#countArrayItems(String, String) </seealso>
        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.Options.Array)
            {
                return(arrayNode.ChildrenLength);
            }
            throw new XmpException("The named property is not an array", XmpError.BADXPATH);
        }
예제 #20
0
        /// <summary>
        /// Returns a property, but the result value can be requested.
        /// </summary>
        /// <seealso cref= XMPMeta#GetProperty(String, String) </seealso>
        /// <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="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.Options.CompositeProperty)
                {
                    throw new XmpException("Property must be simple when a value type is requested",
                                           XmpError.BADXPATH);
                }

                return(evaluateNodeValue(valueType, propNode));
            }
            return(null);
        }
예제 #21
0
        /// <exception cref="XmpException"> </exception>
        /// <seealso cref= XMPMeta#SetProperty(String, String, Object, PropertyOptions) </seealso>
        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);
            }
        }
        public string RegisterNamespace(string namespaceUri, string suggestedPrefix)
        {
            ParameterAsserts.AssertSchemaNs(namespaceUri);
            ParameterAsserts.AssertPrefix(suggestedPrefix);

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

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

            string registeredPrefix = (string)_namespaceToPrefixMap[namespaceUri];
            string registeredNs     = (string)_prefixToNamespaceMap[suggestedPrefix];

            if (registeredPrefix != null)
            {
                // Return the actual prefix
                return(registeredPrefix);
            }
            if (registeredNs != null)
            {
                // the namespace is new, but the prefix is already engaged,
                // we generate a new prefix out of the suggested
                string generatedPrefix = suggestedPrefix;
                for (int i = 1; _prefixToNamespaceMap.Contains(generatedPrefix); i++)
                {
                    generatedPrefix = suggestedPrefix.Substring(0, suggestedPrefix.Length - 1) + "_" + i + "_:";
                }
                suggestedPrefix = generatedPrefix;
            }
            _prefixToNamespaceMap[suggestedPrefix] = namespaceUri;
            _namespaceToPrefixMap[namespaceUri]    = suggestedPrefix;

            // Return the suggested prefix
            return(suggestedPrefix);
        }
예제 #23
0
        /// <seealso cref= XMPUtils#removeProperties(XMPMeta, String, String, boolean, boolean)
        /// </seealso>
        /// <param name="xmp">
        ///            The XMP object containing the properties to be removed.
        /// </param>
        /// <param name="schemaNs">
        ///            Optional schema namespace URI for the properties to be
        ///            removed.
        /// </param>
        /// <param name="propName">
        ///            Optional path expression for the property to be removed.
        /// </param>
        /// <param name="doAllProperties">
        ///            Option flag to control the deletion: do internal properties in
        ///            addition to external properties. </param>
        /// <param name="includeAliases">
        ///            Option flag to control the deletion: Include aliases in the
        ///            "named schema" case above. </param>
        /// <exception cref="XmpException"> If metadata processing fails </exception>
        public static void RemoveProperties(IXmpMeta xmp, string schemaNs, string propName, bool doAllProperties,
                                            bool includeAliases)
        {
            ParameterAsserts.AssertImplementation(xmp);
            XmpMetaImpl xmpImpl = (XmpMetaImpl)xmp;

            if (!string.IsNullOrEmpty(propName))
            {
                // Remove just the one indicated property. This might be an alias,
                // the named schema might not actually exist. So don't lookup the
                // schema node.

                if (string.IsNullOrEmpty(schemaNs))
                {
                    throw new XmpException("Property name requires schema namespace", XmpError.BADPARAM);
                }

                XmpPath expPath = XmpPathParser.ExpandXPath(schemaNs, propName);

                XmpNode propNode = XmpNodeUtils.FindNode(xmpImpl.Root, expPath, false, null);
                if (propNode != null)
                {
                    if (doAllProperties ||
                        !Utils.IsInternalProperty(expPath.GetSegment((int)XmpPath.STEP_SCHEMA).Name,
                                                  expPath.GetSegment((int)XmpPath.STEP_ROOT_PROP).Name))
                    {
                        XmpNode parent = propNode.Parent;
                        parent.RemoveChild(propNode);
                        if (parent.Options.SchemaNode && !parent.HasChildren())
                        {
                            // remove empty schema node
                            parent.Parent.RemoveChild(parent);
                        }
                    }
                }
            }
            else if (!string.IsNullOrEmpty(schemaNs))
            {
                // Remove all properties from the named schema. Optionally include
                // aliases, in which case
                // there might not be an actual schema node.

                // XMP_NodePtrPos schemaPos;
                XmpNode schemaNode = XmpNodeUtils.FindSchemaNode(xmpImpl.Root, schemaNs, false);
                if (schemaNode != null)
                {
                    if (RemoveSchemaChildren(schemaNode, doAllProperties))
                    {
                        xmpImpl.Root.RemoveChild(schemaNode);
                    }
                }

                if (includeAliases)
                {
                    // We're removing the aliases also. Look them up by their
                    // namespace prefix.
                    // But that takes more code and the extra speed isn't worth it.
                    // Lookup the XMP node
                    // from the alias, to make sure the actual exists.

                    IXmpAliasInfo[] aliases = XmpMetaFactory.SchemaRegistry.FindAliases(schemaNs);
                    for (int i = 0; i < aliases.Length; i++)
                    {
                        IXmpAliasInfo info       = aliases[i];
                        XmpPath       path       = XmpPathParser.ExpandXPath(info.Namespace, info.PropName);
                        XmpNode       actualProp = XmpNodeUtils.FindNode(xmpImpl.Root, path, false, null);
                        if (actualProp != null)
                        {
                            XmpNode parent = actualProp.Parent;
                            parent.RemoveChild(actualProp);
                        }
                    }
                }
            }
            else
            {
                // Remove all appropriate properties from all schema. In this case
                // we don't have to be
                // concerned with aliases, they are handled implicitly from the
                // actual properties.
                ArrayList schemasToRemove = new ArrayList();
                for (IEnumerator it = xmpImpl.Root.IterateChildren(); it.MoveNext();)
                {
                    XmpNode schema = (XmpNode)it.Current;
                    if (schema == null)
                    {
                        continue;
                    }
                    if (RemoveSchemaChildren(schema, doAllProperties))
                    {
                        schemasToRemove.Add(schema);
                    }
                }
                foreach (XmpNode xmpNode in schemasToRemove)
                {
                    xmpImpl.Root.Children.Remove(xmpNode);
                }
                schemasToRemove.Clear();
            }
        }
예제 #24
0
        /// <seealso cref= XMPMeta#appendArrayItem(String, String, PropertyOptions, String,
        ///      PropertyOptions) </seealso>
        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.OnlyArrayOptions)
            {
                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.Options.Array)
                {
                    throw new XmpException("The named property is not an array", XmpError.BADXPATH);
                }
                // if (arrayOptions != null && !arrayOptions.equalArrayTypes(arrayNode.getOptions()))
                // {
                // throw new XmpException("Mismatch of existing and specified array form", BADOPTIONS);
                // }
            }
            else
            {
                // The array does not exist, try to create it.
                if (arrayOptions.Array)
                {
                    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);
        }
예제 #25
0
        /// <summary>
        /// see {@link XMPUtils#separateArrayItems(XMPMeta, String, String, String,
        /// PropertyOptions, boolean)}
        /// </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", XmpError.BADPARAM);
            }
            ParameterAsserts.AssertImplementation(xmp);
            XmpMetaImpl xmpImpl = (XmpMetaImpl)xmp;

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

            // Extract the item values one at a time, until the whole input string is done.
            int  charKind = UCK_NORMAL;
            char ch       = (char)0;

            int itemEnd = 0;
            int endPos  = catedStr.Length;

            while (itemEnd < endPos)
            {
                string itemValue;
                int    itemStart;
                // 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.
                for (itemStart = itemEnd; itemStart < endPos; itemStart++)
                {
                    ch       = catedStr[itemStart];
                    charKind = ClassifyCharacter(ch);
                    if (charKind == UCK_NORMAL || charKind == UCK_QUOTE)
                    {
                        break;
                    }
                }
                if (itemStart >= endPos)
                {
                    break;
                }
                int nextKind;
                if (charKind != UCK_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 == UCK_NORMAL || charKind == UCK_QUOTE || (charKind == UCK_COMMA && preserveCommas))
                        {
                            continue;
                        }
                        if (charKind != UCK_SPACE)
                        {
                            break;
                        }
                        if ((itemEnd + 1) < endPos)
                        {
                            ch       = catedStr[itemEnd + 1];
                            nextKind = ClassifyCharacter(ch);
                            if (nextKind == UCK_NORMAL || nextKind == UCK_QUOTE ||
                                (nextKind == UCK_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.

                    char openQuote  = ch;
                    char closeQuote = GetClosingQuote(openQuote);

                    itemStart++; // Skip the opening quote;
                    itemValue = "";

                    for (itemEnd = itemStart; itemEnd < endPos; itemEnd++)
                    {
                        ch       = catedStr[itemEnd];
                        charKind = ClassifyCharacter(ch);

                        if (charKind != UCK_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];
                                nextKind = ClassifyCharacter(nextChar);
                            }
                            else
                            {
                                nextKind = UCK_SEMICOLON;
                                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 (!IsClosingingQuote(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.
                int foundIndex = -1;
                for (int oldChild = 1; oldChild <= arrayNode.ChildrenLength; oldChild++)
                {
                    if (itemValue.Equals(arrayNode.GetChild(oldChild).Value))
                    {
                        foundIndex = oldChild;
                        break;
                    }
                }

                if (foundIndex < 0)
                {
                    XmpNode newItem = new XmpNode(ARRAY_ITEM_NAME, itemValue, null);
                    arrayNode.AddChild(newItem);
                }
            }
        }
예제 #26
0
        /// <seealso cref= XMPUtils#catenateArrayItems(XMPMeta, String, String, String, String,
        ///      boolean)
        /// </seealso>
        /// <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 = "\"";
            }

            XmpMetaImpl xmpImpl = (XmpMetaImpl)xmp;

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

            if (arrayNode == null)
            {
                return("");
            }
            if (!arrayNode.Options.Array || arrayNode.Options.ArrayAlternate)
            {
                throw new XmpException("Named property must be non-alternate array", XmpError.BADPARAM);
            }

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

            // Build the result, quoting the array items, adding separators.
            // Hurl if any item isn't simple.

            StringBuilder catinatedString = new StringBuilder();

            for (IEnumerator it = arrayNode.IterateChildren(); it.MoveNext();)
            {
                XmpNode currItem = (XmpNode)it.Current;
                if (currItem == null)
                {
                    continue;
                }
                if (currItem.Options.CompositeProperty)
                {
                    throw new XmpException("Array items must be simple", XmpError.BADPARAM);
                }
                string str = ApplyQuotes(currItem.Value, openQuote, closeQuote, allowCommas);

                catinatedString.Append(str);
                if (it.MoveNext())
                {
                    catinatedString.Append(separator);
                }
            }

            return(catinatedString.ToString());
        }
예제 #27
0
        /// <seealso cref= XMPMeta#setLocalizedText(String, String, String, String, String,
        ///      PropertyOptions) </seealso>
        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?Utils.NormalizeLangValue(genericLang) : null;

            specificLang = 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);
            }
            if (!arrayNode.Options.ArrayAltText)
            {
                if (!arrayNode.HasChildren() && arrayNode.Options.ArrayAlternate)
                {
                    arrayNode.Options.ArrayAltText = 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.Children)
            {
                if (!currItem.HasQualifier() || !XML_LANG.Equals(currItem.GetQualifier(1).Name))
                {
                    throw new XmpException("Language qualifier must be first", XmpError.BADXPATH);
                }
                if (X_DEFAULT.Equals(currItem.GetQualifier(1).Value))
                {
                    xdItem       = currItem;
                    haveXDefault = true;
                    break;
                }
            }

            // Moves x-default to the beginning of the array
            if (xdItem != null && arrayNode.ChildrenLength > 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)((int?)result[0]);
            XmpNode  itemNode = (XmpNode)result[1];

            bool specificXDefault = 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, 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.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);
                    foreach (XmpNode currItem in arrayNode.Children)
                    {
                        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.CLT_SINGLE_GENERIC:

                // 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.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.ChildrenLength == 1)
                {
                    xdItem.Value = 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.ChildrenLength == 1)
            {
                XmpNodeUtils.AppendLangItem(arrayNode, X_DEFAULT, itemValue);
            }
        }