/
context_property_map.rb
137 lines (119 loc) · 6.2 KB
/
context_property_map.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Defines the external authority predicates used to extract additional context from the graph.
require 'ldpath'
module Qa
module LinkedData
module Config
class ContextPropertyMap
attr_reader :group_id, # id that identifies which group the property should be in
:label # plain text label extracted from locales or using the default
attr_reader :property_map, :ldpath, :expansion_label_ldpath, :expansion_id_ldpath, :prefixes
private :property_map, :ldpath, :expansion_label_ldpath, :expansion_id_ldpath, :prefixes
# @param [Hash] property_map defining information to return to provide context
# @option property_map [String] :group_id (optional) default label to use for a property (default: no label)
# @option property_map [String] :property_label_i18n (optional) i18n key to use to get the label for a property (default: property_label_default OR no label if neither are defined)
# @option property_map [String] :property_label_default (optional) default label to use for a property (default: no label)
# @option property_map [String] :ldpath (required) identifies the values to extract from the graph (based on http://marmotta.apache.org/ldpath/language.html)
# @option property_map [Boolean] :selectable (optional) if true, this property can selected as the value (default: false)
# @option property_map [Boolean] :drillable (optional) if true, the label for this property can be used to execute a second query allowing navi (default: false)
# @param [Hash] shortcut names for URI prefixes with key = part of predicate that is the same for all terms (e.g. { "madsrdf": "http://www.loc.gov/mads/rdf/v1#" })
# @example property_map example
# {
# "group_id": "dates",
# "property_label_i18n": "qa.linked_data.authority.locnames_ld4l_cache.birth_date",
# "property_label_default": "Birth",
# "ldpath": "madsrdf:identifiesRWO/madsrdf:birthDate/schema:label",
# "selectable": false,
# "drillable": false
# }
def initialize(property_map = {}, prefixes = {})
@property_map = property_map
@group_id = Qa::LinkedData::Config::Helper.fetch_symbol(property_map, :group_id, nil)
@label = extract_label
@ldpath = Qa::LinkedData::Config::Helper.fetch_required(property_map, :ldpath, false)
@selectable = Qa::LinkedData::Config::Helper.fetch_boolean(property_map, :selectable, false)
@drillable = Qa::LinkedData::Config::Helper.fetch_boolean(property_map, :drillable, false)
@expansion_label_ldpath = Qa::LinkedData::Config::Helper.fetch(property_map, :expansion_label_ldpath, nil)
@expansion_id_ldpath = Qa::LinkedData::Config::Helper.fetch(property_map, :expansion_id_ldpath, nil)
@prefixes = prefixes
end
# Can this property be the selected value?
# @return [Boolean] true if this property's value can be selected; otherwise, false
def selectable?
@selectable
end
# Can this property be used as a new query
# @return [Boolean] true if this property's value can be used to drill up/down to another level; otherwise, false
def drillable?
@drillable
end
def group?
group_id.present?
end
# Should this URI value be expanded to include its label?
# @return [Boolean] true if this property's value is expected to be a URI and its label should be included in the value; otherwise, false
def expand_uri?
expansion_label_ldpath.present?
end
# Values of this property for a specfic subject URI
# @return [Array<String>] values for this property
def values(graph, subject_uri)
ldpath_evaluate(basic_program, graph, subject_uri)
end
# Values of this property for a specfic subject URI with URI values expanded to include id and label.
# @return [Array<Hash>] expanded values for this property
# @example returned values
# [{
# uri: "http://id.loc.gov/authorities/genreForms/gf2014026551",
# id: "gf2014026551",
# label: "Space operas"
# }]
def expanded_values(graph, subject_uri)
values = values(graph, subject_uri)
return values unless expand_uri?
return values unless values.respond_to? :map!
values.map! do |uri|
{ uri: uri, id: expansion_id(graph, uri), label: expansion_label(graph, uri) }
end
values
end
private
def extract_label
i18n_key = Qa::LinkedData::Config::Helper.fetch(property_map, :property_label_i18n, nil)
default = Qa::LinkedData::Config::Helper.fetch(property_map, :property_label_default, nil)
return I18n.t(i18n_key, default: default) if i18n_key.present?
default
end
def basic_program
@basic_program ||= ldpath_program(ldpath)
end
def expansion_label_program
@expansion_label_program ||= ldpath_program(expansion_label_ldpath)
end
def expansion_id_program
@expansion_id_program ||= ldpath_program(expansion_id_ldpath)
end
def ldpath_program(ldpath)
program_code = ""
prefixes.each { |key, url| program_code << "@prefix #{key} : <#{url}> \;\n" }
program_code << "property = #{ldpath} \;"
Ldpath::Program.parse program_code
end
def ldpath_evaluate(program, graph, subject_uri)
output = program.evaluate subject_uri, graph
output.present? ? output['property'].uniq : nil
rescue
'PARSE ERROR'
end
def expansion_label(graph, uri)
label = ldpath_evaluate(expansion_label_program, graph, RDF::URI(uri))
label.size == 1 ? label.first : label
end
def expansion_id(graph, uri)
return uri if expansion_id_ldpath.blank?
id = ldpath_evaluate(expansion_id_program, graph, RDF::URI(uri))
id.size == 1 ? id.first : id
end
end
end
end
end