rdf 1.1.0p4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +6 -14
  2. data/README +33 -33
  3. data/VERSION +1 -1
  4. data/lib/rdf.rb +60 -12
  5. data/lib/rdf/cli.rb +7 -1
  6. data/lib/rdf/cli/vocab-loader.rb +240 -0
  7. data/lib/rdf/format.rb +2 -2
  8. data/lib/rdf/mixin/enumerable.rb +12 -4
  9. data/lib/rdf/mixin/queryable.rb +13 -13
  10. data/lib/rdf/model/graph.rb +5 -4
  11. data/lib/rdf/model/list.rb +15 -4
  12. data/lib/rdf/model/literal.rb +2 -1
  13. data/lib/rdf/model/statement.rb +10 -1
  14. data/lib/rdf/model/term.rb +8 -0
  15. data/lib/rdf/model/uri.rb +107 -2
  16. data/lib/rdf/model/value.rb +8 -0
  17. data/lib/rdf/ntriples/reader.rb +5 -4
  18. data/lib/rdf/query.rb +47 -12
  19. data/lib/rdf/query/solutions.rb +29 -29
  20. data/lib/rdf/reader.rb +13 -3
  21. data/lib/rdf/repository.rb +1 -0
  22. data/lib/rdf/util/file.rb +86 -6
  23. data/lib/rdf/vocab.rb +158 -58
  24. data/lib/rdf/vocab/cc.rb +28 -11
  25. data/lib/rdf/vocab/cert.rb +127 -9
  26. data/lib/rdf/vocab/dc.rb +242 -60
  27. data/lib/rdf/vocab/dc11.rb +42 -20
  28. data/lib/rdf/vocab/doap.rb +121 -42
  29. data/lib/rdf/vocab/exif.rb +540 -165
  30. data/lib/rdf/vocab/foaf.rb +353 -66
  31. data/lib/rdf/vocab/geo.rb +40 -10
  32. data/lib/rdf/vocab/gr.rb +1094 -0
  33. data/lib/rdf/vocab/http.rb +81 -23
  34. data/lib/rdf/vocab/ical.rb +361 -0
  35. data/lib/rdf/vocab/ma.rb +281 -69
  36. data/lib/rdf/vocab/og.rb +98 -0
  37. data/lib/rdf/vocab/owl.rb +226 -56
  38. data/lib/rdf/vocab/prov.rb +489 -0
  39. data/lib/rdf/vocab/rdfs.rb +38 -14
  40. data/lib/rdf/vocab/rsa.rb +25 -9
  41. data/lib/rdf/vocab/rss.rb +29 -11
  42. data/lib/rdf/vocab/schema.rb +3729 -647
  43. data/lib/rdf/vocab/sioc.rb +224 -89
  44. data/lib/rdf/vocab/skos.rb +141 -33
  45. data/lib/rdf/vocab/skosxl.rb +43 -0
  46. data/lib/rdf/vocab/v.rb +154 -0
  47. data/lib/rdf/vocab/vcard.rb +337 -0
  48. data/lib/rdf/vocab/void.rb +142 -0
  49. data/lib/rdf/vocab/wdrs.rb +129 -0
  50. data/lib/rdf/vocab/wot.rb +52 -18
  51. data/lib/rdf/vocab/xhtml.rb +3 -6
  52. data/lib/rdf/vocab/xhv.rb +239 -0
  53. data/lib/rdf/writer.rb +3 -3
  54. metadata +81 -14
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YzQwOTc4Mjk1Y2NmOWMzODIzZjFiNTdhNzYyZWUxOTYwOGFjNTdiMw==
5
- data.tar.gz: !binary |-
6
- M2NiZTBiYzljOTBiNDkzMmMzODI5NWJjZGFiNmViYzkxNzNhNjZjNg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NmU4YjMwMzUxMmNjZTViYWNjZTQ2ZjU1MzdjZWRmYzY1ZmQ2OTUyYzU0N2Zm
10
- YzYzYmY5Y2FkMmY3MjVjNzUyZjZhOTc2MWUyOWI4NTgwN2Q3MzA4ZjJjNTk0
11
- MmUzOTNhNGU3ZTY3NjI4NzQ2NTllMzk1YjliZjljNzA4ZDQzM2I=
12
- data.tar.gz: !binary |-
13
- MGY0NzJjZTJmM2M0YjQ1ZTRmM2UyYTBiM2RmYjBlZWNmMzZiZjE5ZDkxYWVm
14
- NzMxZTE4MDUxYWZhYTc3MDhkODQ3NTY3YzNiNTZkNzQ3ZWVjODFkYzVkMDAz
15
- YjA2ZjkyOTU5YjI1NzlhY2U3OGYzZTU2YmUzMDhiM2ExZmVmMjI=
2
+ SHA1:
3
+ metadata.gz: 636560fdd9893b6be15ec6aa259dde6b2af2c86e
4
+ data.tar.gz: af38349d48ebb7fd97aa7b20942a2dbb380b3b80
5
+ SHA512:
6
+ metadata.gz: 36b838c62356a7d6d7d31efb4246e1d24e5ee277f79f41f94ed5f908b64e310312387e711e7f14b7b4cfdce79c3f135b164c1f8c4d057a505c320e6799fda7be
7
+ data.tar.gz: 19318c68a807d1f9f3e6d9c3857c48a40ca99e51124d308b0604cdecf147fd5c37e65751845d16e491ca5f0965857881704f3faf690666ed800e43aa1218fad4
data/README CHANGED
@@ -38,36 +38,26 @@ This version of RDF.rb is fully compatible with [RDF 1.1][], but it creates some
38
38
  marginal incompatibilities with [RDF 1.0][], as implemented in versions prior to
