cvsimport
[beagle.git] / Util / SemWeb / N3Writer.cs
blob55fd238ce226679387abba52bd01098a30d685c1
1 using System;
2 using System.IO;
3 using System.Text;
5 using SemWeb;
7 namespace SemWeb {
8 public class N3Writer : RdfWriter {
9 TextWriter writer;
10 NamespaceManager ns;
11 bool hasWritten = false;
12 bool closed = false;
14 string lastSubject = null, lastPredicate = null;
16 long anonCounter = 0;
18 Formats format = Formats.Turtle;
20 public enum Formats {
21 NTriples,
22 Turtle,
23 Notation3
26 public N3Writer(string file) : this(file, null) { }
28 public N3Writer(string file, NamespaceManager ns) : this(GetWriter(file), ns) { }
30 public N3Writer(TextWriter writer) : this(writer, null) { }
32 public N3Writer(TextWriter writer, NamespaceManager ns) {
33 this.writer = writer; this.ns = ns;
36 public override NamespaceManager Namespaces { get { return ns; } }
38 public Formats Format { get { return format; } set { format = value; } }
40 public override void WriteStatement(string subj, string pred, string obj) {
41 WriteStatement2(URI(subj), URI(pred), URI(obj));
44 public override void WriteStatement(string subj, string pred, Literal literal) {
45 WriteStatement2(URI(subj), URI(pred), literal.ToString());
48 public override string CreateAnonymousEntity() {
49 return "_:anon" + (anonCounter++);
52 public override void Close() {
53 base.Close();
54 if (closed) return;
55 if (hasWritten)
56 writer.WriteLine(".");
57 closed = true;
58 hasWritten = false;
59 writer.Flush();
63 private string URI(string uri) {
64 if (uri.StartsWith("_:anon")) return uri;
65 if (BaseUri != null && uri.StartsWith(BaseUri)) {
66 int len = BaseUri.Length;
67 bool ok = true;
68 for (int i = len; i < uri.Length; i++) {
69 if (!char.IsLetterOrDigit(uri[i])) { ok = false; break; }
71 if (ok)
72 return ":" + uri.Substring(len);
74 if (Format == Formats.NTriples || ns == null) return "<" + Escape(uri) + ">";
76 string ret = ns.Normalize(uri);
77 if (ret[0] != '<') return ret;
79 return "<" + Escape(uri) + ">";
82 private static char HexDigit(char c, int digit) {
83 int n = (((int)c) >> (digit * 4)) & 0xF;
84 if (n <= 9)
85 return (char)('0' + n);
86 else
87 return (char)('A' + (n-10));
90 internal static string Escape(string str) {
91 // Check if any escaping is necessary, following the NTriples spec.
92 bool needed = false;
93 for (int i = 0; i < str.Length; i++) {
94 char c = str[i];
95 if (!((c >= 0x20 && c <= 0x21) || (c >= 0x23 && c <= 0x5B) || (c >= 0x5D && c <= 0x7E))) {
96 needed = true;
97 break;
101 if (!needed) return str;
103 StringBuilder b = new StringBuilder();
104 for (int i = 0; i < str.Length; i++) {
105 char c = str[i];
106 if ((c >= 0x20 && c <= 0x21) || (c >= 0x23 && c <= 0x5B) || (c >= 0x5D && c <= 0x7E)) {
107 b.Append(c);
108 } else if (c == 0x9) {
109 b.Append("\\t");
110 } else if (c == 0xA) {
111 b.Append("\\n");
112 } else if (c == 0xD) {
113 b.Append("\\r");
114 } else if (c == 0x22) {
115 b.Append("\\\"");
116 } else if (c == 0x5C) {
117 b.Append("\\\\");
118 } else if (c <= 0x8 || c == 0xB || c == 0xC || (c >= 0xE && c <= 0x1F) || (c >= 0x7F && c <= 0xFFFF)) {
119 b.Append("\\u");
120 b.Append(HexDigit(c, 3));
121 b.Append(HexDigit(c, 2));
122 b.Append(HexDigit(c, 1));
123 b.Append(HexDigit(c, 0));
124 /*} else if (c >= 0x10000) {
125 b.Append("\\U");
126 b.Append(HexDigit(c, 7));
127 b.Append(HexDigit(c, 6));
128 b.Append(HexDigit(c, 5));
129 b.Append(HexDigit(c, 4));
130 b.Append(HexDigit(c, 3));
131 b.Append(HexDigit(c, 2));
132 b.Append(HexDigit(c, 1));
133 b.Append(HexDigit(c, 0));*/
136 return b.ToString();
139 private void WriteStatement2(string subj, string pred, string obj) {
140 closed = false;
142 // Write the prefix directives at the beginning.
143 if (!hasWritten && ns != null && !(Format == Formats.NTriples)) {
144 foreach (string prefix in ns.GetPrefixes()) {
145 writer.Write("@prefix ");
146 writer.Write(prefix);
147 writer.Write(": <");
148 writer.Write(ns.GetNamespace(prefix));
149 writer.Write("> .\n");
153 // Repeated subject.
154 if (lastSubject != null && lastSubject == subj && !(Format == Formats.NTriples)) {
155 // Repeated predicate too.
156 if (lastPredicate != null && lastPredicate == pred) {
157 writer.Write(",\n\t\t");
158 WriteThing(obj);
160 // Just a repeated subject.
161 } else {
162 writer.Write(";\n\t");
163 WriteThing(pred);
164 WriteThing(obj);
165 lastPredicate = pred;
168 // The subject became the object. Abbreviate with
169 // is...of notation (Notation3 format only).
170 } else if (lastSubject != null && lastSubject == obj && (Format == Formats.Notation3)) {
171 writer.Write(";\n\tis ");
172 WriteThing(pred);
173 writer.Write("of ");
174 WriteThing(subj);
175 lastPredicate = null;
177 // Start a new statement.
178 } else {
179 if (hasWritten)
180 writer.Write(".\n");
182 WriteThing(subj);
183 WriteThing(pred);
184 WriteThing(obj);
186 lastSubject = subj;
187 lastPredicate = pred;
190 hasWritten = true;
193 private void WriteThing(string text) {
194 writer.Write(text);
195 writer.Write(" ");