Class: FtrRuby::DCAT_Record

Inherits:
Object
  • Object
show all
Includes:
TripleEasy
Defined in:
lib/dcat_metadata.rb

Overview

Represents a single FAIR Test as a DCAT-compliant DataService with additional FAIR-specific metadata.

This class generates RDF metadata (in a DCAT + DQV + FTR vocabulary profile) describing a test that can be used to assess FAIR compliance of digital objects (typically datasets). The resulting graph follows the DCAT-AP style for Data Services, extended with FAIR Test Registry (FTR) semantics.

Usage

meta = {
  testid:        "ftr-rda-f1-01m",
  testname:      "FAIR Test F1-01M: Persistent Identifier",
  description:   "Checks whether the digital object has a globally unique persistent identifier...",
  keywords:      ["FAIR", "persistent identifier", "F1"],
  creator:       "https://orcid.org/0000-0001-2345-6789",
  indicators:    ["https://w3id.org/ftr/indicator/F1-01M"],
  metric:        "https://w3id.org/ftr/metric/F1-01M",
  license:       "https://creativecommons.org/licenses/by/4.0/",
  testversion:   "1.0",
  # ... other fields
}

record = FtrRuby::DCAT_Record.new(meta: meta)
graph  = record.get_dcat

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(meta:) ⇒ DCAT_Record

Note:

Several fields have sensible defaults (e.g. dctype, supportedby, applicationarea). The end_url and identifier are automatically constructed from protocol, host, basePath, and testid.

Creates a new DCAT_Record from metadata hash.

Parameters:

  • meta (Hash)

    Metadata describing the FAIR test.

Options Hash (meta:):

  • :testid (String)

    Unique identifier for the test (used in URLs)

  • :testname (String)

    Human-readable name/title of the test

  • :description (String)

    Detailed description of what the test does

  • :keywords (String, Array<String>)

    Keywords describing the test

  • :creator (String)

    URI or literal identifying the creator

  • :indicators (String, Array<String>)

    URIs of the FAIR indicators this test addresses

  • :metric (String)

    URI of the metric this test implements

  • :license (String)

    License URI for the test

  • :themes (String, Array<String>)

    Thematic categories (DCAT themes)

  • :testversion (String)

    Version of the test

  • :individuals (Array<Hash>)

    List of contact individuals (name, email)

  • :organizations (Array<Hash>)

    List of responsible organizations (name, url)

  • :protocol (String)

    Protocol (http/https)

  • :host (String)

    Hostname of the test service

  • :basePath (String)

    Base path of the test service



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
# File 'lib/dcat_metadata.rb', line 65

def initialize(meta:)
  indics = [meta[:indicators]] unless meta[:indicators].is_a? Array
  @indicators = indics
  @testid = meta[:testid]
  @testname = meta[:testname]
  @metric = meta[:metric]
  @description = meta[:description] || "No description provided"
  @keywords = meta[:keywords] || []
  @keywords = [@keywords] unless @keywords.is_a? Array
  @creator = meta[:creator]
  @end_desc = meta[:end_desc]
  @end_url = meta[:end_url]
  @dctype = meta[:dctype] || "http://edamontology.org/operation_2428"
  @supportedby = meta[:supportedby] || ["https://tools.ostrails.eu/champion"]
  @applicationarea = meta[:applicationarea] || ["http://www.fairsharing.org/ontology/subject/SRAO_0000401"]
  @isapplicablefor = meta[:isapplicablefor] || ["https://schema.org/Dataset"]
  @license = meta[:license] || "No License"
  @themes = meta[:themes] || []
  @themes = [@themes] unless @themes.is_a? Array
  @testversion = meta[:testversion] || "unversioned"
  @organizations = meta[:organizations] || []
  @individuals = meta[:individuals] || []
  @protocol = meta[:protocol]
  @host = meta[:host]
  @basePath = meta[:basePath]
  cleanhost = @host.gsub("/", "")
  cleanpath = @basePath.gsub("/", "") # TODO: this needs to check only leading and trailing!  NOt internal...
  endpointpath = "assess/test"
  @end_url = "#{protocol}://#{cleanhost}/#{cleanpath}/#{endpointpath}/#{testid}"
  @end_desc = "#{protocol}://#{cleanhost}/#{cleanpath}/#{testid}/api"
  @identifier = "#{protocol}://#{cleanhost}/#{cleanpath}/#{testid}"
  @definedby =  meta[:definedby] || @identifier
  @landingpage = meta[:landingPage] || @identifier

  unless @testid && @testname && @description && @creator && @end_desc && @end_url && @protocol && @host && @basePath
    warn "this record is invalid - it is missing one of  testid testname description creator  end_desc end_url protocol  host  basePath"
  end
