Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Agents should be modeled a little better

  • Loading branch information...
commit f8f95630b7c777d1ba7ea3087677e4fdd1b4b1f2 1 parent f909b4b
Ross Singer authored

Showing 4 changed files with 23,455 additions and 41 deletions. Show diff stats Hide diff stats

  1. +23,087 0 example.ttl
  2. +123 38 marcmodeler.rb
  3. +13 3 rdf_resource.rb
  4. +232 0 relation.yml
23,087 example.ttl
23,087 additions, 0 deletions not shown
161 marcmodeler.rb
@@ -33,6 +33,7 @@ class MARC::Record
33 33 @@base_uri = 'http://library.cca.edu/core'
34 34 @@missing_id_prefix = 'cca'
35 35 @@missing_id_counter = 0
  36 + @@relators = YAML::load_file('relation.yml')
36 37
37 38 def subdivided?(subject)
38 39 subject.subfields.each do | subfield |
@@ -145,23 +146,23 @@ def to_rdf_resources
145 146
146 147 if subject.tag =~ /^(600|610|696|697)$/
147 148 if !subdivided?(subject)
148   - concept = RDFResource.new("#{@@base_uri}/i/#{literal.slug}#concept")
149   - identity = RDFResource.new("#{@@base_uri}/i/#{literal.slug}")
  149 + concept = RDFResource.new("#{@@base_uri}/#{Identity.path(subject)}/#{literal.slug}#concept")
  150 + identity = RDFResource.new("#{@@base_uri}/#{Identity.path(subject)}/#{literal.slug}")
150 151 else
151   - concept = RDFResource.new("#{@@base_uri}/s/#{literal.slug}#concept")
  152 + concept = RDFResource.new("#{@@base_uri}/subjects/#{literal.slug}#concept")
152 153 identity_subject = top_concept(subject)
153   - identity = RDFResource.new("#{@@base_uri}/i/#{subject_to_string(identity_subject).slug}")
  154 + identity = RDFResource.new("#{@@base_uri}/#{Identity.path(subject)}/#{subject_to_string(identity_subject).slug}")
154 155 end
155 156 if subject.tag =~ /^(600|696)$/
156 157 identity.relate("[rdf:type]","[foaf:Person]")
157 158 if subject['u']
158   - identity.assert("[ov:affiliation]", subject['u'].sub)
  159 + identity.assert("[ov:affiliation]", subject['u'].strip_trailing_punct)
159 160 end
160   - concept.relate("[skos:inScheme]", "#{@@base_uri}/s#personalNames")
  161 + concept.relate("[skos:inScheme]", "#{@@base_uri}/subjects#personalNames")
161 162 else
162 163 identity.relate("[rdf:type]","[foaf:Organization]")
163 164 identity.assert("[dct:description]", subject['u'])
164   - concept.relate("[skos:inScheme]", "#{@@base_uri}/s#corporateNames")
  165 + concept.relate("[skos:inScheme]", "#{@@base_uri}/subjects#corporateNames")
165 166 end
166 167 concept.relate("[rdfs:seeAlso]", identity.uri)
167 168 identity.relate("[rdfs:seeAlso]", concept.uri)
@@ -176,12 +177,12 @@ def to_rdf_resources
176 177 resources << identity
177 178 elsif subject.tag =~ /^(611|698)$/
178 179 if !subdivided?(subject)
179   - concept = RDFResource.new("#{@@base_uri}/e/#{literal.slug}#concept")
180   - event = RDFResource.new("#{@@base_uri}/e/#{literal.slug}")
  180 + concept = RDFResource.new("#{@@base_uri}/events/#{literal.slug}#concept")
  181 + event = RDFResource.new("#{@@base_uri}/events/#{literal.slug}")
181 182 else
182   - concept = RDFResource.new("#{@@base_uri}/s/#{literal.slug}#concept")
  183 + concept = RDFResource.new("#{@@base_uri}/subjects/#{literal.slug}#concept")
183 184 event_subject = top_concept(subject)
184   - event = RDFResource.new("#{@@base_uri}/e/#{subject_to_string(event_subject).slug}")
  185 + event = RDFResource.new("#{@@base_uri}/events/#{subject_to_string(event_subject).slug}")
