openlogic-rdf 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +3 -0
- data/CREDITS +9 -0
- data/README +361 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/bin/rdf +18 -0
- data/etc/doap.nt +62 -0
- data/lib/df.rb +1 -0
- data/lib/rdf/cli.rb +200 -0
- data/lib/rdf/format.rb +383 -0
- data/lib/rdf/mixin/countable.rb +39 -0
- data/lib/rdf/mixin/durable.rb +31 -0
- data/lib/rdf/mixin/enumerable.rb +637 -0
- data/lib/rdf/mixin/indexable.rb +26 -0
- data/lib/rdf/mixin/inferable.rb +5 -0
- data/lib/rdf/mixin/mutable.rb +191 -0
- data/lib/rdf/mixin/queryable.rb +265 -0
- data/lib/rdf/mixin/readable.rb +15 -0
- data/lib/rdf/mixin/type_check.rb +21 -0
- data/lib/rdf/mixin/writable.rb +152 -0
- data/lib/rdf/model/graph.rb +263 -0
- data/lib/rdf/model/list.rb +731 -0
- data/lib/rdf/model/literal/boolean.rb +121 -0
- data/lib/rdf/model/literal/date.rb +73 -0
- data/lib/rdf/model/literal/datetime.rb +72 -0
- data/lib/rdf/model/literal/decimal.rb +86 -0
- data/lib/rdf/model/literal/double.rb +189 -0
- data/lib/rdf/model/literal/integer.rb +126 -0
- data/lib/rdf/model/literal/numeric.rb +184 -0
- data/lib/rdf/model/literal/time.rb +87 -0
- data/lib/rdf/model/literal/token.rb +47 -0
- data/lib/rdf/model/literal/xml.rb +39 -0
- data/lib/rdf/model/literal.rb +373 -0
- data/lib/rdf/model/node.rb +156 -0
- data/lib/rdf/model/resource.rb +28 -0
- data/lib/rdf/model/statement.rb +296 -0
- data/lib/rdf/model/term.rb +77 -0
- data/lib/rdf/model/uri.rb +570 -0
- data/lib/rdf/model/value.rb +133 -0
- data/lib/rdf/nquads.rb +152 -0
- data/lib/rdf/ntriples/format.rb +48 -0
- data/lib/rdf/ntriples/reader.rb +239 -0
- data/lib/rdf/ntriples/writer.rb +219 -0
- data/lib/rdf/ntriples.rb +104 -0
- data/lib/rdf/query/pattern.rb +329 -0
- data/lib/rdf/query/solution.rb +252 -0
- data/lib/rdf/query/solutions.rb +237 -0
- data/lib/rdf/query/variable.rb +221 -0
- data/lib/rdf/query.rb +404 -0
- data/lib/rdf/reader.rb +511 -0
- data/lib/rdf/repository.rb +389 -0
- data/lib/rdf/transaction.rb +161 -0
- data/lib/rdf/util/aliasing.rb +63 -0
- data/lib/rdf/util/cache.rb +139 -0
- data/lib/rdf/util/file.rb +38 -0
- data/lib/rdf/util/uuid.rb +36 -0
- data/lib/rdf/util.rb +6 -0
- data/lib/rdf/version.rb +19 -0
- data/lib/rdf/vocab/cc.rb +18 -0
- data/lib/rdf/vocab/cert.rb +13 -0
- data/lib/rdf/vocab/dc.rb +63 -0
- data/lib/rdf/vocab/dc11.rb +23 -0
- data/lib/rdf/vocab/doap.rb +45 -0
- data/lib/rdf/vocab/exif.rb +168 -0
- data/lib/rdf/vocab/foaf.rb +69 -0
- data/lib/rdf/vocab/geo.rb +13 -0
- data/lib/rdf/vocab/http.rb +26 -0
- data/lib/rdf/vocab/owl.rb +59 -0
- data/lib/rdf/vocab/rdfs.rb +17 -0
- data/lib/rdf/vocab/rsa.rb +12 -0
- data/lib/rdf/vocab/rss.rb +14 -0
- data/lib/rdf/vocab/sioc.rb +93 -0
- data/lib/rdf/vocab/skos.rb +36 -0
- data/lib/rdf/vocab/wot.rb +21 -0
- data/lib/rdf/vocab/xhtml.rb +9 -0
- data/lib/rdf/vocab/xsd.rb +58 -0
- data/lib/rdf/vocab.rb +215 -0
- data/lib/rdf/writer.rb +475 -0
- data/lib/rdf.rb +192 -0
- metadata +173 -0
data/lib/rdf/cli.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
require 'rdf/ntriples'
|
3
|
+
require 'rdf/nquads'
|
4
|
+
require 'optparse'
|
5
|
+
begin
|
6
|
+
gem 'linkeddata'
|
7
|
+
require 'linkeddata'
|
8
|
+
rescue LoadError
|
9
|
+
# Silently load without linkeddata
|
10
|
+
end
|
11
|
+
|
12
|
+
class OptionParser
|
13
|
+
def options; @options || {}; end
|
14
|
+
def options=(value); @options = value; end
|
15
|
+
end
|
16
|
+
|
17
|
+
module RDF
|
18
|
+
class CLI
|
19
|
+
|
20
|
+
COMMANDS = {
|
21
|
+
"count" => lambda do |argv, opts|
|
22
|
+
start = Time.new
|
23
|
+
count = 0
|
24
|
+
self.parse(argv, opts) do |reader|
|
25
|
+
reader.each_statement do |statement|
|
26
|
+
count += 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
secs = Time.new - start
|
30
|
+
$stdout.puts "Parsed #{count} statements with #{@readers.join(', ')} in #{secs} seconds @ #{count/secs} statements/second."
|
31
|
+
end,
|
32
|
+
"lenghts" => lambda do |argv, opts|
|
33
|
+
self.parse(argv, opts) do |reader|
|
34
|
+
reader.each_statement do |statement|
|
35
|
+
$stdout.puts statement.to_s.size
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end,
|
39
|
+
"objects" => lambda do |argv, opts|
|
40
|
+
self.parse(argv, opts) do |reader|
|
41
|
+
reader.each_statement do |statement|
|
42
|
+
$stdout.puts statement.object.to_ntriples
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end,
|
46
|
+
"predicates" => lambda do |argv, opts|
|
47
|
+
self.parse(argv, opts) do |reader|
|
48
|
+
reader.each_statement do |statement|
|
49
|
+
$stdout.puts statement.predicate.to_ntriples
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end,
|
53
|
+
"serialize" => lambda do |argv, opts|
|
54
|
+
writer_class = RDF::Writer.for(opts[:output_format]) || RDF::NTriples::Writer
|
55
|
+
out = opts[:output] || $stdout
|
56
|
+
opts = opts.merge(:prefixes => {})
|
57
|
+
writer_opts = opts.merge(:standard_prefixes => true)
|
58
|
+
self.parse(argv, opts) do |reader|
|
59
|
+
writer_class.new(out, writer_opts) do |writer|
|
60
|
+
writer << reader
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end,
|
64
|
+
"subjects" => lambda do |argv, opts|
|
65
|
+
self.parse(argv, opts) do |reader|
|
66
|
+
reader.each_statement do |statement|
|
67
|
+
$stdout.puts statement.subject.to_ntriples
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
}
|
72
|
+
|
73
|
+
##
|
74
|
+
# @return [String]
|
75
|
+
def self.basename() File.basename($0) end
|
76
|
+
|
77
|
+
##
|
78
|
+
# @yield [options]
|
79
|
+
# @yieldparam [OptionParser]
|
80
|
+
# @return [OptionParser]
|
81
|
+
def self.options(&block)
|
82
|
+
options = OptionParser.new
|
83
|
+
opts = options.options = {
|
84
|
+
:base_uri => nil,
|
85
|
+
:canonicalize => false,
|
86
|
+
:debug => false,
|
87
|
+
:evaluate => nil,
|
88
|
+
:format => nil,
|
89
|
+
:output => $stdout,
|
90
|
+
:output_format => :ntriples,
|
91
|
+
:validate => false,
|
92
|
+
}
|
93
|
+
|
94
|
+
# Command-specific options
|
95
|
+
if block_given?
|
96
|
+
case block.arity
|
97
|
+
when 1 then block.call(options)
|
98
|
+
else options.instance_eval(&block)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
options.banner ||= "Usage: #{self.basename} [options] command [args...]"
|
102
|
+
|
103
|
+
options.on('--canonicalize', 'Canonicalize input.') do
|
104
|
+
opts[:canonicalize] = true
|
105
|
+
end
|
106
|
+
|
107
|
+
options.on('-d', '--debug', 'Enable debug output for troubleshooting.') do
|
108
|
+
opts[:debug] = $DEBUG = true
|
109
|
+
end
|
110
|
+
|
111
|
+
options.on("-e", "--evaluate STRING", "Evaluate argument as RDF input, if no files are specified") do |arg|
|
112
|
+
opts[:evaluate] = arg
|
113
|
+
end
|
114
|
+
|
115
|
+
options.on("--input-format FORMAT", "Format of input file, uses heuristic if not specified") do |arg|
|
116
|
+
opts[:format] = arg.downcase.to_sym
|
117
|
+
end
|
118
|
+
|
119
|
+
options.on("-o", "--output FILE", "File to write output, defaults to STDOUT") do |arg|
|
120
|
+
opts[:output] = File.open(arg, "w")
|
121
|
+
end
|
122
|
+
|
123
|
+
options.on("--output-format FORMAT", "Format of output file, defaults to NTriples") do |arg|
|
124
|
+
opts[:output_format] = arg.downcase.to_sym
|
125
|
+
end
|
126
|
+
|
127
|
+
options.on('--uri URI', 'Base URI of input file, defaults to the filename.') do |arg|
|
128
|
+
opts[:base_uri] = arg
|
129
|
+
end
|
130
|
+
|
131
|
+
options.on('--validate', 'Validate input file.') do
|
132
|
+
opts[:validate] = true
|
133
|
+
end
|
134
|
+
|
135
|
+
options.on_tail("-h", "--help", "Show this message") do
|
136
|
+
$stdout.puts options
|
137
|
+
$stdout.puts "Available commands:\n\t#{self.commands.join("\n\t")}"
|
138
|
+
exit
|
139
|
+
end
|
140
|
+
|
141
|
+
begin
|
142
|
+
options.parse!
|
143
|
+
rescue OptionParser::InvalidOption => e
|
144
|
+
abort e
|
145
|
+
end
|
146
|
+
|
147
|
+
options
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# @param [String] command
|
152
|
+
# @param [Array<String>] args
|
153
|
+
# @return [Boolean]
|
154
|
+
def self.exec_command(command, args, options = {})
|
155
|
+
unless COMMANDS.has_key?(command)
|
156
|
+
abort "#{File.basename($0)}: unknown command `#{command}'"
|
157
|
+
end
|
158
|
+
|
159
|
+
COMMANDS[command].call(args, options)
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# @return [Array<String>] list of executable commands
|
164
|
+
def self.commands
|
165
|
+
COMMANDS.keys
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Parse each file, STDIN or specified string in options[:evaluate] yielding
|
170
|
+
# a reader
|
171
|
+
#
|
172
|
+
# @param [Array<String>] files
|
173
|
+
# @yield [reader]
|
174
|
+
# @yieldparam [RDF::Reader]
|
175
|
+
# @return [nil]
|
176
|
+
def self.parse(files, options = {}, &block)
|
177
|
+
if files.empty?
|
178
|
+
# If files are empty, either use options[:execute]
|
179
|
+
input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
|
180
|
+
RDF::Reader.for(options[:format] || :ntriples).new(input, options) do |reader|
|
181
|
+
yield(reader)
|
182
|
+
end
|
183
|
+
else
|
184
|
+
files.each do |file|
|
185
|
+
RDF::Reader.open(file, options) do |reader|
|
186
|
+
(@readers ||= []) << reader.class.to_s
|
187
|
+
yield(reader)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# @param [String] msg
|
195
|
+
# @return [void]
|
196
|
+
def self.abort(msg)
|
197
|
+
Kernel.abort "#{basename}: #{msg}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
data/lib/rdf/format.rb
ADDED
@@ -0,0 +1,383 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# The base class for RDF serialization formats.
|
4
|
+
#
|
5
|
+
# @example Loading an RDF serialization format implementation
|
6
|
+
# require 'rdf/ntriples'
|
7
|
+
#
|
8
|
+
# @example Iterating over known RDF serialization formats
|
9
|
+
# RDF::Format.each { |klass| puts klass.name }
|
10
|
+
#
|
11
|
+
# @example Getting a serialization format class
|
12
|
+
# RDF::Format.for(:ntriples) #=> RDF::NTriples::Format
|
13
|
+
# RDF::Format.for("etc/doap.nt")
|
14
|
+
# RDF::Format.for(:file_name => "etc/doap.nt")
|
15
|
+
# RDF::Format.for(:file_extension => "nt")
|
16
|
+
# RDF::Format.for(:content_type => "text/plain")
|
17
|
+
#
|
18
|
+
# @example Obtaining serialization format MIME types
|
19
|
+
# RDF::Format.content_types #=> {"text/plain" => [RDF::NTriples::Format]}
|
20
|
+
#
|
21
|
+
# @example Obtaining serialization format file extension mappings
|
22
|
+
# RDF::Format.file_extensions #=> {:nt => [RDF::NTriples::Format]}
|
23
|
+
#
|
24
|
+
# @example Defining a new RDF serialization format class
|
25
|
+
# class RDF::NTriples::Format < RDF::Format
|
26
|
+
# content_type 'text/plain', :extension => :nt
|
27
|
+
# content_encoding 'ascii'
|
28
|
+
#
|
29
|
+
# reader RDF::NTriples::Reader
|
30
|
+
# writer RDF::NTriples::Writer
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @example Instantiating an RDF reader or writer class (1)
|
34
|
+
# RDF::Format.for(:ntriples).reader.new($stdin) { |reader| ... }
|
35
|
+
# RDF::Format.for(:ntriples).writer.new($stdout) { |writer| ... }
|
36
|
+
#
|
37
|
+
# @example Instantiating an RDF reader or writer class (2)
|
38
|
+
# RDF::Reader.for(:ntriples).new($stdin) { |reader| ... }
|
39
|
+
# RDF::Writer.for(:ntriples).new($stdout) { |writer| ... }
|
40
|
+
#
|
41
|
+
# @abstract
|
42
|
+
# @see RDF::Reader
|
43
|
+
# @see RDF::Writer
|
44
|
+
# @see http://en.wikipedia.org/wiki/Resource_Description_Framework#Serialization_formats
|
45
|
+
class Format
|
46
|
+
extend ::Enumerable
|
47
|
+
|
48
|
+
##
|
49
|
+
# Enumerates known RDF serialization format classes.
|
50
|
+
#
|
51
|
+
# @yield [klass]
|
52
|
+
# @yieldparam [Class]
|
53
|
+
# @return [Enumerator]
|
54
|
+
def self.each(&block)
|
55
|
+
@@subclasses.each(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Finds an RDF serialization format class based on the given criteria.
|
60
|
+
#
|
61
|
+
# @overload for(format)
|
62
|
+
# Finds an RDF serialization format class based on a symbolic name.
|
63
|
+
#
|
64
|
+
# @param [Symbol] format
|
65
|
+
# @return [Class]
|
66
|
+
#
|
67
|
+
# @overload for(filename)
|
68
|
+
# Finds an RDF serialization format class based on a file name.
|
69
|
+
#
|
70
|
+
# @param [String] filename
|
71
|
+
# @return [Class]
|
72
|
+
#
|
73
|
+
# @overload for(options = {})
|
74
|
+
# Finds an RDF serialization format class based on various options.
|
75
|
+
#
|
76
|
+
# @param [Hash{Symbol => Object}] options
|
77
|
+
# @option options [String, #to_s] :file_name (nil)
|
78
|
+
# @option options [Symbol, #to_sym] :file_extension (nil)
|
79
|
+
# @option options [String, #to_s] :content_type (nil)
|
80
|
+
# Note that content_type will be taken from a URL opened using {RDF::Util::File.open_file}.
|
81
|
+
# @option options [Boolean] :has_reader (false)
|
82
|
+
# Only return a format having a reader.
|
83
|
+
# @option options [Boolean] :has_writer (false)
|
84
|
+
# Only return a format having a writer.
|
85
|
+
# @option options [String] :sample (nil)
|
86
|
+
# A sample of input used for performing format detection.
|
87
|
+
# If we find no formats, or we find more than one, and we have a sample, we can
|
88
|
+
# perform format detection to find a specific format to use, in which case
|
89
|
+
# we pick the first one we find
|
90
|
+
# @return [Class]
|
91
|
+
# @yieldreturn [String] another way to provide a sample, allows lazy for retrieving the sample.
|
92
|
+
#
|
93
|
+
# @return [Class]
|
94
|
+
def self.for(options = {})
|
95
|
+
format = case options
|
96
|
+
when String
|
97
|
+
# Find a format based on the file name
|
98
|
+
self.for(:file_name => options)
|
99
|
+
|
100
|
+
when Hash
|
101
|
+
case
|
102
|
+
# Find a format based on the MIME content type:
|
103
|
+
when mime_type = options[:content_type]
|
104
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
|
105
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
|
106
|
+
mime_type = mime_type.to_s
|
107
|
+
mime_type = mime_type.split(';').first # remove any media type parameters
|
108
|
+
content_types[mime_type]
|
109
|
+
# Find a format based on the file name:
|
110
|
+
when file_name = options[:file_name]
|
111
|
+
self.for(:file_extension => File.extname(file_name.to_s)[1..-1])
|
112
|
+
# Find a format based on the file extension:
|
113
|
+
when file_ext = options[:file_extension]
|
114
|
+
file_extensions[file_ext.to_sym]
|
115
|
+
end
|
116
|
+
|
117
|
+
when Symbol
|
118
|
+
case format = options
|
119
|
+
# Special case, since we want this to work despite autoloading
|
120
|
+
when :ntriples
|
121
|
+
RDF::NTriples::Format
|
122
|
+
# For anything else, find a match based on the full class name
|
123
|
+
else
|
124
|
+
@@subclasses.detect { |klass| klass.to_sym == format }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
if format.is_a?(Array)
|
129
|
+
format = format.select {|f| f.reader} if options[:has_reader]
|
130
|
+
format = format.select {|f| f.writer} if options[:has_writer]
|
131
|
+
|
132
|
+
return format.first if format.uniq.length == 1
|
133
|
+
elsif !format.nil?
|
134
|
+
return format
|
135
|
+
end
|
136
|
+
|
137
|
+
# If we have a sample, use that for format detection
|
138
|
+
if sample = (options[:sample] if options.is_a?(Hash)) || (yield if block_given?)
|
139
|
+
# Given a sample, perform format detection across the appropriate formats, choosing
|
140
|
+
# the first that matches
|
141
|
+
format ||= @@subclasses
|
142
|
+
|
143
|
+
# Return first format that has a positive detection
|
144
|
+
format.detect {|f| f.detect(sample)} || format.first
|
145
|
+
elsif format.is_a?(Array)
|
146
|
+
# Otherwise, just return the first matching format
|
147
|
+
format.first
|
148
|
+
else
|
149
|
+
nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Returns MIME content types for known RDF serialization formats.
|
155
|
+
#
|
156
|
+
# @return [Hash{String => Array<Class>}]
|
157
|
+
def self.content_types
|
158
|
+
@@content_types
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Returns file extensions for known RDF serialization formats.
|
163
|
+
#
|
164
|
+
# @return [Hash{Symbol => Array<Class>}]
|
165
|
+
def self.file_extensions
|
166
|
+
@@file_extensions
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Returns a symbol appropriate to use with RDF::Format.for()
|
171
|
+
# @return [Symbol]
|
172
|
+
def self.to_sym
|
173
|
+
elements = self.to_s.split("::")
|
174
|
+
sym = elements.pop
|
175
|
+
sym = elements.pop if sym == 'Format'
|
176
|
+
sym.downcase.to_s.to_sym
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Retrieves or defines the reader class for this RDF serialization
|
181
|
+
# format.
|
182
|
+
#
|
183
|
+
# @overload reader(klass)
|
184
|
+
# Defines the reader class for this RDF serialization format.
|
185
|
+
#
|
186
|
+
# The class should be a subclass of {RDF::Reader}, or implement the
|
187
|
+
# same interface.
|
188
|
+
#
|
189
|
+
# @param [Class] klass
|
190
|
+
# @return [void]
|
191
|
+
#
|
192
|
+
# @overload reader
|
193
|
+
# Defines the reader class for this RDF serialization format.
|
194
|
+
#
|
195
|
+
# The block should return a subclass of {RDF::Reader}, or a class that
|
196
|
+
# implements the same interface. The block won't be invoked until the
|
197
|
+
# reader class is first needed.
|
198
|
+
#
|
199
|
+
# @yield
|
200
|
+
# @yieldreturn [Class] klass
|
201
|
+
# @return [void]
|
202
|
+
#
|
203
|
+
# @overload reader
|
204
|
+
# Retrieves the reader class for this RDF serialization format.
|
205
|
+
#
|
206
|
+
# @return [Class]
|
207
|
+
#
|
208
|
+
# @return [void]
|
209
|
+
def self.reader(klass = nil, &block)
|
210
|
+
case
|
211
|
+
when klass
|
212
|
+
@@readers[self] = klass
|
213
|
+
when block_given?
|
214
|
+
@@readers[self] = block
|
215
|
+
else
|
216
|
+
klass = @@readers[self]
|
217
|
+
klass = @@readers[self] = klass.call if klass.is_a?(Proc)
|
218
|
+
klass
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# Retrieves or defines the writer class for this RDF serialization
|
224
|
+
# format.
|
225
|
+
#
|
226
|
+
# @overload writer(klass)
|
227
|
+
# Defines the writer class for this RDF serialization format.
|
228
|
+
#
|
229
|
+
# The class should be a subclass of {RDF::Writer}, or implement the
|
230
|
+
# same interface.
|
231
|
+
#
|
232
|
+
# @param [Class] klass
|
233
|
+
# @return [void]
|
234
|
+
#
|
235
|
+
# @overload writer
|
236
|
+
# Defines the writer class for this RDF serialization format.
|
237
|
+
#
|
238
|
+
# The block should return a subclass of {RDF::Writer}, or a class that
|
239
|
+
# implements the same interface. The block won't be invoked until the
|
240
|
+
# writer class is first needed.
|
241
|
+
#
|
242
|
+
# @yield
|
243
|
+
# @yieldreturn [Class] klass
|
244
|
+
# @return [void]
|
245
|
+
#
|
246
|
+
# @overload writer
|
247
|
+
# Retrieves the writer class for this RDF serialization format.
|
248
|
+
#
|
249
|
+
# @return [Class]
|
250
|
+
#
|
251
|
+
# @return [void]
|
252
|
+
def self.writer(klass = nil, &block)
|
253
|
+
case
|
254
|
+
when klass
|
255
|
+
@@writers[self] = klass
|
256
|
+
when block_given?
|
257
|
+
@@writers[self] = block
|
258
|
+
else
|
259
|
+
klass = @@writers[self]
|
260
|
+
klass = @@writers[self] = klass.call if klass.is_a?(Proc)
|
261
|
+
klass
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
##
|
267
|
+
# Use a text sample to detect the format of an input file. Sub-classes implement
|
268
|
+
# a matcher sufficient to detect probably format matches, including disambiguating
|
269
|
+
# between other similar formats.
|
270
|
+
#
|
271
|
+
# Used to determine format class from loaded formats by {RDF::Format.for} when a
|
272
|
+
# match cannot be unambigiously found otherwise.
|
273
|
+
#
|
274
|
+
# @example
|
275
|
+
# RDF::NTriples::Format.detect("<a> <b> <c> .") => true
|
276
|
+
#
|
277
|
+
# @param [String] sample Beginning several bytes (~ 1K) of input.
|
278
|
+
# @return [Boolean]
|
279
|
+
def self.detect(sample)
|
280
|
+
false
|
281
|
+
end
|
282
|
+
|
283
|
+
class << self
|
284
|
+
alias_method :reader_class, :reader
|
285
|
+
alias_method :writer_class, :writer
|
286
|
+
end
|
287
|
+
|
288
|
+
##
|
289
|
+
# Retrieves or defines MIME content types for this RDF serialization format.
|
290
|
+
#
|
291
|
+
# @overload content_type(type, options)
|
292
|
+
# Retrieves or defines the MIME content type for this RDF serialization format.
|
293
|
+
#
|
294
|
+
# Optionally also defines alias MIME content types for this RDF serialization format.
|
295
|
+
#
|
296
|
+
# Optionally also defines a file extension, or a list of file
|
297
|
+
# extensions, that should be mapped to the given MIME type and handled
|
298
|
+
# by this class.
|
299
|
+
#
|
300
|
+
# @param [String] type
|
301
|
+
# @param [Hash{Symbol => Object}] options
|
302
|
+
# @option options [String] :alias (nil)
|
303
|
+
# @option options [Array<String>] :aliases (nil)
|
304
|
+
# @option options [Symbol] :extension (nil)
|
305
|
+
# @option options [Array<Symbol>] :extensions (nil)
|
306
|
+
# @return [void]
|
307
|
+
#
|
308
|
+
# @overload content_type
|
309
|
+
# Retrieves the MIME content types for this RDF serialization format.
|
310
|
+
#
|
311
|
+
# The return is an array where the first element is the cannonical
|
312
|
+
# MIME type for the format and following elements are alias MIME types.
|
313
|
+
#
|
314
|
+
# @return [Array<String>]
|
315
|
+
def self.content_type(type = nil, options = {})
|
316
|
+
if type.nil?
|
317
|
+
[@@content_type[self], @@content_types.map {
|
318
|
+
|ct, cl| (cl.include?(self) && ct != @@content_type[self]) ? ct : nil }].flatten.compact
|
319
|
+
else
|
320
|
+
@@content_type[self] = type
|
321
|
+
(@@content_types[type] ||= []) << self
|
322
|
+
|
323
|
+
if extensions = (options[:extension] || options[:extensions])
|
324
|
+
extensions = [extensions].flatten.map(&:to_sym)
|
325
|
+
extensions.each { |ext| (@@file_extensions[ext] ||= []) << self }
|
326
|
+
end
|
327
|
+
if aliases = (options[:alias] || options[:aliases])
|
328
|
+
aliases = [aliases].flatten.each { |a| (@@content_types[a] ||= []) << self }
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
protected
|
334
|
+
|
335
|
+
##
|
336
|
+
# Defines a required Ruby library for this RDF serialization format.
|
337
|
+
#
|
338
|
+
# The given library will be required lazily, i.e. only when it is
|
339
|
+
# actually first needed, such as when instantiating a reader or parser
|
340
|
+
# instance for this format.
|
341
|
+
#
|
342
|
+
# @param [String, #to_s] library
|
343
|
+
# @return [void]
|
344
|
+
def self.require(library)
|
345
|
+
(@@requires[self] ||= []) << library.to_s
|
346
|
+
end
|
347
|
+
|
348
|
+
##
|
349
|
+
# Defines the content encoding for this RDF serialization format.
|
350
|
+
#
|
351
|
+
# @param [#to_sym] encoding
|
352
|
+
# @return [void]
|
353
|
+
def self.content_encoding(encoding)
|
354
|
+
@@content_encoding[self] = encoding.to_sym
|
355
|
+
end
|
356
|
+
|
357
|
+
private
|
358
|
+
|
359
|
+
private_class_method :new
|
360
|
+
|
361
|
+
@@requires = {} # @private
|
362
|
+
@@file_extensions = {} # @private
|
363
|
+
@@content_type = {} # @private
|
364
|
+
@@content_types = {} # @private
|
365
|
+
@@content_encoding = {} # @private
|
366
|
+
@@readers = {} # @private
|
367
|
+
@@writers = {} # @private
|
368
|
+
@@subclasses = [] # @private
|
369
|
+
|
370
|
+
##
|
371
|
+
# @private
|
372
|
+
# @return [void]
|
373
|
+
def self.inherited(child)
|
374
|
+
@@subclasses << child
|
375
|
+
super
|
376
|
+
end
|
377
|
+
end # Format
|
378
|
+
|
379
|
+
##
|
380
|
+
# The base class for RDF serialization format errors.
|
381
|
+
class FormatError < IOError
|
382
|
+
end # FormatError
|
383
|
+
end # RDF
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# @since 0.2.0
|
4
|
+
module Countable
|
5
|
+
extend RDF::Util::Aliasing::LateBound
|
6
|
+
|
7
|
+
##
|
8
|
+
# Returns `true` if `self` contains no RDF statements.
|
9
|
+
#
|
10
|
+
# @return [Boolean]
|
11
|
+
def empty?
|
12
|
+
empty = true
|
13
|
+
each { empty = false; break }
|
14
|
+
empty
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Returns the number of RDF statements in `self`.
|
19
|
+
#
|
20
|
+
# @return [Integer]
|
21
|
+
def count
|
22
|
+
count = 0
|
23
|
+
each { count += 1 }
|
24
|
+
count
|
25
|
+
end
|
26
|
+
alias_method :size, :count
|
27
|
+
|
28
|
+
##
|
29
|
+
# @private
|
30
|
+
# @param [Symbol, #to_sym] method
|
31
|
+
# @return [Enumerator]
|
32
|
+
# @see Object#enum_for
|
33
|
+
def enum_for(method = :each, *args)
|
34
|
+
# Ensure that enumerators support the `#empty?` and `#count` methods:
|
35
|
+
super.extend(RDF::Countable)
|
36
|
+
end
|
37
|
+
alias_method :to_enum, :enum_for
|
38
|
+
end # Countable
|
39
|
+
end # RDF
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
module Durable
|
4
|
+
extend RDF::Util::Aliasing::LateBound
|
5
|
+
|
6
|
+
##
|
7
|
+
# Returns `true` if `self` is durable.
|
8
|
+
#
|
9
|
+
# @return [Boolean]
|
10
|
+
# @see #nondurable?
|
11
|
+
def durable?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method :persistent?, :durable?
|
16
|
+
|
17
|
+
##
|
18
|
+
# Returns `true` if `self` is nondurable.
|
19
|
+
#
|
20
|
+
# @return [Boolean]
|
21
|
+
# @see #durable?
|
22
|
+
def nondurable?
|
23
|
+
!durable?
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :ephemeral?, :nondurable?
|
27
|
+
alias_method :nonpersistent?, :nondurable?
|
28
|
+
alias_method :transient?, :nondurable?
|
29
|
+
alias_method :volatile?, :nondurable?
|
30
|
+
end
|
31
|
+
end
|