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 }