roadforest 0.0.3 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/examples/file-management.rb +7 -9
  3. data/lib/roadforest/application/dispatcher.rb +44 -31
  4. data/lib/roadforest/application/parameters.rb +5 -4
  5. data/lib/roadforest/application/path-provider.rb +14 -1
  6. data/lib/roadforest/application/route-adapter.rb +15 -4
  7. data/lib/roadforest/application/services-host.rb +41 -7
  8. data/lib/roadforest/application.rb +4 -8
  9. data/lib/roadforest/authorization.rb +231 -0
  10. data/lib/roadforest/blob-model.rb +2 -11
  11. data/lib/roadforest/content-handling/engine.rb +12 -6
  12. data/lib/roadforest/content-handling/handler-wrap.rb +45 -0
  13. data/lib/roadforest/content-handling/media-type.rb +20 -12
  14. data/lib/roadforest/content-handling/type-handler.rb +76 -0
  15. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +2 -146
  16. data/lib/roadforest/content-handling/type-handlers/rdf-handler.rb +38 -0
  17. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/document-environment.rb +34 -0
  18. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/object-environment.rb +62 -0
  19. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/property-environment.rb +46 -0
  20. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/render-engine.rb +574 -0
  21. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/render-environment.rb +144 -0
  22. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/subject-environment.rb +80 -0
  23. data/lib/roadforest/content-handling/type-handlers/rdfa-writer.rb +163 -0
  24. data/lib/roadforest/content-handling/type-handlers/rdfa.rb +175 -0
  25. data/lib/roadforest/content-handling/type-handlers/rdfpost.rb +297 -0
  26. data/lib/roadforest/debug.rb +10 -0
  27. data/lib/roadforest/http/graph-response.rb +3 -7
  28. data/lib/roadforest/http/graph-transfer.rb +28 -106
  29. data/lib/roadforest/http/keychain.rb +79 -0
  30. data/lib/roadforest/http/message.rb +9 -1
  31. data/lib/roadforest/http/user-agent.rb +115 -0
  32. data/lib/roadforest/http.rb +8 -0
  33. data/lib/roadforest/model.rb +48 -3
  34. data/lib/roadforest/rdf/graph-focus.rb +5 -3
  35. data/lib/roadforest/rdf/graph-store.rb +4 -2
  36. data/lib/roadforest/rdf/normalization.rb +6 -1
  37. data/lib/roadforest/remote-host.rb +22 -7
  38. data/lib/roadforest/resource/rdf/read-only.rb +15 -1
  39. data/lib/roadforest/templates/base/doc.haml +13 -0
  40. data/lib/roadforest/templates/base/property_value.haml +12 -0
  41. data/lib/roadforest/templates/base/property_values.haml +6 -0
  42. data/lib/roadforest/templates/base/subject.haml +4 -0
  43. data/lib/roadforest/templates/distiller/doc.haml +20 -0
  44. data/lib/roadforest/templates/distiller/nil-object.haml +1 -0
  45. data/lib/roadforest/templates/distiller/property_value.haml +7 -0
  46. data/lib/roadforest/templates/distiller/property_values.haml +7 -0
  47. data/lib/roadforest/templates/distiller/subject.haml +5 -0
  48. data/lib/roadforest/templates/min/doc.haml +10 -0
  49. data/lib/roadforest/templates/min/property_values.haml +7 -0
  50. data/lib/roadforest/templates/min/subject.haml +2 -0
  51. data/lib/roadforest/templates/nil-object.haml +0 -0
  52. data/lib/roadforest/templates/node-object.haml +1 -0
  53. data/lib/roadforest/templates/object.haml +1 -0
  54. data/lib/roadforest/templates/uri-object.haml +1 -0
  55. data/lib/roadforest/templates/xml-literal-object.haml +1 -0
  56. data/lib/roadforest/utility/class-registry.rb +4 -0
  57. data/spec/client.rb +119 -77
  58. data/spec/{excon-adapater.rb → excon-adapter.rb} +4 -0
  59. data/spec/full-integration.rb +6 -2
  60. data/spec/graph-store.rb +1 -1
  61. data/spec/media-types.rb +29 -2
  62. metadata +102 -125
