/// <summary> /// Obtains multiple metadata values in a single operation. /// Much faster than using the indexers. /// </summary> public Hashtable GetValues(string[] propertyNames) { ArrayList properties = new ArrayList(propertyNames.Length); Hashtable results = new Hashtable(propertyNames.Length); string title = T[_DC.title]; string creator = T[_DC.creator]; string Class = T[_UPNP.Class]; foreach (string pn in propertyNames) { if (pn == title) { ICdsElement[] elements = new ICdsElement[1]; elements[0] = this.m_Title; results.Add(title, elements); } else if (pn == creator) { ICdsElement[] elements = new ICdsElement[1]; elements[0] = this.m_Creator; results.Add(creator, elements); } else if (pn == Class) { ICdsElement[] elements = new ICdsElement[1]; elements[0] = this.m_Class; results.Add(Class, elements); } else { properties.Add(pn); } } this.m_LockTable.AcquireReaderLock(-1); _Hashtable.Get(results, this.m_Table, (object[])properties.ToArray(typeof(object))); this.m_LockTable.ReleaseReaderLock(); return(results); }
/// <summary> /// <para> /// Each property always returns a listing of values /// because the schema allows for multiple values. /// For example, there may be more than one /// artist, genre, codec, etc. associated with the item. /// </para> /// /// <para> /// The list is a shallow copy. /// </para> /// /// <para> /// Every element in this class implements /// <see cref="ICdsElement"/>. /// The interface helps strongly type the classes /// when instantiating from xml. /// </para> /// <para> /// If using a <see cref="Tags"/> /// object, then do not use the /// <see cref="_DIDL"/> /// <see cref="_ATTRIB"/> /// enumerators in the Tags indexer. Only the /// <see cref="CommonPropertyNames"/>, /// <see cref="_DC"/>, or /// <see cref="_UPNP"/> /// enumerators will work with this class. /// </para> /// <para> /// The set operation for this indexer will throw an /// <see cref="ApplicationException"/> if the /// caller does not have the same namespace /// and assembly as this class. /// </para> /// </summary> /// <exception cref="ApplicationException"> /// Thrown on a set-operation if the caller does /// is not defined in the same assembly and /// namespace as this class. /// </exception> public IList this[string propName] { get { Exception error = null; IList retVal = null; ICdsElement[] elements; elements = new ICdsElement[1]; if ((propName == T[_DC.title]) && (this.m_Title != null)) { elements[0] = this.m_Title; } else if ((propName == T[_DC.creator]) && (this.m_Creator != null)) { elements[0] = this.m_Creator; } else if ((propName == T[_UPNP.Class]) && (this.m_Class != null)) { elements[0] = this.m_Class; } else { // in the worst case, ensure empty list elements = new ICdsElement[0]; this.m_LockTable.AcquireReaderLock(-1); try { retVal = (IList)_Hashtable.Get(m_Table, propName); if (error == null) { // return a shallow copy if (retVal != null) { if (retVal.Count > 0) { elements = new ICdsElement[retVal.Count]; int i = 0; foreach (ICdsElement e in retVal) { elements[i] = e; i++; } } } } } catch (Exception e) { error = e; } this.m_LockTable.ReleaseReaderLock(); if (error != null) { Exception ne = new Exception("MediaProperties.get_this[string]()", error); throw ne; } } return(elements); } set { this.CheckProtection(); int count = value.Count; ICdsElement[] elements = new ICdsElement[count]; for (int i = 0; i < count; i++) { elements[i] = (ICdsElement)value[i]; } this.SetVal(propName, elements); } }
/// <summary> /// Sets a value in the hashtable /// </summary> /// <param name="key">property name</param> private void SetVal(string key, ICdsElement[] objs) { //this.m_Table[key] = objs; if ((key == T[_DC.title])) { this.m_Title = (PropertyString)objs[0]; } else if ((key == T[_DC.creator])) { this.m_Creator = (PropertyString)objs[0]; } else if ((key == T[_UPNP.Class])) { this.m_Class = (MediaClass)objs[0]; } else { Exception error = null; try { this.m_LockTable.AcquireWriterLock(-1); try { _Hashtable.Set(m_Table, key, objs); } catch (Exception e) { error = e; } } finally { this.m_LockTable.ReleaseWriterLock(); } if (error != null) { Exception ne = new Exception("MediaProperties.set_this[string]()", error); throw ne; } } this.IncrementStateNumber(); }
/// <summary> /// Obtains multiple metadata values in a single operation. /// Much faster than using the indexers. /// </summary> public Hashtable GetValues(string[] propertyNames) { ArrayList properties = new ArrayList(propertyNames.Length); Hashtable results = new Hashtable(propertyNames.Length); string title = T[_DC.title]; string creator = T[_DC.creator]; string Class = T[_UPNP.Class]; foreach (string pn in propertyNames) { if (pn == title) { ICdsElement[] elements = new ICdsElement[1]; elements[0] = this.m_Title; results.Add(title, elements); } else if (pn == creator) { ICdsElement[] elements = new ICdsElement[1]; elements[0] = this.m_Creator; results.Add(creator, elements); } else if (pn == Class) { ICdsElement[] elements = new ICdsElement[1]; elements[0] = this.m_Class; results.Add(Class, elements); } else { properties.Add(pn); } } this.m_LockTable.AcquireReaderLock(-1); _Hashtable.Get(results, this.m_Table, (object[])properties.ToArray(typeof(object))); this.m_LockTable.ReleaseReaderLock(); return results; }
/// <summary> /// <para> /// Each property always returns a listing of values /// because the schema allows for multiple values. /// For example, there may be more than one /// artist, genre, codec, etc. associated with the item. /// </para> /// /// <para> /// The list is a shallow copy. /// </para> /// /// <para> /// Every element in this class implements /// <see cref="ICdsElement"/>. /// The interface helps strongly type the classes /// when instantiating from xml. /// </para> /// <para> /// If using a <see cref="Tags"/> /// object, then do not use the /// <see cref="_DIDL"/> /// <see cref="_ATTRIB"/> /// enumerators in the Tags indexer. Only the /// <see cref="CommonPropertyNames"/>, /// <see cref="_DC"/>, or /// <see cref="_UPNP"/> /// enumerators will work with this class. /// </para> /// <para> /// The set operation for this indexer will throw an /// <see cref="ApplicationException"/> if the /// caller does not have the same namespace /// and assembly as this class. /// </para> /// </summary> /// <exception cref="ApplicationException"> /// Thrown on a set-operation if the caller does /// is not defined in the same assembly and /// namespace as this class. /// </exception> public IList this[string propName] { get { Exception error = null; IList retVal = null; ICdsElement[] elements; elements = new ICdsElement[1]; if ((propName == T[_DC.title]) && (this.m_Title != null)) { elements[0] = this.m_Title; } else if ((propName == T[_DC.creator]) && (this.m_Creator != null)) { elements[0] = this.m_Creator; } else if ((propName == T[_UPNP.Class]) && (this.m_Class != null)) { elements[0] = this.m_Class; } else { // in the worst case, ensure empty list elements = new ICdsElement[0]; this.m_LockTable.AcquireReaderLock(-1); try { retVal = (IList)_Hashtable.Get(m_Table, propName); if (error == null) { // return a shallow copy if (retVal != null) { if (retVal.Count > 0) { elements = new ICdsElement[retVal.Count]; int i = 0; foreach (ICdsElement e in retVal) { elements[i] = e; i++; } } } } } catch (Exception e) { error = e; } this.m_LockTable.ReleaseReaderLock(); if (error != null) { Exception ne = new Exception("MediaProperties.get_this[string]()", error); throw ne; } } return elements; } set { this.CheckProtection(); int count = value.Count; ICdsElement[] elements = new ICdsElement[count]; for (int i = 0; i < count; i++) { elements[i] = (ICdsElement)value[i]; } this.SetVal(propName, elements); } }
/// <summary> /// Updates the metadata obtained retrievable /// from the Properties property. Such metadata is /// limited to metadata in the CommonPropertyNames attributes /// and does not include /// associated children, resources, ID, searchable/restricted attributes /// of the object. /// </summary> /// <param name="child"> /// XmlElement that's a child of the item or container element. /// The element's name must map to something in CommonPropertyNames, /// as defined by the <see cref="PropertyMappings.PropertyNameToType"/> /// method. /// </param> protected void UpdateProperty(XmlElement child) { bool isMultiple; // figure out what .NET type the data should Type type = PropertyMappings.PropertyNameToType(child.Name, out isMultiple); if (type != null) { try { Type[] constructorArgTypes = new Type[1]; constructorArgTypes[0] = typeof(XmlElement); ConstructorInfo ci = type.GetConstructor(constructorArgTypes); ICdsElement metadata = null; if (ci != null) { object[] obj = new object[1]; obj[0] = child; metadata = (ICdsElement) ci.Invoke(obj); } // ensure proper case-sensitive spelling of property CommonPropertyNames prop = (CommonPropertyNames) Enum.Parse(typeof(CommonPropertyNames), child.LocalName, true); string propName = T[prop]; if (propName == T[_UPNP.Class]) { MediaClass mc = (MediaClass) metadata; metadata = (ICdsElement) CdsMetadataCaches.MediaClasses.CacheThis(mc.FullClassName, mc.FriendlyName); } else if (propName == T[_UPNP.writeStatus]) { PropertyEnumWriteStatus ws = (PropertyEnumWriteStatus) metadata; metadata = (ICdsElement) CdsMetadataCaches.PropertyEnumWriteStatus.CacheThis(T[_UPNP.writeStatus], ws._Value); } else if (propName == T[_UPNP.storageMedium]) { PropertyStorageMedium sm = (PropertyStorageMedium) metadata; metadata = (ICdsElement) CdsMetadataCaches.PropertyStorageMediums.CacheThis(T[_UPNP.storageMedium], sm._Value); } if (isMultiple) { this.m_Properties.AddVal(propName, metadata); } else { //this.m_Properties.SetVal(propName, metadata); ICdsElement[] elements = new ICdsElement[1]; elements[0] = metadata; this.m_Properties[propName] = elements; } } catch (Exception e) { // if we failed to instantiate a property, just keep going // with the next one and don't worry about other people's mistakes. // just do the best you can with what they give you. OpenSource.Utilities.EventLogger.Log(e); } } }