39
39
  the 1.1 release of RDF.rb:
40
40
 
41
- * Introduces {RDF::IRI}, as a synonym for {RDF::URI} either {RDF::IRI} or {RDF::URI} can be used interchangeably.
42
- Versions of RDF.rb prior to the 1.1 release were already compatible with IRIs.
43
- Internationalized Resource Identifiers (see [RFC3987][]) are a super-set of URIs (see [RFC3986][])
44
- which allow for characters other than standard US-ASCII.
45
- * {RDF::List} no longer emits a `rdf:List` type. However, it will now recognize
46
- any subjects that are {RDF::Node} instances as being list elements, as long
47
- as they have both `rdf:first` and `rdf:rest` predicates.
48
- * {RDF::Graph} adding a `context` to a graph may only be done when the underlying
49
- storage model supports contexts (the default {RDF::Repository} does).
50
- The notion of `context` in RDF.rb is treated equivalently to [Named
51
- Graphs](http://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) within an RDF
52
- Dataset, and graphs on their own are not named.
53
- * {RDF::Graph}, {RDF::Statement} and {RDF::List} now include {RDF::Value}, and not {RDF::Resource}.
54
- Made it clear that using {RDF::Graph} does not mean that it may be used within an
55
- {RDF::Statement}, for this see {RDF::Term}.
56
- * {RDF::Dataset} is introduced as a class alias of {RDF::Repository}.
57
- This allows closer alignment to the RDF concept
58
- of [Dataset](http://www.w3.org/TR/rdf11-concepts/#dfn-dataset).
59
- * The `context` (or `name`) of a named graph within a Dataset or Repository may be
60
- either an {RDF::IRI} or {RDF::Node}. Implementations of repositories may restrict
61
- this to being only {RDF::IRI}.
62
- * There are substantial and somewhat incompatible changes to {RDF::Literal}. In [RDF 1.1][],
63
- all literals are typed, including plain literals and language tagged literals.
64
- Internally, plain literals are given the `xsd:string` datatype and language tagged
65
- literals are given the `rdf:langString` datatype. Creating a plain literal, without
66
- a datatype or language, will automatically provide the `xsd:string` datatype; similar
67
- for language tagged literals. Note that most serialization formats will remove this
68
- datatype. Code which depends on a literal having the `xsd:string` datatype being different
69
- from a plain literal (formally, without a datatype) may break. However note that the
70
- `#has\_datatype?` will continue to return `false` for plain or language-tagged literals.
41
+ * Introduces {RDF::IRI}, as a synonym for {RDF::URI} either {RDF::IRI} or {RDF::URI} can be used interchangeably. Versions of RDF.rb prior to the 1.1 release were already compatible with IRIs. Internationalized Resource Identifiers (see [RFC3987][]) are a super-set of URIs (see [RFC3986][]) which allow for characters other than standard US-ASCII.
42
+ * {RDF::URI} no longer uses the `Addressable` gem. As URIs typically don't need to be parsed, this provides a substantial performance improvement when enumerating or querying graphs and repositories.
43
+ * {RDF::List} no longer emits a `rdf:List` type. However, it will now recognize any subjects that are {RDF::Node} instances as being list elements, as long as they have both `rdf:first` and `rdf:rest` predicates.
44
+ * {RDF::Graph} adding a `context` to a graph may only be done when the underlying storage model supports contexts (the default {RDF::Repository} does). The notion of `context` in RDF.rb is treated equivalently to [Named Graphs](http://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) within an RDF Dataset, and graphs on their own are not named.
45
+ * {RDF::Graph}, {RDF::Statement} and {RDF::List} now include {RDF::Value}, and not {RDF::Resource}. Made it clear that using {RDF::Graph} does not mean that it may be used within an {RDF::Statement}, for this see {RDF::Term}.
46
+ * {RDF::Statement} now is stricter about checking that all elements are valid when validating.
47
+ * {RDF::NTriples::Writer} and {RDF::NQuads::Writer} now default to validate output, only allowing valid statements to be emitted. This may disabled by setting the `:validate` option to `false`.
48
+ * {RDF::Dataset} is introduced as a class alias of {RDF::Repository}. This allows closer alignment to the RDF concept of [Dataset](http://www.w3.org/TR/rdf11-concepts/#dfn-dataset).
49
+ * The `context` (or `name`) of a named graph within a Dataset or Repository may be either an {RDF::IRI} or {RDF::Node}. Implementations of repositories may restrict this to being only {RDF::IRI}.
50
+ * There are substantial and somewhat incompatible changes to {RDF::Literal}. In [RDF 1.1][], all literals are typed, including plain literals and language tagged literals. Internally, plain literals are given the `xsd:string` datatype and language tagged literals are given the `rdf:langString` datatype. Creating a plain literal, without a datatype or language, will automatically provide the `xsd:string` datatype; similar for language tagged literals. Note that most serialization formats will remove this datatype. Code which depends on a literal having the `xsd:string` datatype being different from a plain literal (formally, without a datatype) may break. However note that the `#has\_datatype?` will continue to return `false` for plain or language-tagged literals.
51
+ * {RDF::Query#execute} now accepts a block and returns {RDF::Query::Solutions}. This allows `enumerable.query(query)` to behave like `query.execute(enumerable)` and either return an enumerable or yield each solution.
52
+ * {RDF::Queryable#query} now returns {RDF::Query::Solutions} instead of an Enumerator if it's argument is an {RDF::Query}.
53
+ * {RDF::Util::File.open\_file} now performs redirects and manages `base_uri` based on W3C recommendations:
54
+ * `base_uri` is set to the original URI if a status 303 is provided, otherwise any other redirect will set `base_uri` to the redirected location.
55
+ * `base_uri` is set to the content of the `Location` header if status is _success_.
56
+ * Additionally, {RDF::Util::File.open\_file} sets the result encoding from `charset` if provided, defaulting to `UTF-8`. Other access methods include `last_modified` and `content_type`,
57
+ * {RDF::StrictVocabulary} added with an easy way to keep vocabulary definitions up to date based on their OWL or RDFS definitions. Most vocabularies are now StrictVocabularies meaning that an attempt to resolve a particular term in that vocabulary will error if the term is not defined in the vocabulary.
58
+ * New vocabulary definitions have been added for [ICal](http://www.w3.org/2002/12/cal/icaltzd#), [Media Annotations (MA)](http://www.w3.org/ns/ma-ont#), [Facebook OpenGraph (OG)](http://ogp.me/ns#), [PROV](http://www.w3.org/ns/prov#), [SKOS-XL (SKOSXL)](http://www.w3.org/2008/05/skos-xl#), [Data Vocabulary (V)](http://rdf.data-vocabulary.org/), [VCard](http://www.w3.org/2006/vcard/ns#), [VOID](http://rdfs.org/ns/void#http://rdfs.org/ns/void#), [Powder-S (WDRS)](http://www.w3.org/2007/05/powder-s#), and [XHV](http://www.w3.org/1999/xhtml/vocab#).
59
+
60
+ Notably, {RDF::Queryable#query} and {RDF::Query#execute} are now completely symmetric; this allows an implementation of {RDF::Queryable} to optimize queries using implementation-specific logic, allowing for substantial performance improvements when executing BGP queries.
71
61
 
72
62
  ## Tutorials
73
63
 
@@ -188,10 +178,18 @@ Note that no prefixes are loaded automatically, however they can be provided as
188
178
  }
189
179
  })
190
180
 
191
- query.execute(graph).each do |solution|
181
+ query.execute(graph) do |solution|
192
182
  puts "name=#{solution.name} email=#{solution.email}"
193
183
  end
194
184
 
185
+ The same query may also be run from the graph:
186
+
187
+ graph.query(query) do |solution|
188
+ puts "name=#{solution.name} email=#{solution.email}"
189
+ end
190
+
191
+ In general, querying from using the `queryable` instance allows a specific implementation of `queryable` to perform query optimizations specific to the datastore on which it is based.
192
+
195
193
  A separate [SPARQL][SPARQL doc] gem builds on basic BGP support to provide full support for [SPARQL 1.0](http://www.w3.org/TR/rdf-sparql-query/) queries.
196
194
 
197
195
  ### Using pre-defined RDF vocabularies
@@ -373,7 +371,7 @@ follows:
373
371
 
374
372
  * [Arto Bendiken](http://github.com/bendiken) - <http://ar.to/>
375
373
  * [Ben Lavender](http://github.com/bhuga) - <http://bhuga.net/>
376
- * [Gregg Kellogg](http://github.com/gkellogg) - <http://kellogg-assoc.com/>
374
+ * [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
377
375
 
378
376
  ## Contributors
379
377
 
@@ -392,6 +390,8 @@ follows:
392
390
 
393
391
  ## Contributing
394
392
 
393
+ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
394
+
395
395
  * Do your best to adhere to the existing coding conventions and idioms.
396
396
  * Don't use hard tabs, and don't leave trailing whitespace on any line.
397
397
  Before committing, run `git diff --check` to make sure of this.
@@ -419,7 +419,7 @@ see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
419
419
  [YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
420
420
  [PDD]: http://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
421
421
  [Backports]: http://rubygems.org/gems/backports
422
- [JSONLD doc]: http://rubydoc.info/github/gkellogg/json-ld/frames
422
+ [JSONLD doc]: http://rubydoc.info/github/ruby-rdf/json-ld/frames
423
423
  [LinkedData doc]: http://rubydoc.info/github/datagraph/linkeddata/master/frames
424
424
  [Microdata doc]: http://rubydoc.info/github/ruby-rdf/rdf-microdata/frames
425
425
  [N3 doc]: http://rubydoc.info/github/ruby-rdf/rdf-n3/master/frames
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0p4
1
+ 1.1.0
data/lib/rdf.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'enumerator'
2
- require 'open-uri'
3
1
  require 'stringio'
4
2
  require 'bigdecimal'
5
3
  require 'date'
@@ -55,6 +53,7 @@ module RDF
55
53
 
56
54
  # RDF vocabularies
57
55
  autoload :Vocabulary, 'rdf/vocab'
56
+ autoload :StrictVocabulary, 'rdf/vocab'
58
57
  VOCABS = Dir.glob(File.join(File.dirname(__FILE__), 'rdf', 'vocab', '*.rb')).map { |f| File.basename(f)[0...-(File.extname(f).size)].to_sym } rescue []
59
58
  VOCABS.each { |v| autoload v.to_s.upcase.to_sym, "rdf/vocab/#{v}" unless v == :rdf }
60
59
 
@@ -116,12 +115,60 @@ module RDF
116
115
  end
117
116
 
118
117
  ##
119
- # Alias for `RDF::Statement.new`.
118
+ # @overload List()
119
+ # @return [RDF::URI] returns the IRI for `rdf:List`
120
120
  #
121
- # @param (see RDF::Statement#initialize)
122
- # @return [RDF::Statement]
123
- def self.Statement(*args, &block)
124
- Statement.new(*args, &block)
121
+ # @overload List(*args)
122
+ # @param (see RDF::List#[])
123
+ # @return [RDF::List]
124
+ #
125
+ # @overload List(array)
126
+ # @param [Array] array
127
+ # @return [RDF::List]
128
+ #
129
+ # @overload List(list)
130
+ # @param [RDF::List] list
131
+ # @return [RDF::List] returns itself
132
+ def self.List(*args)
133
+ case
134
+ when args.empty?
135
+ RDF[:List]
136
+ when args.length == 1 && args.first.is_a?(RDF::List)
137
+ args.first
138
+ when args.length == 1 && args.first.is_a?(Array)
139
+ List[*args.first]
140
+ else
141
+ List[*args]
142
+ end
143
+ end
144
+
145
+ ##
146
+ # @overload Statement()
147
+ # @return [RDF::URI] returns the IRI for `rdf:Statement`
148
+ #
149
+ # @overload Statement(options = {})
150
+ # @param [Hash{Symbol => Object}] options
151
+ # @option options [RDF::Resource] :subject (nil)
152
+ # @option options [RDF::URI] :predicate (nil)
153
+ # @option options [RDF::Term] :object (nil)
154
+ # @option options [RDF::Resource] :context (nil)
155
+ # Note, in RDF 1.1, a context MUST be an IRI.
156
+ # @return [RDF::Statement]
157
+ #
158
+ # @overload Statement(subject, predicate, object, options = {})
159
+ # @param [RDF::Resource] subject
160
+ # @param [RDF::URI] predicate
161
+ # @param [RDF::Term] object
162
+ # @param [Hash{Symbol => Object}] options
163
+ # @option options [RDF::Resource] :context (nil)
164
+ # @return [RDF::Statement]
165
+ #
166
+ def self.Statement(*args)
167
+ if args.empty?
168
+ RDF[:Statement]
169
+ else
170
+ Statement.new(*args)
171
+ end
125
172
  end
126
173
 
127
174
  ##
@@ -134,9 +181,12 @@ module RDF
134
181
  end
135
182
 
136
183
  ##
137
- # @return [URI]
138
- def self.value
139
- self[:value]
184
+ # Alias for `RDF::StrictVocabulary.create`.
185
+ #
186
+ # @param (see RDF::Vocabulary#initialize)
187
+ # @return [Class]
188
+ def self.StrictVocabulary(prefix)
189
+ StrictVocabulary.create(prefix)
140
190
  end
141
191
 
142
192
  ##
@@ -177,14 +227,12 @@ module RDF
177
227
  first
178
228
  HTML
179
229
  langString
180
- List
181
230
  nil
182
231
  object
183
232
  predicate
184
233
  Property
185
234
  rest
186
235
  Seq
187
- Statement
188
236
  subject
189
237
  type
190
238
  value
data/lib/rdf/cli.rb CHANGED
@@ -6,7 +6,13 @@ begin
6
6
  gem 'linkeddata'
7
7
  require 'linkeddata'
8
8
  rescue LoadError
9
- # Silently load without linkeddata
9
+ # Silently load without linkeddata, but try some others
10
+ %w(rdfa rdfxml turtle).each do |ser|
11
+ begin
12
+ require "rdf/#{ser}"
13
+ rescue LoadError
14
+ end
15
+ end
10
16
  end
11
17
 
12
18
  class OptionParser
@@ -0,0 +1,240 @@
1
+ require 'rdf'
2
+ require 'linkeddata'
3
+ require 'optparse'
4
+
5
+ module RDF
6
+ # Utility class to load RDF vocabularies from files or their canonical
7
+ # definitions and emit either a class file for RDF::StrictVocabulary,
8
+ # RDF::Vocabulary or the raw RDF vocabulary
9
+ class VocabularyLoader
10
+ def initialize(class_name = nil)
11
+ @class_name = class_name
12
+ @output = $stdout
13
+ @output_class_file = true
14
+ @prefix = nil
15
+ @url = nil
16
+ @strict = true
17
+ @extra = []
18
+ end
19
+ attr_accessor :class_name, :output, :output_class_file
20
+ attr_reader :prefix, :source
21
+
22
+ # Set the prefix for the loaded RDF file - by default, sets the source as
23
+ # well
24
+ def prefix=(uri)
25
+ @prefix = uri
26
+ @source ||= uri
27
+ end
28
+
29
+ # Set the source for the loaded RDF - by default, sets the prefix as well
30
+ def source=(uri)
31
+ @source = uri
32
+ @prefix ||= uri
33
+ end
34
+
35
+ # Set output
36
+ def output=(out)
37
+ @output = out
38
+ end
39
+
40
+ # Extra properties to define
41
+ def extra=(extra)
42
+ @extra = extra
43
+ end
44
+
45
+ # Use StrictVocabulary or Vocabulary
46
+ def strict=(strict)
47
+ @strict = strict
48
+ end
49
+
50
+ # Parses arguments, for use in a command line tool
51
+ def parse_options(argv)
52
+ opti = OptionParser.new
53
+ opti.banner = "Usage: #{File.basename($0)} [options] [prefix [outfile]]\nFetch an RDFS file and produce an RDF::StrictVocabulary with it.\n\n"
54
+
55
+ opti.on("--prefix URI", "The prefix for the fetched RDF vocabulary") do |uri|
56
+ self.prefix = uri
57
+ end
58
+
59
+ opti.on("--source SOURCE", "The source URI or file for the vocabulary") do |uri|
60
+ self.source = uri
61
+ end
62
+
63
+ opti.on("--class-name NAME", "The class name for the output StrictVocabulary subclass") do |name|
64
+ self.class_name = name
65
+ end
66
+
67
+ opti.on("--raw", "Don't output an output file - just the RDF") do
68
+ @output_class_file = false
69
+ end
70
+
71
+ opti.on_tail("--help", "This help text") do
72
+ $stdout.puts opti
73
+ exit 1
74
+ end
75
+
76
+ others = opti.parse(argv)
77
+
78
+ if @class_name.nil? and @output_class_file
79
+ raise "Class name (--class-name) is required!"
80
+ end
81
+
82
+ if prefix.nil?
83
+ self.prefix, outfile, extra = *others
84
+ else
85
+ outfile, extra = *others
86
+ end
87
+
88
+ unless outfile.nil?
89
+ @output = File.open(outfile, "w")
90
+ end
91
+
92
+ unless extra.nil?
93
+ $stderr.puts "Too many arguments!"
94
+ $stderr.puts opti
95
+ exit 1
96
+ end
97
+ end
98
+
99
+ # Loads the graph
100
+ def graph
101
+ @graph ||= RDF::Graph.load(source)
102
+ end
103
+
104
+ # Parse command line arguments and run the load-and-emit process
105
+ def go(argv)
106
+ parse_options(argv)
107
+ run
108
+
109
+ if @output != $stdout
110
+ @output.close
111
+ end
112
+ end
113
+
114
+ # @private
115
+ def from_solution(solution)
116
+ prefix_match = %r{\A#{@prefix}(.*)}
117
+ return if !solution.resource.uri? || (match = prefix_match.match(solution.resource.to_s)).nil?
118
+ name = match[1]
119
+
120
+ # If there's a label or comment, the must either have no language, or be en
121
+ label = solution[:label]
122
+ comment = solution[:comment]
123
+
124
+ return if label && label.has_language? && !label.language.to_s.start_with?("en")
125
+ return if comment && comment.has_language? && !comment.language.to_s.start_with?("en")
126
+ label = label.to_s.
127
+ encode(Encoding::US_ASCII). # also force exception if invalid
128
+ strip.
129
+ gsub(/\s+/m, ' ')
130
+ comment = comment.to_s.
131
+ encode(Encoding::US_ASCII). # also force exception if invalid
132
+ strip.
133
+ gsub(/\s+/m, ' ').
134
+ gsub(/([\(\)])/, '\\\\\\1')
135
+
136
+ @output.write " property #{name.to_sym.inspect}"
137
+ @output.write ", :label => '#{label}'" unless label.empty?
138
+ @output.write ", :comment =>\n %(#{comment.scan(/\S.{0,60}\S(?=\s|$)|\S+/).join("\n ")})" unless comment.empty?
139
+ @output.puts
140
+ rescue Encoding::UndefinedConversionError
141
+ end
142
+
143
+ # Actually executes the load-and-emit process - useful when using this
144
+ # class outside of a command line - instantiate, set attributes manually,
145
+ # then call #run
146
+ def run
147
+ @output.print %(# This file generated automatically using vocab-fetch from #{source}
148
+ require 'rdf'
149
+ module RDF
150
+ class #{class_name} < #{"Strict" if @strict}Vocabulary("#{prefix}")
151
+ ).gsub(/^ /, '') if @output_class_file
152
+
153
+ classes = RDF::Query.new do
154
+ pattern [:resource, RDF.type, RDFS.Class]
155
+ pattern [:resource, RDFS.label, :label], :optional => true
156
+ pattern [:resource, RDFS.comment, :comment], :optional => true
157
+ end
158
+
159
+ owl_classes = RDF::Query.new do
160
+ pattern [:resource, RDF.type, OWL.Class]
161
+ pattern [:resource, RDFS.label, :label], :optional => true
162
+ pattern [:resource, RDFS.comment, :comment], :optional => true
163
+ end
164
+
165
+ class_defs = graph.query(classes).to_a + graph.query(owl_classes).to_a
166
+ unless class_defs.empty?
167
+ @output.puts "\n # Class definitions"
168
+ class_defs.sort_by {|s| (s[:label] || s[:resource]).to_s}.each do |klass|
169
+ from_solution(klass)
170
+ end
171
+ end
172
+
173
+ properties = RDF::Query.new do
174
+ pattern [:resource, RDF.type, RDF.Property]
175
+ pattern [:resource, RDFS.label, :label], :optional => true
176
+ pattern [:resource, RDFS.comment, :comment], :optional => true
177
+ end
178
+
179
+ dt_properties = RDF::Query.new do
180
+ pattern [:resource, RDF.type, OWL.DatatypeProperty]
181
+ pattern [:resource, RDFS.label, :label], :optional => true
182
+ pattern [:resource, RDFS.comment, :comment], :optional => true
183
+ end
184
+
185
+ obj_properties = RDF::Query.new do
186
+ pattern [:resource, RDF.type, OWL.ObjectProperty]
187
+ pattern [:resource, RDFS.label, :label], :optional => true
188
+ pattern [:resource, RDFS.comment, :comment], :optional => true
189
+ end
190
+
191
+ ann_properties = RDF::Query.new do
192
+ pattern [:resource, RDF.type, OWL.AnnotationProperty]
193
+ pattern [:resource, RDFS.label, :label], :optional => true
194
+ pattern [:resource, RDFS.comment, :comment], :optional => true
195
+ end
196
+
197
+ ont_properties = RDF::Query.new do
198
+ pattern [:resource, RDF.type, OWL.OntologyProperty]
199
+ pattern [:resource, RDFS.label, :label], :optional => true
200
+ pattern [:resource, RDFS.comment, :comment], :optional => true
201
+ end
202
+ prop_defs = graph.query(properties).to_a.sort_by {|s| (s[:label] || s[:resource]).to_s}
203
+ prop_defs += graph.query(dt_properties).to_a.sort_by {|s| (s[:label] || s[:resource]).to_s}
204
+ prop_defs += graph.query(obj_properties).to_a.sort_by {|s| (s[:label] || s[:resource]).to_s}
205
+ prop_defs += graph.query(ann_properties).to_a.sort_by {|s| (s[:label] || s[:resource]).to_s}
206
+ prop_defs += graph.query(ont_properties).to_a.sort_by {|s| (s[:label] || s[:resource]).to_s}
207
+ unless prop_defs.empty?
208
+ @output.puts "\n # Property definitions"
209
+ prop_defs.each do |prop|
210
+ from_solution(prop)
211
+ end
212
+ end
213
+
214
+
215
+ datatypes = RDF::Query.new do
216
+ pattern [:resource, RDF.type, RDFS.Datatype]
217
+ pattern [:resource, RDFS.label, :label], :optional => true
218
+ pattern [:resource, RDFS.comment, :comment], :optional => true
219
+ end
220
+
221
+ dt_defs = graph.query(datatypes).to_a.sort_by {|s| (s[:label] || s[:resource]).to_s}
222
+ unless dt_defs.empty?
223
+ @output.puts "\n # Datatype definitions"
224
+ dt_defs.each do |dt|
225
+ from_solution(dt)
226
+ end
227
+ end
228
+
229
+ unless @extra.empty?
230
+ @output.puts "\n # Extra definitions"
231
+ @extra.each do |extra|
232
+ @output.puts " property #{extra.to_sym.inspect}"
233
+ end
234
+ end
235
+
236
+ # Query the vocabulary to extract property and class definitions
237
+ @output.puts " end\nend" if @output_class_file
238
+ end
239
+ end
240
+ end