end

Instance Attribute Details

#applicationareaObject

Returns the value of attribute applicationarea.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def applicationarea
  @applicationarea
end

#basePathObject

Returns the value of attribute basePath.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def basePath
  @basePath
end

#creatorObject

Returns the value of attribute creator.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def creator
  @creator
end

#dctypeObject

Returns the value of attribute dctype.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def dctype
  @dctype
end

#definedbyObject

Returns the value of attribute definedby.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def definedby
  @definedby
end

#descriptionObject

Returns the value of attribute description.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def description
  @description
end

#end_descObject

Returns the value of attribute end_desc.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def end_desc
  @end_desc
end

#end_urlObject

Returns the value of attribute end_url.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def end_url
  @end_url
end

#hostObject

Returns the value of attribute host.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def host
  @host
end

#identifierObject

Returns the value of attribute identifier.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def identifier
  @identifier
end

#implementationsObject

Returns the value of attribute implementations.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def implementations
  @implementations
end

#indicatorsObject

Returns the value of attribute indicators.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def indicators
  @indicators
end

#individualsObject

Returns the value of attribute individuals.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def individuals
  @individuals
end

#isapplicableforObject

Returns the value of attribute isapplicablefor.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def isapplicablefor
  @isapplicablefor
end

#keywordsObject

Returns the value of attribute keywords.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def keywords
  @keywords
end

#landingpageObject

Returns the value of attribute landingpage.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def landingpage
  @landingpage
end

#licenseObject

Returns the value of attribute license.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def license
  @license
end

#metricObject

Returns the value of attribute metric.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def metric
  @metric
end

#organizationsObject

Returns the value of attribute organizations.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def organizations
  @organizations
end

#protocolObject

Returns the value of attribute protocol.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def protocol
  @protocol
end

#supportedbyObject

Returns the value of attribute supportedby.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def supportedby
  @supportedby
end

#testidObject

Returns the value of attribute testid.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def testid
  @testid
end

#testnameObject

Returns the value of attribute testname.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def testname
  @testname
end

#testversionObject

Returns the value of attribute testversion.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def testversion
  @testversion
end

#themesObject

Returns the value of attribute themes.



32
33
34
# File 'lib/dcat_metadata.rb', line 32

def themes
  @themes
end

Instance Method Details

#get_dcatRDF::Graph

Returns an RDF::Graph containing the DCAT metadata for this test.

The graph describes the test as both a dcat:DataService and an ftr:Test. It includes:

  • Core DCAT properties (identifier, title, description, keywords, landing page, etc.)

  • FAIR-specific extensions via the FTR vocabulary

  • Contact points (individuals and organizations) using vCard

  • Link to the metric it implements (SIO)

  • Supported-by relationships, application areas, and applicability statements

Returns:

  • (RDF::Graph)

    RDF graph with the complete DCAT record



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/dcat_metadata.rb', line 118

