Skip to content

Commit 86af939

Browse files
committed
Add language operator for matching lanugage tags. JSON-LD predicate is languageTag.
1 parent e6d3bf0 commit 86af939

File tree

6 files changed

+77
-2
lines changed

6 files changed

+77
-2
lines changed

examples/lang_stem.shex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
PREFIX my: <http://my.example/>
2+
3+
my:IssueShape {
4+
my:status [@en~ @fr];
5+
}

lib/shex/algebra.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Algebra
1313
autoload :External, 'shex/algebra/external'
1414
autoload :IriStem, 'shex/algebra/stem'
1515
autoload :IriStemRange, 'shex/algebra/stem_range'
16+
autoload :Language, 'shex/algebra/language'
1617
autoload :LanguageStem, 'shex/algebra/stem'
1718
autoload :LanguageStemRange,'shex/algebra/stem_range'
1819
autoload :LiteralStem, 'shex/algebra/stem'
@@ -56,6 +57,7 @@ def self.from_shexj(operator, options = {})
5657
when 'EachOf' then EachOf
5758
when 'IriStem' then IriStem
5859
when 'IriStemRange' then IriStemRange
60+
when 'Language' then Language
5961
when 'LanguageStem' then LanguageStem
6062
when 'LanguageStemRange' then LanguageStemRange
6163
when 'LiteralStem' then LiteralStem

lib/shex/algebra/language.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module ShEx::Algebra
2+
##
3+
class Language < Operator::Unary
4+
NAME = :language
5+
6+
##
7+
# matches any literal having a language tag that matches value
8+
def match?(value, depth: 0)
9+
status "", depth: depth
10+
if case expr = operands.first
11+
when RDF::Literal then value.lanuage == expr.to_sym
12+
else false
13+
end
14+
status "matched #{value}", depth: depth
15+
true
16+
else
17+
status "not matched #{value}", depth: depth
18+
false
19+
end
20+
end
21+
end
22+
end

lib/shex/algebra/operator.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,12 @@ def self.from_shexj(operator, options = {})
269269
case k
270270
when /length|clusive|digits/ then operands << [k.to_sym, RDF::Literal(v)]
271271
when 'id' then id = iri(v, options)
272-
when 'flags' then ; # consumed in pattern below
272+
when 'flags' then ; # consumed in pattern below
273273
when 'min', 'max' then operands << [k.to_sym, (v == -1 ? '*' : v)]
274274
when 'inverse', 'closed' then operands << k.to_sym
275275
when 'nodeKind' then operands << v.to_sym
276276
when 'object' then operands << value(v, options)
277+
when 'languageTag' then operands << v
277278
when 'pattern'
278279
# Include flags as well
279280
operands << [:pattern, RDF::Literal(v), operator['flags']].compact
@@ -408,6 +409,7 @@ def to_h
408409
when EachOf, OneOf then (obj['expressions'] ||= []) << op.to_s
409410
when And, Or then (obj['shapeExprs'] ||= []) << op.to_s
410411
when Not then obj['shapeExpr'] = op.to_s
412+
when Language then obj['languageTag'] = op.to_s
411413
else
412414
raise "How to serialize Value #{op.inspect} to json for #{self}"
413415
end

lib/shex/parser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ def shape_definition(input, data)
641641
elsif data[:dot]
642642
Algebra::LanguageStemRange.new(:wildcard, exclusions)
643643
else
644-
data[:language]
644+
Algebra::Language.new(data[:language])
645645
end
646646
end
647647

spec/parser_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,50 @@
11531153
(min 0)
11541154
(max 1)) ))))}
11551155
},
1156+
"Language Stems" => {
1157+
shexc: %(
1158+
PREFIX my: <http://my.example/>
1159+
1160+
my:IssueShape {
1161+
my:status [@en~ @fr];
1162+
}
1163+
),
1164+
sxp: %{(schema
1165+
(prefix (("my" <http://my.example/>)))
1166+
(shapes
1167+
(shape
1168+
(id <http://my.example/IssueShape>)
1169+
(tripleConstraint
1170+
(predicate <http://my.example/status>)
1171+
(nodeConstraint (value (languageStem "en")) (value (language "fr")))) )) )},
1172+
shexj: %({
1173+
"@context": "http://www.w3.org/ns/shex.jsonld",
1174+
"type": "Schema",
1175+
"shapes": [
1176+
{
1177+
"id": "http://my.example/IssueShape",
1178+
"type": "Shape",
1179+
"expression": {
1180+
"type": "TripleConstraint",
1181+
"predicate": "http://my.example/status",
1182+
"valueExpr": {
1183+
"type": "NodeConstraint",
1184+
"values": [
1185+
{
1186+
"type": "LanguageStem",
1187+
"stem": "en"
1188+
},
1189+
{
1190+
"type": "Language",
1191+
"languageTag": "fr"
1192+
}
1193+
]
1194+
}
1195+
}
1196+
}
1197+
]
1198+
})
1199+
},
11561200
}.each do |name, params|
11571201
it "#{name} (shexc)" do
11581202
expect(params[:shexc]).to generate(params[:sxp].gsub(/^ /m, ''), progress: true, logger: RDF::Spec.logger)

0 commit comments

Comments
 (0)