The property flags are used when properties are fetched from the XMPMeta-object and provide more detailed information about the property. @since 03.07.2006
상속: XmpOptions
예제 #1
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);
        }
예제 #2
0
        // -------------------------------------------------------------------------------------
        // private


        /// <summary>
        /// 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.
        /// </summary>
        /// <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="XmpException"> </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.ChildrenLength + 1 : arrayNode.ChildrenLength;
            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);
            }
        }
예제 #3
0
 /// <seealso cref= XMPMeta#SetPropertyBase64(String, String, byte[], PropertyOptions) </seealso>
 public virtual void SetPropertyBase64(string schemaNs, string propName, sbyte[] propValue,
                                       PropertyOptions options) {
     SetProperty(schemaNs, propName, propValue, options);
 }
예제 #4
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);
            }
        }
예제 #5
0
 /// <seealso cref= XMPMeta#SetPropertyInteger(String, String, int, PropertyOptions) </seealso>
 public virtual void SetPropertyInteger(string schemaNs, string propName, int propValue, PropertyOptions options) {
     SetProperty(schemaNs, propName, propValue, options);
 }
예제 #6
0
 /// <seealso cref= XMPMeta#SetPropertyDouble(String, String, double, PropertyOptions) </seealso>
 public virtual void SetPropertyDouble(string schemaNs, string propName, double propValue,
                                       PropertyOptions options) {
     SetProperty(schemaNs, propName, propValue, options);
 }
예제 #7
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);
                }
            }
        }
예제 #8
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);
            }
        }
예제 #9
0
        /// <summary>
        /// Follow an expanded path expression to find or create a node.
        /// </summary>
        /// <param name="xmpTree"> the node to begin the search. </param>
        /// <param name="xpath"> the complete xpath </param>
        /// <param name="createNodes"> flag if nodes shall be created 
        /// 			(when called by <code>setProperty()</code>) </param>
        /// <param name="leafOptions"> the options for the created leaf nodes (only when
        ///			<code>createNodes == true</code>). </param>
        /// <returns> Returns the node if found or created or <code>null</code>. </returns>
        /// <exception cref="XmpException"> An exception is only thrown if an error occurred, 
        /// 			not if a node was not found. </exception>
        internal static XmpNode FindNode(XmpNode xmpTree, XmpPath xpath, bool createNodes, PropertyOptions leafOptions) {
            // check if xpath is set.
            if (xpath == null || xpath.Size() == 0) {
                throw new XmpException("Empty XmpPath", XmpError.BADXPATH);
            }

            // Root of implicitly created subtree to possible delete it later. 
            // Valid only if leaf is new.
            XmpNode rootImplicitNode = null;

            // resolve schema step
            XmpNode currNode = FindSchemaNode(xmpTree, xpath.GetSegment((int) XmpPath.STEP_SCHEMA).Name, createNodes);
            if (currNode == null) {
                return null;
            }
            if (currNode.Implicit) {
                currNode.Implicit = false; // Clear the implicit node bit.
                rootImplicitNode = currNode; // Save the top most implicit node.
            }


            // Now follow the remaining steps of the original XmpPath.
            try {
                for (int i = 1; i < xpath.Size(); i++) {
                    currNode = FollowXPathStep(currNode, xpath.GetSegment(i), createNodes);
                    if (currNode == null) {
                        if (createNodes) {
                            // delete implicitly created nodes
                            DeleteNode(rootImplicitNode);
                        }
                        return null;
                    }
                    if (currNode.Implicit) {
                        // clear the implicit node flag
                        currNode.Implicit = false;

                        // if node is an ALIAS (can be only in root step, auto-create array 
                        // when the path has been resolved from a not simple alias type
                        if (i == 1 && xpath.GetSegment(i).Alias && xpath.GetSegment(i).AliasForm != 0) {
                            currNode.Options.SetOption(xpath.GetSegment(i).AliasForm, true);
                        }
                            // "CheckImplicitStruct" in C++
                        else if (i < xpath.Size() - 1 && xpath.GetSegment(i).Kind == XmpPath.STRUCT_FIELD_STEP &&
                                 !currNode.Options.CompositeProperty) {
                            currNode.Options.Struct = true;
                        }

                        if (rootImplicitNode == null) {
                            rootImplicitNode = currNode; // Save the top most implicit node.
                        }
                    }
                }
            }
            catch (XmpException e) {
                // if new notes have been created prior to the error, delete them
                if (rootImplicitNode != null) {
                    DeleteNode(rootImplicitNode);
                }
                throw e;
            }


            if (rootImplicitNode != null) {
                // set options only if a node has been successful created
                currNode.Options.MergeWith(leafOptions);
                currNode.Options = currNode.Options;
            }

            return currNode;
        }
