Class: Hip3::Bib

Inherits:
Object
  • Object
show all
Defined in:
app/models/hip3/bib.rb

Overview

Bib record/object from HIP. Fetches in it's own data via HIP XML interface. Which may make it sensitive, sorry. If not fetched in yet, # for an item with 'copy' (serial) control, we have to do TWO fetches to get complete information, one for summary holdings statements, plus another for items. Sigh, sorry.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argBibNum, a_hip_base_path, params) ⇒ Bib

it already, give it to us and we won't have to fetch it. http_session => optional already initialized http session. You are

advised to use a Hip3::HTTPSession for it's error 
handling.

Raises:

  • (ArgumentException)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/models/hip3/bib.rb', line 31

def initialize(argBibNum, a_hip_base_path, params)
    @title_label = 'Title'
    
    self.bibNum = argBibNum
    raise ArgumentException.new("Nil 1st argument: You must supply a bib number to first arg of Bib.new") unless self.bibNum

    self.hip_base_url = a_hip_base_path
    raise ArgumentException.new("Nil 2nd arg: You must supply the HIP instance base URL as a Net::URI object in 2nd arg to Bib.new") unless self.hip_base_url
   
  
  self.httpSession = params[:http_session]
    self.httpSession ||= Hip3::HTTPSession.create(hip_base_url.host() )

    self.title = params[:title]
    
  self.copies = nil

  @bib_xml = params[:bib_xml_doc]
end

Instance Attribute Details

#bib_field_lookupObject

CustomFieldLookup objects



18
19
20
# File 'app/models/hip3/bib.rb', line 18

def bib_field_lookup
  @bib_field_lookup
end

#bib_xmlObject

Returns the value of attribute bib_xml



19
20
21
# File 'app/models/hip3/bib.rb', line 19

def bib_xml
  @bib_xml
end

#bibNumObject

should have copies or items, not both



14
15
16
# File 'app/models/hip3/bib.rb', line 14

def bibNum
  @bibNum
end

#copiesObject

copy records, in case of serial bib



14
15
16
# File 'app/models/hip3/bib.rb', line 14

def copies
  @copies
end

#copy_field_lookupObject

Lookup custom HIP admin assigned fields in copy summary record

> CustomFieldLookup object.



18
19
20
# File 'app/models/hip3/bib.rb', line 18

def copy_field_lookup
  @copy_field_lookup
end

#hip_base_urlObject

Returns the value of attribute hip_base_url



12
13
14
# File 'app/models/hip3/bib.rb', line 12

def hip_base_url
  @hip_base_url
end

#httpSessionObject

Returns the value of attribute httpSession



12
13
14
# File 'app/models/hip3/bib.rb', line 12

def httpSession
  @httpSession
end

#item_field_lookupObject

CustomFieldLookup objects



18
19
20
# File 'app/models/hip3/bib.rb', line 18

def item_field_lookup
  @item_field_lookup
end

#itemsObject

Items directly held by this bib, only in case of mono bib



14
15
16
# File 'app/models/hip3/bib.rb', line 14

def items
  @items
end

#marx_xmlObject

and the beautiful MARC xml object for the bib, ruby-marc object.



21
22
23
# File 'app/models/hip3/bib.rb', line 21

def marx_xml
  @marx_xml
end

#titleObject



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'app/models/hip3/bib.rb', line 221

def title
  unless (@title)
    # title may already have been lazily loaded, or loaded by the

    # bibsearcher. Otherwise, we need to extract it from the bib_xml, 

    # which is kind of a pain.


    # first find the index number of the title.

    labels = bib_xml().search('//fullnonmarc/searchresults/header/col/label')
    title_index = nil
    (0..(labels.length-1)).each do |i|
      if (labels[i].inner_text == @title_label)
        title_index = i
        break
      end
    end

    if title_index
      raw_title = bib_xml().at("//fullnonmarc/searchresults/results/row/cell[#{title_index + 1}]/data/text").inner_text
      # remove possible author on there, after a '/' char. That's how HIP rolls. 

      @title = raw_title.sub(/\/.*$/, '')
    else
      @title = 'unknown'
    end
    
  end
  

  return @title
end

#xml_with_itemsObject

This method gets the XML from HIP and puts it in an ivar.



84
85
86
# File 'app/models/hip3/bib.rb', line 84

def xml_with_items
  @xml_with_items
end

Instance Method Details

#copy_for_id(copy_id) ⇒ Object

We could try to store the copies in a hash for efficiency, but we're only going to have a handful, it's not worth it.



253
254
255
# File 'app/models/hip3/bib.rb', line 253

def copy_for_id(copy_id)
  copies.find { |c|  c.id == copy_id }
end

#custom_field_for_label(label) ⇒ Object

Look up a field added in HIP Admin screen, by label given in that screen.



197
198
199
200
# File 'app/models/hip3/bib.rb', line 197

