rdf_context 0.4.8 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +27 -0
- data/README.rdoc +22 -9
- data/Rakefile +11 -6
- data/VERSION +1 -1
- data/bin/rdf_context +12 -4
- data/lib/rdf_context.rb +3 -1
- data/lib/rdf_context/aggregate_graph.rb +86 -0
- data/lib/rdf_context/array_hacks.rb +53 -0
- data/lib/rdf_context/conjunctive_graph.rb +1 -1
- data/lib/rdf_context/exceptions.rb +9 -7
- data/lib/rdf_context/graph.rb +174 -15
- data/lib/rdf_context/literal.rb +34 -2
- data/lib/rdf_context/n3_grammar.treetop +213 -129
- data/lib/rdf_context/n3parser.rb +281 -57
- data/lib/rdf_context/namespace.rb +23 -12
- data/lib/rdf_context/parser.rb +4 -3
- data/lib/rdf_context/quoted_graph.rb +38 -0
- data/lib/rdf_context/rdfaparser.rb +2 -1
- data/lib/rdf_context/rdfxmlparser.rb +4 -3
- data/lib/rdf_context/store/abstract_sql_store.rb +4 -4
- data/lib/rdf_context/store/abstract_store.rb +5 -1
- data/lib/rdf_context/store/sqlite3_store.rb +10 -8
- data/lib/rdf_context/string_hacks.rb +44 -21
- data/lib/rdf_context/term_utils.rb +73 -4
- data/lib/rdf_context/triple.rb +32 -47
- data/lib/rdf_context/uriref.rb +33 -26
- data/spec/aggregate_graph_spec.rb +59 -0
- data/spec/conjunctive_graph_spec.rb +1 -1
- data/spec/cwm_spec.rb +32 -0
- data/spec/graph_spec.rb +114 -3
- data/spec/literal_spec.rb +107 -5
- data/spec/matchers.rb +104 -51
- data/spec/n3parser_spec.rb +798 -99
- data/spec/namespaces_spec.rb +26 -0
- data/spec/quoted_graph_spec.rb +0 -0
- data/spec/rdf_helper.rb +197 -0
- data/spec/rdfa_helper.rb +15 -11
- data/spec/rdfa_parser_spec.rb +6 -8
- data/spec/rdfxml_spec.rb +21 -28
- data/spec/spec_helper.rb +20 -0
- data/spec/sqlite3_store_spec.rb +6 -5
- data/spec/store_helper.rb +9 -1
- data/spec/string_hacks_spec.rb +14 -0
- data/spec/{rdfxml_helper.rb → swap_helper.rb} +8 -9
- data/spec/swap_spec.rb +77 -0
- data/spec/swap_test/animal.rdf +17 -0
- data/spec/swap_test/anon-prop.n3 +14 -0
- data/spec/swap_test/anonymous_loop.n3 +2 -0
- data/spec/swap_test/contexts.n3 +16 -0
- data/spec/swap_test/daml-pref.n3 +10 -0
- data/spec/swap_test/i18n/hiragana.n3 +22 -0
- data/spec/swap_test/i18n/n3string.n3 +4 -0
- data/spec/swap_test/list/itemType.rdf +12 -0
- data/spec/swap_test/lists-simple.n3 +40 -0
- data/spec/swap_test/lists.n3 +35 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10001.nt +3 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10002.nt +7 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10003.nt +3 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10004.nt +119 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10005.nt +3 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10006.nt +225 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10007.nt +79 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10008.nt +5 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10009.nt +13 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10010.nt +21 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10011.nt +9 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10012.nt +53 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10013.nt +19 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10014.nt +103 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10015.nt +103 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10016.nt +3 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10017.nt +151 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10018.nt +9 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10019.nt +3 -0
- data/spec/swap_test/n3/n3parser.tests_n3_10020.nt +13 -0
- data/spec/swap_test/n3parser.tests +160 -0
- data/spec/swap_test/nodeID/classes.n3 +9 -0
- data/spec/swap_test/nodeID/classes.ref.rdf +15 -0
- data/spec/swap_test/nodeID/ex1.rdf +15 -0
- data/spec/swap_test/norm/fix.rdf +33 -0
- data/spec/swap_test/owl-ex.rdf +150 -0
- data/spec/swap_test/ref/animal.n3 +11 -0
- data/spec/swap_test/ref/anon-prop-1.n3 +8 -0
- data/spec/swap_test/ref/anonymous_loop.ref +7 -0
- data/spec/swap_test/ref/bnode.n3 +6 -0
- data/spec/swap_test/ref/bnode.rdf +16 -0
- data/spec/swap_test/ref/colon-in-uri.n3 +15 -0
- data/spec/swap_test/ref/daml-ex.n3 +103 -0
- data/spec/swap_test/ref/daml-ont.n3 +289 -0
- data/spec/swap_test/ref/djb1a-out.n3 +4 -0
- data/spec/swap_test/ref/dot-dash.n3 +8 -0
- data/spec/swap_test/ref/in-xml-t.n3 +4 -0
- data/spec/swap_test/ref/itemType.n3 +9 -0
- data/spec/swap_test/ref/keywords1.n3 +11 -0
- data/spec/swap_test/ref/keywords2.n3 +11 -0
- data/spec/swap_test/ref/lists-simple-1.rdf +108 -0
- data/spec/swap_test/ref/lists.n3 +43 -0
- data/spec/swap_test/ref/lstring-out.n3 +20 -0
- data/spec/swap_test/ref/n3string.n3 +13 -0
- data/spec/swap_test/ref/no-last-nl.n3 +3 -0
- data/spec/swap_test/ref/numbers.n3 +18 -0
- data/spec/swap_test/ref/path1.n3 +8 -0
- data/spec/swap_test/ref/path2.n3 +39 -0
- data/spec/swap_test/ref/prefix1.rdf +31 -0
- data/spec/swap_test/ref/prefix3.rdf +31 -0
- data/spec/swap_test/ref/rdf-redefine.rdf +11 -0
- data/spec/swap_test/ref/reluri-1.rdf +18 -0
- data/spec/swap_test/ref/strquot.n3 +23 -0
- data/spec/swap_test/ref/strquot_a.n3 +23 -0
- data/spec/swap_test/ref/xml-base3.n3 +5 -0
- data/spec/swap_test/ref/xml-redefine.rdf +20 -0
- data/spec/swap_test/ref/xml-redefine2.rdf +23 -0
- data/spec/swap_test/ref/xml-syntax-basic-serialization.rdf +10 -0
- data/spec/swap_test/ref/xmllit.nt +3 -0
- data/spec/swap_test/regression.n3 +231 -0
- data/spec/swap_test/reluri-1.n3 +10 -0
- data/spec/swap_test/strquot.n3 +23 -0
- data/spec/swap_test/syntax/colon-in-uri.rdf +27 -0
- data/spec/swap_test/syntax/djb1a.n3 +3 -0
- data/spec/swap_test/syntax/dot-dash.n3 +15 -0
- data/spec/swap_test/syntax/equals1.n3 +1 -0
- data/spec/swap_test/syntax/equals2.n3 +1 -0
- data/spec/swap_test/syntax/keywords1.n3 +17 -0
- data/spec/swap_test/syntax/keywords2.n3 +18 -0
- data/spec/swap_test/syntax/lstring.n3 +26 -0
- data/spec/swap_test/syntax/neg-formula-predicate.n3 +1 -0
- data/spec/swap_test/syntax/neg-keywords3.n3 +1 -0
- data/spec/swap_test/syntax/neg-literal-predicate.n3 +1 -0
- data/spec/swap_test/syntax/neg-single-quote.n3 +1 -0
- data/spec/swap_test/syntax/neg-thisadoc.n3 +1 -0
- data/spec/swap_test/syntax/no-last-nl.n3 +2 -0
- data/spec/swap_test/syntax/numbers.n3 +26 -0
- data/spec/swap_test/syntax/path1.n3 +23 -0
- data/spec/swap_test/syntax/path2.n3 +31 -0
- data/spec/swap_test/syntax/qvars1.n3 +19 -0
- data/spec/swap_test/syntax/qvars2.n3 +19 -0
- data/spec/swap_test/syntax/this-quantifiers.n3 +164 -0
- data/spec/swap_test/syntax/this-rules.n3 +43 -0
- data/spec/swap_test/syntax/too-nested.n3 +25 -0
- data/spec/swap_test/syntax/trailing-semicolon.n3 +12 -0
- data/spec/swap_test/syntax/zero-objects.n3 +1 -0
- data/spec/swap_test/syntax/zero-predicates.n3 +3 -0
- data/spec/swap_test/tests-work.txt +25 -0
- data/spec/swap_test/xml-syntax/basic-serialization.n3 +8 -0
- data/spec/swap_test/xml-syntax/in-xml.xml +13 -0
- data/spec/swap_test/xml-syntax/non-ascii-pred.rdf +14 -0
- data/spec/swap_test/xml-syntax/rdf_prefix.n3 +2 -0
- data/spec/swap_test/xml-syntax/xml_prefix.n3 +7 -0
- data/spec/swap_test/xml-syntax/xml_prefix2.n3 +9 -0
- data/spec/swap_test/xml-syntax/xmlbase3.rdf +10 -0
- data/spec/swap_test/xml-syntax/xmllit.rdf +33 -0
- data/spec/triple_spec.rb +90 -46
- data/spec/turtle/README.txt +20 -0
- data/spec/turtle/bad-00.ttl +2 -0
- data/spec/turtle/bad-01.ttl +3 -0
- data/spec/turtle/bad-02.ttl +3 -0
- data/spec/turtle/bad-03.ttl +3 -0
- data/spec/turtle/bad-04.ttl +3 -0
- data/spec/turtle/bad-05.ttl +4 -0
- data/spec/turtle/bad-06.ttl +3 -0
- data/spec/turtle/bad-07.ttl +4 -0
- data/spec/turtle/bad-08.ttl +2 -0
- data/spec/turtle/bad-09.ttl +3 -0
- data/spec/turtle/bad-10.ttl +3 -0
- data/spec/turtle/bad-11.ttl +3 -0
- data/spec/turtle/bad-12.ttl +3 -0
- data/spec/turtle/bad-13.ttl +3 -0
- data/spec/turtle/bad-14.ttl +6 -0
- data/spec/turtle/manifest-bad.ttl +88 -0
- data/spec/turtle/manifest.ttl +215 -0
- data/spec/turtle/rdf-schema.out +126 -0
- data/spec/turtle/rdf-schema.ttl +156 -0
- data/spec/turtle/rdfq-results.out +36 -0
- data/spec/turtle/rdfq-results.ttl +39 -0
- data/spec/turtle/rdfs-namespace.out +131 -0
- data/spec/turtle/rdfs-namespace.ttl +160 -0
- data/spec/turtle/test-00.out +1 -0
- data/spec/turtle/test-00.ttl +2 -0
- data/spec/turtle/test-01.out +3 -0
- data/spec/turtle/test-01.ttl +7 -0
- data/spec/turtle/test-02.out +3 -0
- data/spec/turtle/test-02.ttl +5 -0
- data/spec/turtle/test-03.out +3 -0
- data/spec/turtle/test-03.ttl +5 -0
- data/spec/turtle/test-04.out +2 -0
- data/spec/turtle/test-04.ttl +4 -0
- data/spec/turtle/test-05.out +4 -0
- data/spec/turtle/test-05.ttl +4 -0
- data/spec/turtle/test-06.out +1 -0
- data/spec/turtle/test-06.ttl +3 -0
- data/spec/turtle/test-07.out +5 -0
- data/spec/turtle/test-07.ttl +3 -0
- data/spec/turtle/test-08.out +1 -0
- data/spec/turtle/test-08.ttl +3 -0
- data/spec/turtle/test-09.out +4 -0
- data/spec/turtle/test-09.ttl +10 -0
- data/spec/turtle/test-10.out +5 -0
- data/spec/turtle/test-10.ttl +5 -0
- data/spec/turtle/test-11.out +4 -0
- data/spec/turtle/test-11.ttl +10 -0
- data/spec/turtle/test-12.out +4 -0
- data/spec/turtle/test-12.ttl +9 -0
- data/spec/turtle/test-13.out +2 -0
- data/spec/turtle/test-13.ttl +7 -0
- data/spec/turtle/test-14.out +10000 -0
- data/spec/turtle/test-14.ttl +10002 -0
- data/spec/turtle/test-15.out +10000 -0
- data/spec/turtle/test-15.ttl +3 -0
- data/spec/turtle/test-16.out +10000 -0
- data/spec/turtle/test-16.ttl +10002 -0
- data/spec/turtle/test-17.out +1 -0
- data/spec/turtle/test-17.ttl +6 -0
- data/spec/turtle/test-18.out +2 -0
- data/spec/turtle/test-18.ttl +9 -0
- data/spec/turtle/test-19.out +1 -0
- data/spec/turtle/test-19.ttl +4 -0
- data/spec/turtle/test-20.out +2 -0
- data/spec/turtle/test-20.ttl +6 -0
- data/spec/turtle/test-21.out +3 -0
- data/spec/turtle/test-21.ttl +4 -0
- data/spec/turtle/test-22.out +3 -0
- data/spec/turtle/test-22.ttl +4 -0
- data/spec/turtle/test-23.out +1 -0
- data/spec/turtle/test-23.ttl +3 -0
- data/spec/turtle/test-24.out +2 -0
- data/spec/turtle/test-24.ttl +3 -0
- data/spec/turtle/test-25.out +7 -0
- data/spec/turtle/test-25.ttl +14 -0
- data/spec/turtle/test-26.out +1 -0
- data/spec/turtle/test-26.ttl +4 -0
- data/spec/turtle/test-27.out +1 -0
- data/spec/turtle/test-27.ttl +5 -0
- data/spec/turtle/test-28-out.ttl +6 -0
- data/spec/turtle/test-28.out +22 -0
- data/spec/turtle/test-28.ttl +22 -0
- data/spec/turtle/test-29.out +1 -0
- data/spec/turtle/test-29.ttl +1 -0
- data/spec/turtle/test-30.out +5 -0
- data/spec/turtle/test-30.ttl +12 -0
- data/spec/turtle_spec.rb +64 -0
- data/spec/uriref_spec.rb +74 -34
- data/test/n3_tests/rdflib/n3-writer-teset-26.n3 +31 -0
- data/test/n3_tests/rdflib/n3-writer-teset-26.nt +14 -0
- data/test/rdf_tests/xml-literal-mixed.nt +1 -2
- metadata +278 -39
- data/lib/rdf_context/n3_grammar.rb +0 -2171
- data/test/perf_test/test.rb +0 -11
- data/test/perf_test/tommorris.rdf +0 -2267
data/History.txt
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
=== 0.5.0
|
2
|
+
* Support for Ruby 1.9, 1.8.7 and 1.8.6.
|
3
|
+
* Unicode escapes and URIRefs only work properly in Ruby 1.9
|
4
|
+
* Replaced some (&:meth) spells with {|c| c.meth} for Ruby 1.8.6 compatibility
|
5
|
+
* Fully compliant N3 parser (n3-rdf level) with extnensive tests, including SWAP, CWM and Turtle test suites.
|
6
|
+
* Supports paths, keywords, all semantic expressions.
|
7
|
+
* No support yet for Formulae, variables, rules or automatic reification
|
8
|
+
* Allow Triple#subject to be like an object, allowing literals and graphs
|
9
|
+
* Allow Triple#predicate to be a BNode as well as a URIRef
|
10
|
+
* Graph changes
|
11
|
+
* Graph#properties(subject) returns properties of a subject expressed as a hash to arrays of objects.
|
12
|
+
* Graph#seq(subject) returns ordered rdf:_n objects if subject is a rdf:Seq., or list of rdf:first/rdf:rest
|
13
|
+
* Graph#qname(uri) as alternative to uri.qname, has namespaces available.
|
14
|
+
* Graph#type_of(subject) array of RDF_TYPE objects.
|
15
|
+
* Graph#allow_n3 (getter/setter and option) controls if extra N3 semantics for graphs are allowed. Otherwise, calls Triple#validate_rdf to raise exception
|
16
|
+
* Real graph comparisons, including permutation search of triples containing BNodes (obviously, may be expensive)
|
17
|
+
* Add QuotedGraph and AggregateGraph
|
18
|
+
* Literal changes
|
19
|
+
* Literal#== as alias to eql? Needed for sort and uniq.
|
20
|
+
* Normalize valid typed literals
|
21
|
+
* Added Literal#valid? to perform some content validations.
|
22
|
+
* URIRef/Namespace changes
|
23
|
+
* Fix URI generation, performing normalizations for normal URI refs, and not for Namespace URIs.
|
24
|
+
* Fixed bug in URIRef#namespace & to_qname when namespace does not have a trailing / or #
|
25
|
+
* URIRef#short_name may return a different value after a namespace is assigned.
|
26
|
+
* Reduce dependency on Redland when running tests
|
27
|
+
|
1
28
|
=== 0.4.8
|
2
29
|
* Add Duration and support in Literal
|
3
30
|
* Add datatype support for xs:boolean, xs:double, xs:duration and xs:time.
|
data/README.rdoc
CHANGED
@@ -7,7 +7,7 @@ A set of compliant RDF parsers:
|
|
7
7
|
* RDF/XML
|
8
8
|
* RDFa
|
9
9
|
|
10
|
-
Multiple
|
10
|
+
Multiple data-stores may be attached to a Graph, including Memory, List and SQLite3
|
11
11
|
|
12
12
|
== DESCRIPTION:
|
13
13
|
|
@@ -18,7 +18,7 @@ RdfContext parses RDF/XML, RDFa and N3-rdf into a Graph object. It also serializ
|
|
18
18
|
|
19
19
|
* Fully compliant RDF/XML parser.
|
20
20
|
* Fully compliant XHTML/RDFa 1.0 parser.
|
21
|
-
* N3-rdf parser
|
21
|
+
* Fully compliant N3-rdf parser (N3-rdf level)
|
22
22
|
* N-Triples and RDF/XML serializer
|
23
23
|
* RDFa tests use SPARQL for most tests due to Rasqal limitations. Other tests compare directly against N-triples.
|
24
24
|
* Graph serializes into RDF/XML and N-Triples.
|
@@ -49,11 +49,24 @@ Graphs also store namespace associations, and can serialize graphs to RDF/XML or
|
|
49
49
|
g.to_rdfxml
|
50
50
|
g.to_ntriples
|
51
51
|
|
52
|
+
Resource properties
|
53
|
+
|
54
|
+
graph.parse(':foo a :bar; rdfs:label "An example" .', "http://example.com/")
|
55
|
+
graph.resources("http://example.com/subject") =>
|
56
|
+
{
|
57
|
+
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type" => [<http://example.com/#bar>],
|
58
|
+
"http://example.com/#label" => ["An example"]
|
59
|
+
}
|
60
|
+
|
52
61
|
Instantiate an existing graph from a datastore
|
53
62
|
|
54
63
|
s = SQLIte3Store.new(:path => "store.db")
|
55
64
|
g = Graph.new(:store => s, :identifier => "http://example.com/context")
|
56
65
|
|
66
|
+
QuotedGraph implements N3 Formulae semantics, by creating a graph within a store that is formula_aware. QuotedGraph triples are not returned in a query to a ConjunctiveGraph.
|
67
|
+
|
68
|
+
AggregateGraphs allow multiple graphs from a given context_aware store to be combined into a single read-only graph.
|
69
|
+
|
57
70
|
=== Parsers
|
58
71
|
Instantiate a parser and parse source, specifying type and base-URL
|
59
72
|
|
@@ -94,14 +107,9 @@ SQLite3Store:: context aware datastore using a SQLite3 database to create a pers
|
|
94
107
|
|
95
108
|
== TODO:
|
96
109
|
* Testing
|
97
|
-
* Integrate ntriples tests in spec/ntriples/test.nt
|
98
|
-
* Turtle tests from http://www.w3.org/2000/10/swap/test/n3/turtle-manifest.n3 (if can find .ttl and .out files)
|
99
|
-
* N3-RDF tests from http://www.w3.org/2000/10/swap/test/n3/n3-rdf.tests
|
100
|
-
* N3-Full tests from http://www.w3.org/2000/10/swap/test/n3/n3-full.tests
|
101
|
-
* N3 grammar tests?
|
102
110
|
* RDFa updates for new tests and non XHTML representations.
|
103
111
|
* Graphs
|
104
|
-
* n3 serialization
|
112
|
+
* n3/turtle serialization
|
105
113
|
* Reasoner/inference engine
|
106
114
|
* SPARQL
|
107
115
|
* RDFS logic and RDF entailment tests
|
@@ -109,11 +117,16 @@ SQLite3Store:: context aware datastore using a SQLite3 database to create a pers
|
|
109
117
|
* ActiveRDF-like class support
|
110
118
|
* Integrate with RDFObjects (http://github.com/rsinger/RDFObjects)
|
111
119
|
|
120
|
+
== Resources:
|
121
|
+
* Distiller[http://kellogg-assoc/distiller]
|
122
|
+
* RDoc[http://rdoc.info/projects/gkellogg/rdf_context]
|
123
|
+
* History[http://github.com/gkellogg/rdf_context/blob/master/History.txt]
|
124
|
+
|
112
125
|
== LICENSE:
|
113
126
|
|
114
127
|
(The MIT License)
|
115
128
|
|
116
|
-
Copyright (c) 2009 Gregg Kellogg
|
129
|
+
Copyright (c) 2009-2010 Gregg Kellogg
|
117
130
|
|
118
131
|
Copyright (c) 2008 Tom Morris and contributors
|
119
132
|
|
data/Rakefile
CHANGED
@@ -50,28 +50,33 @@ Spec::Rake::SpecTask.new(:spec) do |spec|
|
|
50
50
|
end
|
51
51
|
|
52
52
|
desc "Run specs through RCov"
|
53
|
-
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
53
|
+
Spec::Rake::SpecTask.new("spec:rcov") do |spec|
|
54
54
|
spec.libs << 'lib' << 'spec'
|
55
55
|
spec.pattern = 'spec/*_spec.rb'
|
56
56
|
spec.rcov = true
|
57
57
|
end
|
58
58
|
|
59
|
+
desc "Generate HTML report specs"
|
60
|
+
Spec::Rake::SpecTask.new("doc:spec") do |spec|
|
61
|
+
spec.libs << 'lib' << 'spec'
|
62
|
+
spec.spec_files = FileList['spec/*_spec.rb']
|
63
|
+
spec.spec_opts = ["--format", "html:doc/spec.html"]
|
64
|
+
end
|
65
|
+
|
59
66
|
task :spec => :check_dependencies
|
60
67
|
|
61
68
|
task :default => :spec
|
62
69
|
|
63
70
|
require 'rake/rdoctask'
|
64
|
-
Rake::RDocTask.new do |rdoc|
|
71
|
+
Rake::RDocTask.new("doc:rdoc") do |rdoc|
|
65
72
|
if File.exist?('VERSION')
|
66
73
|
version = File.read('VERSION')
|
67
74
|
else
|
68
|
-
version =
|
75
|
+
version = RdfContext::VERSION
|
69
76
|
end
|
70
77
|
|
71
|
-
rdoc.rdoc_dir = 'rdoc'
|
78
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
72
79
|
rdoc.title = "rdf_context #{version}"
|
73
80
|
rdoc.rdoc_files.include('README*', "History.txt")
|
74
81
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
75
82
|
end
|
76
|
-
|
77
|
-
# vim: syntax=Ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bin/rdf_context
CHANGED
@@ -9,7 +9,7 @@ class Parse
|
|
9
9
|
graph_opts = {:identifier => base_uri}
|
10
10
|
graph_opts[:store] = store if store
|
11
11
|
parser = Parser.new(:graph => Graph.new(graph_opts))
|
12
|
-
parser.parse(File.
|
12
|
+
parser.parse(file.respond_to?(:read) ? file : File.open(file), base_uri, :strict => true)
|
13
13
|
output = case $format
|
14
14
|
when "xml"
|
15
15
|
parser.graph.to_rdfxml
|
@@ -30,9 +30,12 @@ class Parse
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
mode = ARGV.shift
|
34
|
+
raise "Mode must be one of 'parse'" unless mode == "parse"
|
35
|
+
|
33
36
|
$verbose = false
|
34
37
|
base_uri = "http://example.com"
|
35
|
-
store
|
38
|
+
store = :list_store
|
36
39
|
opts = GetoptLong.new(
|
37
40
|
["--verbose", GetoptLong::NO_ARGUMENT],
|
38
41
|
["--quiet", GetoptLong::NO_ARGUMENT],
|
@@ -62,7 +65,12 @@ opts.each do |opt, arg|
|
|
62
65
|
end
|
63
66
|
|
64
67
|
x = Parse.new
|
65
|
-
ARGV.
|
66
|
-
|
68
|
+
if ARGV.empty?
|
69
|
+
s = $stdin.read
|
70
|
+
x.parse(StringIO.new(s), base_uri, store)
|
71
|
+
else
|
72
|
+
ARGV.each do |test_file|
|
73
|
+
x.parse(test_file, base_uri, store)
|
74
|
+
end
|
67
75
|
end
|
68
76
|
|
data/lib/rdf_context.rb
CHANGED
@@ -43,7 +43,7 @@ module RdfContext
|
|
43
43
|
| \\\\u[0-9a-fA-F]
|
44
44
|
)
|
45
45
|
( [0-9a-zA-Z_\.-]
|
46
|
-
| \\\\u([0-9a-fA-F]{4})
|
46
|
+
| \\\\u([0-9a-fA-F]{4})
|
47
47
|
)*
|
48
48
|
$},
|
49
49
|
Regexp::EXTENDED)
|
@@ -51,6 +51,8 @@ module RdfContext
|
|
51
51
|
RDF_TYPE = URIRef.new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
|
52
52
|
XML_LITERAL = Literal::Encoding.xmlliteral
|
53
53
|
|
54
|
+
OWL_NS = Namespace.new("http://www.w3.org/2002/07/owl#", "owl")
|
55
|
+
LOG_NS = Namespace.new("http://www.w3.org/2000/10/swap/log#", "log")
|
54
56
|
RDF_NS = Namespace.new("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf")
|
55
57
|
RDFS_NS = Namespace.new("http://www.w3.org/2000/01/rdf-schema#", "rdfs")
|
56
58
|
XHV_NS = Namespace.new("http://www.w3.org/1999/xhtml/vocab#", "xhv")
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "graph")
|
2
|
+
|
3
|
+
module RdfContext
|
4
|
+
# AggregateGraph - A read-only graph composed of multiple other graphs.
|
5
|
+
#
|
6
|
+
# Essentially a ConjunctiveGraph over an explicit subset of the entire store.
|
7
|
+
class AggregateGraph < Graph
|
8
|
+
attr_reader :graphs
|
9
|
+
|
10
|
+
# List of graphs to aggregate
|
11
|
+
def initialize(*graph)
|
12
|
+
@graphs = graph
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy(configuration = nil); raise ReadOnlyGraphException; end
|
16
|
+
def commit; raise ReadOnlyGraphException; end
|
17
|
+
def rollback; raise ReadOnlyGraphException; end
|
18
|
+
def add; raise ReadOnlyGraphException; end
|
19
|
+
def remove; raise ReadOnlyGraphException; end
|
20
|
+
def bind(namespace); raise ReadOnlyGraphException; end
|
21
|
+
def parse(stream, uri, options = {}); raise ReadOnlyGraphException; end
|
22
|
+
def n3; raise ReadOnlyGraphException; end
|
23
|
+
|
24
|
+
# Open the graphs
|
25
|
+
def open(configuration = {})
|
26
|
+
@graphs.each {|g| g.open(configuration)}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Close the graphs
|
30
|
+
def close(configuration = {})
|
31
|
+
@graphs.each {|g| g.close(configuration)}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Number of Triples in the graph
|
35
|
+
def size
|
36
|
+
@graphs.inject(0) {|memo, g| memo += g.size}
|
37
|
+
end
|
38
|
+
|
39
|
+
# List of distinct subjects in graph
|
40
|
+
def subjects
|
41
|
+
@graphs.inject([]) {|memo, g| memo += g.subjects}
|
42
|
+
end
|
43
|
+
|
44
|
+
# List of distinct predicates in graph
|
45
|
+
def predicates
|
46
|
+
@graphs.inject([]) {|memo, g| memo += g.predicates}
|
47
|
+
end
|
48
|
+
|
49
|
+
# List of distinct objects in graph
|
50
|
+
def objects
|
51
|
+
@graphs.inject([]) {|memo, g| memo += g.objects}
|
52
|
+
end
|
53
|
+
|
54
|
+
# Triples from graph, optionally matching subject, predicate, or object.
|
55
|
+
# Delegates to Store#triples.
|
56
|
+
#
|
57
|
+
# @param [Triple, nil] triple:: Triple to match, may be a pattern triple or nil
|
58
|
+
# @return [Array]:: List of matched triples
|
59
|
+
def triples(triple = Triple.new(nil, nil, nil), &block) # :yields: triple, context
|
60
|
+
@graphs.inject([]) {|memo, g| memo += g.triples(triple, &block)}
|
61
|
+
end
|
62
|
+
|
63
|
+
# Check to see if this graph contains the specified triple
|
64
|
+
def contains?(triple)
|
65
|
+
@graphs.any? {|g| g.contains?(triple) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get all BNodes with usage count used within graph
|
69
|
+
def bnodes
|
70
|
+
@graphs.inject([]) {|memo, g| memo += g.bnodes}
|
71
|
+
end
|
72
|
+
|
73
|
+
# Only compares to another AggregateGraph. Compares each sub-graph
|
74
|
+
def eql?(other)
|
75
|
+
other.is_a?(AggregateGraph) ? super : false
|
76
|
+
end
|
77
|
+
|
78
|
+
def nsbinding
|
79
|
+
@graphs.inject({}) {|memo, g| memo.merge(g.nsbinding)}
|
80
|
+
end
|
81
|
+
|
82
|
+
def uri_binding
|
83
|
+
@graphs.inject({}) {|memo, g| memo.merge(g.uri_binding)}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Array
|
2
|
+
# http://wiki.rubygarden.org/Ruby/page/show/ArrayPermute
|
3
|
+
# Permute an array, and call a block for each permutation
|
4
|
+
# Author: Paul Battley
|
5
|
+
def permute(prefixed=[])
|
6
|
+
if (length < 2)
|
7
|
+
# there are no elements left to permute
|
8
|
+
yield(prefixed + self)
|
9
|
+
else
|
10
|
+
# recursively permute the remaining elements
|
11
|
+
each_with_index do |e, i|
|
12
|
+
(self[0,i]+self[(i+1)..-1]).permute(prefixed+[e]) { |a| yield a }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
|
18
|
+
# * <tt>:words_connector</tt> - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
|
19
|
+
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
|
20
|
+
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
|
21
|
+
def to_sentence(options = {})
|
22
|
+
default_words_connector = ", "
|
23
|
+
default_two_words_connector = " and "
|
24
|
+
default_last_word_connector = ", and "
|
25
|
+
|
26
|
+
# Try to emulate to_senteces previous to 2.3
|
27
|
+
if options.has_key?(:connector) || options.has_key?(:skip_last_comma)
|
28
|
+
::ActiveSupport::Deprecation.warn(":connector has been deprecated. Use :words_connector instead", caller) if options.has_key? :connector
|
29
|
+
::ActiveSupport::Deprecation.warn(":skip_last_comma has been deprecated. Use :last_word_connector instead", caller) if options.has_key? :skip_last_comma
|
30
|
+
|
31
|
+
skip_last_comma = options.delete :skip_last_comma
|
32
|
+
if connector = options.delete(:connector)
|
33
|
+
options[:last_word_connector] ||= skip_last_comma ? connector : ", #{connector}"
|
34
|
+
else
|
35
|
+
options[:last_word_connector] ||= skip_last_comma ? default_two_words_connector : default_last_word_connector
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
40
|
+
options = {:words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector}.merge(options)
|
41
|
+
|
42
|
+
case length
|
43
|
+
when 0
|
44
|
+
""
|
45
|
+
when 1
|
46
|
+
self[0].to_s
|
47
|
+
when 2
|
48
|
+
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
49
|
+
else
|
50
|
+
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -36,7 +36,7 @@ module RdfContext
|
|
36
36
|
# Triples across all contexts in store, optionally matching subject, predicate, or object.
|
37
37
|
# Delegates to Store#triples.
|
38
38
|
#
|
39
|
-
# @param [Triple, nil] triple:: Triple to match, may be a
|
39
|
+
# @param [Triple, nil] triple:: Triple to match, may be a pattern triple or nil
|
40
40
|
# @return [Array]:: List of matched triples
|
41
41
|
def triples(triple = Triple.new(nil, nil, nil), &block) # :yields: triple, context
|
42
42
|
@store.triples(triple, nil, &block) || []
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module RdfContext
|
2
|
-
class RdfException
|
2
|
+
class RdfException < RuntimeError; end
|
3
|
+
|
3
4
|
class ParserException < RdfException; end
|
4
|
-
class GraphException
|
5
|
-
class StoreException
|
6
|
-
class BNodeException
|
7
|
-
class TypeError
|
5
|
+
class GraphException < RdfException; end
|
6
|
+
class StoreException < RdfException; end
|
7
|
+
class BNodeException < RdfException; end
|
8
|
+
class TypeError < RdfException; end
|
9
|
+
class InvalidNode < RdfException; end
|
8
10
|
class InvalidPredicate < RdfException; end
|
9
|
-
|
10
|
-
class
|
11
|
+
|
12
|
+
class ReadOnlyGraphException < GraphException; end
|
11
13
|
end
|
data/lib/rdf_context/graph.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'namespace')
|
2
2
|
require File.join(File.dirname(__FILE__), 'triple')
|
3
|
+
require File.join(File.dirname(__FILE__), 'array_hacks')
|
3
4
|
require File.join(File.dirname(__FILE__), 'store', 'list_store')
|
4
5
|
require File.join(File.dirname(__FILE__), 'store', 'memory_store')
|
5
6
|
|
@@ -12,6 +13,7 @@ module RdfContext
|
|
12
13
|
attr_reader :nsbinding
|
13
14
|
attr_reader :identifier
|
14
15
|
attr_reader :store
|
16
|
+
attr_accessor :allow_n3
|
15
17
|
|
16
18
|
# Create a Graph with the given store and identifier.
|
17
19
|
#
|
@@ -30,6 +32,7 @@ module RdfContext
|
|
30
32
|
# @param [Hash] options:: Options
|
31
33
|
# <em>options[:store]</em>:: storage, defaults to a new ListStore instance. May be symbol :list_store or :memory_store
|
32
34
|
# <em>options[:identifier]</em>:: Identifier for this graph, BNode or URIRef
|
35
|
+
# <em>options[:allow_n3]</em>:: Allow N3-specific triples: Literals as subject, BNodes as predicate
|
33
36
|
def initialize(options = {})
|
34
37
|
@nsbinding = {}
|
35
38
|
|
@@ -41,7 +44,9 @@ module RdfContext
|
|
41
44
|
else ListStore.new
|
42
45
|
end
|
43
46
|
|
44
|
-
@
|
47
|
+
@allow_n3 = options[:allow_n3]
|
48
|
+
|
49
|
+
@identifier = Triple.coerce_node(options[:identifier]) || BNode.new
|
45
50
|
end
|
46
51
|
|
47
52
|
def inspect
|
@@ -53,7 +58,7 @@ module RdfContext
|
|
53
58
|
[self.class.to_s, self.identifier].hash
|
54
59
|
end
|
55
60
|
|
56
|
-
def context_aware?; @context_aware
|
61
|
+
def context_aware?; @store.context_aware?; end
|
57
62
|
|
58
63
|
# Data Store interface
|
59
64
|
def nsbinding; @store.nsbinding; end
|
@@ -136,7 +141,8 @@ module RdfContext
|
|
136
141
|
# Add bindings for predicates not already having bindings
|
137
142
|
tmp_ns = "ns0"
|
138
143
|
predicates.each do |p|
|
139
|
-
unless
|
144
|
+
raise "Attempt to serialize graph containing non-strict RDF compiant BNode as predicate" unless p.is_a?(URIRef)
|
145
|
+
if !p.namespace(uri_bindings)
|
140
146
|
uri_bindings[p.base] = Namespace.new(p.base, tmp_ns)
|
141
147
|
rdf_attrs["xmlns:#{tmp_ns}"] = p.base
|
142
148
|
tmp_ns = tmp_ns.succ
|
@@ -188,6 +194,11 @@ module RdfContext
|
|
188
194
|
# Hash of uri => Namespace bindings
|
189
195
|
def uri_binding; @store.uri_binding; end
|
190
196
|
|
197
|
+
# QName for a URI
|
198
|
+
def qname(uri)
|
199
|
+
uri.to_qname(self.uri_binding)
|
200
|
+
end
|
201
|
+
|
191
202
|
# Namespace for prefix
|
192
203
|
def namespace(prefix); @store.namespace(prefix); end
|
193
204
|
|
@@ -235,6 +246,7 @@ module RdfContext
|
|
235
246
|
# @param [Triple] t:: the triple to be added to the graph
|
236
247
|
# @return [Graph]:: Returns the graph
|
237
248
|
def << (triple)
|
249
|
+
triple.validate_rdf unless @allow_n3 # Only add triples if n3-mode is set
|
238
250
|
@store.add(triple, self)
|
239
251
|
self
|
240
252
|
end
|
@@ -254,7 +266,10 @@ module RdfContext
|
|
254
266
|
def add(*triples)
|
255
267
|
options = triples.last.is_a?(Hash) ? triples.pop : {}
|
256
268
|
ctx = options[:context] || @default_context || self
|
257
|
-
triples.each
|
269
|
+
triples.each do |t|
|
270
|
+
t.validate_rdf unless @allow_n3 # Only add triples if n3-mode is set
|
271
|
+
@store.add(t, ctx)
|
272
|
+
end
|
258
273
|
self
|
259
274
|
end
|
260
275
|
|
@@ -265,19 +280,73 @@ module RdfContext
|
|
265
280
|
# Triples from graph, optionally matching subject, predicate, or object.
|
266
281
|
# Delegates to Store#triples.
|
267
282
|
#
|
268
|
-
# @param [Triple, nil] triple:: Triple to match, may be a
|
283
|
+
# @param [Triple, nil] triple:: Triple to match, may be a pattern triple or nil
|
269
284
|
# @return [Array]:: List of matched triples
|
270
285
|
def triples(triple = Triple.new(nil, nil, nil), &block) # :yields: triple, context
|
271
286
|
@store.triples(triple, self, &block) || []
|
272
287
|
end
|
273
288
|
alias_method :find, :triples
|
289
|
+
|
290
|
+
# Returns ordered rdf:_n objects or rdf:first, rdf:rest for a given subject
|
291
|
+
def seq(subject)
|
292
|
+
props = properties(subject)
|
293
|
+
rdf_type = props[RDF_TYPE.to_s] || []
|
294
|
+
|
295
|
+
if rdf_type.include?(RDF_NS.Seq)
|
296
|
+
props.keys.select {|k| k.match(/#{RDF_NS.uri}_(\d)$/)}.
|
297
|
+
sort_by {|i| i.sub(RDF_NS._.to_s, "").to_i}.
|
298
|
+
map {|key| props[key]}.
|
299
|
+
flatten
|
300
|
+
elsif self.triples(Triple.new(subject, RDF_NS.first, nil))
|
301
|
+
# N3-style first/rest chain
|
302
|
+
list = []
|
303
|
+
while subject != RDF_NS.nil
|
304
|
+
props = properties(subject)
|
305
|
+
list += props[RDF_NS.first.to_s]
|
306
|
+
subject = props[RDF_NS.rest.to_s].first
|
307
|
+
end
|
308
|
+
list
|
309
|
+
else
|
310
|
+
[]
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
# Resource properties
|
315
|
+
#
|
316
|
+
# Properties arranged as a hash with the predicate Term as index to an array of resources or literals
|
317
|
+
#
|
318
|
+
# Example:
|
319
|
+
# graph.parse(':foo a :bar; rdfs:label "An example" .', "http://example.com/")
|
320
|
+
# graph.resources("http://example.com/subject") =>
|
321
|
+
# {
|
322
|
+
# "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" => [<http://example.com/#bar>],
|
323
|
+
# "http://example.com/#label" => ["An example"]
|
324
|
+
# }
|
325
|
+
def properties(subject)
|
326
|
+
@properties ||= {}
|
327
|
+
@properties[subject.to_s] ||= begin
|
328
|
+
hash = Hash.new
|
329
|
+
self.triples(Triple.new(subject, nil, nil)).map do |t, ctx|
|
330
|
+
pred = t.predicate.to_s
|
331
|
+
|
332
|
+
hash[pred] ||= []
|
333
|
+
hash[pred] << t.object
|
334
|
+
end
|
335
|
+
hash
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# Return an n3 identifier for the Graph
|
340
|
+
def n3
|
341
|
+
"[#{self.identifier.to_n3}]"
|
342
|
+
end
|
274
343
|
|
275
344
|
# Detect the presence of a BNode in the graph, either as a subject or an object
|
276
345
|
#
|
277
346
|
# @param [BNode] bn:: BNode to find
|
278
347
|
#
|
279
348
|
def has_bnode_identifier?(bn)
|
280
|
-
triples do |triple, context|
|
349
|
+
self.triples do |triple, context|
|
281
350
|
return true if triple.subject.eql?(bn) || triple.object.eql?(bn)
|
282
351
|
end
|
283
352
|
false
|
@@ -300,6 +369,11 @@ module RdfContext
|
|
300
369
|
triples(Triple.new(nil, RDF_TYPE, object)).map {|t, ctx| t.subject}
|
301
370
|
end
|
302
371
|
|
372
|
+
# Get type(s) of subject, returns a list of symbols
|
373
|
+
def type_of(subject)
|
374
|
+
triples(Triple.new(subject, RDF_TYPE, nil)).map {|t, ctx| t.object}
|
375
|
+
end
|
376
|
+
|
303
377
|
# Merge a graph into this graph
|
304
378
|
def merge!(graph)
|
305
379
|
raise GraphException.new("merge without a graph") unless graph.is_a?(Graph)
|
@@ -310,9 +384,10 @@ module RdfContext
|
|
310
384
|
|
311
385
|
graph.triples do |triple, context|
|
312
386
|
# If triple contains bnodes, remap to new values
|
313
|
-
if triple.subject.is_a?(BNode) || triple.object.is_a?(BNode)
|
387
|
+
if triple.subject.is_a?(BNode) || triple.predicate.is_a?(BNode) || triple.object.is_a?(BNode)
|
314
388
|
triple = triple.clone
|
315
389
|
triple.subject = bn[triple.subject] if triple.subject.is_a?(BNode)
|
390
|
+
triple.predicate = bn[triple.predicate] if triple.predicate.is_a?(BNode)
|
316
391
|
triple.object = bn[triple.object] if triple.object.is_a?(BNode)
|
317
392
|
end
|
318
393
|
self << triple
|
@@ -326,26 +401,53 @@ module RdfContext
|
|
326
401
|
#
|
327
402
|
# We just follow Python RDFlib's lead and do a simple comparison
|
328
403
|
def eql?(other)
|
329
|
-
|
404
|
+
puts "eql? size #{self.size} vs #{other.size}" if $DEBUG
|
330
405
|
return false if !other.is_a?(Graph) || self.size != other.size
|
331
|
-
return false unless other.identifier.to_s == identifier.to_s
|
406
|
+
return false unless other.identifier.to_s == identifier.to_s unless other.identifier.is_a?(BNode) && identifier.is_a?(BNode)
|
332
407
|
|
333
408
|
bn_self = bnodes.values.sort
|
334
409
|
bn_other = other.bnodes.values.sort
|
335
|
-
|
410
|
+
puts "eql? bnodes '#{bn_self.to_sentence}' vs '#{bn_other.to_sentence}'" if $DEBUG
|
336
411
|
return false unless bn_self == bn_other
|
337
412
|
|
338
413
|
# Check each triple to see if it's contained in the other graph
|
339
414
|
triples do |t, ctx|
|
340
|
-
next if t.subject.is_a?(BNode) || t.object.is_a?(BNode)
|
341
|
-
|
415
|
+
next if t.subject.is_a?(BNode) || t.predicate.is_a?(BNode) || t.object.is_a?(BNode)
|
416
|
+
puts "eql? contains '#{t.to_ntriples}: #{other.contains?(t)}'" if $DEBUG
|
342
417
|
return false unless other.contains?(t)
|
343
418
|
end
|
344
|
-
|
419
|
+
|
420
|
+
# For each BNode, check permutations of similar bnodes in other graph
|
421
|
+
bnode_permutations(bnodes, other.bnodes) do |bn_map|
|
422
|
+
puts "bnode permutations: #{bn_map.inspect}" if $DEBUG
|
423
|
+
# bn_map contains 1-1 mapping of bnodes from self to other
|
424
|
+
catch :next_perm do
|
425
|
+
triples do |t, ctx|
|
426
|
+
next unless t.subject.is_a?(BNode) || t.predicate.is_a?(BNode) || t.object.is_a?(BNode)
|
427
|
+
subject, predicate, object = t.subject, t.predicate, t.object
|
428
|
+
subject = bn_map[subject] if bn_map.has_key?(subject)
|
429
|
+
predicate = bn_map[predicate] if bn_map.has_key?(predicate)
|
430
|
+
object = bn_map[object] if bn_map.has_key?(object)
|
431
|
+
tn = Triple.new(subject, predicate, object)
|
432
|
+
puts " eql? contains '#{tn.inspect}': #{other.contains?(tn)}" if $DEBUG
|
433
|
+
next if other.contains?(tn)
|
434
|
+
|
435
|
+
puts " no, next permutation" if $DEBUG
|
436
|
+
# Not a match, try next permutation
|
437
|
+
throw :next_perm
|
438
|
+
end
|
439
|
+
|
440
|
+
# If we matched all triples in the graph using this permutation, we're done
|
441
|
+
return true
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# Exhausted all permutations, unless there were no bnodes
|
446
|
+
bn_self.length == 0
|
345
447
|
end
|
346
448
|
|
347
449
|
alias_method :==, :eql?
|
348
|
-
|
450
|
+
|
349
451
|
# Parse source into Graph.
|
350
452
|
#
|
351
453
|
# Merges results into a common Graph
|
@@ -356,9 +458,66 @@ module RdfContext
|
|
356
458
|
# <em>options[:debug]</em>:: Array to place debug messages
|
357
459
|
# <em>options[:type]</em>:: One of _rdfxml_, _html_, or _n3_
|
358
460
|
# <em>options[:strict]</em>:: Raise Error if true, continue with lax parsing, otherwise
|
461
|
+
# <em>options[:allow_n3]</em>:: Allow N3-specific triples: Literals as subject, BNodes as predicate
|
359
462
|
# @return [Graph]:: Returns the graph containing parsed triples
|
360
|
-
def parse(stream, uri, options = {}, &block) # :yields: triple
|
463
|
+
def parse(stream, uri = nil, options = {}, &block) # :yields: triple
|
464
|
+
@allow_n3 ||= options[:allow_n3]
|
361
465
|
Parser.parse(stream, uri, options.merge(:graph => self), &block)
|
362
466
|
end
|
363
467
|
end
|
468
|
+
|
469
|
+
protected
|
470
|
+
|
471
|
+
# Permutations of two BNode lists
|
472
|
+
#
|
473
|
+
# Take source keys and run permutations mapping to other keys, if the permutation
|
474
|
+
# maps to the same counts for each
|
475
|
+
def bnode_permutations(bn_source, bn_other)
|
476
|
+
puts "compare #{bn_source.inspect}\n with #{bn_other.inspect}" if $DEBUG
|
477
|
+
|
478
|
+
source_keys = bn_source.keys
|
479
|
+
other_keys = bn_other.keys
|
480
|
+
values = bn_source.values.uniq
|
481
|
+
|
482
|
+
# Break key lists into groups based on sharing equivalent usage counts
|
483
|
+
case values.length
|
484
|
+
when 0
|
485
|
+
{}
|
486
|
+
when 1
|
487
|
+
# All keys have equivalent counts, yield permutations
|
488
|
+
if source_keys.length == 1
|
489
|
+
puts "yield #{{source_keys.first => other_keys.first}.inspect}" if $DEBUG
|
490
|
+
yield({source_keys.first => other_keys.first})
|
491
|
+
else
|
492
|
+
(0..(source_keys.length-1)).to_a.permute do |indicies|
|
493
|
+
puts "indicies #{indicies.inspect}" if $DEBUG
|
494
|
+
ok = other_keys.dup
|
495
|
+
map = indicies.inject({}) { |hash, i| hash[source_keys[i]] = ok.shift; hash}
|
496
|
+
puts "yield #{map.inspect}" if $DEBUG
|
497
|
+
yield(map)
|
498
|
+
end
|
499
|
+
end
|
500
|
+
else
|
501
|
+
# Break bnodes into 2 arrays sharing a common usage count and permute each separately
|
502
|
+
max = values.max
|
503
|
+
bn_source_min = bn_source.clone
|
504
|
+
bn_other_min = bn_other.clone
|
505
|
+
bn_source_max = {}
|
506
|
+
bn_other_max = {}
|
507
|
+
bn_source.each_pair do |bn, v|
|
508
|
+
bn_source_max[bn] = bn_source_min.delete(bn) if v == max
|
509
|
+
end
|
510
|
+
bn_other.each_pair do |bn, v|
|
511
|
+
bn_other_max[bn] = bn_other_min.delete(bn) if v == max
|
512
|
+
end
|
513
|
+
|
514
|
+
puts "yield permutations of multiple with max #{bn_source_max.inspect}\n and #{bn_other_max.inspect}" if $DEBUG
|
515
|
+
# Yield for each permutation of max joined with permutations of min
|
516
|
+
bnode_permutations(bn_source_max, bn_other_max) do |bn_perm_max|
|
517
|
+
bnode_permutations(bn_source_min, bn_other_min) do |bn_perm_min|
|
518
|
+
yield bn_perm_max.merge(bn_perm_min)
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
364
523
|
end
|