예제 #10
0
        /// <summary>
        /// Verifies the PropertyOptions for consistancy and updates them as needed. 
        /// If options are <code>null</code> they are created with default values.
        /// </summary>
        /// <param name="options"> the <code>PropertyOptions</code> </param>
        /// <param name="itemValue"> the node value to set </param>
        /// <returns> Returns the updated options. </returns>
        /// <exception cref="XmpException"> If the options are not consistant.  </exception>
        internal static PropertyOptions VerifySetOptions(PropertyOptions options, object itemValue) {
            // create empty and fix existing options
            if (options == null) {
                // set default options
                options = new PropertyOptions();
            }

            if (options.ArrayAltText) {
                options.ArrayAlternate = true;
            }

            if (options.ArrayAlternate) {
                options.ArrayOrdered = true;
            }

            if (options.ArrayOrdered) {
                options.Array = true;
            }

            if (options.CompositeProperty && itemValue != null && itemValue.ToString().Length > 0) {
                throw new XmpException("Structs and arrays can't have values", XmpError.BADOPTIONS);
            }

            options.AssertConsistency(options.Options);

            return options;
        }
예제 #11
0
        /// <summary>
        /// Find or create a child node under a given parent node. If the parent node is no 
        /// Returns the found or created child node.
        /// </summary>
        /// <param name="parent">
        ///            the parent node </param>
        /// <param name="childName">
        ///            the node name to find </param>
        /// <param name="createNodes">
        ///            flag, if new nodes shall be created. </param>
        /// <returns> Returns the found or created node or <code>null</code>. </returns>
        /// <exception cref="XmpException"> Thrown if  </exception>
        internal static XmpNode FindChildNode(XmpNode parent, string childName, bool createNodes) {
            if (!parent.Options.SchemaNode && !parent.Options.Struct) {
                if (!parent.Implicit) {
                    throw new XmpException("Named children only allowed for schemas and structs",
                                           XmpError.BADXPATH);
                }
                if (parent.Options.Array) {
                    throw new XmpException("Named children not allowed for arrays", XmpError.BADXPATH);
                }
                if (createNodes) {
                    parent.Options.Struct = true;
                }
            }

            XmpNode childNode = parent.FindChildByName(childName);

            if (childNode == null && createNodes) {
                PropertyOptions options = new PropertyOptions();
                childNode = new XmpNode(childName, options);
                childNode.Implicit = true;
                parent.AddChild(childNode);
            }

            Debug.Assert(childNode != null || !createNodes);

            return childNode;
        }
