1 ///
2 /// Convert a filter into a list of queries based on a list of capabilities.
3 ///	@file		querylist.h - pianod
4 ///	@author		Perette Barella
5 ///	@date		2015-01-21
6 ///	@copyright	Copyright (c) 2015-2017 Devious Fish. All rights reserved.
7 ///
8 
9 #ifndef __pianod__querylist__
10 #define __pianod__querylist__
11 
12 #include <config.h>
13 
14 #include <cstdint>
15 
16 #include <typeinfo>
17 #include <vector>
18 #include <stdexcept>
19 
20 #include "enumeratedarray.h"
21 #include "querylist.h"
22 #include "filter.h"
23 
24 /// Filter-to-query converter.
25 namespace Query {
26     /// Exception indicating a query is impossible to perform on a source.
27     class impossible : public std::invalid_argument {
28     public:
impossible(void)29         explicit impossible (void) : invalid_argument ("impossible") { };
30     };
31     typedef int8_t Preference;
32 
33     /// Manners in which fields may be queried for a source.
34     typedef enum search_methods_t {
35         SearchMethodNone,
36         ExactCompare,
37         MatchBeginning,
38         SubstringMatch,
39         Fuzzy
40     } SearchMethod;
41 
42     /** Media sources mark the available fields (array index) to
43         true to indicate they are capable of searching in that manner.  */
44     struct Constraints {
45         /// Fields searched by permuted filters, i.e., 'like'.
46         EnumeratedArray<Filter::Field, bool> participatesInFuzzy;
47         EnumeratedArray<Filter::Field, bool> canExactCompare;
48         EnumeratedArray<Filter::Field, bool> canMatchBeginning;
49         EnumeratedArray<Filter::Field, bool> canSubstringMatch;
50         /// Fields that can't be properly searched on, but are part of Field::Search searches.
51         EnumeratedArray<Filter::Field, bool> fieldInGeneralSearch;
52         /// Relative field preferences: higher is better
53         EnumeratedArray<Filter::Field, Preference> fieldPreference;
54         /// May query with 'AND' semantics.
55         bool andCapable = false;
56     };
57 
58     class DetailList;
59     class Queries;
60     class List;
61 
62     /// Information about how a query should be performed by a source.
63     class Details {
64         friend class DetailList; // Collection manages quality.
65     private:
66         float quality = 1; /// Specificity of the search; more is better.
67         Filter::Field filterField = Filter::Field::Invalid; /// Field filtered on
68     public:
69         Filter::Field searchField = Filter::Field::Invalid; ///< Field to search on
70         SearchMethod searchMethod = SearchMethodNone; ///< Method of comparison
71         std::string value; ///< Value to search for
72 
73         Details (Filter::Field filter_field,
74                  Filter::Field field, SearchMethod method, const char *val);
75     };
76 
77     /** A list of queries representing a filter expression or portion thereof.
78         Queries represent intersection (AND) of data. */
79     class DetailList : public std::vector<Details> {
80         friend class Queries;
81         unsigned preference (const Constraints &con) const; ///< Field Preference of searches
82         float quality (void) const; ///< Specificity of the collection of searches.
83 
84     };
85 
86 
87     /** A list of queries representing a filter expression or portion thereof.
88         Queries represent union (OR) of data. */
89     class Queries: public std::vector<DetailList> {
90         friend class List;
91         unsigned preference (const Constraints &con) const; ///< Field Preference of searches
92         float quality (void) const; ///< Specificity of the collection of searches.
93     };
94 
95     /** A adapter to convert filters into a list of queries for a source. */
96     class List : public Queries {
97     public:
98         const Constraints &capabilities;
99         SearchMethod findMethodForField (SearchMethod requestedMethod,
100                                          Filter::Field field);
101         Details interpretComparison (const Filter::Operation *filter);
102         Queries interpretAnd (const Filter::Operation *filter);
103         Queries interpret (const Filter::Operation *filter);
104         Queries interpretFuzzy (const PermutedFilter &filter);
105         List (const Filter &filter, const Constraints &constraints);
106     };
107 }
108 
109 #endif // defined(__pianod__querylist__)
110