185 186 end
186 187 concept.relate("[skos:inScheme]", "#{@@base_uri}/s#meetings")
187 188 event.relate("[rdf:type]","[event:Event]")
@@ -249,6 +250,7 @@ def to_rdf_resources
249 250 end
250 251 end
251 252 resources << concept
  253 + manifestation.relate("[dct:subject]", concept.uri)
252 254 end
253 255 authority = false
254 256 end
@@ -266,21 +268,65 @@ def to_rdf_resources
266 268 if self.form
267 269 manifestation.assert("[dc:format]", self.form(true))
268 270 end
269   - if self['100']
270   - identity = Identity.new_from_field(self['100'], "#{@@base_uri}/i/")
271   - end
272 271
273   - persons = self.find_all{|field| field.tag =~ /700|100|800|600|896|790|690/ && (field['e'] || field['4'])}
274   - persons.each do | person |
275   - if person['e']
276   - puts "$e: #{person['e']}"
277   - end
278   - if person['4']
279   - puts "$4: #{person['4']}"
280   - end
281   - end
  272 + identities = self.find_all{|field| field.tag =~ /100|110|400|410|700|710|720|790|791|796|797|800|810|896|897/}
  273 + identities.each do | identity_field |
  274 + identity = Identity.new_from_field(identity_field, "#{@@base_uri}/")
  275 + resources << identity.resource
  276 + relate_identity(identity_field, manifestation, identity)
  277 + end
  278 +
  279 + meetings = self.find_all{|field| field.tag =~ /111|411|711|792|798|811|898/}
  280 + meetings.each do | meeting |
  281 + identity = Identity.new_from_field(identity_field, "#{@@base_uri}/events/")
  282 + resources << identity.resource
  283 + relate_identity(identity_field, manifestation, identity)
  284 + end
282 285 resources
283 286 end
  287 +
  288 + def relate_identity(datafield, resource, identity)
  289 + if ["100","110"].index(datafield.tag)
  290 + resource.relate("[dct:creator]", identity.resource.uri)
  291 + resource.assert("[dc:creator]",identity.name)
  292 + end
  293 + relationships = []
  294 + datafield.subfields.each do | subfield |
  295 + next unless subfield.code == 'e' || subfield.code == '4'
  296 + next unless @@relators[subfield.value.strip_trailing_punct]
  297 + if pointer = @@relators[subfield.value.strip_trailing_punct]["use"]
  298 + if @@relators[subfield.value.strip_trailing_punct]["use"].is_a?(Array)
  299 + @@relators[subfield.value.strip_trailing_punct]["use"].each {|u| relationships << @@relators[u] }
  300 + else
  301 + relationships << @@relators[pointer]
  302 + end
  303 + else
  304 + relationships << @@relators[subfield.value.strip_trailing_punct]
  305 + end
  306 + end
  307 +
  308 + unless relationships.empty?
  309 + relationships.uniq.each do | rel |
  310 + if rel["relationship"]
  311 + if rel["relationship"].is_a?(Array)
  312 + rel["relationship"].each do | r |
  313 + resource.relate(r, identity.resource.uri)
  314 + end
  315 + else
  316 + resource.relate(rel['relationship'], identity.resource.uri)
  317 + end
  318 + end
  319 + if rel["literal"]
  320 + resource.assert(rel['literal'], identity.name)
  321 + end
  322 + end
  323 + else
  324 + unless ["100","110"].index(datafield.tag)
  325 + resource.relate("[dct:contributor]", identity.resource.uri)
  326 + resource.assert("[dc:contributor]", identity.resource.name)
  327 + end
  328 + end
  329 + end
284 330 end
285 331
286 332 class MARC::BookRecord
@@ -312,23 +358,32 @@ def [](code)
312 358 end
313 359
314 360 class Identity
  361 + attr_accessor :name, :resource
315 362 def self.new_from_field(field, base_uri)
  363 + identity = self.new
316 364 name = ''
317   - if field.tag == '100'
318   - name << field['a'].strip_trailing_punct
  365 +
  366 + personal = ["100","400","700","790","796", "800","896"]
  367 + corporate = ["110","410","710","791","797", "810", "897"]
  368 +
  369 + if personal.index(field.tag)
  370 + name << field['a']