예제 #12
0
        /// <summary>
        /// Find or create a schema node if <code>createNodes</code> is true.
        /// </summary>
        /// <param name="tree"> the root of the xmp tree. </param>
        /// <param name="namespaceUri"> a namespace </param>
        /// <param name="suggestedPrefix"> If a prefix is suggested, the namespace is allowed to be registered. </param>
        /// <param name="createNodes"> a flag indicating if the node shall be created if not found.
        /// 		  <em>Note:</em> The namespace must be registered prior to this call.
        /// </param>
        /// <returns> Returns the schema node if found, <code>null</code> otherwise.
        /// 		   Note: If <code>createNodes</code> is <code>true</code>, it is <b>always</b>
        /// 		   returned a valid node. </returns>
        /// <exception cref="XmpException"> An exception is only thrown if an error occurred, not if a
        ///         		node was not found. </exception>
        internal static XmpNode FindSchemaNode(XmpNode tree, string namespaceUri, string suggestedPrefix,
                                               bool createNodes) {
            Debug.Assert(tree.Parent == null); // make sure that its the root
            XmpNode schemaNode = tree.FindChildByName(namespaceUri);

            if (schemaNode == null && createNodes) {
                PropertyOptions propertyOptions = new PropertyOptions();
                propertyOptions.SchemaNode = true;
                schemaNode = new XmpNode(namespaceUri, propertyOptions);
                schemaNode.Implicit = true;

                // only previously registered schema namespaces are allowed in the XMP tree.
                string prefix = XMPMetaFactory.SchemaRegistry.GetNamespacePrefix(namespaceUri);
                if (prefix == null) {
                    if (!String.IsNullOrEmpty(suggestedPrefix)) {
                        prefix = XMPMetaFactory.SchemaRegistry.RegisterNamespace(namespaceUri, suggestedPrefix);
                    }
                    else {
                        throw new XmpException("Unregistered schema namespace URI", XmpError.BADSCHEMA);
                    }
                }

                schemaNode.Value = prefix;

                tree.AddChild(schemaNode);
            }

            return schemaNode;
        }
예제 #13
0
        /// <summary>
        /// Initializes the map that contains the known arrays, that are fixed by 
        /// <seealso cref="NormalizeDcArrays"/>. 
        /// </summary>
        private static void InitDcArrays() {
            _dcArrayForms = new Hashtable();

            // Properties supposed to be a "Bag".
            PropertyOptions bagForm = new PropertyOptions();
            bagForm.Array = true;
            _dcArrayForms["dc:contributor"] = bagForm;
            _dcArrayForms["dc:language"] = bagForm;
            _dcArrayForms["dc:publisher"] = bagForm;
            _dcArrayForms["dc:relation"] = bagForm;
            _dcArrayForms["dc:subject"] = bagForm;
            _dcArrayForms["dc:type"] = bagForm;

            // Properties supposed to be a "Seq".
            PropertyOptions seqForm = new PropertyOptions();
            seqForm.Array = true;
            seqForm.ArrayOrdered = true;
            _dcArrayForms["dc:creator"] = seqForm;
            _dcArrayForms["dc:date"] = seqForm;

            // Properties supposed to be an "Alt" in alternative-text form.
            PropertyOptions altTextForm = new PropertyOptions();
            altTextForm.Array = true;
            altTextForm.ArrayOrdered = true;
            altTextForm.ArrayAlternate = true;
            altTextForm.ArrayAltText = true;
            _dcArrayForms["dc:description"] = altTextForm;
            _dcArrayForms["dc:rights"] = altTextForm;
            _dcArrayForms["dc:title"] = altTextForm;
        }
예제 #14
0
 /// <summary>
 /// Compares two options set for array compatibility.
 /// </summary>
 /// <param name="options"> other options </param>
 /// <returns> Returns true if the array options of the sets are equal. </returns>
 public bool EqualArrayTypes(PropertyOptions options)
 {
     return(Array == options.Array && ArrayOrdered == options.ArrayOrdered &&
            ArrayAlternate == options.ArrayAlternate && ArrayAltText == options.ArrayAltText);
 }
예제 #15
0
        /// <summary>
        /// Utility to find or create the array used by <code>separateArrayItems()</code>. </summary>
        /// <param name="schemaNs"> a the namespace fo the array </param>
        /// <param name="arrayName"> the name of the array </param>
        /// <param name="arrayOptions"> the options for the array if newly created </param>
        /// <param name="xmp"> the xmp object </param>
        /// <returns> Returns the array node. </returns>
        /// <exception cref="XmpException"> Forwards exceptions </exception>
        private static XmpNode SeparateFindCreateArray(string schemaNs, string arrayName, PropertyOptions arrayOptions,
                                                       XmpMetaImpl xmp) {
            arrayOptions = XmpNodeUtils.VerifySetOptions(arrayOptions, null);
            if (!arrayOptions.OnlyArrayOptions) {
                throw new XmpException("Options can only provide array form", XmpError.BADOPTIONS);
            }

            // Find the array node, make sure it is OK. Move the current children
            // aside, to be readded later if kept.
            XmpPath arrayPath = XmpPathParser.ExpandXPath(schemaNs, arrayName);
            XmpNode arrayNode = XmpNodeUtils.FindNode(xmp.Root, arrayPath, false, null);
            if (arrayNode != null) {
                // The array exists, make sure the form is compatible. Zero
                // arrayForm means take what exists.
                PropertyOptions arrayForm = arrayNode.Options;
                if (!arrayForm.Array || arrayForm.ArrayAlternate) {
                    throw new XmpException("Named property must be non-alternate array", XmpError.BADXPATH);
                }
                if (arrayOptions.EqualArrayTypes(arrayForm)) {
                    throw new XmpException("Mismatch of specified and existing array form", XmpError.BADXPATH);
                    // *** Right error?
                }
            }
            else {
                // The array does not exist, try to create it.
                // don't modify the options handed into the method
                arrayOptions.Array = true;
                arrayNode = XmpNodeUtils.FindNode(xmp.Root, arrayPath, true, arrayOptions);
                if (arrayNode == null) {
                    throw new XmpException("Failed to create named array", XmpError.BADXPATH);
                }
            }
            return arrayNode;
        }
