/[gnomoradio]/gnomoradio/rainbow/rdf-resource.cc
ViewVC logotype

Contents of /gnomoradio/rainbow/rdf-resource.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.16 - (show annotations) (download)
Sun Oct 17 04:09:35 2004 UTC (19 years, 7 months ago) by garrison
Branch: MAIN
Changes since 1.15: +13 -15 lines
port to gtkmm 2.4

1 // Gnomoradio - rainbow/rdf-resource.cc
2 // Copyright (C) 2003 Jim Garrison
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 #include "rdf-resource.h"
19 #include <deque>
20
21 using namespace Rainbow;
22 using namespace sigc;
23 using namespace std;
24
25 map<Glib::ustring,RdfResource*> Rainbow::RdfResource::resource_map;
26
27 void Rainbow::RdfResource::get_and_do (const Glib::ustring &uri,
28 const sigc::slot<void,xmlpp::Element*,ref_ptr<RdfResource> > &slot)
29 {
30 ref_ptr<RdfResource> resource;
31 Glib::ustring base_uri(uri), id;
32 remove_tag_from_uri(base_uri, id);
33 map<Glib::ustring,RdfResource*>::iterator p = resource_map.find(base_uri);
34 if (p != resource_map.end()) {
35 resource = ref_ptr<RdfResource>(p->second);
36 if (resource->downloaded) { // already downloaded
37 map<Glib::ustring,xmlpp::Element*>::iterator el = resource->id_map.find(id);
38 signal<void,xmlpp::Element*,ref_ptr<RdfResource> > sig;
39 sig.connect(slot);
40 sig(el != resource->id_map.end() ? el->second : 0, resource);
41 return;
42 }
43 } else {
44 resource = ref_ptr<RdfResource>(new RdfResource(base_uri));
45
46 // make sure it is actually a valid url
47 Glib::ustring host, file;
48 unsigned short port;
49 if (!HttpClient::parse_url(uri, host, port, file)) {
50 signal<void,xmlpp::Element*,ref_ptr<RdfResource> > sig;
51 sig.connect(slot);
52 sig(0, resource);
53 return;
54 }
55 }
56
57 // connect mem_fun to appropriate signal
58 map<Glib::ustring,signal<void,xmlpp::Element*, ref_ptr<RdfResource> >*>::iterator sig;
59 sig = resource->signal_map.find(id);
60 if (sig != resource->signal_map.end()) {
61 // found existing signal for id
62 sig->second->connect(slot);
63 } else {
64 // need to create new signal to handle id
65 signal<void,xmlpp::Element*,ref_ptr<RdfResource> > *signal_ = new signal<void,xmlpp::Element*,ref_ptr<RdfResource> >;
66 signal_->connect(slot);
67 resource->signal_map.insert(make_pair(id, signal_));
68 }
69 }
70
71 void Rainbow::RdfResource::make_absolute_uri (Glib::ustring &uri,
72 const Glib::ustring &base)
73 {
74 if (uri.size() && uri[0] == '#') {
75 Glib::ustring b(base), id;
76 remove_tag_from_uri(b, id);
77 uri = b + uri;
78 }
79 }
80
81 void Rainbow::RdfResource::remove_tag_from_uri (Glib::ustring &uri,
82 Glib::ustring &id)
83 {
84 Glib::ustring::size_type pound = uri.find('#');
85 if (pound != Glib::ustring::npos) {
86 id = uri.substr(pound + 1);
87 uri = uri.substr(0, pound);
88 }
89 }
90
91 Rainbow::RdfResource::RdfResource (const Glib::ustring &uri)
92 : refcnt(0),
93 resource_uri(uri),
94 downloaded(false)
95 {
96 base_uri = resource_uri;
97 Glib::ustring tmpid;
98 remove_tag_from_uri(base_uri, tmpid);
99
100 resource_map.insert(make_pair(uri, this));
101
102 // cache
103 const unsigned int cache_size = 10;
104 static deque<ref_ptr<RdfResource> > cache;
105 if (cache.size() == cache_size)
106 cache.pop_front();
107 cache.push_back(ref_ptr<RdfResource>(this));
108
109 alarm.signal_alarm().connect(mem_fun(*this, &RdfResource::get));
110 get();
111 }
112
113 void Rainbow::RdfResource::get ()
114 {
115 Glib::ustring host, file;
116 unsigned short port;
117 HttpClient::parse_url(base_uri, host, port, file); // error case is taken care of above
118
119 http.reset(new HttpClient(host, port));
120 http->signal_request_done.connect(mem_fun(*this, &RdfResource::on_downloaded));
121 ref();
122 http->get(file);
123 }
124
125 Rainbow::RdfResource::~RdfResource ()
126 {
127 // remove all occurances from global map
128 for (map<Glib::ustring,RdfResource*>::iterator i = resource_map.begin(); i != resource_map.end(); ++i) {
129 if (i->second == this)
130 resource_map.erase(i);
131 }
132
133 clear_signal_map();
134 }
135
136 void Rainbow::RdfResource::on_downloaded (bool success)
137 {
138 xmlpp::Element *root;
139 xmlpp::Node::NodeList nodes;
140 xmlpp::Attribute *xml_base;
141 string buffer;
142
143 downloaded = true;
144
145 if (!success)
146 goto error;
147
148 // this block is for rdf files embedded in something larger
149 {
150 string::size_type rdf_block_begin = http->get_buffer().find("<rdf:RDF");
151 string::size_type rdf_block_end = http->get_buffer().find("</rdf:RDF>");
152 if (rdf_block_begin != string::npos
153 && rdf_block_end != string::npos
154 && rdf_block_begin < rdf_block_end) {
155 buffer = http->get_buffer().substr(rdf_block_begin,
156 rdf_block_end - rdf_block_begin + 10);
157 } else
158 buffer = http->get_buffer();
159 }
160
161 try {
162 xml_tree.parse_memory(buffer);
163 } catch (...) {
164 goto error;
165 }
166
167 // iterate through document and take note of ID tags and about tags
168 root = dynamic_cast<xmlpp::Element*>(xml_tree.get_document()->get_root_node());
169 if (!root || root->get_name() != "RDF")
170 goto error;
171 id_map.insert(make_pair(Glib::ustring(), root));
172 xml_base = root->get_attribute("base");
173 if (xml_base && xml_base->get_value().size())
174 base_uri = xml_base->get_value();
175 nodes = root->get_children();
176 for (xmlpp::Node::NodeList::iterator i = nodes.begin(); i != nodes.end(); ++i) {
177 xmlpp::Element *node = dynamic_cast<xmlpp::Element*>(*i);
178 if (!node)
179 continue;
180
181 xmlpp::Attribute *id = node->get_attribute("ID");
182 if (id)
183 id_map.insert(make_pair(id->get_value(), node));
184 else {
185 xmlpp::Attribute *about = node->get_attribute("about");
186 if (about)
187 about_map.insert(make_pair(about->get_value(), node));
188 }
189 }
190
191 error:
192 // call all signals
193 map<Glib::ustring,signal<void,xmlpp::Element*,ref_ptr<RdfResource> >*>::iterator signal;
194 for (signal = signal_map.begin(); signal != signal_map.end(); ++signal) {
195 map<Glib::ustring,xmlpp::Element*>::iterator el = id_map.find(signal->first);
196 signal->second->emit(el != id_map.end() ? el->second : 0, ref_ptr<RdfResource>(this));
197 }
198 clear_signal_map();
199
200 http.reset();
201 alarm.set_relative(3600 * 12); // FIXME: make this time interval configurable
202 unref();
203 }
204
205 void Rainbow::RdfResource::clear_signal_map ()
206 {
207 map<Glib::ustring,signal<void,xmlpp::Element*,ref_ptr<RdfResource> >*>::iterator signal;
208 for (signal = signal_map.begin(); signal != signal_map.end(); ++signal)
209 delete signal->second;
210 signal_map.clear();
211 }
212
213 xmlpp::Element *Rainbow::RdfResource::get_secondary_info (const Glib::ustring &uri)
214 {
215 map<Glib::ustring,xmlpp::Element*>::iterator p = about_map.find(uri);
216 return p != about_map.end() ? p->second : 0;
217 }

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26