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