Created
April 22, 2015 23:37
-
-
Save mwlang/58637144c7bf032c7205 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Onix21 | |
class Base | |
include Logger | |
attr_reader :values | |
attr_reader :properties | |
def section_matches_class section | |
self_class = self.class.to_s.underscore.split('/').last.gsub("_",'').to_sym | |
raise "#{self_class.inspect} expected, but got #{section.inspect}" unless self_class == section | |
end | |
def initialize section, values, parent = nil | |
section_matches_class section | |
@properties = [] | |
@values = values.first.is_a?(Array) ? values : [values] | |
assign_properties | |
unless fully_consumed? | |
puts '=' * 40 | |
puts section.inspect | |
pp @values | |
puts "Belongs to: #{parent.class.name}" if parent | |
puts '-' * 40 | |
end | |
end | |
def extract_items xml_tag | |
(extracted, @values = @values.partition{|p| p[0] == xml_tag}).first | |
end | |
def extract section, parent = nil | |
xml_tag = section.to_s.gsub("_", '').to_sym | |
klass = "Onix21::#{section.to_s.camelize}".constantize | |
extract_items(xml_tag).map{ |values| klass.new(*values, parent) } | |
end | |
def set_if_present property_name, xml_tag, present_value | |
extracted = extract_items xml_tag | |
instance_variable_set "@#{property_name}", (extracted.empty? ? !present_value : present_value) | |
end | |
def extract_property property_name, xml_tag, repeatable = false | |
limit = (!!repeatable ? 999 : 1) | |
extracted = extract_items xml_tag | |
if extracted.size > limit | |
raise "set_property expects only one instance for #{property_name}/#{xml_tag}, but got #{extracted.size}" | |
end | |
return Array(extracted.first).last | |
end | |
def set_property property_name, xml_tag, repeatable = false | |
value = extract_property(property_name, xml_tag, repeatable) | |
instance_variable_set "@#{property_name}", value | |
end | |
# Can set date from any of YYYY, YYYYMM, or YYYYMMDD | |
def set_property_date property_name, xml_tag | |
value = extract_property(property_name, xml_tag, false) | |
if value and matches = value.match(/(\d{4})(\d{2})?(\d{2})?/) | |
instance_variable_set "@#{property_name}", Date.new(*matches.captures.compact.map(&:to_i)) | |
else | |
instance_variable_set "@#{property_name}", nil | |
end | |
end | |
def set_property_list property_name, xml_tag, repeatable = false | |
value = extract_property(property_name, xml_tag, repeatable) | |
instance_variable_set "@#{property_name}", value.nil? ? nil : value.split(" ") | |
end | |
def fully_consumed? | |
values.empty? | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Onix21 | |
class Product < Base | |
attr_reader :values | |
attr_reader :main_subject, :subjects, :identifiers, :contributors, :supply_details | |
attr_reader :series, :sales_rights, :measures, :work_identifiers | |
attr_reader :publishers, :product_websites, :audience_ranges | |
attr_reader :imprints, :related_products, :titles | |
attr_reader :contained_items, :sets, :extents | |
attr_reader :bwk_rec_ref_num, :other_texts | |
attr_reader :notification_type, :record_source_type, :record_source_name | |
attr_reader :barcodes, :product_form, :product_form_details, :product_packaging | |
attr_reader :epub_type, :epub_type_description, :epub_type_note, :epub_format, :epub_source, :epub_source_description | |
attr_reader :number_of_pages, :number_of_illustrations, :pages_roman, :pages_arabic | |
attr_reader :bisac_main_subject_category, :bisac_version | |
attr_reader :audience_codes | |
attr_reader :city_of_publication, :country_of_publication | |
attr_reader :publication_date, :copyright_year, :year_first_published, :out_of_print_date | |
attr_reader :edition_type_codes, :edition_number | |
attr_reader :publishing_status_code | |
attr_reader :illustrations_note | |
attr_reader :no_contributor | |
attr_reader :no_series | |
attr_reader :trade_category | |
attr_reader :number_of_volumes | |
attr_reader :languages | |
attr_reader :distinctive_title, :title_prefix, :title_without_prefix, :sub_title | |
attr_reader :title_text_case, :translated_title, :former_title | |
def id | |
@id ||= (item = @identifiers.detect{|d| d.type == '03'} and item.id) | |
end | |
def isbn | |
@isbn ||= (item = @identifiers.detect{|d| d.type == '02'} and item.id) | |
end | |
def publisher_record | |
@publisher_record ||= publishers.first.record rescue nil | |
end | |
def publisher_id | |
publisher_record and publisher_record[:id] | |
end | |
def imprint_record | |
@imprint_record ||= imprints.first.record rescue nil | |
end | |
def imprint_id | |
return imprint_record[:id] if imprint_record | |
return publisher_record[:id] if publisher_record | |
end | |
def imprint_name | |
return imprint_record[:name] if imprint_record | |
return publisher_record[:name] if publisher_record | |
end | |
def description | |
if other_text = other_texts.detect{|d| d.type == '01'} | |
other_text.description | |
else | |
'' | |
end | |
end | |
def title_parts | |
if product_title = titles.detect{|d| d.type == '01'} | |
product_title.title_parts | |
else | |
raise ImportError, "Title not found for type '01'" | |
end | |
end | |
def get_avail_status_id(avail_status_code) | |
raise ImportError, "No avail_status_code given!" if avail_status_code.blank? | |
db[:avail_statuses].filter(code: avail_status_code).get(:id) | |
end | |
def get_avail_status_code | |
unless publishing_status_code.blank? | |
code = db[:avail_statuses___av]. | |
join(:publishing_statuses___ps, :ps__avail_status_id => :av__id). | |
filter(ps__code: publishing_status_code). | |
get(:av__code) | |
return code unless code.blank? | |
end | |
return product_availability_code unless product_availability_code.blank? | |
unless fallback_availability_status_code.blank? | |
code = db[:avail_statuses___av]. | |
join(:product_avail_statuses___pas, :pas__avail_status_id => :av__id). | |
filter(pas__code: fallback_availability_status_code). | |
get(:av__code) | |
return code unless code.blank? | |
end | |
raise ImportError, "Could not look up avail_status_code" | |
end | |
def product_availability_code | |
(sd = supply_details.first) ? sd.product_availability_code : nil | |
end | |
def fallback_availability_status_code | |
(sd = supply_details.first) ? sd.availability_status_code : nil | |
end | |
def availability_status_code | |
@avail_status_code ||= get_avail_status_code(fallback_avail_status) | |
end | |
def availability_status_id | |
@avail_status_id ||= get_avail_status_id(availability_status_code) | |
end | |
# supply_to_country and supply_to_territory supplies detailed regional availability, | |
# however, Polybook only cares about "US" and "GB" where Bowker data is concerned, | |
# so we base market_code off the Bowker UID for the product and ignore the territorial data | |
def market_code | |
return "US" if bwk_rec_ref_num =~ /USA/ | |
return "GB" | |
end | |
def replaced_by_product | |
@replaced ||= related_products.detect{|p| p.type == '05'} | |
end | |
def replaces_product | |
@replaces ||= related_products.detect{|p| p.type == '03'} | |
end | |
def replaced_by_item_id | |
replaced_by_product ? replaced_by_product.id : nil | |
end | |
def replaces_item_id | |
replaces_product ? replaces_product.id : nil | |
end | |
# NOTE: the leading comma is intentional (as taken from original Perl script). | |
def pagination | |
[pages_roman.to_s, (pages_arabic || number_of_pages).to_s].join(", ") | |
end | |
def get_measure type | |
@measures.detect{|d| d.type == type} | |
end | |
def weight | |
(measure = get_measure("08")) ? measure.convert_to_grams : nil | |
end | |
def dimensions_length | |
(measure = get_measure("01")) ? measure.convert_to_cm : nil | |
end | |
def dimensions_width | |
(measure = get_measure("02")) ? measure.convert_to_cm : nil | |
end | |
def dimensions_height | |
(measure = get_measure("03")) ? measure.convert_to_cm : nil | |
end | |
def website_urls | |
product_websites.map(&:short_url).join(";") | |
end | |
def publication_language | |
(lang = @languages.detect{|l| l.role == '01'}) ? lang.code : nil | |
end | |
def original_language | |
(lang = @languages.detect{|l| l.role == '02'}) ? lang.code : nil | |
end | |
def all_subjects | |
@all_subjects = main_subject + subjects | |
end | |
def dewey | |
@dewey ||= (subj = all_subjects.detect{|s| s.scheme_id == '01'}) ? subj.value : nil | |
end | |
def lc_class | |
@lc_class ||= (subj = all_subjects.detect{|s| s.scheme_id == '03'}) ? subj.value : nil | |
end | |
def work_id | |
(ident = @worker_identifiers.detect{|w| w.type == '01'}) ? ident.id : nil | |
end | |
def assign_properties | |
@main_subject = extract(:main_subject) | |
@subjects = extract(:subject) | |
@identifiers = extract(:product_identifier) | |
@contributors = extract(:contributor) | |
@supply_details = extract(:supply_detail) | |
@series = extract(:series) | |
@other_texts = Array(extract(:other_text)) | |
@sales_rights = extract(:sales_rights) | |
@measures = extract(:measure) | |
@work_identifiers = extract(:work_identifier) | |
@publishers = extract(:publisher) | |
@titles = extract(:title) | |
@languages = extract(:language) | |
@product_websites = extract(:product_website) | |
@audience_ranges = extract(:audience_range) | |
@imprints = extract(:imprint) | |
@related_products = extract(:related_product) | |
@prizes = extract(:prize) | |
@contained_items = extract(:contained_item) | |
@sets = extract(:set) | |
@extents = extract(:extent) | |
set_property :bwk_rec_ref_num, :a001 | |
set_property :notification_type, :a002 | |
set_property :record_source_type, :a194 | |
set_property :record_source_name, :a197 | |
set_property :barcode, :b246, :repeatable | |
set_property :product_form, :b012 | |
set_property :product_form_details, :b333, :repeatable | |
set_property :product_packaging, :b225 | |
set_property :epub_type, :b211 | |
set_property :epub_type_description, :b213 | |
set_property :epub_type_note, :b277 | |
set_property :epub_format, :b214 | |
set_property :epub_source, :b278 | |
set_property :epub_source_description, :b280 | |
set_property :number_of_pages, :b061 | |
set_property :pages_roman, :b254 | |
set_property :pages_arabic, :b255 | |
set_property :bisac_main_subject_category, :b064 | |
set_property :bisac_version, :b200 | |
set_property :audience_codes, :b073, :repeatable | |
set_property :city_of_publication, :b209 | |
set_property :country_of_publication, :b083 | |
set_property_date :publication_date, :b003 | |
set_property_date :out_of_print_date, :h134 | |
set_property :copyright_year, :b087 | |
set_property :edition_type_codes, :b056, :repeatable | |
set_property :publishing_status_code, :b394 | |
set_property :number_of_illustrations, :b125 | |
set_property :illustrations_note, :b062 | |
set_property :edition_number, :b057 | |
set_property :year_first_published, :b088 | |
set_if_present :no_contributor, :n339, true | |
set_if_present :no_series, :n338, true | |
set_property :trade_category, :b384 | |
set_property :number_of_volumes, :b210 | |
set_property :distinctive_title, :b028 | |
set_property :title_prefix, :b030 | |
set_property :title_without_prefix, :b031 | |
set_property :sub_title, :b029 | |
set_property :title_text_case, :b027 | |
set_property :translated_title, :b032 | |
set_property :former_title, :b033 | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment