예제 #1
0
        /// <summary>
        /// This method is used to take values of a specific metadata field from a MediaProperties object,
        /// and store the values in another MediaProperties object that is used for merging values
        /// from multiple MediaProperties objects.
        /// </summary>
        /// <param name="propName">Property name, usually acquired through Tags[CommonPropertyNames] enumeration.</param>
        /// <param name="mergedProps">The IMediaProperties object that will hold the merged values.</param>
        /// <param name="source">The IMediaProperties object that provides a set of values to copy from.</param>
        /// <returns></returns>
        private ArrayList GetMergedValues(string propName, IMediaProperties mergedProps, IMediaProperties source)
        {
            // contains a shallow copy of the results
            ArrayList results = new ArrayList();

            // get the values from the merged table
            IList list = (IList)mergedProps[propName];

            if (list != null)
            {
                if (list.Count > 0)
                {
                    results.AddRange(list);
                }
            }

            bool allowsMultiple;

            PropertyMappings.PropertyNameToType(propName, out allowsMultiple);

            // get the values that we will be merging with
            list = (IList)source[propName];

            if (list != null)
            {
                if (list.Count > 0)
                {
                    if (allowsMultiple == false)
                    {
                        results = new ArrayList();
                        results.Add(list[0]);
                    }
                    else
                    {
                        results.AddRange(list);
                    }
                }
            }

            return(results);
        }
        /// <summary>
        /// Constructs an instance designed to extract a specific metadata property
        /// from an <see cref="IUPnPMedia"/> object
        /// </summary>
        /// <param name="property">
        /// string formatted in the form "[namespace]:
        /// </param>
        /// <exception cref="OpenSource.UPnP.AV.CdsMetadata.Error_InvalidAttribute">
        /// Thrown if the provided property maps to an invalid attribute,
        /// as per ContentDirectory metadata conventions.
        /// </exception>
        public TagExtractor(string property)
        {
            // obtain the specified namespace, tagname, and attribute name
            // for the metadata that needs to be extracted
            ParseNsTagAttrib(property, out m_Ns, out m_Tag, out m_Attrib);

            bool checkedTags = false;

            // Do some preprocessing that will properly set all of
            // the m_SearchXXX booleans to true to properly
            // indicate what objects the tag extractor should
            // examine.

            if (m_Ns == "")
            {
                // Blank namespace assumes DIDL-Lite top level tags.
                // Attempt to match the tag name against one of the
                // top level DIDL-Lite top level tags. Also accept
                // the case where the tag name is not specified,
                // in which case we assume any top-level DIDL-Lite
                // element.
                switch (m_Tag)
                {
                // search item objects
                case "item":
                    this.m_SearchItem = true;
                    break;

                // search container objects
                case "container":
                    this.m_SearchContainer = true;
                    break;

                // search resource objects
                case "res":
                    this.m_SearchRes = true;
                    break;

                // search any DIDL top level object?
                case "":
                    if (
                        (string.Compare(this.m_Attrib, T[_ATTRIB.id]) == 0) ||
                        (string.Compare(this.m_Attrib, T[_ATTRIB.restricted]) == 0) ||
                        (string.Compare(this.m_Attrib, T[_ATTRIB.parentID]) == 0) ||
                        (string.Compare(this.m_Attrib, T[_ATTRIB.childCount]) == 0) ||
                        (string.Compare(this.m_Attrib, T[_ATTRIB.refID]) == 0)
                        )
                    {
                        // limit the search to item and container objects
                        checkedTags            = true;
                        this.m_SearchItem      = true;
                        this.m_SearchContainer = true;
                    }
                    else if (string.Compare(this.m_Attrib, T[_ATTRIB.searchable]) == 0)
                    {
                        // limit the search to container objects
                        checkedTags            = true;
                        this.m_SearchContainer = true;
                    }
                    else
                    {
                        // limit the search to resource objects
                        this.m_SearchRes = true;
                    }
                    break;
                }

                if (!(this.m_SearchItem || this.m_SearchContainer || this.m_SearchRes))
                {
                    this.m_SearchDesc = true;
                }
            }
            else if ((m_Ns == "dc") || (m_Ns == "upnp"))
            {
                // if the namespace is dublin-core or upnp, then
                // we can't be searching vendor-specific metadata.
                this.m_SearchDesc = false;
            }

            // At this point, we're either configuring to extract
            // custom metadata or we're configuring to extract
            // CDS normative metadata.

            if (this.m_SearchDesc == false)
            {
                // If extracting CDS normative metadata...

                if (this.m_SearchItem || this.m_SearchContainer)
                {
                    // If we're searching item and container elements

                    if (!checkedTags)
                    {
                        // If by chance we haven't examined the attribute
                        // that is to be extracted, then check the
                        // attribute against the CDS normative attributes
                        // for item and container elements.

//						string[] attribs = { T[_ATTRIB.id], T[_ATTRIB.parentID], T[_ATTRIB.restricted] };
//
//						bool c = this.CheckAttribute(this.m_Ns, this.m_Tag, this.m_Attrib, attribs);
//						if (!c)
//						{
//							throw new Error_InvalidAttribute(this.m_Attrib + " is not a legal attribute of the item or container element.");
//						}

                        if ((m_Attrib != null) && (m_Attrib != ""))
                        {
                            bool c = true;
                            if (this.m_SearchItem && this.m_SearchContainer)
                            {
                                string[] refid = { T[_ATTRIB.id], T[_ATTRIB.parentID], T[_ATTRIB.restricted], T[_ATTRIB.refID] };
                                c = this.CheckAttribute(this.m_Ns, this.m_Tag, this.m_Attrib, refid);
                                if (!c)
                                {
                                    throw new Error_InvalidAttribute(this.m_Attrib + " is not a legal attribute of an item or container element.");
                                }
                            }
                            else if (this.m_SearchItem)
                            {
                                string[] refid = { T[_ATTRIB.id], T[_ATTRIB.parentID], T[_ATTRIB.restricted], T[_ATTRIB.refID] };
                                c = this.CheckAttribute(this.m_Ns, this.m_Tag, this.m_Attrib, refid);
                                if (!c)
                                {
                                    throw new Error_InvalidAttribute(this.m_Attrib + " is not a legal attribute of an item element.");
                                }
                            }
                            else if (this.m_SearchContainer)
                            {
                                string[] searchable = { T[_ATTRIB.id], T[_ATTRIB.parentID], T[_ATTRIB.restricted], T[_ATTRIB.searchable] };
                                c = this.CheckAttribute(this.m_Ns, this.m_Tag, this.m_Attrib, searchable);
                                if (!c)
                                {
                                    throw new Error_InvalidAttribute(this.m_Attrib + " is not a legal attribute of a container element.");
                                }
                            }
                        }
                    }
                    else
                    {
                        // Otherwise, we've already matched the attribute with a CDS normative
                        // attribute and we're ok.
                    }
                }
                else if (this.m_SearchRes)
                {
                    // Compare the desired attribute for extraction and ensure
                    // that the attribute is CDS-normative.

                    if ((m_Attrib != null) && (m_Attrib != ""))
                    {
                        string[] attribs =
                        {
                            T[_ATTRIB.bitrate],
                            T[_ATTRIB.bitsPerSample],
                            T[_ATTRIB.colorDepth],
                            T[_ATTRIB.duration],
                            T[_ATTRIB.importUri],
                            T[_ATTRIB.nrAudioChannels],
                            T[_ATTRIB.protection],
                            T[_ATTRIB.protocolInfo],
                            T[_ATTRIB.resolution],
                            T[_ATTRIB.sampleFrequency],
                            T[_ATTRIB.size]
                        };

                        bool c = this.CheckAttribute(this.m_Ns, this.m_Tag, this.m_Attrib, attribs);
                        if (!c)
                        {
                            throw new Error_InvalidAttribute(this.m_Attrib + " is not a legal attribute of the res element.");
                        }
                    }
                }
                else
                {
                    // Otherwise we're attempting to extract something from upnp: or dc:
                    // In such a case, we'll take the element name and find the ICdsElement
                    // class type and call the static GetPossibleAttributes() method.
                    // This will provide us with a list of valid attributes for that particular
                    // metadata class. Then we'll compare the attribute that we're
                    // supposed to extract with the provided list and throw an exception
                    // if no match exists.

                    StringBuilder elementName = new StringBuilder();
                    elementName.AppendFormat("{0}:{1}", this.m_Ns, this.m_Tag);

                    if (this.m_Attrib != "")
                    {
                        bool        ignore;
                        System.Type type = PropertyMappings.PropertyNameToType(elementName.ToString(), out ignore);

                        MethodInfo mi = type.GetMethod("GetPossibleAttributes", BindingFlags.Public | BindingFlags.Static);

                        if (mi != null)
                        {
                            IList possibleAttributes = (IList)mi.Invoke(null, null);

                            if (possibleAttributes.Contains(this.m_Attrib) == false)
                            {
                                throw new Error_InvalidAttribute(this.m_Attrib + " is not a legal attribute of " + elementName.ToString());
                            }
                        }
                        else
                        {
                            throw new ApplicationException(type.ToString() + " does not implement GetPossibleAttributes.");
                        }
                    }
                }
            }
            else
            {
                // Do not extract custom metadata values for now.
                //
                throw new Error_InvalidAttribute("Cannot extract metadata value from <desc> elements or child elements in <desc> elements. Feature is not yet implemented.");
            }
        }