src/RDF.vala (6240B) - raw
1 /*
2 * xmpedit
3 * Copyright 2010 Dan Callaghan <djc@djc.id.au>
4 * Released under GPLv2
5 */
6
7 namespace RDF {
8
9 public abstract class Node : Object {
10
11 public abstract bool equals(Node other);
12
13 public abstract string to_string();
14
15 }
16
17 public abstract class SubjectNode : Node {
18
19 }
20
21 public class URIRef : SubjectNode {
22
23 public string uri { get; construct; }
24
25 public URIRef(string uri) {
26 Object(uri: uri);
27 }
28
29 public override bool equals(Node _other) {
30 var other = _other as URIRef;
31 if (other != null) {
32 return this.uri == other.uri;
33 }
34 return false;
35 }
36
37 public override string to_string() {
38 return @"<$uri>";
39 }
40
41 }
42
43 public class Blank : SubjectNode {
44
45 /** This is for informational purposes only! Not a unique id for equality! */
46 public string? id { get; construct; }
47
48 public Blank(string? id = null) {
49 Object(id: id);
50 }
51
52 public override bool equals(Node _other) {
53 return this == _other;
54 }
55
56 public override string to_string() {
57 if (id != null)
58 return @"_:$id";
59 return "Blank@%p".printf(&this);
60 }
61
62 }
63
64 public abstract class Literal : Node {
65
66 }
67
68 public class PlainLiteral : Literal {
69
70 public string lexical_value { get; construct; }
71 public string? lang { get; construct; }
72
73 public PlainLiteral(string lexical_value) {
74 Object(lexical_value: lexical_value);
75 }
76
77 public PlainLiteral.with_lang(string lexical_value, string lang) {
78 Object(lexical_value: lexical_value, lang: lang);
79 }
80
81 public override bool equals(Node _other) {
82 var other = _other as PlainLiteral;
83 if (other != null) {
84 return this.lexical_value == other.lexical_value &&
85 this.lang == other.lang;
86 }
87 return false;
88 }
89
90 public override string to_string() {
91 if (lang != null)
92 return @"\"$lexical_value\"@$lang";
93 return @"\"$lexical_value\"";
94 }
95
96 }
97
98 public class Statement : Object {
99
100 public SubjectNode subject { get; construct; }
101 public URIRef predicate { get; construct; }
102 public Node object { get; construct; }
103
104 public Statement(SubjectNode subject, URIRef predicate, Node object) {
105 Object(subject: subject, predicate: predicate, object: object);
106 }
107
108 public string to_string() {
109 return @"$subject $predicate $object .";
110 }
111
112 public static bool equal(Statement left, Statement right) {
113 return left.subject.equals(right.subject) &&
114 left.predicate.equals(right.predicate) &&
115 left.object.equals(right.object);
116 }
117
118 }
119
120 // XXX naive
121 public class Graph : Object {
122
123 static construct {
124 Xml.Parser.init();
125 }
126
127 private Gee.List<Statement> statements =
128 new Gee.ArrayList<Statement>((EqualFunc) Statement.equal);
129 private string? base_uri;
130
131 public Graph() {
132 }
133
134 public Graph.from_xml(string xml, string base_uri) throws ParseError {
135 this.base_uri = base_uri;
136 Parser(this, base_uri).parse(xml);
137 }
138
139 /**
140 * N.B. not a general RDF writer,
141 * only includes statements reachable from start_node!
142 */
143 public string to_xml(URIRef start_node) {
144 var writer = new Writer(this);
145 writer.write(start_node);
146 return writer.get_xml();
147 }
148
149 public void insert(Statement statement) {
150 if (!has_matching_statement(statement.subject, statement.predicate, statement.object))
151 statements.add(statement);
152 }
153
154 public Gee.List<Statement> get_statements() {
155 return statements.read_only_view;
156 }
157
158 public Gee.List<Statement> find_matching_statements(
159 SubjectNode? subject, URIRef? predicate, Node? object) {
160 // XXX naive
161 var result = new Gee.ArrayList<Statement>((EqualFunc) Statement.equal);
162 foreach (var s in statements) {
163 if ((subject == null || s.subject.equals(subject)) &&
164 (predicate == null || s.predicate.equals(predicate)) &&
165 (object == null || s.object.equals(object)))
166 result.add(s);
167 }
168 return result;
169 }
170
171 public bool has_matching_statement(
172 SubjectNode? subject, URIRef? predicate, Node? object) {
173 // XXX naive
174 foreach (var s in statements) {
175 if ((subject == null || s.subject.equals(subject)) &&
176 (predicate == null || s.predicate.equals(predicate)) &&
177 (object == null || s.object.equals(object)))
178 return true;
179 }
180 return false;
181 }
182
183 public void remove_matching_statements(
184 SubjectNode? subject, URIRef? predicate, Node? object) {
185 var it = statements.iterator();
186 while (it.has_next()) {
187 it.next();
188 var s = it.get();
189 if ((subject == null || s.subject.equals(subject)) &&
190 (predicate == null || s.predicate.equals(predicate)) &&
191 (object == null || s.object.equals(object)))
192 it.remove();
193 }
194 }
195
196 public Gee.List<Node> find_objects(SubjectNode subject, URIRef predicate) {
197 // XXX naive
198 var result = new Gee.ArrayList<Node>();
199 foreach (var s in statements) {
200 if ((subject == null || s.subject.equals(subject)) &&
201 (predicate == null || s.predicate.equals(predicate)))
202 result.add(s.object);
203 }
204 return result;
205 }
206
207 public Node? find_object(SubjectNode subject, URIRef predicate) {
208 foreach (var s in statements) {
209 if ((subject == null || s.subject.equals(subject)) &&
210 (predicate == null || s.predicate.equals(predicate)))
211 return s.object;
212 }
213 return null;
214 }
215
216 }
217
218 private const string RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
219 private const string XML_NS = "http://www.w3.org/XML/1998/namespace";
220
221 #if TEST
222
223 public void register_tests() {
224 register_parser_tests();
225 register_writer_tests();
226 }
227
228 #endif
229
230 }