xmpedit

GTK+ editor for XMP metadata embedded in images
git clone https://code.djc.id.au/git/xmpedit/

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 }