319 371 ['b','c','d','q'].each do | code |
320   - name << field[code].lpad.strip_trailing_punct if field[code]
  372 + name << field[code].lpad if field[code]
321 373 end
322   - elsif field.tag == '110'
  374 + elsif corporate.index(field.tag)
323 375 name << field['a'].strip_trailing_punct
324 376 ['b','c','d'].each do | code |
325   - name << field[code].lpad.strip_trailing_punct if field[code]
  377 + name << field[code].lpad if field[code]
326 378 end
327   - end
328   - resource = RDFResource.new("#{base_uri}#{name.slug}")
329   - if field.tag == '100'
  379 + elsif field.tag == "720"
  380 + name = field['a'].strip_trailing_punct
  381 + end
  382 + identity.name = name.strip_trailing_punct
  383 + resource = RDFResource.new("#{base_uri}#{self.path(field)}/#{name.slug}")
  384 + if personal.index(field.tag)
330 385 resource.relate("[rdf:type]", "[foaf:Person]")
331   - if field.indicator1 == "2"
  386 + if field.indicator1 == "1"
332 387 last,first = field['a'].strip_trailing_punct.split(", ")
333 388 if last && first
334 389 resource.assert("[foaf:surname]", last)
@@ -338,16 +393,44 @@ def self.new_from_field(field, base_uri)
338 393 if field['q']
339 394 resource.assert("[dct:alternate]", field['q'].strip_leading_and_trailing_punct)
340 395 end
341   - elsif field.tag == '110'
  396 + if field['u']
  397 + resource.assert("[ov:affiliation]", field['u'].strip_trailing_punct)
  398 + end
  399 + elsif corporate.index(field.tag)
342 400 resource.relate("[rdf:type]", "[foaf:Organization]")
  401 + if field['u']
  402 + resource.assert("[dct:description]", field['u'].strip_trailing_punct)
  403 + end
  404 + elsif field.tag == "720"
  405 + if field.indicator1 == "1"
  406 + resource.relate("[rdf:type]", "[foaf:Person]")
  407 + else
  408 + resource.relate("[rdf:type]", "[foaf:Agent]")
  409 + end
343 410 end
344 411 resource.assert("[foaf:name]", field['a'].strip_trailing_punct)
345 412 if field['d']
346 413 resource.assert("[dct:date]", field['d'])
347 414 end
348   - resource
  415 + identity.resource = resource
  416 + identity
349 417 end
350   -
  418 + def self.path(datafield)
  419 + personal = ["100","400", "600","696","700","790","796", "800","896"]
  420 + corporate = ["110","410", "610", "697","710","791","797", "810", "897"]
  421 + if personal.index(datafield.tag)
  422 + return "people"
  423 + elsif corporate.index(datafield.tag)
  424 + return "organizations"
  425 + elsif datafield.tag == "720"
  426 + if datafield.indicator1 == "1"
  427 + return "people"
  428 + else
  429 + return "agents"
  430 + end
  431 + end
  432 + end
  433 +
351 434 def self.relations(field)
352 435
353 436 end
@@ -380,8 +463,10 @@ def self.relations(field)
380 463 reader.each do | record |
381 464 @resources += record.to_rdf_resources
382 465 i += 1
383   - #break if i > 1000
  466 + break if i > 1000
384 467 end
  468 +puts "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
385 469 @resources.each do | resource |
386   - #puts resource.to_rdfxml
387   -end
  470 + puts resource.to_rdfxml
  471 +end
  472 +puts "</rdf:RDF>"
16 rdf_resource.rb
@@ -7,15 +7,25 @@ class RDFResource
7 7 def initialize(uri)
8 8 Curie.add_prefixes! :frbr=>"http://vocab.org/frbr/core#", :dct=>"http://purl.org/dc/terms/", :bibo=>"http://purl.org/ontology/bibo/",
9 9 :skos=>"http://www.w3.org/2004/02/skos/core#", :rda=>"http://RDVocab.info/Elements/", :cat=>"http://schema.talis.com/2009/catalontology/",
10   - :rdfs=>"http://www.w3.org/2000/01/rdf-schema#", :ov=>"http://open.vocab.org/terms/", :event=>"http://purl.org/NET/c4dm/event.owl#"
11   - @uri = Curie.parse uri
  10 + :rdfs=>"http://www.w3.org/2000/01/rdf-schema#", :ov=>"http://open.vocab.org/terms/", :event=>"http://purl.org/NET/c4dm/event.owl#",
  11 + :role=>"http://RDVocab.info/roles/", :mo=>"http://purl.org/ontology/mo/", :rdf=>'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
  12 +
  13 + if uri.could_be_a_safe_curie?
  14 + @uri = Curie.parse uri
  15 + else
  16 + @uri = uri
  17 + end