예제 #16
0
 /// <summary>
 /// Merges the set options of a another options object with this.
 /// If the other options set is null, this objects stays the same. </summary>
 /// <param name="options"> other options </param>
 /// <exception cref="XmpException"> If illegal options are provided  </exception>
 public void MergeWith(PropertyOptions options) {
     if (options != null) {
         Options = Options | options.Options;
     }
 }
예제 #17
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);
                }
            }
        }
예제 #18
0
 /// <exception cref="XmpException"> </exception>
 /// <seealso cref= XMPMeta#SetPropertyBoolean(String, String, boolean, PropertyOptions) </seealso>
 public virtual void SetPropertyBoolean(string schemaNs, string propName, bool propValue, PropertyOptions options) {
     SetProperty(schemaNs, propName, propValue ? TRUESTR : FALSESTR, options);
 }
예제 #19
0
 /// <summary>
 /// Creates an <code>XMPNode</code> with initial values.
 /// </summary>
 /// <param name="name"> the name of the node </param>
 /// <param name="value"> the value of the node </param>
 /// <param name="options"> the options of the node </param>
 public XmpNode(string name, string value, PropertyOptions options) {
     _name = name;
     _value = value;
     _options = options;
 }
예제 #20
0
 /// <seealso cref= XMPMeta#SetPropertyLong(String, String, long, PropertyOptions) </seealso>
 public virtual void SetPropertyLong(string schemaNs, string propName, long propValue, PropertyOptions options) {
     SetProperty(schemaNs, propName, propValue, options);
 }
예제 #21
0
 /// <summary>
 /// Constructor for the node without value.
 /// </summary>
 /// <param name="name"> the name of the node </param>
 /// <param name="options"> the options of the node </param>
 public XmpNode(string name, PropertyOptions options)
     : this(name, null, options) {
 }
예제 #22
0
 /// <seealso cref= XMPMeta#SetPropertyCalendar(String, String, Calendar,
 ///      PropertyOptions) </seealso>
 public virtual void SetPropertyCalendar(string schemaNs, string propName, DateTime propValue,
                                         PropertyOptions options) {
     SetProperty(schemaNs, propName, propValue, options);
 }
예제 #23
0
        /// <summary>
        /// Performs a <b>deep clone</b> of the node and the complete subtree.
        /// </summary>
        /// <seealso cref= java.lang.Object#clone() </seealso>
        public virtual object Clone() {
            PropertyOptions newOptions;
            try {
                newOptions = new PropertyOptions(Options.Options);
            }
            catch (XmpException) {
                // cannot happen
                newOptions = new PropertyOptions();
            }

            XmpNode newNode = new XmpNode(_name, _value, newOptions);
            CloneSubtree(newNode);

            return newNode;
        }
예제 #24
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);
            }
        }
예제 #25
0
 /// <summary>
 /// Resets the node.
 /// </summary>
 public virtual void Clear() {
     _options = null;
     _name = null;
     _value = null;
     _children = null;
     _qualifier = null;
 }
예제 #26
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);
        }
