Mercurial > hg > classical
comparison utilities/composer/composer.cpp @ 20:c4cb65c436ef classical-rdf
* Simple query utility
author | Chris Cannam |
---|---|
date | Tue, 23 Feb 2010 16:37:49 +0000 |
parents | |
children | ea477e4cc75c |
comparison
equal
deleted
inserted
replaced
19:559a001e1bf5 | 20:c4cb65c436ef |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 #include "Objects.h" | |
4 #include "TypeRegistrar.h" | |
5 | |
6 #include <dataquay/BasicStore.h> | |
7 #include <dataquay/RDFException.h> | |
8 #include <dataquay/objectmapper/ObjectMapper.h> | |
9 #include <dataquay/Debug.h> | |
10 | |
11 #include <QMultiMap> | |
12 #include <QFileInfo> | |
13 | |
14 #include <iostream> | |
15 | |
16 using namespace Dataquay; | |
17 using namespace ClassicalData; | |
18 using namespace std; | |
19 | |
20 ostream &operator<<(ostream &target, const QString &str) | |
21 { | |
22 return target << str.toLocal8Bit().data(); | |
23 } | |
24 | |
25 ostream &operator<<(ostream &target, const QUrl &u) | |
26 { | |
27 return target << "<" << u.toString() << ">"; | |
28 } | |
29 | |
30 | |
31 bool | |
32 load(BasicStore *store, QString fileName) | |
33 { | |
34 QUrl url = QUrl::fromLocalFile(fileName); | |
35 | |
36 cerr << "Importing from URL " << url << " ..."; | |
37 try { | |
38 store->import(url, BasicStore::ImportIgnoreDuplicates, "ntriples"); | |
39 } catch (RDFException e) { | |
40 cerr << "failed" << endl; | |
41 cerr << "Import failed: " << e.what() << endl; | |
42 return false; | |
43 } | |
44 | |
45 cerr << " done" << endl; | |
46 return true; | |
47 } | |
48 | |
49 void | |
50 usage(char *name) | |
51 { | |
52 int s = 0; | |
53 for (int i = 0; name[i]; ++i) if (name[i] == '/') s = i + 1; | |
54 name = name + s; | |
55 cerr << "Usage: " << name << " <input-rdf-file> list" << endl; | |
56 cerr << "Usage: " << name << " <input-rdf-file> list-uris" << endl; | |
57 cerr << "Usage: " << name << " <input-rdf-file> show <uri> [<uri> ...]" << endl; | |
58 cerr << "Usage: " << name << " <input-rdf-file> search <text>" << endl; | |
59 cerr << "Usage: " << name << " <input-rdf-file> match <text>" << endl; | |
60 exit(-1); | |
61 } | |
62 | |
63 static QList<Composer *> allComposers; | |
64 static QMap<Composer *, QSet<Work *> > worksMap; | |
65 | |
66 void | |
67 show(Composer *c) | |
68 { | |
69 cout << c->property("uri").value<Uri>() << endl; | |
70 cout << c->getSortName(true); | |
71 QString d = c->getDisplayDates(); | |
72 if (d != "") cout << " (" << d << ")"; | |
73 if (!c->nationality().empty() || c->period() != "") { | |
74 cout << " ["; | |
75 bool first = true; | |
76 foreach (QString n, c->nationality()) { | |
77 if (!first) cout << "/"; | |
78 cout << n; | |
79 first = false; | |
80 } | |
81 if (c->period() != "") { | |
82 if (!first) cout << ", "; | |
83 cout << c->period(); | |
84 } | |
85 cout << "]"; | |
86 } | |
87 if (c->gender() != "") { | |
88 cout << " *" << c->gender(); | |
89 } | |
90 if (!worksMap[c].empty()) { | |
91 cout << " [" << worksMap[c].size() << " work(s)]"; | |
92 } | |
93 cout << endl; | |
94 foreach (QString a, c->aliases()) { | |
95 cout << " - " << a << endl; | |
96 } | |
97 if (c->remarks() != "") { | |
98 cout << " " << c->remarks() << endl; | |
99 } | |
100 foreach (Document *d, c->pages()) { | |
101 cout << " " << d->siteName() << " -> " << d->uri() << endl; | |
102 } | |
103 } | |
104 | |
105 void | |
106 showBrief(Composer *c) | |
107 { | |
108 cout << c->property("uri").value<Uri>() << endl; | |
109 cout << c->getSortName(false); | |
110 QString d = c->getDisplayDates(); | |
111 if (d != "") cout << " (" << d << ")"; | |
112 if (!c->nationality().empty() || c->period() != "") { | |
113 cout << " ["; | |
114 bool first = true; | |
115 foreach (QString n, c->nationality()) { | |
116 if (!first) cout << "/"; | |
117 cout << n; | |
118 first = false; | |
119 } | |
120 if (c->period() != "") { | |
121 if (!first) cout << " "; | |
122 cout << c->period(); | |
123 } | |
124 cout << "]"; | |
125 } | |
126 if (c->gender() != "") { | |
127 cout << " *" << c->gender(); | |
128 } | |
129 if (!worksMap[c].empty()) { | |
130 cout << " [" << worksMap[c].size() << " work(s)]"; | |
131 } | |
132 cout << endl; | |
133 } | |
134 | |
135 void | |
136 listBrief(QList<Composer *> composers) | |
137 { | |
138 QMultiMap<QString, Composer *> sorted; | |
139 foreach (Composer *c, composers) { | |
140 sorted.insert(c->getSortName(false), c); | |
141 } | |
142 foreach (Composer *c, sorted) { | |
143 showBrief(c); | |
144 } | |
145 } | |
146 | |
147 void | |
148 listUris(QList<Composer *> composers) | |
149 { | |
150 QMultiMap<Uri, Composer *> sorted; | |
151 foreach (Composer *c, composers) { | |
152 sorted.insert(c->property("uri").value<Uri>(), c); | |
153 } | |
154 foreach (Uri uri, sorted.keys()) { | |
155 cout << uri << endl; | |
156 } | |
157 } | |
158 | |
159 void | |
160 showSearchResults(QMultiMap<float, Composer *> matches, int count) | |
161 { | |
162 int n = 0; | |
163 for (QMultiMap<float, Composer *>::const_iterator i = matches.end(); | |
164 i != matches.begin(); ) { | |
165 --i; | |
166 if (i.key() <= 0) continue; | |
167 cout << endl; | |
168 if (n == 0) { | |
169 cout << "Best match:" << endl; | |
170 } else if (n == 1) { | |
171 cout << "Other candidate(s):" << endl; | |
172 } | |
173 cout << "[" << i.key() << "] "; | |
174 if (n == 0) show(i.value()); | |
175 else showBrief(i.value()); | |
176 if (++n > count) break; | |
177 } | |
178 if (n == 0) cout << "No matches" << endl; | |
179 cout << endl; | |
180 } | |
181 | |
182 void | |
183 search(QString typing) | |
184 { | |
185 cout << "Searching for: " << typing << endl; | |
186 QMultiMap<float, Composer *> matches; | |
187 foreach (Composer *c, allComposers) { | |
188 float value = c->matchTyping(typing); | |
189 matches.insert(value, c); | |
190 } | |
191 showSearchResults(matches, 5); | |
192 } | |
193 | |
194 void | |
195 match(QString text) | |
196 { | |
197 cout << "Matching: " << text << endl; | |
198 QMultiMap<float, Composer *> matches; | |
199 QRegExp sre("[\\., -]+"); | |
200 QStringList elements = text.toLower().split(sre, QString::SkipEmptyParts); | |
201 foreach (Composer *c, allComposers) { | |
202 float value = c->matchFuzzyName(elements); | |
203 matches.insert(value, c); | |
204 } | |
205 showSearchResults(matches, 5); | |
206 } | |
207 | |
208 void | |
209 showWildcard(QString text) | |
210 { | |
211 cout << "Showing URI or wildcard: " << text << endl; | |
212 QRegExp re(text, Qt::CaseInsensitive, QRegExp::Wildcard); | |
213 foreach (Composer *c, allComposers) { | |
214 if (re.exactMatch(c->property("uri").value<Uri>().toString())) { | |
215 cout << endl; | |
216 show(c); | |
217 } | |
218 } | |
219 cout << endl; | |
220 } | |
221 | |
222 int | |
223 main(int argc, char **argv) | |
224 { | |
225 if (argc < 3) usage(argv[0]); | |
226 QString inFileName = argv[1]; | |
227 QString command = argv[2]; | |
228 QStringList args; | |
229 for (int i = 3; i < argc; ++i) { | |
230 args.push_back(argv[i]); | |
231 } | |
232 | |
233 BasicStore *store = new BasicStore(); | |
234 store->setBaseUri(Uri("http://dbtune.org/classical/resource/")); | |
235 ObjectMapper *mapper = new ObjectMapper(store); | |
236 | |
237 TypeRegistrar::addMappings(store, mapper); | |
238 | |
239 if (!load(store, inFileName)) { | |
240 cerr << "Failed to load data source" << endl; | |
241 return 1; | |
242 } | |
243 | |
244 cerr << "Imported RDF data, mapping to objects..."; | |
245 QObject *root = mapper->loadAllObjects(0); | |
246 cerr << " done" << endl; | |
247 | |
248 delete mapper; | |
249 delete store; | |
250 | |
251 allComposers = root->findChildren<Composer *>(); | |
252 | |
253 QList<Work *> works = root->findChildren<Work *>(); | |
254 foreach (Work *w, works) { | |
255 Composition *c = w->composition(); | |
256 if (c) { | |
257 Composer *cp = c->composer(); | |
258 if (cp) worksMap[cp].insert(w); | |
259 } | |
260 } | |
261 | |
262 if (command == "list") { | |
263 listBrief(allComposers); | |
264 } else if (command == "list-uris") { | |
265 listUris(allComposers); | |
266 } else { | |
267 if (args.empty()) usage(argv[0]); | |
268 if (command == "show") { | |
269 foreach (QString s, args) { | |
270 if (!s.contains('/') && !s.contains('*')) { | |
271 s = "*" + s + "*"; | |
272 } | |
273 showWildcard(s); | |
274 } | |
275 } else if (command == "search") { | |
276 foreach (QString s, args) { | |
277 search(s); | |
278 } | |
279 } else if (command == "match") { | |
280 foreach (QString s, args) { | |
281 match(s); | |
282 } | |
283 } | |
284 } | |
285 | |
286 } | |
287 |