added regex core functionality for filter_query_rewrite
[metaproxy-moved-to-github.git] / src / filter_query_rewrite.cpp
1 /* $Id: filter_query_rewrite.cpp,v 1.2 2006-01-20 22:38:12 marc Exp $
2    Copyright (c) 2005, Index Data.
3
4 %LICENSE%
5  */
6
7
8 #include "config.hpp"
9 #include "filter.hpp"
10 #include "package.hpp"
11
12 //#include <boost/thread/mutex.hpp>
13 #include <boost/regex.hpp>
14
15 #include "util.hpp"
16 #include "filter_query_rewrite.hpp"
17
18 #include <yaz/zgdu.h>
19
20 namespace yf = yp2::filter;
21
22 namespace yp2 {
23     namespace filter {
24         class QueryRewrite::Rep {
25             //friend class QueryRewrite;
26         public:
27             void process(yp2::Package &package) const;
28         private:
29             void rewriteRegex(Z_Query *query) const;
30         };
31     }
32 }
33
34 yf::QueryRewrite::QueryRewrite() : m_p(new Rep)
35 {
36 }
37
38 yf::QueryRewrite::~QueryRewrite()
39 {  // must have a destructor because of boost::scoped_ptr
40 }
41
42 void yf::QueryRewrite::process(yp2::Package &package) const
43 {
44     m_p->process(package);
45 }
46
47 void yf::QueryRewrite::Rep::process(yp2::Package &package) const
48 {
49     if (package.session().is_closed())
50     {
51         std::cout << "Got Close.\n";
52     }
53     
54     Z_GDU *gdu = package.request().get();
55     
56     if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
57         Z_APDU_initRequest)
58     {
59         std::cout << "Got Z3950 Init PDU\n";         
60         //Z_InitRequest *req = gdu->u.z3950->u.initRequest;
61         //package.request() = gdu;
62     } 
63     else if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
64              Z_APDU_searchRequest)
65     {
66         std::cout << "Got Z3950 Search PDU\n";   
67         Z_SearchRequest *req = gdu->u.z3950->u.searchRequest;
68
69         // applying regex query rewriting
70         rewriteRegex(req->query);
71             
72         // fold new query structure into gdu package ..       
73         // yp2::util::pqf(odr, gdu->u.z3950, query_out);
74         // question: which odr structure to use in this call ??
75         // memory alignment has to be correct, this is a little tricky ...
76         // I'd rather like to alter the gdu and pack it back using:
77         package.request() = gdu;
78     } 
79     else if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
80              Z_APDU_scanRequest)
81     {
82         std::cout << "Got Z3950 Scan PDU\n";   
83         //Z_ScanRequest *req = gdu->u.z3950->u.scanRequest;
84         //package.request() = gdu;
85     } 
86     package.move();
87 }
88
89
90 void yf::QueryRewrite::Rep::rewriteRegex(Z_Query *query) const
91 {
92     std::string query_in = yp2::util::zQueryToString(query);
93     std::cout << "QUERY IN  '" << query_in << "'\n";
94
95     std::string query_out;
96     
97     boost::regex rgx;
98     try{
99         // make regular expression replacement here 
100         std::string expression("@attr 1=4");
101         std::string format("@attr 1=4 @attr 4=3");
102         //std::string expression("the");
103         //std::string format("else");
104         //std::string expression("(<)|(>)|\\r");
105         //std::string format("(?1&lt;)(?2&gt;)");
106
107         std::cout << "EXPRESSION  '" << expression << "'\n";
108         std::cout << "FORMAT      '" << format << "'\n";
109
110         rgx.assign(expression.c_str());
111
112         bool match(false);
113         bool search(false);
114
115         // other flags
116         // see http://www.boost.org/libs/regex/doc/match_flag_type.html
117         //boost::match_flag_type flags = boost::match_default;
118         // boost::format_default
119         // boost::format_perl
120         // boost::format_literal
121         // boost::format_all
122         // boost::format_no_copy
123         // boost::format_first_only
124
125         boost::match_flag_type flags 
126             = boost::match_default | boost::format_all;
127
128         match = regex_match(query_in, rgx, flags);
129         search = regex_search(query_in, rgx, flags);
130         query_out = boost::regex_replace(query_in, rgx, format, flags);
131         std::cout << "MATCH  '" << match <<  "'\n";
132         std::cout << "SEARCH '" << search <<  "'\n";
133         std::cout << "QUERY OUT '" << query_out << "'\n";
134
135     }
136     catch(boost::regex_error &e)
137     {
138         std::cout << "REGEX Error code=" << e.code() 
139                   << " position=" << e.position() << "\n";
140     }
141     
142     //std::cout << "QUERY OUT '" << query_out << "'\n";
143     // still need to fold this new rpn query string into Z_Query structure...
144 }
145
146
147
148 static yp2::filter::Base* filter_creator()
149 {
150     return new yp2::filter::QueryRewrite;
151 }
152
153 extern "C" {
154     struct yp2_filter_struct yp2_filter_query_rewrite = {
155         0,
156         "query-rewrite",
157         filter_creator
158     };
159 }
160
161 extern "C" {
162     extern struct yp2_filter_struct yp2_filter_query_rewrite;
163 }
164
165
166 /*
167  * Local variables:
168  * c-basic-offset: 4
169  * indent-tabs-mode: nil
170  * c-file-style: "stroustrup"
171  * End:
172  * vim: shiftwidth=4 tabstop=8 expandtab
173  */