12 18 @namespaces = ['http://www.w3.org/1999/02/22-rdf-syntax-ns#']
13 19
14 20 @modifiers = {}
15 21 end
16 22
17 23 def assert(predicate, object, type=nil, lang=nil)
18   - uri = URI.parse(Curie.parse predicate)
  24 + if predicate.could_be_a_safe_curie?
  25 + uri = URI.parse(Curie.parse predicate)
  26 + else
  27 + uri = URI.parse(predicate)
  28 + end
19 29 ns = nil
20 30 elem = nil
21 31 if uri.fragment
232 relation.yml
... ... @@ -0,0 +1,232 @@
  1 +---
  2 +dst:
  3 + label: Distributor
  4 + relationship: "[bibo:distributor]"
  5 +
  6 +music:
  7 + use: intr
  8 +ed:
  9 + label: Editor
  10 + relationship: "[bibo:editor]"
  11 + multiple: "[bibo:editorList]"
  12 + literal: "[dc:contributor]"
  13 +illus:
  14 + label: Illustrator
  15 + relationship: "[role:illustrator]"
  16 + literal: "[dc:contributor]"
  17 +dedicatee:
  18 + label: Dedicatee
  19 + relationship: "[role:dedicatee]"
  20 +printer:
  21 + use: prt
  22 +intr:
  23 + label: Instrumentalist
  24 + relationship: "[role:instrumentalist]"
  25 + literal: "[dc:contributor]"
  26 +nrt:
  27 + label: Narrator
  28 + relationship: "[role:narrator]"
  29 + literal: "[dc:contributor]"
  30 +artist, illus:
  31 + use: illus
  32 +jt. comp:
  33 + use: comp
  34 +prt:
  35 + label: Printer
  36 + relationship: "[role:printer]"
  37 +translator:
  38 + use: tr
  39 +ed. and tr:
  40 + use:
  41 + - ed
  42 + - translator
  43 +pbl:
  44 + label: Publisher
  45 + relationship: "[dct:publisher]"
  46 + literal: "[dc:publisher]"
  47 +cover designer:
  48 + label: Cover Designer
  49 + relationship: "[role:designer]"
  50 +artist:
  51 + label: Artist
  52 + relationship: "[role:artist]"
  53 + literal: "[dc:contributor]"
  54 +fot:
  55 +hst:
  56 + label: Host
  57 + relationship: "[role:host]"
  58 + literal: "[dc:contributor]"
  59 +act:
  60 + label: Actor
  61 + relationship: "[role:actor]"
  62 + literal: "[dc:contributor]"
  63 +editor:
  64 + use: ed
  65 +arr:
  66 + label: Arranger
  67 + relationship: "[role:arrangerOfMusic]"
  68 + literal: "[dc:contributor]"
  69 +trans:
  70 + use: tr
  71 +prd:
  72 + label: Production personnel
  73 + relationship: "[dct:contributor]"
  74 +art:
  75 + use: artist
  76 +joint illus:
  77 + use: illus
  78 +camera operator:
  79 + label: Videographer
  80 + relationship: "[role:cinematographer]"
  81 +ctb:
  82 + label: Contributor
  83 + relationship: "[dct:contributor]"
  84 + literal: "[dc:contributor]"
  85 +coaut:
  86 + use: aut
  87 +annotator:
  88 + label: Annotator
  89 + relationship: "[role:annotator]"
  90 + literal: "[dc:contributor]"
  91 +flm:
  92 + label: Film editor
  93 + relationship: "[role:editorOfMovingImageWork]"
  94 +pht:
  95 + label: Photographer
  96 + relationship: "[role:photographer]"
  97 + literal: "[dc:contributor]"
  98 +Co-auteur:
  99 + use: aut
  100 +prf:
  101 + label: Performer
  102 + relationship: "[role:performer]"
  103 + literal: "[dc:contributor]"
  104 +Translator:
  105 + use: tr
  106 +joint compiler:
  107 + use: com
  108 +com:
  109 + label: Compiler
  110 + relationship: "[role:compiler]"
  111 +ill:
  112 + use: illus
  113 +illustrator:
  114 + use: illus
  115 +drt:
  116 + label: Director
  117 + relationship: "[role:filmDirector]"
  118 + literal: "[dc:contributor]"
  119 +adp:
  120 + label: Adapter
  121 + relationship: "[dct:contributor]"
  122 + literal: "[dc:contributor]"
  123 +donor:
  124 + label: Donor
  125 + relationship: "[role:donor]"
  126 +defendant:
  127 + label: Defendant
  128 + relationship: "[role:defendant]"
  129 +architects:
  130 + label: Architect
  131 + relationship: "[role:architect]"
  132 +jt. ed:
  133 + use: ed
  134 +bookjacket designer:
  135 + label: Bookjacket designer
  136 + relationship: "[role:designer]"
  137 +research:
  138 + label: Researcher
  139 + relationship: "[dct:contributor]"
  140 +cnd:
  141 + label: Conductor
  142 + relationship: "[role:conductor]"
  143 + literal: "[dc:contributor]"
  144 +aus:
  145 + label: Screenwriter
  146 + relationship: "[role:screenwriter]"
  147 +jt. au:
  148 + use: aut
  149 +book designer:
  150 + label: Book designer
  151 + relationship: "[role:bookDesigner]"
  152 +joint comp:
  153 + use: cmp
  154 +cmm:
  155 + label: Commentator
  156 + relationship: "[role:commentator]"
  157 + literal: "[dc:contributor]"
  158 +cur:
  159 + label: Curator of an Exhibition
  160 + relationship: "[role:curator]"
  161 + literal: "[dc:contributor]"
  162 +photographer:
  163 + use: pht
  164 +bookbinder:
  165 + label: Binder
  166 + relationship: "[role:binder]"
  167 +comp. and illus:
  168 + use:
  169 + - com
  170 + - illus
  171 +sgn:
  172 + label: Signer
  173 + relationship: "[role:signer]"
  174 +aut:
  175 + label: Author
  176 + relationship: "[dct:creator]"
  177 + literal: "[dc:creator]"
  178 +jt. auth:
  179 + use: aut
  180 +publisher:
  181 + use: pbl
  182 +cng:
  183 + label: Cinematographer
  184 + relationship: "[role:directorOfPhotography]"
  185 + literal: "[dc:contributor]"
  186 +joint tr:
  187 + use: tr
  188 +ive:
  189 + label: Interviewee
  190 + relationship:
  191 + - "[bibo:interviewee]"
  192 + - "[role:interviewee]"
  193 + literal: "[dc:contributor]"
  194 +aud:
  195 + label: Author of dialog
  196 + relationship: "[dct:contributor]"
  197 + literal: "[dc:contributor]"
  198 +spk:
  199 + label: Speaker
  200 + relationship: "[role:speaker]"
  201 +tr:
  202 + label: Translator
  203 + relationship:
  204 + - "[bibo:translator]"
  205 + - "[role:translator]"
  206 + literal: "[dc:contributor]"
  207 +bkp:
  208 + label: Book producer
  209 + relationship: "[role:producer]"
  210 + literal: "[dc:publisher]"
  211 +cmp:
  212 + label: Composer
  213 + relationship: "[role:composer]"
  214 + literal: "[dc:contributor]"
  215 +comp:
  216 + use: cmp
  217 +pro:
  218 + label: Producer
  219 + relationship:
  220 + - "[bibo:producer]"
  221 + - "[role:filmProducer]"
  222 + literal: "[dc:contributor]"
  223 +comp. and tr:
  224 + use:
  225 + - com
  226 + - tr
  227 +edt:
  228 + use: ed
  229 +trl:
  230 + use: tr
  231 +binder:
  232 + use: bookbinder

0 comments on commit f8f9563

Please sign in to comment.
Something went wrong with that request. Please try again.