@@ -0,0 +1,144 @@
1
+ require 'roadforest/content-handling/type-handlers/rdfa-writer'
2
+ module RoadForest::MediaType
3
+ class RDFaWriter
4
+ class RenderEnvironment
5
+ attr_accessor :heading_predicates, :lang
6
+
7
+ def initialize(engine)
8
+ @_engine = engine
9
+ end
10
+
11
+ def add_debug(msg = nil, &block)
12
+ @_engine.add_debug(msg, &block)
13
+ end
14
+
15
+ def inspect
16
+ "<#{self.class.name}:#{"%x" % self.object_id} #{instance_variables.map do |name|
17
+ next if name == :@_engine
18
+ "#{name}=#{instance_variable_get(name).inspect}"
19
+ end.compact.join(" ")}>"
20
+ end
21
+ # Display a subject.
22
+ #
23
+ # If the Haml template contains an entry matching the subject's rdf:type URI, that entry will be used as the template for this subject and it's properties.
24
+ #
25
+ # @example Displays a subject as a Resource Definition:
26
+ # <div typeof="rdfs:Resource" about="http://example.com/resource">
27
+ # <h1 property="dc:title">label</h1>
28
+ # <ul>
29
+ # <li content="2009-04-30T06:15:51Z" property="dc:created">2009-04-30T06:15:51+00:00</li>
30
+ # </ul>
31
+ # </div>
32
+ #
33
+ # @param [RDF::Resource] subject
34
+ # @param [Hash{Symbol => Object}] options
35
+ # @option options [:li, nil] :element(:div)
36
+ # Serialize using &lt;li&gt; rather than template default element
37
+ # @option options [RDF::Resource] :rel (nil)
38
+ # Optional @rel property
39
+ # @return [String]
40
+ def subject(subject, &block)
41
+ @_engine.render_subject(subject, &block)
42
+ end
43
+
44
+ def is_subject?
45
+ false
46
+ end
47
+
48
+ def literal?
49
+ false
50
+ end
51
+
52
+ def render_checked
53
+ false
54
+ end
55
+
56
+ # Haml rendering helper. Return CURIE for the literal datatype, if the
57
+ # literal is a typed literal.
58
+ #
59
+ # @param [RDF::Resource] literal
60
+ # @return [String, nil]
61
+ # @raise [RDF::WriterError]
62
+ def get_dt_curie(literal)
63
+ raise RDF::WriterError, "Getting datatype CURIE for #{literal.inspect}, which must be a literal" unless literal.is_a?(RDF::Literal)
64
+ get_curie(literal.datatype) if literal.literal? && literal.datatype?
65
+ end
66
+
67
+ # Haml rendering helper. Return language for plain literal, if there is no language, or it is the same as the document, return nil
68
+ #
69
+ # @param [RDF::Literal] literal
70
+ # @return [Symbol, nil]
71
+ # @raise [RDF::WriterError]
72
+ def get_lang(literal)
73
+ raise RDF::WriterError, "Getting datatype CURIE for #{literal.inspect}, which must be a literal" unless literal.is_a?(RDF::Literal)
74
+ literal.language if literal.literal? && literal.language && literal.language.to_s != @_engine.lang.to_s
75
+ end
76
+
77
+ # Haml rendering helper. Data to be added to a @content value
78
+ #
79
+ # @param [RDF::Literal] literal
80
+ # @return [String, nil]
81
+ # @raise [RDF::WriterError]
82
+ def get_content(literal)
83
+ raise RDF::WriterError, "Getting content for #{literal.inspect}, which must be a literal" unless literal.is_a?(RDF::Literal)
84
+ case literal
85
+ when RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime
86
+ literal.to_s
87
+ end
88
+ end
89
+
90
+ # Haml rendering helper. Display value for object, may be non-canonical if get_content returns a non-nil value
91
+ #
92
+ # @param [RDF::Literal] literal
93
+ # @return [String]
94
+ # @raise [RDF::WriterError]
95
+ def get_value(literal)
96
+ raise RDF::WriterError, "Getting value for #{literal.inspect}, which must be a literal" unless literal.is_a?(RDF::Literal)
97
+ case literal
98
+ when RDF::Literal::Date
99
+ literal.object.strftime("%A, %d %B %Y")
100
+ when RDF::Literal::Time
101
+ literal.object.strftime("%H:%M:%S %Z").sub(/\+00:00/, "UTC")
102
+ when RDF::Literal::DateTime
103
+ literal.object.strftime("%H:%M:%S %Z on %A, %d %B %Y").sub(/\+00:00/, "UTC")
104
+ else
105
+ literal.to_s
106
+ end
107
+ rescue
108
+ literal.to_s # When all else fails ...
109
+ end
110
+
111
+ # Haml rendering helper. Return an appropriate label for a resource.
112
+ #
113
+ # @param [RDF::Resource] resource
114
+ # @return [String]
115
+ # @raise [RDF::WriterError]
116
+ def get_predicate_name(resource)
117
+ raise RDF::WriterError, "Getting predicate name for #{resource.inspect}, which must be a resource" unless resource.is_a?(RDF::Resource)
118
+ get_curie(resource)
119
+ end
120
+
121
+ # rendering helper. Return appropriate, term, CURIE or URI for the given
122
+ # resource.
123
+ #
124
+ # @param [RDF::Value] resource
125
+ # @return [String] value to use to identify URI
126
+ # @raise [RDF::WriterError]
127
+ def get_curie(resource)
128
+ @_engine.get_curie(resource)
129
+ end
130
+
131
+ ##
132
+ # Haml rendering helper. Escape entities to avoid whitespace issues.
133
+ #
134
+ # # In addtion to "&<>, encode \n and \r to ensure that whitespace is properly preserved
135
+ #
136
+ # @param [String] str
137
+ # @return [String]
138
+ # Entity-encoded string
139
+ def escape_entities(str)
140
+ CGI.escapeHTML(str).gsub(/[\n\r]/) {|c| '&#x' + c.unpack('h').first + ';'}
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,80 @@
1
+ require 'roadforest/content-handling/type-handlers/rdfa-writer/render-environment'
2
+ module RoadForest::MediaType
3
+ class RDFaWriter
4
+ class SubjectEnvironment < RenderEnvironment
5
+ attr_accessor :base, :element, :predicate_terms, :property_objects, :rel, :inlist, :subject, :typeof
6
+
7
+ # Write a predicate with one or more values.
8
+ #
9
+ # Values may be a combination of Literal and Resource (Node or URI).
10
+ # @param [RDF::Resource] predicate
11
+ # Predicate to serialize
12
+ # @param [Array<RDF::Resource>] objects
13
+ # Objects to serialize
14
+ # @return [String]
15
+ def predicate(predicate)
16
+ @_engine.render_predicate(subject, predicate)
17
+ end
18
+
19
+ def attrs
20
+ {:rel => rel, :resource => (about || resource), :typeof => typeof, :inlist => inlist}
21
+ end
22
+
23
+ def is_subject?
24
+ true
25
+ end
26
+
27
+ def predicates
28
+ enum_for(:each_predicate)
29
+ end
30
+
31
+ def each_predicate
32
+ predicate_terms.each do |predicate|
33
+ predicate = RDF::URI(predicate) if predicate.is_a?(String)
34
+ objects = property_objects[predicate.to_s]
35
+ next if objects.nil? or objects.empty?
36
+
37
+ nonlists, lists = objects.partition do |object|
38
+ !@_engine.is_list?(object)
39
+ end
40
+
41
+ add_debug {"properties with lists: #{lists} non-lists: #{nonlists}"}
42
+
43
+ ([@_engine.simple_property_env(predicate, nonlists)] + @_engine.list_property_envs(predicate, lists)).compact.each do |env|
44
+ yield(env)
45
+ end
46
+ end
47
+ end
48
+
49
+ def template_kinds
50
+ %w{subject}
51
+ end
52
+
53
+ def render_checked
54
+ return true if @_engine.is_done?(subject)
55
+ @_engine.subject_done(subject)
56
+ return false
57
+ end
58
+
59
+ def about
60
+ if rel.nil?
61
+ get_curie(subject)
62
+ else
63
+ nil
64
+ end
65
+ end
66
+
67
+ def resource
68
+ if rel.nil?
69
+ nil
70
+ else
71
+ get_curie(subject)
72
+ end
73
+ end
74
+
75
+ def yielded(pred)
76
+ @_engine.render(pred)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,163 @@
1
+ require 'cgi'
2
+ require 'roadforest/debug'
3
+ require 'rdf/rdfa'
4
+
5
+ module RoadForest::MediaType
6
+ ##
7
+ # An RDFa 1.1 serialiser in Ruby. The RDFa serializer makes use of Haml templates, allowing runtime-replacement with alternate templates. Note, however, that templates should be checked against the W3C test suite to ensure that valid RDFa is emitted.
8
+ #
9
+ # Note that the natural interface is to write a whole graph at a time. Writing statements or Triples will create a graph to add them to and then serialize the graph.
10
+ #
11
+ # The writer will add prefix definitions, and use them for creating @prefix definitions, and minting CURIEs
12
+ #
13
+ # @example Obtaining a RDFa writer class
14
+ # RDF::Writer.for(:html) => RDF::RDFa::Writer
15
+ # RDF::Writer.for("etc/test.html")
16
+ # RDF::Writer.for(:file_name => "etc/test.html")
17
+ # RDF::Writer.for(:file_extension => "html")
18
+ # RDF::Writer.for(:content_type => "application/xhtml+xml")
19
+ # RDF::Writer.for(:content_type => "text/html")
20
+ #
21
+ # @example Serializing RDF graph into an XHTML+RDFa file
22
+ # RDF::RDFa::Write.open("etc/test.html") do |writer|
23
+ # writer << graph
24
+ # end
25
+ #
26
+ # @example Serializing RDF statements into an XHTML+RDFa file
27
+ # RDF::RDFa::Writer.open("etc/test.html") do |writer|
28
+ # graph.each_statement do |statement|
29
+ # writer << statement
30
+ # end
31
+ # end
32
+ #
33
+ # @example Serializing RDF statements into an XHTML+RDFa string
34
+ # RDF::RDFa::Writer.buffer do |writer|
35
+ # graph.each_statement do |statement|
36
+ # writer << statement
37
+ # end
38
+ # end
39
+ #
40
+ # @example Creating @base and @prefix definitions in output
41
+ # RDF::RDFa::Writer.buffer(:base_uri => "http://example.com/", :prefixes => {
42
+ # :foaf => "http://xmlns.com/foaf/0.1/"}
43
+ # ) do |writer|
44
+ # graph.each_statement do |statement|
45
+ # writer << statement
46
+ # end
47
+ # end
48
+ #
49
+ # @author [Gregg Kellogg](http://kellogg-assoc.com/)
50
+ class RDFaWriter < RDF::Writer
51
+ HAML_OPTIONS = {
52
+ :ugly => true, # to preserve whitespace without using entities
53
+ }
54
+
55
+ # @return [Graph] Graph of statements serialized
56
+ attr_accessor :graph
57
+
58
+ # @return [RDF::URI] Base URI used for relativizing URIs
59
+ attr_accessor :base_uri
60
+
61
+ ##
62
+ # Initializes the RDFa writer instance.
63
+ #
64
+ # @param [IO, File] output
65
+ # the output stream
66
+ # @param [Hash{Symbol => Object}] options
67
+ # any additional options
68
+ # @option options [Boolean] :canonicalize (false)
69
+ # whether to canonicalize literals when serializing
70
+ # @option options [Hash] :prefixes (Hash.new)
71
+ # the prefix mappings to use
72
+ # @option options [#to_s] :base_uri (nil)
73
+ # the base URI to use when constructing relative URIs, set as html>head>base.href
74
+ # @option options [Boolean] :validate (false)
75
+ # whether to validate terms when serializing
76
+ # @option options [#to_s] :lang (nil)
77
+ # Output as root @lang attribute, and avoid generation _@lang_ where possible
78
+ # @option options [Boolean] :standard_prefixes (false)
79
+ # Add standard prefixes to _prefixes_, if necessary.
80
+ # @option options [Array<RDF::URI>] :top_classes ([RDF::RDFS.Class])
81
+ # Defines rdf:type of subjects to be emitted at the beginning of the document.
82
+ # @option options [Array<RDF::URI>] :predicate_order ([RDF.type, RDF::RDFS.label, RDF::DC.title])
83
+ # Defines order of predicates to to emit at begninning of a resource description..
84
+ # @option options [Array<RDF::URI>] :heading_predicates ([RDF::RDFS.label, RDF::DC.title])
85
+ # Defines order of predicates to use in heading.
86
+ # @option options [String, Symbol, Hash{Symbol => String}] :haml (DEFAULT_HAML) HAML templates used for generating code
87
+ # @option options [Hash] :haml_options (HAML_OPTIONS)
88
+ # Options to pass to Haml::Engine.new. Default options set `:ugly => false` to ensure that whitespace in literals with newlines is properly preserved.
89
+ # @yield [writer]
90
+ # @yieldparam [RDF::Writer] writer
91
+ def initialize(output = $stdout, options = {}, &block)
92
+ super do
93
+ @graph = RDF::Graph.new
94
+ @valise = nil
95
+
96
+ block.call(self) if block_given?
97
+ end
98
+ end
99
+
100
+ ##
101
+ # Write whole graph
102
+ #
103
+ # @param [Graph] graph
104
+ # @return [void]
105
+ def write_graph(graph)
106
+ @graph = graph
107
+ end
108
+
109
+ ##
110
+ # Addes a statement to be serialized
111
+ # @param [RDF::Statement] statement
112
+ # @return [void]
113
+ # @raise [RDF::WriterError] if validating and attempting to write an invalid {RDF::Term}.
114
+ def write_statement(statement)
115
+ raise RDF::WriterError, "Statement #{statement.inspect} is invalid" if validate? && statement.invalid?
116
+ @graph.insert(statement)
117
+ end
118
+
119
+ ##
120
+ # Addes a triple to be serialized
121
+ # @param [RDF::Resource] subject
122
+ # @param [RDF::URI] predicate
123
+ # @param [RDF::Value] object
124
+ # @return [void]
125
+ # @raise [NotImplementedError] unless implemented in subclass
126
+ # @abstract
127
+ # @raise [RDF::WriterError] if validating and attempting to write an invalid {RDF::Term}.
128
+ def write_triple(subject, predicate, object)
129
+ write_statement Statement.new(subject, predicate, object)
130
+ end
131
+
132
+ ##
133
+ # Outputs the XHTML+RDFa representation of all stored triples.
134
+ #
135
+ # @return [void]
136
+ def write_epilogue
137
+ require 'roadforest/content-handling/type-handlers/rdfa-writer/render-engine'
138
+ @base_uri = RDF::URI(@options[:base_uri]) if @options[:base_uri]
139
+ @lang = @options[:lang]
140
+ @debug = @options[:debug]
141
+ engine = RenderEngine.new(@graph, @debug) do |engine|
142
+ engine.valise = Valise.define do
143
+ ro up_to("lib") + "roadforest"
144
+ end
145
+ engine.style_name = @options[:haml]
146
+ engine.base_uri = base_uri
147
+ engine.lang = @lang
148
+ engine.standard_prefixes = @options[:standard_prefixes]
149
+ engine.top_classes = @options[:top_classes] || [RDF::RDFS.Class]
150
+ engine.predicate_order = @options[:predicate_order] || [RDF.type, RDF::RDFS.label, RDF::DC.title]
151
+ engine.heading_predicates = @options[:heading_predicates] || [RDF::RDFS.label, RDF::DC.title]
152
+ engine.haml_options = @options[:haml_options]
153
+ end
154
+
155
+ engine.prefixes.merge! @options[:prefixes] unless @options[:prefixes].nil?
156
+
157
+ # Generate document
158
+ rendered = engine.render_document
159
+
160
+ @output.write(rendered)
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,175 @@
1
+ require 'rdf/rdfa' #XXX Otherwise json-ld grabs RDFa documents. Awaiting fix upstream
2
+ require 'roadforest/content-handling/type-handlers/rdf-handler'
3
+ module RoadForest
4
+ module MediaType
5
+ module Handlers
6
+ class RESTfulRDFaWriter < ::RDF::RDFa::Writer
7
+ HAML = ::RDF::RDFa::Writer::BASE_HAML.merge(:property_values => %q{
8
+ - objects.each do |object|
9
+ /
10
+ = object.inspect
11
+ %div.property
12
+ %span.label
13
+ = get_predicate_name(predicate)
14
+ %ul
15
+ - objects.each do |object|
16
+ - if res = yield(object, :inlist => inlist, :element => :li)
17
+ != res
18
+ - elsif object.node?
19
+ %li{:property => get_curie(predicate), :resource => get_curie(object), :inlist => inlist}= get_curie(object)
20
+ - elsif object.uri?
21
+ %li
22
+ %a{:property => get_curie(predicate), :href => object.to_s, :inlist => inlist}= object.to_s
23
+ - elsif object.datatype == RDF.XMLLiteral
24
+ %li{:property => get_curie(predicate), :lang => get_lang(object), :datatype => get_curie(object.datatype), :inlist => inlist}<!= get_value(object)
25
+ - else
26
+ %li{:property => get_curie(predicate), :content => get_content(object), :lang => get_lang(object), :datatype => get_dt_curie(object), :inlist => inlist}= escape_entities(get_value(object))
27
+ })
28
+
29
+ def initialize(output = $stdout, options = nil, &block)
30
+ options ||= {}
31
+ options = {:haml => HAML}
32
+ super(output, options, &block)
33
+ end
34
+
35
+
36
+ # Write a predicate with one or more values.
37
+ #
38
+ # Values may be a combination of Literal and Resource (Node or URI).
39
+ # @param [RDF::Resource] predicate
40
+ # Predicate to serialize
41
+ # @param [Array<RDF::Resource>] objects
42
+ # Objects to serialize
43
+ # @return [String]
44
+ def predicate(predicate, objects, options = nil)
45
+ add_debug {"predicate: #{predicate.inspect}, objects: #{objects}"}
46
+
47
+ return if objects.to_a.empty?
48
+
49
+ add_debug {"predicate: #{get_curie(predicate)}"}
50
+ render_property(predicate, objects, options || {}) do |o, opts|
51
+ # Yields each object, for potential recursive definition.
52
+ # If nil is returned, a leaf is produced
53
+ opts = {:rel => get_curie(predicate), :element => (:li if objects.length > 1)}.merge(opts||{})
54
+
55
+ if !is_done?(o) && @subjects.include?(o)
56
+ depth {subject(o, opts)}
57
+ end
58
+ end
59
+ end
60
+
61
+
62
+ # Render a single- or multi-valued predicate using
63
+ # `haml_template[:property_value]` or
64
+ # `haml_template[:property_values]`. Yields each object for optional
65
+ # rendering. The block should only render for recursive subject
66
+ # definitions (i.e., where the object is also a subject and is rendered
67
+ # underneath the first referencing subject).
68
+ #
69
+ # If a multi-valued property definition is not found within the template, the writer will use the single-valued property definition multiple times.
70
+ #
71
+ # @param [Array<RDF::Resource>] predicate
72
+ # Predicate to render.
73
+ # @param [Array<RDF::Resource>] objects
74
+ # List of objects to render. If the list contains only a single element, the :property_value template will be used. Otherwise, the :property_values template is used.
75
+ # @param [Hash{Symbol => Object}] options Rendering options passed to Haml render.
76
+ # @option options [String] haml (haml_template[:property_value], haml_template[:property_values])
77
+ # Haml template to render. Otherwise, uses `haml_template[:property_value] or haml_template[:property_values]`
78
+ # depending on the cardinality of objects.
79
+ # @yield [object]
80
+ # Yields object.
81
+ # @yieldparam [RDF::Resource] object
82
+ # @yieldreturn [String, nil]
83
+ # The block should only return a string for recursive object definitions.
84
+ # @return String
85
+ # The rendered document is returned as a string
86
+ def render_property(predicate, objects, options = {}, &block)
87
+ add_debug {"render_property(#{predicate}): #{objects.inspect}"}
88
+ # If there are multiple objects, and no :property_values is defined, call recursively with
89
+ # each object
90
+
91
+ template = options[:haml]
92
+ template ||= objects.length > 1 ? haml_template[:property_values] : haml_template[:property_value]
93
+
94
+ # Separate out the objects which are lists and render separately
95
+ list_objects = objects.select {|o| o != ::RDF.nil && ::RDF::List.new(o, @graph).valid?}
96
+ unless list_objects.empty?
97
+ # Render non-list objects
98
+ add_debug {"properties with lists: non-lists: #{objects - list_objects} lists: #{list_objects}"}
99
+ nl = render_property(predicate, objects - list_objects, options, &block) unless objects == list_objects
100
+ return nl.to_s + list_objects.map do |object|
101
+ # Render each list as multiple properties and set :inlist to true
102
+ list = ::RDF::List.new(object, @graph)
103
+ list.each_statement {|st| subject_done(st.subject)}
104
+
105
+ add_debug {"list: #{list.inspect} #{list.to_a}"}
106
+ render_property(predicate, list.to_a, options.merge(:inlist => "true"), &block)
107
+ end.join(" ")
108
+ end
109
+
110
+ if objects.length > 1 && template.nil?
111
+ # Uf there is no property_values template, render each property using property_value template
112
+ objects.map do |object|
113
+ render_property(predicate, [object], options, &block)
114
+ end.join(" ")
115
+ else
116
+ raise ::RDF::WriterError, "Missing property template" if template.nil?
117
+
118
+ template = options[:haml] || (
119
+ objects.to_a.length > 1 &&
120
+ haml_template.has_key?(:property_values) ?
121
+ :property_values :
122
+ :property_value)
123
+ options = {
124
+ :objects => objects,
125
+ :object => objects.first,
126
+ :predicate => predicate,
127
+ :property => get_curie(predicate),
128
+ :rel => get_curie(predicate),
129
+ :inlist => nil,
130
+ }.merge(options)
131
+ hamlify(template, options) do |object, options|
132
+ yield(object, options) if block_given?
133
+ end
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ #text/html;q=1;rdfa
140
+ #image/svg+xml;q=1;rdfa
141
+ #application/xhtml+xml;q=1;rdfa
142
+ #text/html
143
+ #image/svg+xml
144
+ #application/xhtml+xml
145
+ class RDFa < RDFHandler
146
+ include RDF::Normalization
147
+
148
+ def local_to_network(base_uri, rdf)
149
+ raise "Invalid base uri: #{base_uri}" if base_uri.nil?
150
+ prefixes = relevant_prefixes_for_graph(rdf)
151
+ prefixes.keys.each do |prefix|
152
+ prefixes[prefix.to_sym] = prefixes[prefix]
153
+ end
154
+ #::RDF::RDFa.debug = true
155
+ RESTfulRDFaWriter.buffer(:base_uri => base_uri.to_s,
156
+ :prefixes => prefixes) do |writer|
157
+ rdf.each_statement do |statement|
158
+ writer << statement
159
+ end
160
+ end
161
+ end
162
+
163
+ def network_to_local(base_uri, source)
164
+ raise "Invalid base uri: #{base_uri.inspect}" if base_uri.nil?
165
+ graph = ::RDF::Graph.new
166
+ reader = ::RDF::RDFa::Reader.new(source.to_s, :base_uri => base_uri.to_s)
167
+ reader.each_statement do |statement|
168
+ graph.insert(statement)
169
+ end
170
+ graph
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end