def get_dcat
  schema = RDF::Vocab::SCHEMA
  dcterms = RDF::Vocab::DC
  xsd = RDF::Vocab::XSD
  dcat = RDF::Vocab::DCAT
  sio = RDF::Vocabulary.new("http://semanticscience.org/resource/")
  ftr = RDF::Vocabulary.new("https://w3id.org/ftr#")
  dqv = RDF::Vocabulary.new("http://www.w3.org/ns/dqv#")
  vcard = RDF::Vocabulary.new("http://www.w3.org/2006/vcard/ns#")
  dpv = RDF::Vocabulary.new("https://w3id.org/dpv#")

  g = RDF::Graph.new
  #      me = "#{identifier}/about"   # at the hackathon we decided that the test id would return the metadata
  # so now there is no need for /about
  me = "#{identifier}"

  triplify(me, RDF.type, dcat.DataService, g)
  triplify(me, RDF.type, ftr.Test, g)

  # triplify tests and rejects anything that is empty or nil  --> SAFE
  # Test Unique Identifier	dcterms:identifier	Literal
  triplify(me, dcterms.identifier, identifier.to_s, g, datatype: xsd.string)

  # Title/Name of the test	dcterms:title	Literal
  triplify(me, dcterms.title, testname, g)

  # Description	dcterms:description	Literal
  # descriptions.each do |d|
  #   triplify(me, dcterms.description, d, g)
  # end
  triplify(me, dcterms.description, description, g)

  # Keywords	dcat:keyword	Literal
  keywords.each do |kw|
    triplify(me, dcat.keyword, kw, g)
  end

  # Test creator	dcterms:creator	dcat:Agent (URI)
  triplify(me, dcterms.creator, creator, g)

  # Dimension	ftr:indicator
  indicators.each do |ind|
    triplify(me, dqv.inDimension, ind, g)
  end

  # API description	dcat:endpointDescription	rdfs:Resource
  triplify(me, dcat.endpointDescription, end_desc, g)

  # API URL	dcat:endpointURL	rdfs:Resource
  triplify(me, dcat.endpointURL, end_url, g)

  # API URL	dcat:landingPage	rdfs:Resource
  triplify(me, dcat.landingPage, landingpage, g)

  # pointer to this turtle file
  triplify(me, RDF::Vocab::RDFS.isDefinedBy, definedby, g)

  # Functional Descriptor/Operation	dcterms:type	xsd:anyURI
  triplify(me, dcterms.type, dctype, g)

  # License	dcterms:license	xsd:anyURI
  triplify(me, dcterms.license, license, g)

  # Semantic Annotation	dcat:theme	xsd:anyURI
  themes.each do |theme|
    triplify(me, dcat.theme, theme, g)
  end

  # Version	dcat:version	rdfs:Literal
  triplify(me, RDF::Vocab::DCAT.to_s + "version", testversion, g)

  triplify(me, sio["SIO_000233"], metric, g) # is implementation of
  triplify(metric, RDF.type, dqv.Metric, g) # is implementation of

  # Responsible	dcat:contactPoint	dcat:Kind (includes Individual/Organization)
  individuals.each do |i|
    # i = {name: "Mark WAilkkinson", "email": "asmlkfj;askjf@a;lksdjfas"}
    guid = SecureRandom.uuid
    cp = "urn:fairchampion:testmetadata:individual#{guid}"
    triplify(me, dcat.contactPoint, cp, g)
    triplify(cp, RDF.type, vcard.Individual, g)
    triplify(cp, vcard.fn, i["name"], g) if i["name"]
    next unless i["email"]

    email = i["email"].to_s
    email = "mailto:#{email}" unless email =~ /mailto:/
    triplify(cp, vcard.hasEmail, RDF::URI.new(email), g)
  end

  organizations.each do |o|
    # i = {name: "CBGP", "url": "https://dbdsf.orhf"}
    guid = SecureRandom.uuid
    cp = "urn:fairchampion:testmetadata:org:#{guid}"
    triplify(me, dcat.contactPoint, cp, g)
    triplify(cp, RDF.type, vcard.Organization, g)
    triplify(cp, vcard["organization-name"], o["name"], g)
    triplify(cp, vcard.url, RDF::URI.new(o["url"].to_s), g)
  end

  supportedby.each do |tool|
    triplify(me, ftr.supportedBy, tool, g)
    triplify(tool, RDF.type, schema.SoftwareApplication, g)
  end

  applicationarea.each do |domain|
    triplify(me, ftr.applicationArea, domain, g)
  end
  isapplicablefor.each do |digitalo|
    triplify(me, dpv.isApplicableFor, digitalo, g)
  end

  g
end