class RoadForest::TypeHandlers::RDFaWriter::RenderEngine

Attributes

base_uri[RW]
debug[R]
debugging_comments[RW]
decoration_set[R]
doc_title[RW]
graph[RW]
graph_name[RW]
heading_predicates[RW]
lang[RW]
predicate_order[RW]
prefixes[RW]
standard_prefixes[RW]
template_handler[RW]
titles[RW]
top_classes[RW]

Public Class Methods

new(graph, debug=nil) { |self| ... } click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 64
def initialize(graph, debug=nil)
  @debugging_comments = false
  @debug = debug
  @graph = graph
  @graph_name = nil
  @decoration_set = DecorationSet.new
  @render_stack = []

  reset

  yield self

  setup
end

Public Instance Methods

add_debug(message = nil) { || ... } click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 108
def add_debug(message = nil)
  return unless ::RoadForest.debug_io || @debug
  message ||= "  " * @debug_indent
  begin
    message = message + yield if block_given?
  rescue => ex
    message += ex.inspect
    message += "\n"
    message += ex.backtrace[0...10].map do |line|
      ("  " * (@debug_indent + 1)) + line
    end.join("\n")
  end
  RoadForest::debug(message)
  @debug << message.force_encoding("utf-8") if @debug.is_a?(Array)
end
build_env(klass) { |env| ... } click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 348
def build_env(klass)
  env = klass.new(self)
  env.heading_predicates = heading_predicates
  env.lang = lang
  env.parent = @render_stack.last
  yield(env)
  return decoration_set.decoration_for(env)
end
bump_reference(resource) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 100
def bump_reference(resource)
  @references[resource] += 1
end
depth() { || ... } click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 93
def depth
  @debug_indent += 1
  ret = yield
  @debug_indent -= 1
  ret
end
document_env() click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 357
def document_env
  build_env(DocumentEnvironment) do |env|
    env.subject_terms = @ordered_subjects
    env.title = doc_title
    env.prefixes = prefixes
    env.lang = lang
    env.base = base_uri
  end
end
find_environment_template(env) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 293
def find_environment_template(env)
  template_handler.find_template(env.template_kinds)
rescue Valise::Errors::NotFound
  raise RDF::WriterError, "No template found for #{env.class} in #{template_handler.inspect}"
end
get_curie(resource) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 234
def get_curie(resource)
  raise RDF::WriterError, "Getting CURIE for #{resource.inspect}, which must be an RDF value" unless resource.is_a? RDF::Value
  return resource.to_s unless resource.uri?

  uri = resource.to_s

  curie =
    case
    when @uri_to_term_or_curie.has_key?(uri)
      add_debug {"get_curie(#{uri}): cached: #{@uri_to_term_or_curie[uri].inspect}"}
      return @uri_to_term_or_curie[uri]
    when base_uri && uri.index(base_uri.to_s) == 0
      add_debug {"get_curie(#{uri}): base_uri: (#{base_uri} + #{uri.sub(base_uri.to_s, "")})"}
      uri.sub(base_uri.to_s, "")
    when @vocabulary && uri.index(@vocabulary) == 0
      add_debug {"get_curie(#{uri}): vocabulary: #{@vocabulary.inspect}"}
      uri.sub(@vocabulary, "")
    when u = @uri_to_prefix.keys.detect {|u| uri.index(u.to_s) == 0}
      add_debug {"get_curie(#{uri}): uri_to_prefix: #{@uri_to_prefix[u]}"}
      prefix = @uri_to_prefix[u]
      @prefixes[prefix] = u
      uri.sub(u.to_s, "#{prefix}:")
    when @standard_prefixes && vocab = RDF::Vocabulary.detect {|v| uri.index(v.to_uri.to_s) == 0}
      add_debug {"get_curie(#{uri}): standard_prefixes: #{vocab}"}
      prefix = vocab.__name__.to_s.split('::').last.downcase
      @prefixes[prefix] = vocab.to_uri
      uri.sub(vocab.to_uri.to_s, "#{prefix}:")
    else
      add_debug {"get_curie(#{uri}): none"}
      uri
    end

  add_debug {"get_curie(#{resource}) => #{curie}"}

  @uri_to_term_or_curie[uri] = curie
rescue ArgumentError => e
  raise RDF::WriterError, "Invalid URI #{uri.inspect}: #{e.message}"
end
is_done?(subject) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 334
def is_done?(subject)
  @serialized.include?(subject)
end
is_list?(object) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 326
def is_list?(object)
  !(object == RDF.nil || (RDF::List.new(object, @graph)).invalid?)
end
list_property_envs(predicate, list_objects) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 417
def list_property_envs(predicate, list_objects)
  return list_objects.map do |object|
    # Render each list as multiple properties and set :inlist to true
    list = RDF::List.new(object, @graph)
    list.each_statement {|st| subject_done(st.subject)}

    add_debug {"list: #{list.inspect} #{list.to_a}"}
    env = simple_property_env(predicate, list.to_a)
    env.inlist = "true"
    env
  end
end
object_env(predicate, object) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 390
def object_env(predicate, object)
  subj = subject_env(object)
  unless subj.nil?
    subj.rel = get_curie(predicate)
    return subj
  end

  env_klass =
    if get_curie(object) == 'rdf:nil'
      NilObjectEnvironment
    elsif object.node?
      NodeObjectEnvironment
    elsif object.uri?
      UriObjectEnvironment
    elsif object.datatype == RDF.XMLLiteral
      XMLLiteralObjectEnvironment
    else
      ObjectEnvironment
    end

  build_env(env_klass) do |env|
    env.predicate = predicate
    env.object = object
    env.inlist = nil
  end
end
order_properties(properties) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 201
def order_properties(properties)
  # Make sorted list of properties
  prop_list = []

  predicate_order.each do |prop|
    next unless properties[prop.to_s]
    prop_list << prop.to_s
  end

  properties.keys.sort.each do |prop|
    next if prop_list.include?(prop.to_s)
    prop_list << prop.to_s
  end

  add_debug {"order_properties: #{prop_list.join(', ')}"}
  prop_list
end
order_subjects() click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 169
def order_subjects
  seen = {}
  subjects = []

  # Start with base_uri
  if base_uri && @subjects.keys.include?(base_uri)
    subjects << base_uri
    seen[base_uri] = true
  end

  # Add distinguished classes
  top_classes.select do |s|
    !seen.include?(s)
  end.each do |class_uri|
    graph.query(:predicate => RDF.type, :object => class_uri).map {|st| st.subject}.sort.uniq.each do |subject|
      subjects << subject
      seen[subject] = true
    end
  end

  # Sort subjects by resources over nodes, ref_counts and the subject URI itself
  recursable = @subjects.keys.select do |s|
    !seen.include?(s)
  end.map do |r|
    [r.is_a?(RDF::Node) ? 1 : 0, ref_count(r), r]
  end.sort

  subjects += recursable.map{|r| r.last}
  add_debug {"order_subjects: (final) \n  #{subjects.join("\n  ")}"}
  return subjects
end
preprocess() click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 144
def preprocess
  [RDF::RDFa::XML_RDFA_CONTEXT, RDF::RDFa::HTML_RDFA_CONTEXT].each do |uri|
    ctx = RDF::RDFa::Context.find(uri)
    ctx.prefixes.each_pair do |k, v|
      @uri_to_prefix[v] = k unless k.to_s == "dcterms"
    end

    ctx.terms.each_pair do |k, v|
      @uri_to_term_or_curie[v] = k
    end

    @vocabulary = ctx.vocabulary.to_s if ctx.vocabulary
  end

  # Load defined prefixes
  (@prefixes || {}).each_pair do |k, v|
    @uri_to_prefix[v.to_s] = k
  end
  @prefixes = {}  # Will define actual used when matched

  # Process each statement to establish CURIEs and Terms
  @graph.each {|statement| preprocess_statement(statement)}
  add_debug{ "preprocess prefixes: #{@prefixes.inspect}" }
end
preprocess_statement(statement) click to toggle source

Perform any statement preprocessing required. This is used to perform reference counts and determine required prefixes. @param [RDF::Statement] statement @return [ignored]

# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 222
def preprocess_statement(statement)
  #add_debug {"preprocess: #{statement.inspect}"}
  return unless statement.context == graph_name
  bump_reference(statement.subject)
  bump_reference(statement.object)
  @subjects[statement.subject] = true
  get_curie(statement.subject)
  get_curie(statement.predicate)
  get_curie(statement.object)
  get_curie(statement.object.datatype) if statement.object.literal? && statement.object.has_datatype?
end
properties_for_subject(subject) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 338
def properties_for_subject(subject)
  properties = {}
  @graph.query(:subject => subject, :context => false) do |st|
    key = st.predicate.to_s.freeze
    properties[key] ||= []
    properties[key] << st.object
  end
  properties
end
ref_count(node) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 104
def ref_count(node)
  @references[node]
end
render(context) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 299
def render(context)
  add_debug "render"
  if context.render_checked
    return ""
  end
  template = find_environment_template(context)
  depth do
    add_debug{ "template: #{template.file}" }
    add_debug{ "options: #{template.options}" }
    add_debug{ "context: #{context.class.name}"}
    add_debug{ "  #{context.attrs}" } if context.respond_to?(:attrs)

    begin
      @render_stack.push context
      prefix = ""
      if debugging_comments
        prefix = "<!-- #{template.file} -->"
      end
      prefix + template.render(context) do |item|
        context.yielded(item)
      end.sub(/\n\Z/,'')
    ensure
      @render_stack.pop
    end
  end
end
render_document() { |env| ... } click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 430
def render_document
  add_debug{ "engine prefixes: #{prefixes.inspect}"}
  env = document_env

  yield env if block_given?

  render(env)
end
reset() click to toggle source

Reset parser to run again

# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 80
def reset
  @debug_indent = 0
  @uri_to_term_or_curie = {}
  @uri_to_prefix = {}
  @references = Hash.new{|h,k| h[k] = 0}
  @prefixes = {}
  @serialized = {}
  @subjects = {}
  @ordered_subjects = []
  @titles = {}
  @doc_title = ""
end
setup() click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 124
def setup
  add_debug {"\nserialize setup: graph size: #{@graph.size}"}

  @base_uri = ::RDF::URI.intern(@base_uri) unless @base_uri.nil? or @base_uri.is_a?(::RDF::URI)

  preprocess

  @ordered_subjects = order_subjects

  # Take title from first subject having a heading predicate
  @doc_title = nil
  heading_predicates.each do |pred|
    @graph.query(:predicate => pred) do |statement|
      titles[statement.subject] ||= statement.object
    end
  end
  title_subject = @ordered_subjects.detect {|subject| titles[subject]}
  @doc_title = titles[title_subject]
end
simple_property_env(predicate, objects) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 380
def simple_property_env(predicate, objects)
  return nil if objects.to_a.empty?

  build_env(PropertyEnvironment) do |env|
    env.object_terms = objects
    env.predicate = predicate
    env.inlist = nil
  end
end
subject_done(subject) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 330
def subject_done(subject)
  @serialized[subject] = true
end
subject_env(subject) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 367
def subject_env(subject)
  return unless @subjects.include?(subject)
  properties = properties_for_subject(subject)

  build_env(SubjectEnvironment) do |env|
    env.base = base_uri
    env.predicate_terms = order_properties(properties)
    env.property_objects = properties
    env.subject = subject
    env.typeof = type_of(properties.delete(RDF.type.to_s), subject)
  end
end
type_of(type, subject) click to toggle source
# File lib/roadforest/type-handlers/rdfa-writer/render-engine.rb, line 273
def type_of(type, subject)
  # Find appropriate template
  curie = case
          when subject.node?
            subject.to_s if ref_count(subject) > 1
          else
            get_curie(subject)
          end

  typeof = Array(type).map {|r| get_curie(r)}.join(" ")
  typeof = nil if typeof.empty?

  # Nodes without a curie need a blank @typeof to generate a subject
  typeof ||= "" unless curie

  add_debug {"subject: #{curie.inspect}, typeof: #{typeof.inspect}" }

  typeof.freeze
end