/// <summary> /// <para> /// Instantiates a sorter based on the sortCriteria string. The basic algorithm for /// sorting is to supply a comma-separated-value (CSV) listing of property names /// (easily retrieved from using <see cref="Tags"/>'s indexer with the /// <see cref="CommonPropertyNames"/>, /// <see cref="_DC"/>, /// <see cref="_UPNP"/>, or /// <see cref="_ATTRIB"/> /// enumerators.) /// with each property name having a + or - sign to indicate ascending or descending /// order of the sorting for that property name. Assuming "T" is an instance of a /// <see cref="Tags"/> object. /// Example below. /// </para> /// /// <para> /// <list type="table"> /// <item> /// <term>"+" +T[CommonPropertyNames.title]+ ",-" +T[CommonPropertyNames.creator]</term> /// <description>Sorts with ascending titles first, then descending creators</description> /// </item> /// </list> /// </para> /// /// </summary> /// <param name="forceDistinction">if true, then any comparison that evaluates to equal will force an arbitrary ordering of the two objects in question</param> /// <param name="sortCriteria">a string with the property names in a CSV list, where /// each property name has a + or - sign to indicate ascending or descending order</param> public MediaSorter(bool forceDistinction, string sortCriteria) { this.forceDistinction = forceDistinction; if (sortCriteria != null) { if (sortCriteria != "") { DText parser = new DText(); parser.ATTRMARK = ","; parser[0] = sortCriteria; int size = parser.DCOUNT(); this.sortKeys = new ArrayList(size); // iterate through properties for sorting // for (int i = 1; i <= size; i++) { string prop = parser[i].Trim(); char asc_dsc = prop[0]; string property = prop.Substring(1); bool ascending = true; if (asc_dsc == '-') { ascending = false; } else if (asc_dsc == '+') { ascending = true; } else { throw new UPnPCustomException(709, "Invalid sort flag."); } MetadataValueComparer mvc = new MetadataValueComparer(property, ascending); this.sortKeys.Add(mvc); } } } if (this.sortKeys == null) { this.sortKeys = new ArrayList(0); } }
/// <summary> /// Evaluates a subexpression of a whole expression. /// </summary> /// <param name="media">the media object with the metadata</param> /// <param name="prop">the property/attribute metadata to examine</param> /// <param name="op">the operator to use for examination</param> /// <param name="val">the value to compare against in string form</param> /// <returns></returns> /// <exception cref="OpenSource.UPnP.AV.CdsMetadata.Error_MalformedSearchCriteria"> /// Thrown when the expression provided at constructor time could not /// be used to evaluate the media because of syntax errors in /// the expression. /// </exception> private bool Evaluate(IUPnPMedia media, string prop, OperatorTokens op, string val) { bool result = false; TagExtractor te = (TagExtractor)this.m_PE[prop]; IList values = te.Extract(media); if (op == OperatorTokens.Exists) { bool testVal = (string.Compare(val, "true", true) == 0); result = ( ((values.Count > 0) && (testVal)) || ((values.Count == 0) && (testVal == false)) ); } else { foreach (object testVal in values) { int opCode = (int)op; if ((opCode >= (int)OperatorTokens.Equal) && (opCode <= (int)OperatorTokens.GreaterThanEqualTo)) { // Compare using a relational operator // try { int relResult = MetadataValueComparer.CompareTagValues(testVal, val, this.IgnoreCase); if (relResult == 0) { result = true; break; } } catch //(Exception e) { string opString = Enum.GetName(typeof(OperatorTokens), opCode); throw new Error_MalformedSearchCriteria("(" + val + ") " + opString + " " + testVal.ToString() + ") could not occur."); } } else if (op == OperatorTokens.Contains) { string tv = testVal.ToString(); int pos = tv.IndexOf(val); result = (pos >= 0); } else if (op == OperatorTokens.DoesNotContain) { string tv = testVal.ToString(); int pos = tv.IndexOf(val); result = (pos < 0); } else if (op == OperatorTokens.DerivedFrom) { string tv = testVal.ToString(); result = tv.StartsWith(val); } } } return(result); }
/// <summary> /// <para> /// Instantiates a sorter based on the sortCriteria string. The basic algorithm for /// sorting is to supply a comma-separated-value (CSV) listing of property names /// (easily retrieved from using <see cref="Tags"/>'s indexer with the /// <see cref="CommonPropertyNames"/>, /// <see cref="_DC"/>, /// <see cref="_UPNP"/>, or /// <see cref="_ATTRIB"/> /// enumerators.) /// with each property name having a + or - sign to indicate ascending or descending /// order of the sorting for that property name. Assuming "T" is an instance of a /// <see cref="Tags"/> object. /// Example below. /// </para> /// /// <para> /// <list type="table"> /// <item> /// <term>"+" +T[CommonPropertyNames.title]+ ",-" +T[CommonPropertyNames.creator]</term> /// <description>Sorts with ascending titles first, then descending creators</description> /// </item> /// </list> /// </para> /// /// </summary> /// <param name="forceDistinction">if true, then any comparison that evaluates to equal will force an arbitrary ordering of the two objects in question</param> /// <param name="sortCriteria">a string with the property names in a CSV list, where /// each property name has a + or - sign to indicate ascending or descending order</param> public MediaSorter (bool forceDistinction, string sortCriteria) { this.forceDistinction = forceDistinction; if (sortCriteria != null) { if (sortCriteria != "") { DText parser = new DText(); parser.ATTRMARK = ","; parser[0] = sortCriteria; int size = parser.DCOUNT(); this.sortKeys = new ArrayList(size); // iterate through properties for sorting // for (int i=1; i <= size; i++) { string prop = parser[i].Trim(); char asc_dsc = prop[0]; string property = prop.Substring(1); bool ascending = true; if (asc_dsc == '-') { ascending = false; } else if (asc_dsc == '+') { ascending = true; } else { throw new UPnPCustomException(709, "Invalid sort flag."); } MetadataValueComparer mvc = new MetadataValueComparer(property, ascending); this.sortKeys.Add(mvc); } } } if (this.sortKeys == null) { this.sortKeys = new ArrayList(0); } }