• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ruby-rdf / rdf-json / 7451961379

08 Jan 2024 07:01PM UTC coverage: 92.517%. Remained the same
7451961379

push

github

gkellogg
* CI on Ruby 3.3.
* Reference release notes on GitHub.

136 of 147 relevant lines covered (92.52%)

87.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.83
/lib/rdf/json/reader.rb
1
module RDF::JSON
2✔
2
  ##
3
  # RDF/JSON parser.
4
  #
5
  # @example Loading RDF/JSON parsing support
6
  #   require 'rdf/json'
7
  #
8
  # @example Obtaining an RDF/JSON reader class
9
  #   RDF::Reader.for(:rj)         #=> RDF::JSON::Reader
10
  #   RDF::Reader.for("etc/doap.rj")
11
  #   RDF::Reader.for(:file_name      => "etc/doap.rj")
12
  #   RDF::Reader.for(:file_extension => "rj")
13
  #   RDF::Reader.for(:content_type   => "application/rj")
14
  #
15
  # @example Parsing RDF statements from an RDF/JSON file
16
  #   RDF::JSON::Reader.open("etc/doap.rj") do |reader|
17
  #     reader.each_statement do |statement|
18
  #       puts statement.inspect
19
  #     end
20
  #   end
21
  #
22
  # @example Parsing RDF statements from an RDF/JSON string
23
  #   data = StringIO.new(File.read("etc/doap.rj"))
24
  #   RDF::JSON::Reader.new(data) do |reader|
25
  #     reader.each_statement do |statement|
26
  #       puts statement.inspect
27
  #     end
28
  #   end
29
  #
30
  # @see http://n2.talis.com/wiki/RDF_JSON_Specification
31
  class Reader < RDF::Reader
2✔
32
    include RDF::Util::Logger
2✔
33
    format RDF::JSON::Format
2✔
34

35
    ##
36
    # The graph constructed when parsing.
37
    #
38
    # @return [RDF::Graph]
39
    attr_reader :graph
2✔
40

41
    ##
42
    # Initializes the RDF/JSON reader instance.
43
    #
44
    # @param  [IO, File, String]       input
45
    # @param  [Hash{Symbol => Object}] options
46
    #   any additional options (see `RDF::Reader#initialize`)
47
    # @yield  [reader] `self`
48
    # @yieldparam  [RDF::Reader] reader
49
    # @yieldreturn [void] ignored
50
    def initialize(input = $stdin, **options, &block)
2✔
51
      super do
260✔
52
        if block_given?
260✔
53
          case block.arity
62✔
54
            when 0 then instance_eval(&block)
×
55
            else block.call(self)
62✔
56
          end
57
        end
58
      end
59
    end
60

61
    ##
62
    # Parses an RDF/JSON subject string into a URI reference or blank node.
63
    #
64
    # @param  [String] subject
65
    # @return [RDF::Resource]
66
    def parse_subject(subject)
2✔
67
      case subject
80✔
68
        when /^_:/ then parse_node(subject)
12✔
69
        else parse_uri(subject)
68✔
70
      end
71
    end
72

73
    ##
74
    # Parses an RDF/JSON predicate string into a URI reference.
75
    #
76
    # @param  [String] predicate
77
    # @return [RDF::URI]
78
    def parse_predicate(predicate)
2✔
79
      # TODO: optional support for CURIE predicates? (issue #1 on GitHub).
80
      parse_uri(predicate, :intern => true)
610✔
81
    end
82

83
    ##
84
    # Parses an RDF/JSON object string into an RDF value.
85
    #
86
    # @param  [Hash{String => Object}] object
87
    # @return [RDF::Value]
88
    def parse_object(object)
2✔
89
      log_error("missing 'type' key in #{object.inspect}", exception: RDF::ReaderError) unless object.has_key?('type')
626✔
90
      log_error("missing 'value' key in #{object.inspect}", exception: RDF::ReaderError) unless object.has_key?('value')
626✔
91

92
      case type = object['type']
626✔
93
        when 'bnode'
94
          parse_node(object['value'])
12✔
95
        when 'uri'
96
          parse_uri(object['value'])
428✔
97
        when 'literal'
98
          literal = RDF::Literal.new(object['value'],
186✔
99
            language: object['lang'],
100
            datatype: object['datatype'],
101
            )
102
          literal.validate!     if validate?
186✔
103
          literal.canonicalize! if canonicalize?
186✔
104
          literal
186✔
105
        else
106
          log_error("expected 'type' to be 'bnode', 'uri', or 'literal', but got #{type.inspect}", exception: RDF::ReaderError)
×
107
      end
108
    rescue RDF::ReaderError
109
      nil
×
110
    end
111

112
    ##
113
    # Parses an RDF/JSON blank node string into an `RDF::Node` instance.
114
    #
115
    # @param  [String] string
116
    # @return [RDF::Node]
117
    # @since  0.3.0
118
    def parse_node(string)
2✔
119
      @nodes ||= {}
24✔
120
      id = string[2..-1] # strips off the initial '_:'
24✔
121
      @nodes[id.to_sym] ||= RDF::Node.new(id)
24✔
122
    end
123
    alias_method :parse_bnode, :parse_node
2✔
124

125
    ##
126
    # Parses an RDF/JSON URI string into an `RDF::URI` instance.
127
    #
128
    # @param  [String] string
129
    # @param  [Hash{Symbol => Object}] options
130
    # @option options [Boolean] :intern (false)
131
    # @return [RDF::URI]
132
    # @since  0.3.0
133
    def parse_uri(string, **options)
2✔
134
      uri = RDF::URI.send(intern = intern? && options[:intern] ? :intern : :new, string)
1,106✔
135
      uri.validate!     if validate?
1,106✔
136
      uri.canonicalize! if canonicalize? && !intern
1,106✔
137
      uri
1,106✔
138
    end
139

140
    ##
141
    # @private
142
    # @see   RDF::Reader#each_statement
143
    def each_statement(&block)
2✔
144
      if block_given?
48✔
145
        @input.rewind rescue nil
46✔
146
        begin
147
          ::JSON.parse(@input.read).each do |subject, predicates|
46✔
148
            subject = parse_subject(subject)
76✔
149
            predicates.each do |predicate, objects|
76✔
150
              predicate = parse_predicate(predicate)
610✔
151
              objects.each do |object|
610✔
152
                object = parse_object(object)
616✔
153
                yield RDF::Statement(subject, predicate, object) if object
616✔
154
              end
155
            end
156
          end
157
        rescue ::JSON::ParserError => e
158
          log_error(e.message)
2✔
159
        end
160
        if validate? && log_statistics[:error]
44✔
161
          raise RDF::ReaderError, "Errors found during processing"
4✔
162
        end
163
      end
164
      enum_for(:each_statement)
42✔
165
    end
166

167
    ##
168
    # @private
169
    # @see   RDF::Reader#each_triple
170
    def each_triple(&block)
2✔
171
      if block_given?
6✔
172
        each_statement do |statement|
4✔
173
          block.call(*statement.to_triple)
84✔
174
        end
175
      end
176
      enum_for(:each_triple)
6✔
177
    end
178
  end # Reader
179
end # RDF::JSON
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc