Module: JSON::LD::Flatten
Instance Method Summary collapse
-
#generate_node_map(element, node_map, graph, list, namer, id = nil) ⇒ Object
Build hash of nodes used for framing.
Methods included from Utils
#blank_node?, #list?, #node?, #node_reference?, #value?
Instance Method Details
#generate_node_map(element, node_map, graph, list, namer, id = nil) ⇒ Object
Build hash of nodes used for framing. Also returns flattened representation of input.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/json/ld/flatten.rb', line 19 def generate_node_map(element, node_map, graph, list, namer, id = nil) depth do debug("nodeMap") {"element: #{element.inspect}, graph: #{graph}"} if element.is_a?(Array) element.map {|o| generate_node_map(o, node_map, graph, list, namer)} elsif !element.is_a?(Hash) || value?(element) list << element if list else # If the @id property exists and is an IRI, set id to its value, otherwise set it to a blank node identifier created by the Generate Blank Node Identifier algorithm. # FIXME: (spec) id passed when it is allocated, so it is not re-allocated here. id ||= blank_node?(element) ? namer.get_name(element.fetch('@id', nil)) : element['@id'] # If list is not nil, append a new node reference to list using id at the value for @id. list << {'@id' => id} if list # Let nodes be the value in nodeMap where the key is graph; if no such value exists, insert a new JSON object for the key graph. debug("nodeMap") {"new graph: #{graph}"} unless node_map.has_key?(graph) nodes = (node_map[graph] ||= Hash.ordered) # If id is not in nodes, create a new JSON object node with id as the value for @id. Let node be the value of id in nodes. debug("nodeMap") {"new node: #{id}"} unless nodes.has_key?(id) node = (nodes[id] ||= Hash.ordered) node['@id'] ||= id # For each property that is not @id and each value in element ordered by property: element.each do |prop, value| case prop when '@id' # Skip @id, already assigned when '@graph' # If property is @graph, recursively call this algorithm passing value for element, nodeMap, nil for list and if graph is @merged use graph, otherwise use id for graph and then continue. graph = graph == '@merged' ? '@merged' : id generate_node_map(value, node_map, graph, nil, namer) when /^@(?!type)/ # If property is not @type and is a keyword, merge property and value into node and then continue. debug("nodeMap") {"merge keyword#{prop}: #{value.inspect}"} node[prop] = value else raise InvalidFrame::Syntax, "unexpected value: #{value.inspect}, expected array" unless value.is_a?(Array) # For each value v in the array value: value.each do |v| if node?(v) || node_reference?(v) debug("nodeMap") {"node value #{prop}: #{v.inspect}"} # If v is a node definition or node reference: # If the property @id is not an IRI or it does not exist, map v to a new blank node identifier to avoid collisions. name = blank_node?(v) ? namer.get_name(v.fetch('@id', nil)) : v['@id'] # If one does not already exist, add a node reference for v into node for property. node[prop] ||= [] node[prop] << {'@id' => name} unless node[prop].any? {|n| node_reference?(n) && n['@id'] == name } # Recursively call this algorithm passing v for value, nodeMap, graph, and nil for list. generate_node_map(v, node_map, graph, nil, namer, name) elsif list?(v) # Otherwise if v has the property @list then recursively call this algorithm with the value of @list as element, nodeMap, graph, and a new array flattenedList as list. debug("nodeMap") {"list value #{prop}: #{v.inspect}"} flattened_list = [] generate_node_map(v['@list'], node_map, graph, flattened_list, namer) # Create a new JSON object with the property @list set to flattenedList and add it to node for property. (node[prop] ||= []) << {'@list' => flattened_list} elsif prop == '@type' # Otherwise, if property is @type and v is not an IRI, generate a new blank node identifier and add it to node for property. # FIXME: @type shouldn't really be a BNode, and not clear how we even get here from expansion name = blank_node?({'@id' => v}) ? namer.get_name(v) : v (node[prop] ||= []) << name else debug("nodeMap") {"value #{prop}: #{v.inspect}"} # Otherwise, add v to node for property. (node[prop] ||= []) << v end end end end end debug("nodeMap") {node_map.to_json(JSON_STATE)} end end |