def custom_field_for_label(label)
  dataRows = self.bib_xml.search('searchresponse/fullnonmarc/results/row[1]/cell');
  return bib_field_lookup.text_value_for(dataRows, label)
end

#hip_http_pathObject



53
54
55
56
# File 'app/models/hip3/bib.rb', line 53

def hip_http_path
  # 1000 items and copies per page, we want em all

  return hip_base_url.path + "?index=BIB&term=#{bibNum}&ipp=1000&cpp=1000" 
end

#hip_http_xml_pathObject



57
58
59
# File 'app/models/hip3/bib.rb', line 57

def hip_http_xml_path
  return hip_http_path + "&GetXML=1"
end

#holdingsObject

Returns items OR copies, depending on whether it's a serial or a mono bib. HIP doesn't generally allow a mixture of of both.



217
218
219
# File 'app/models/hip3/bib.rb', line 217

def holdings
  return items + copies
end

#http_urlObject



280
281
282
283
# File 'app/models/hip3/bib.rb', line 280

def http_url

  return "#{hip_base_url.scheme}://#{hip_base_url.host}:#{hip_base_url.port}#{hip_http_path}"
end

#load_from_storeObject

Fetch in our data from HIP. Called lazily by accessor methods.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/hip3/bib.rb', line 62

def load_from_store
    
  # If we have serial copies, load those. We never should have both, but oh well. 

  serialElements = bib_xml.search('searchresponse/subscriptionsummary/serial')
  self.copies = serialElements.collect do |serialElement|
    holding = Hip3::SerialCopy.new( self, serialElement )       
  
    holding # collect holdings

  end
  @copies_loaded = true
        
  # If we didn't have copies, we might have items directly in this bib.  

  if (self.copies.length == 0 &&
    !bib_xml.search('searchresponse/items/searchresults/results/row').nil?)
    self.xml_with_items = bib_xml
    load_items_from_store
  end
  @items_loaded = true

end

#load_items_from_storeObject

Load serial Item data from HIP belonging to this BIB. Called lazily by accessors. Will also work for mono item data, but no reason to call it, can get mono item data without this extra fetch.



153
154
155
156
157
158
159
160
161
162
163
# File 'app/models/hip3/bib.rb', line 153

def load_items_from_store
      
  itemRowElements =  xml_with_items.search('searchresponse/items/searchresults/results/row');      
  itemRowElements.each do | el |
    # constructor will take care of registering the thing with us

    Hip3::Item.new(el, self)
  end
  # Tell all our copies they're loaded, so they won't try and load again

  copies.each { |c| c.items_loaded = true }
  
end

#marc_xmlObject



116
117
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
# File 'app/models/hip3/bib.rb', line 116

def marc_xml
  # Sadly, loading this takes ANOTHER request. At least this

  # request, unlike the HIP requests, is speedy. We need this

    # for getting 856 urls with sub-fields. Depends on Casey

    # Durfee's package to provide marcxml from hip being installed. 

  unless (@marc_xml)
    # should have copies or items, not both

    path = "/mods/?format=marcxml&bib=#{bibNum}"
      #host = hip_base_url.host

      host = hip_base_url.host
      port = hip_base_url.port

      # If it's https, rejigger it to be http, that's just the way we roll.      

      port = 80 if port == 443;
      
      # put in a rescue on bad http, reword error. 

      resp = Hip3::HTTPSession.start(host, port) {|http| http.get(path) }
      
      
    
    reader = MARC::XMLReader.new( StringIO.new(resp.body.to_s) )
    # there should only be one record in there, just grap one. Since

      # this is an odd object, we can't just do reader[0], but instead:        

    xml = reader.find { true }
      
      # HIP marc doesn't have the bibID in it. We want the bibID in there.

      # Set it ourselves.

      xml.fields.push( MARC::ControlField.new('001', bibNum()))
      
    @marc_xml = xml 
  end
  return @marc_xml
end

#register_direct_item(item) ⇒ Object

An item that does not have a copy parent, but is directly related to the big.



275
276
277
278
# File 'app/models/hip3/bib.rb', line 275

def register_direct_item( item )
  @items ||= []
  @items.push( item ) if ! @items.include?(item) 
end

#register_item(item) ⇒ Object

Will add this to an appropriate Copy record if one exists, otherwise directly to our items array. According to HIP's constriants, a bib should never have copies and directly included items, just one or the other.



262
263
264
265
266
267
268
269
270
271
# File 'app/models/hip3/bib.rb', line 262

def register_item(item)     
  copy = copy_for_id( item.copy_id )
  if ( copy.nil? )
    # can't find a copy record, guess it's a directly registered item

    register_direct_item( item )
  else
    copy.register_item( item )
  end
  
end

#to_sObject



285
286
287
# File 'app/models/hip3/bib.rb', line 285

def to_s
  return "#<Hip3::Bib bibnum=#{bibNum} #{http_url}>"
end