예제 #27
0
        /// <summary>
        /// Adds a child node.
        /// </summary>
        /// <param name="xmp"> the xmp metadata object that is generated </param>
        /// <param name="xmpParent"> the parent xmp node </param>
        /// <param name="xmlNode"> the currently processed XML node </param>
        /// <param name="value"> Node value </param>
        /// <param name="isTopLevel"> Flag if the node is a top-level node </param>
        /// <returns> Returns the newly created child node. </returns>
        /// <exception cref="XmpException"> thown on parsing errors </exception>
        private static XmpNode AddChildNode(XmpMetaImpl xmp, XmpNode xmpParent, XmlNode xmlNode, string value,
                                            bool isTopLevel) {
            IXmpSchemaRegistry registry = XmpMetaFactory.SchemaRegistry;
            string @namespace = xmlNode.NamespaceURI;
            string childName;
            if (@namespace != null) {
                if (NS_DC_DEPRECATED.Equals(@namespace)) {
                    // Fix a legacy DC namespace
                    @namespace = NS_DC;
                }

                string prefix = registry.GetNamespacePrefix(@namespace);
                if (prefix == null) {
                    prefix = xmlNode.Prefix ?? DEFAULT_PREFIX;
                    prefix = registry.RegisterNamespace(@namespace, prefix);
                }
                childName = prefix + xmlNode.LocalName;
            }
            else {
                throw new XmpException("XML namespace required for all elements and attributes",
                                       XmpError.BADRDF);
            }


            // create schema node if not already there
            PropertyOptions childOptions = new PropertyOptions();
            bool isAlias = false;
            if (isTopLevel) {
                // Lookup the schema node, adjust the XMP parent pointer.
                // Incoming parent must be the tree root.
                XmpNode schemaNode = XmpNodeUtils.FindSchemaNode(xmp.Root, @namespace, DEFAULT_PREFIX, true);
                schemaNode.Implicit = false; // Clear the implicit node bit.
                // need runtime check for proper 32 bit code.
                xmpParent = schemaNode;

                // If this is an alias set the alias flag in the node 
                // and the hasAliases flag in the tree.
                if (registry.FindAlias(childName) != null) {
                    isAlias = true;
                    xmp.Root.HasAliases = true;
                    schemaNode.HasAliases = true;
                }
            }


            // Make sure that this is not a duplicate of a named node.
            bool isArrayItem = "rdf:li".Equals(childName);
            bool isValueNode = "rdf:value".Equals(childName);

            // Create XMP node and so some checks
            XmpNode newChild = new XmpNode(childName, value, childOptions);
            newChild.Alias = isAlias;

            // Add the new child to the XMP parent node, a value node first.
            if (!isValueNode) {
                xmpParent.AddChild(newChild);
            }
            else {
                xmpParent.AddChild(1, newChild);
            }


            if (isValueNode) {
                if (isTopLevel || !xmpParent.Options.Struct) {
                    throw new XmpException("Misplaced rdf:value element", XmpError.BADRDF);
                }
                xmpParent.HasValueChild = true;
            }

            if (isArrayItem) {
                if (!xmpParent.Options.Array) {
                    throw new XmpException("Misplaced rdf:li element", XmpError.BADRDF);
                }
                newChild.Name = ARRAY_ITEM_NAME;
            }

            return newChild;
        }
예제 #28
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);
        }
예제 #29
0
 /// <summary>
 /// Compares two options set for array compatibility.
 /// </summary>
 /// <param name="options"> other options </param>
 /// <returns> Returns true if the array options of the sets are equal. </returns>
 public bool EqualArrayTypes(PropertyOptions options) {
     return Array == options.Array && ArrayOrdered == options.ArrayOrdered &&
            ArrayAlternate == options.ArrayAlternate && ArrayAltText == options.ArrayAltText;
 }
예제 #30
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="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.Options.MergeWith(newOptions);

            if (!node.Options.CompositeProperty) {
                // 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();
            }
        }
예제 #31
0
 /// <summary>
 /// Separate a single edit string into an array of strings.
 /// </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) {
     XmpUtilsImpl.SeparateArrayItems(xmp, schemaNs, arrayName, catedStr, arrayOptions, preserveCommas);
 }