1 /* 2 * (C) Copyright 2007-2015 Diomidis Spinellis 3 * 4 * You may only use this code if you agree to the terms of the CScout 5 * Source Code License agreement (see License.txt). 6 * If you do not agree to the terms, do not use the code. 7 * 8 * Encapsulates a (user interface) metrics query part 9 * Can be used to evaluate elements referenced through E against M metrics 10 * 11 */ 12 13 #ifndef MQUERY_ 14 #define MQUERY_ 15 16 #include <vector> 17 #include <sstream> 18 19 using namespace std; 20 21 #include "query.h" 22 #include "swill.h" 23 #include "metrics.h" 24 25 template <class M, class E> 26 class MQuery { 27 // Query arguments 28 char match_type; // Type of boolean match 29 int sort_order; // Order to use for sorting 30 bool reverse; // Reverse the sort order 31 vector <int> op; 32 vector <int> n; 33 public: MQuery()34 MQuery() : 35 sort_order(-1), 36 reverse(0), 37 op(M::metric_max, 0), 38 n(M::metric_max, 0) 39 { 40 for (int i = 0; i < M::metric_max; i++) { 41 ostringstream argspec; 42 43 argspec << "|i(c" << i << ")"; 44 argspec << "i(n" << i << ")"; 45 op[i] = n[i] = 0; 46 (void)swill_getargs(argspec.str().c_str(), &(op[i]), &(n[i])); 47 } 48 if (!swill_getargs("i(order)", &sort_order)) 49 sort_order = -1; 50 reverse = !!swill_getvar("reverse"); 51 } 52 53 // Accessor methods set_match_type(char mt)54 void set_match_type(char mt) { match_type = mt; } get_sort_order()55 int get_sort_order() const { return (sort_order); } get_reverse()56 bool get_reverse() const { return (reverse); } 57 58 // Return the URL for re-executing this query part param_url()59 string param_url() const { 60 ostringstream url; 61 62 for (int i = 0; i < M::metric_max; i++) 63 if (op[i]) { 64 url << "&c" << i << '=' << op[i]; 65 url << "&n" << i << '=' << n[i]; 66 } 67 if (sort_order != -1) 68 url << "&order=" << sort_order; 69 if (reverse) 70 url << "&reverse=1"; 71 return url.str(); 72 } 73 74 // Evaluate the stored query against e eval(E e)75 bool eval(E e) { 76 bool add; 77 78 switch (match_type) { 79 default: 80 case 'Y': // anY match 81 add = false; 82 for (int j = 0; j < M::metric_max; j++) 83 if (op[j] && Query::apply(op[j], e.metrics().get_metric(j), n[j])) { 84 add = true; 85 break; 86 } 87 break; 88 case 'L': // alL match 89 case 'T': // exactT match 90 add = true; 91 for (int j = 0; j < M::metric_max; j++) 92 if (op[j] && !Query::apply(op[j], e.metrics().get_metric(j), n[j])) { 93 add = false; 94 break; 95 } 96 break; 97 case 'E': // excludE match 98 add = true; 99 for (int j = 0; j < M::metric_max; j++) 100 if (op[j] && Query::apply(op[j], e.metrics().get_metric(j), n[j])) { 101 add = false; 102 break; 103 } 104 break; 105 } 106 return (add); 107 } 108 109 // Generate a form's metrics query part metrics_query_form(FILE * of)110 static void metrics_query_form(FILE *of) { 111 fputs("<table>" 112 "<tr><th>Sort-by</th><th>Metric</th><th>Compare</th><th>Value</th></tr>\n", of); 113 for (int i = 0; i < M::metric_max; i++) { 114 if (Metrics::is_internal<M>(i)) 115 continue; 116 fprintf(of, "<tr><td><input type=\"radio\" name=\"order\" value=\"%d\"> </td>\n", i); 117 fprintf(of, "<td>%s</td><td><select name=\"c%d\" value=\"1\">\n", 118 Metrics::get_name<M>(i).c_str(), i); 119 Query::equality_selection(of); 120 fprintf(of, "</td><td><INPUT TYPE=\"text\" NAME=\"n%d\" SIZE=5 MAXLENGTH=10></td></tr>\n", i); 121 } 122 fputs( "<tr>" 123 "<td><input type=\"radio\" name=\"order\" value=\"-1\" CHECKED></td>\n" 124 "<td>Entity name</td>" 125 "<td></td><td></td></tr>" 126 "</table>\n" 127 "<p>" 128 "<input type=\"checkbox\" name=\"reverse\" value=\"0\">Reverse sort order\n", of); 129 } 130 }; 131 132 #endif /* MQUERY_ */ 133