sufia 0.0.1.pre2 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/Gemfile +2 -5
  2. data/README.md +44 -12
  3. data/app/assets/javascripts/{scholarsphere.js → sufia.js} +0 -0
  4. data/app/assets/stylesheets/{scholarsphere.css → sufia.css} +0 -0
  5. data/app/controllers/batch_controller.rb +2 -3
  6. data/app/controllers/batch_edits_controller.rb +4 -4
  7. data/app/controllers/dashboard_controller.rb +5 -3
  8. data/app/controllers/generic_files_controller.rb +77 -41
  9. data/app/controllers/users_controller.rb +9 -21
  10. data/app/helpers/blacklight/render_constraints_helper_behavior.rb +2 -2
  11. data/app/helpers/sufia_helper.rb +23 -2
  12. data/app/models/datastreams/file_content_datastream.rb +17 -9
  13. data/app/models/generic_file.rb +1 -809
  14. data/app/views/_add_assets_links.html.erb +1 -1
  15. data/app/views/_user_util_links.html.erb +2 -2
  16. data/app/views/batch/_metadata.html.erb +16 -16
  17. data/app/views/batch/edit.html.erb +16 -10
  18. data/app/views/batch_edits/_metadata.html.erb +16 -16
  19. data/app/views/catalog/_index_partials/_list_files.html.erb +2 -2
  20. data/app/views/catalog/index.html.erb +5 -0
  21. data/app/views/dashboard/_facet_limit.html.erb +1 -1
  22. data/app/views/dashboard/_facet_pagination.html.erb +4 -4
  23. data/app/views/dashboard/_facet_selected.html.erb +1 -1
  24. data/app/views/dashboard/_index_partials/_list_files.html.erb +8 -8
  25. data/app/views/dashboard/_search_form.html.erb +1 -1
  26. data/app/views/dashboard/_sort_and_per_page.html.erb +1 -1
  27. data/app/views/dashboard/index.html.erb +0 -1
  28. data/app/views/generic_files/_breadcrumbs.html.erb +1 -1
  29. data/app/views/generic_files/_descriptions.html.erb +3 -3
  30. data/app/views/generic_files/_field_form +3 -3
  31. data/app/views/generic_files/_media_display.html.erb +5 -4
  32. data/app/views/generic_files/_permission.html.erb +5 -5
  33. data/app/views/generic_files/_versioning.html.erb +1 -1
  34. data/app/views/generic_files/edit.html.erb +2 -2
  35. data/app/views/generic_files/show.html.erb +3 -3
  36. data/app/views/static/versions.html.erb +1 -1
  37. data/app/views/users/edit.html.erb +5 -3
  38. data/app/views/users/index.html.erb +3 -3
  39. data/app/views/users/show.html.erb +6 -6
  40. data/config/jetty.yml +6 -0
  41. data/config/routes.rb +8 -4
  42. data/features/browse_dashboard_files.feature +11 -1
  43. data/features/browse_files.feature +6 -5
  44. data/features/contact_form.feature +4 -0
  45. data/features/display_dashboard.feature +6 -3
  46. data/features/ingest_upload_files.feature +2 -2
  47. data/features/step_definitions/fixture_steps.rb +6 -5
  48. data/features/step_definitions/scholarsphere.rb +24 -1
  49. data/features/step_definitions/user_steps.rb +2 -2
  50. data/features/step_definitions/web_steps.rb +1 -1
  51. data/features/support/env.rb +26 -0
  52. data/features/users.feature +18 -0
  53. data/lib/active_support/core_ext/marshal.rb +22 -0
  54. data/lib/generators/sufia/sufia_generator.rb +18 -2
  55. data/lib/generators/sufia/templates/catalog_controller.rb +3 -4
  56. data/{spec/support → lib/generators/sufia/templates}/config/redis.yml +0 -0
  57. data/lib/generators/sufia/templates/config/sufia.rb +68 -0
  58. data/lib/generators/sufia/templates/migrations/add_ldap_attrs_to_user.rb +41 -0
  59. data/lib/kaminari/helpers/tag.rb +11 -0
  60. data/lib/sufia.rb +30 -7
  61. data/lib/sufia/controller.rb +1 -5
  62. data/lib/sufia/generic_file.rb +200 -0
  63. data/lib/sufia/generic_file/audit.rb +119 -0
  64. data/lib/sufia/generic_file/characterization.rb +82 -0
  65. data/lib/sufia/generic_file/export.rb +339 -0
  66. data/lib/sufia/generic_file/permissions.rb +64 -0
  67. data/lib/sufia/generic_file/thumbnail.rb +68 -0
  68. data/{app/models → lib/sufia/jobs}/audit_job.rb +13 -3
  69. data/lib/sufia/jobs/batch_update_job.rb +86 -0
  70. data/lib/sufia/jobs/characterize_job.rb +35 -0
  71. data/{app/models → lib/sufia/jobs}/content_delete_event_job.rb +3 -1
  72. data/{app/models → lib/sufia/jobs}/content_deposit_event_job.rb +1 -1
  73. data/{app/models → lib/sufia/jobs}/content_new_version_event_job.rb +1 -1
  74. data/{app/models → lib/sufia/jobs}/content_restored_version_event_job.rb +8 -0
  75. data/{app/models → lib/sufia/jobs}/content_update_event_job.rb +1 -1
  76. data/{app/models → lib/sufia/jobs}/event_job.rb +7 -3
  77. data/{app/models → lib/sufia/jobs}/resolrize_job.rb +4 -2
  78. data/lib/sufia/jobs/transcode_video_job.rb +79 -0
  79. data/{app/models → lib/sufia/jobs}/unzip_job.rb +11 -3
  80. data/{app/models → lib/sufia/jobs}/user_edit_profile_event_job.rb +6 -0
  81. data/{app/models → lib/sufia/jobs}/user_follow_event_job.rb +9 -4
  82. data/{app/models → lib/sufia/jobs}/user_unfollow_event_job.rb +6 -0
  83. data/lib/sufia/queue/resque.rb +30 -0
  84. data/lib/sufia/role_mapper.rb +0 -1
  85. data/{app/models/characterize_job.rb → lib/sufia/solr_document_behavior.rb} +6 -7
  86. data/lib/sufia/user.rb +3 -3
  87. data/lib/sufia/version.rb +1 -1
  88. data/lib/tasks/fixtures.rake +38 -38
  89. data/lib/tasks/resque.rake +1 -0
  90. data/solr_conf/conf/solrconfig.xml +32 -1615
  91. data/solr_conf/solr.xml +1 -1
  92. data/spec/active_fedora/unsaved_digital_object_spec.rb +4 -4
  93. data/spec/config/host_to_vhost_spec.rb +4 -4
  94. data/spec/controllers/authorities_controller_spec.rb +1 -1
  95. data/spec/controllers/batch_controller_spec.rb +12 -10
  96. data/spec/controllers/catalog_controller_spec.rb +13 -13
  97. data/spec/controllers/dashboard_controller_spec.rb +15 -15
  98. data/spec/controllers/downloads_controller_spec.rb +14 -14
  99. data/spec/controllers/generic_files_controller_spec.rb +88 -46
  100. data/spec/controllers/mailbox_controller_spec.rb +2 -2
  101. data/spec/controllers/sessions_controller_spec.rb +1 -1
  102. data/spec/controllers/single_use_link_controller_spec.rb +18 -18
  103. data/spec/controllers/users_controller_spec.rb +47 -31
  104. data/spec/fixtures/countdown.avi +0 -0
  105. data/spec/fixtures/sufia/.gitignore +1 -0
  106. data/spec/fixtures/{scholarsphere → sufia}/bg_header.jpg +0 -0
  107. data/spec/fixtures/sufia/sufia_test1.descMeta.txt +12 -0
  108. data/spec/fixtures/{scholarsphere → sufia}/sufia_test1.foxml.erb +2 -2
  109. data/spec/fixtures/{scholarsphere/scholarsphere_test1.txt → sufia/sufia_test1.txt} +0 -0
  110. data/spec/fixtures/sufia/sufia_test2.descMeta.txt +12 -0
  111. data/spec/fixtures/{scholarsphere/scholarsphere_test2.docx → sufia/sufia_test2.docx} +0 -0
  112. data/spec/fixtures/{scholarsphere/scholarsphere_test2.foxml.erb → sufia/sufia_test2.foxml.erb} +6 -6
  113. data/spec/fixtures/sufia/sufia_test3.descMeta.txt +12 -0
  114. data/spec/fixtures/{scholarsphere/scholarsphere_test3.foxml.erb → sufia/sufia_test3.foxml.erb} +6 -6
  115. data/spec/fixtures/{scholarsphere/scholarsphere_test3.xls → sufia/sufia_test3.xls} +0 -0
  116. data/spec/fixtures/sufia/sufia_test4.descMeta.txt +12 -0
  117. data/spec/fixtures/{scholarsphere/scholarsphere_test4.foxml.erb → sufia/sufia_test4.foxml.erb} +6 -6
  118. data/spec/fixtures/{scholarsphere/scholarsphere_test4.pdf → sufia/sufia_test4.pdf} +0 -0
  119. data/spec/fixtures/sufia/sufia_test5.descMeta.txt +19 -0
  120. data/spec/fixtures/{scholarsphere → sufia}/sufia_test5.foxml.erb +3 -3
  121. data/spec/fixtures/{scholarsphere/scholarsphere_test5.mp3 → sufia/sufia_test5.mp3} +0 -0
  122. data/spec/fixtures/sufia/sufia_test5.txt +1 -0
  123. data/spec/fixtures/sufia/sufia_test6.descMeta.txt +12 -0
  124. data/spec/fixtures/{scholarsphere/scholarsphere_test6.foxml.erb → sufia/sufia_test6.foxml.erb} +6 -6
  125. data/spec/fixtures/{scholarsphere/scholarsphere_test6.jp2 → sufia/sufia_test6.jp2} +0 -0
  126. data/spec/fixtures/sufia/sufia_test6.txt +1 -0
  127. data/spec/fixtures/sufia_generic_stub.descMeta.txt +12 -0
  128. data/spec/fixtures/{scholarsphere_generic_stub.foxml.erb → sufia_generic_stub.foxml.erb} +3 -3
  129. data/spec/fixtures/sufia_generic_stub.txt +1 -0
  130. data/spec/lib/sufia/role_mapper_spec.rb +1 -1
  131. data/spec/models/audit_job_spec.rb +8 -11
  132. data/spec/models/batch_spec.rb +5 -5
  133. data/spec/models/batch_update_job_spec.rb +18 -15
  134. data/spec/models/checksum_audit_log_spec.rb +6 -19
  135. data/spec/models/event_jobs_spec.rb +23 -23
  136. data/spec/models/file_content_datastream_spec.rb +14 -14
  137. data/spec/models/fits_datastream_spec.rb +1 -1
  138. data/spec/models/generic_file_spec.rb +88 -41
  139. data/spec/models/single_use_link_spec.rb +3 -3
  140. data/spec/models/transcode_video_job_spec.rb +30 -0
  141. data/spec/models/unzip_job_spec.rb +6 -4
  142. data/spec/rake/{scholarsphere_fixtures_spec.rb → sufia_fixtures_spec.rb} +16 -16
  143. data/spec/routing/route_spec.rb +4 -8
  144. data/spec/spec_helper.rb +0 -7
  145. data/spec/support/Gemfile +4 -2
  146. data/spec/support/fedora_conf/fedora.fcfg +953 -0
  147. data/spec/support/lib/generators/test_app_generator.rb +1 -11
  148. data/sufia.gemspec +5 -3
  149. data/tasks/{scholarsphere-db.rake → sufia-db.rake} +1 -1
  150. data/tasks/{scholarsphere-dev.rake → sufia-dev.rake} +7 -3
  151. data/tasks/{scholarsphere-fixtures.rake → sufia-fixtures.rake} +43 -43
  152. data/tasks/{scholarsphere.rake → sufia.rake} +2 -2
  153. metadata +126 -95
  154. data/app/models/batch_update_job.rb +0 -82
  155. data/app/models/solr_document.rb +0 -50
  156. data/lib/sufia/permissions.rb +0 -43
  157. data/spec/fixtures/scholarsphere/scholarsphere_test1.descMeta.txt +0 -12
  158. data/spec/fixtures/scholarsphere/scholarsphere_test2.descMeta.txt +0 -12
  159. data/spec/fixtures/scholarsphere/scholarsphere_test3.descMeta.txt +0 -12
  160. data/spec/fixtures/scholarsphere/scholarsphere_test4.descMeta.txt +0 -12
  161. data/spec/fixtures/scholarsphere/scholarsphere_test5.descMeta.txt +0 -19
  162. data/spec/fixtures/scholarsphere/scholarsphere_test5.txt +0 -1
  163. data/spec/fixtures/scholarsphere/scholarsphere_test6.descMeta.txt +0 -12
  164. data/spec/fixtures/scholarsphere/scholarsphere_test6.txt +0 -1
  165. data/spec/fixtures/scholarsphere/sufia_scholarsphere1.descMeta.txt +0 -12
  166. data/spec/fixtures/scholarsphere/sufia_scholarsphere1.foxml.erb +0 -79
  167. data/spec/fixtures/scholarsphere/sufia_scholarsphere1.txt +0 -1
  168. data/spec/fixtures/scholarsphere_generic_stub.descMeta.txt +0 -12
  169. data/spec/fixtures/scholarsphere_generic_stub.txt +0 -1
@@ -0,0 +1,119 @@
1
+ module Sufia
2
+ module GenericFile
3
+ module Audit
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ end
7
+
8
+ NO_RUNS = 999
9
+
10
+ def audit(force = false)
11
+ logs = []
12
+ self.per_version do |ver|
13
+ logs << ::GenericFile.audit(ver, force)
14
+ end
15
+ logs
16
+ end
17
+
18
+ def per_version(&block)
19
+ self.datastreams.each do |dsid, ds|
20
+ ds.versions.each do |ver|
21
+ block.call(ver)
22
+ end
23
+ end
24
+ end
25
+
26
+ def logs(dsid)
27
+ ChecksumAuditLog.where(:dsid=>dsid, :pid=>self.pid).order('created_at desc, id desc')
28
+ end
29
+
30
+ def audit!
31
+ audit(true)
32
+ end
33
+
34
+ def audit_stat!
35
+ audit_stat(true)
36
+ end
37
+
38
+ def audit_stat(force = false)
39
+ logs = audit(force)
40
+ audit_results = logs.collect { |result| result["pass"] }
41
+
42
+ # check how many non runs we had
43
+ non_runs =audit_results.reduce(0) { |sum, value| (value == NO_RUNS) ? sum = sum+1 : sum }
44
+ if (non_runs == 0)
45
+ result =audit_results.reduce(true) { |sum, value| sum && value }
46
+ return result
47
+ elsif (non_runs < audit_results.length)
48
+ result =audit_results.reduce(true) { |sum, value| (value == NO_RUNS) ? sum : sum && value }
49
+ return 'Some audits have not been run, but the ones run were '+ ((result)? 'passing' : 'failing') + '.'
50
+ else
51
+ return 'Audits have not yet been run on this file.'
52
+ end
53
+ end
54
+
55
+
56
+ module ClassMethods
57
+ def audit!(version)
58
+ ::GenericFile.audit(version, true)
59
+ end
60
+
61
+ def audit(version, force = false)
62
+ latest_audit = self.find(version.pid).logs(version.dsid).first
63
+ unless force
64
+ return latest_audit unless ::GenericFile.needs_audit?(version, latest_audit)
65
+ end
66
+ # Resque.enqueue(AuditJob, version.pid, version.dsid, version.versionID)
67
+ Sufia.queue.push(AuditJob.new(version.pid, version.dsid, version.versionID))
68
+
69
+ # run the find just incase the job has finished already
70
+ latest_audit = self.find(version.pid).logs(version.dsid).first
71
+ latest_audit = ChecksumAuditLog.new(:pass=>NO_RUNS, :pid=>version.pid, :dsid=>version.dsid, :version=>version.versionID) unless latest_audit
72
+ return latest_audit
73
+ end
74
+
75
+ def needs_audit?(version, latest_audit)
76
+ if latest_audit and latest_audit.updated_at
77
+ #logger.debug "***AUDIT*** last audit = #{latest_audit.updated_at.to_date}"
78
+ days_since_last_audit = (DateTime.now - latest_audit.updated_at.to_date).to_i
79
+ #logger.debug "***AUDIT*** days since last audit: #{days_since_last_audit}"
80
+ if days_since_last_audit < Sufia::Engine.config.max_days_between_audits
81
+ #logger.debug "***AUDIT*** No audit needed for #{version.pid} #{version.versionID} (#{latest_audit.updated_at})"
82
+ return false
83
+ end
84
+ else
85
+ logger.warn "***AUDIT*** problem with audit log! Latest Audit is not nil, but updated_at is not set #{latest_audit}" unless latest_audit.nil?
86
+ end
87
+ #logger.info "***AUDIT*** Audit needed for #{version.pid} #{version.versionID}"
88
+ return true
89
+ end
90
+
91
+ def audit_everything(force = false)
92
+ ::GenericFile.find(:all, :rows => ::GenericFile.count).each do |gf|
93
+ gf.per_version do |ver|
94
+ ::GenericFile.audit(ver, force)
95
+ end
96
+ end
97
+ end
98
+
99
+ def audit_everything!
100
+ ::GenericFile.audit_everything(true)
101
+ end
102
+
103
+ def run_audit(version)
104
+ if version.dsChecksumValid
105
+ #logger.info "***AUDIT*** Audit passed for #{version.pid} #{version.versionID}"
106
+ passing = 1
107
+ ChecksumAuditLog.prune_history(version)
108
+ else
109
+ logger.warn "***AUDIT*** Audit failed for #{version.pid} #{version.versionID}"
110
+ passing = 0
111
+ end
112
+ check = ChecksumAuditLog.create!(:pass=>passing, :pid=>version.pid,
113
+ :dsid=>version.dsid, :version=>version.versionID)
114
+ return check
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,82 @@
1
+ require 'datastreams/fits_datastream'
2
+ module Sufia
3
+ module GenericFile
4
+ module Characterization
5
+ extend ActiveSupport::Concern
6
+ included do
7
+ has_metadata :name => "characterization", :type => FitsDatastream
8
+ delegate :mime_type, :to => :characterization, :unique => true
9
+ delegate_to :characterization, [:format_label, :file_size, :last_modified,
10
+ :filename, :original_checksum, :rights_basis,
11
+ :copyright_basis, :copyright_note,
12
+ :well_formed, :valid, :status_message,
13
+ :file_title, :file_author, :page_count,
14
+ :file_language, :word_count, :character_count,
15
+ :paragraph_count, :line_count, :table_count,
16
+ :graphics_count, :byte_order, :compression,
17
+ :width, :height, :color_space, :profile_name,
18
+ :profile_version, :orientation, :color_map,
19
+ :image_producer, :capture_device,
20
+ :scanning_software, :exif_version,
21
+ :gps_timestamp, :latitude, :longitude,
22
+ :character_set, :markup_basis,
23
+ :markup_language, :duration, :bit_depth,
24
+ :sample_rate, :channels, :data_format, :offset]
25
+
26
+ end
27
+
28
+ def characterize_if_changed
29
+ content_changed = self.content.changed?
30
+ yield
31
+ #logger.debug "DOING CHARACTERIZE ON #{self.pid}"
32
+ Sufia.queue.push(CharacterizeJob.new(self.pid)) if content_changed
33
+ end
34
+
35
+ ## Extract the metadata from the content datastream and record it in the characterization datastream
36
+ def characterize
37
+ self.characterization.content = self.content.extract_metadata
38
+ self.append_metadata
39
+ self.filename = self.label
40
+ self.terms_of_service = '1'
41
+ save unless self.new_object?
42
+ end
43
+
44
+ # Populate descMetadata with fields from FITS (e.g. Author from pdfs)
45
+ def append_metadata
46
+ terms = self.characterization_terms
47
+ Sufia::Engine.config.fits_to_desc_mapping.each_pair do |k, v|
48
+ if terms.has_key?(k)
49
+ # coerce to array to remove a conditional
50
+ terms[k] = [terms[k]] unless terms[k].is_a? Array
51
+ terms[k].each do |term_value|
52
+ proxy_term = self.send(v)
53
+ if proxy_term.kind_of?(Array)
54
+ proxy_term << term_value unless proxy_term.include?(term_value)
55
+ else
56
+ # these are single-valued terms which cannot be appended to
57
+ self.send("#{v}=", term_value)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def characterization_terms
65
+ h = {}
66
+ self.characterization.class.terminology.terms.each_pair do |k, v|
67
+ next unless v.respond_to? :proxied_term
68
+ term = v.proxied_term
69
+ begin
70
+ value = self.send(term.name)
71
+ h[term.name] = value unless value.empty?
72
+ rescue NoMethodError
73
+ next
74
+ end
75
+ end
76
+ h
77
+ end
78
+
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,339 @@
1
+ module Sufia
2
+ module GenericFile
3
+ module Export
4
+ # MIME: 'application/x-endnote-refer'
5
+ def export_as_endnote
6
+ end_note_format = {
7
+ '%T' => [:title, lambda { |x| x.first }],
8
+ '%Q' => [:title, lambda { |x| x.drop(1) }],
9
+ '%A' => [:creator],
10
+ '%C' => [:publication_place],
11
+ '%D' => [:date_created],
12
+ '%8' => [:date_uploaded],
13
+ '%E' => [:contributor],
14
+ '%I' => [:publisher],
15
+ '%J' => [:series_title],
16
+ '%@' => [:isbn],
17
+ '%U' => [:related_url],
18
+ '%7' => [:edition_statement],
19
+ '%R' => [:persistent_url],
20
+ '%X' => [:description],
21
+ '%G' => [:language],
22
+ '%[' => [:date_modified],
23
+ '%9' => [:resource_type],
24
+ '%~' => Application.config.application_name,
25
+ '%W' => 'Penn State University'
26
+ }
27
+ text = []
28
+ text << "%0 GenericFile"
29
+ end_note_format.each do |endnote_key, mapping|
30
+ if mapping.is_a? String
31
+ values = [mapping]
32
+ else
33
+ values = self.send(mapping[0]) if self.respond_to? mapping[0]
34
+ values = mapping[1].call(values) if mapping.length == 2
35
+ values = [values] unless values.is_a? Array
36
+ end
37
+ next if values.empty? or values.first.nil?
38
+ spaced_values = values.join("; ")
39
+ text << "#{endnote_key} #{spaced_values}"
40
+ end
41
+ return text.join("\n")
42
+ end
43
+
44
+ # MIME type: 'application/x-openurl-ctx-kev'
45
+ def export_as_openurl_ctx_kev
46
+ export_text = []
47
+ export_text << "url_ver=Z39.88-2004&ctx_ver=Z39.88-2004&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&rfr_id=info%3Asid%2Fblacklight.rubyforge.org%3Agenerator"
48
+ field_map = {
49
+ :title => 'title',
50
+ :creator => 'creator',
51
+ :subject => 'subject',
52
+ :description => 'description',
53
+ :publisher => 'publisher',
54
+ :contributor => 'contributor',
55
+ :date_created => 'date',
56
+ :resource_type => 'format',
57
+ :identifier => 'identifier',
58
+ :language => 'language',
59
+ :tag => 'relation',
60
+ :based_near => 'coverage',
61
+ :rights => 'rights'
62
+ }
63
+ field_map.each do |element, kev|
64
+ values = self.send(element)
65
+ next if values.empty? or values.first.nil?
66
+ values.each do |value|
67
+ export_text << "rft.#{kev}=#{CGI::escape(value)}"
68
+ end
69
+ end
70
+ export_text.join('&') unless export_text.blank?
71
+ end
72
+
73
+ def export_as_apa_citation
74
+ text = ''
75
+ authors_list = []
76
+ authors_list_final = []
77
+
78
+ #setup formatted author list
79
+ authors = get_author_list
80
+ authors.each do |author|
81
+ next if author.blank?
82
+ authors_list.push(abbreviate_name(author))
83
+ end
84
+ authors_list.each do |author|
85
+ if author == authors_list.first #first
86
+ authors_list_final.push(author.strip)
87
+ elsif author == authors_list.last #last
88
+ authors_list_final.push(", &amp; " + author.strip)
89
+ else #all others
90
+ authors_list_final.push(", " + author.strip)
91
+ end
92
+ end
93
+ text << authors_list_final.join
94
+ unless text.blank?
95
+ if text[-1,1] != "."
96
+ text << ". "
97
+ else
98
+ text << " "
99
+ end
100
+ end
101
+ # Get Pub Date
102
+ text << "(" + setup_pub_date + "). " unless setup_pub_date.nil?
103
+
104
+ # setup title info
105
+ title_info = setup_title_info
106
+ text << "<i>" + title_info + "</i> " unless title_info.nil?
107
+
108
+ # Publisher info
109
+ text << setup_pub_info unless setup_pub_info.nil?
110
+ unless text.blank?
111
+ if text[-1,1] != "."
112
+ text += "."
113
+ end
114
+ end
115
+ text.html_safe
116
+ end
117
+
118
+ def export_as_mla_citation
119
+ text = ''
120
+ authors_final = []
121
+
122
+ #setup formatted author list
123
+ authors = get_author_list
124
+
125
+ if authors.length < 4
126
+ authors.each do |author|
127
+ if author == authors.first #first
128
+ authors_final.push(author)
129
+ elsif author == authors.last #last
130
+ authors_final.push(", and " + name_reverse(author) + ".")
131
+ else #all others
132
+ authors_final.push(", " + name_reverse(author))
133
+ end
134
+ end
135
+ text << authors_final.join
136
+ unless text.blank?
137
+ if text[-1,1] != "."
138
+ text << ". "
139
+ else
140
+ text << " "
141
+ end
142
+ end
143
+ else
144
+ text << authors.first + ", et al. "
145
+ end
146
+ # setup title
147
+ title_info = setup_title_info
148
+ text << "<i>" + mla_citation_title(title_info) + "</i> " unless title.blank?
149
+
150
+ # Publication
151
+ text << setup_pub_info + ", " unless setup_pub_info.nil?
152
+
153
+ # Get Pub Date
154
+ text << setup_pub_date unless setup_pub_date.nil?
155
+ if text[-1,1] != "."
156
+ text << "." unless text.blank?
157
+ end
158
+ text.html_safe
159
+ end
160
+
161
+ def export_as_chicago_citation
162
+ author_text = ""
163
+ authors = get_all_authors
164
+ unless authors.blank?
165
+ if authors.length > 10
166
+ authors.each_with_index do |author, index|
167
+ if index < 7
168
+ if index == 0
169
+ author_text << "#{author}"
170
+ if author.ends_with?(",")
171
+ author_text << " "
172
+ else
173
+ author_text << ", "
174
+ end
175
+ else
176
+ author_text << "#{name_reverse(author)}, "
177
+ end
178
+ end
179
+ end
180
+ author_text << " et al."
181
+ elsif authors.length > 1
182
+ authors.each_with_index do |author,index|
183
+ if index == 0
184
+ author_text << "#{author}"
185
+ if author.ends_with?(",")
186
+ author_text << " "
187
+ else
188
+ author_text << ", "
189
+ end
190
+ elsif index + 1 == authors.length
191
+ author_text << "and #{name_reverse(author)}."
192
+ else
193
+ author_text << "#{name_reverse(author)}, "
194
+ end
195
+ end
196
+ else
197
+ author_text << authors.first
198
+ end
199
+ end
200
+ title_info = ""
201
+ title_info << citation_title(clean_end_punctuation(CGI::escapeHTML(title.first)).strip) unless title.blank?
202
+
203
+ pub_info = ""
204
+ place = self.based_near.first
205
+ publisher = self.publisher.first
206
+ unless place.blank?
207
+ place = CGI::escapeHTML(place)
208
+ pub_info << place
209
+ pub_info << ": " unless publisher.blank?
210
+ end
211
+ unless publisher.blank?
212
+ publisher = CGI::escapeHTML(publisher)
213
+ pub_info << publisher
214
+ pub_info << ", " unless setup_pub_date.nil?
215
+ end
216
+ unless setup_pub_date.nil?
217
+ pub_info << setup_pub_date
218
+ end
219
+
220
+ citation = ""
221
+ citation << "#{author_text} " unless author_text.blank?
222
+ citation << "<i>#{title_info}.</i> " unless title_info.blank?
223
+ citation << "#{pub_info}." unless pub_info.blank?
224
+ citation.html_safe
225
+ end
226
+
227
+ private
228
+
229
+ def setup_pub_date
230
+ first_date = self.date_created.first
231
+ unless first_date.blank?
232
+ first_date = CGI::escapeHTML(first_date)
233
+ date_value = first_date.gsub(/[^0-9|n\.d\.]/, "")[0,4]
234
+ return nil if date_value.nil?
235
+ end
236
+ clean_end_punctuation(date_value) if date_value
237
+ end
238
+
239
+ def setup_pub_info
240
+ text = ''
241
+ place = self.based_near.first
242
+ publisher = self.publisher.first
243
+ unless place.blank?
244
+ place = CGI::escapeHTML(place)
245
+ text << place
246
+ text << ": " unless publisher.blank?
247
+ end
248
+ unless publisher.blank?
249
+ publisher = CGI::escapeHTML(publisher)
250
+ text << publisher
251
+ end
252
+ return nil if text.strip.blank?
253
+ clean_end_punctuation(text.strip)
254
+ end
255
+
256
+ def mla_citation_title(text)
257
+ no_upcase = ["a","an","and","but","by","for","it","of","the","to","with"]
258
+ new_text = []
259
+ word_parts = text.split(" ")
260
+ word_parts.each do |w|
261
+ if !no_upcase.include? w
262
+ new_text.push(w.capitalize)
263
+ else
264
+ new_text.push(w)
265
+ end
266
+ end
267
+ new_text.join(" ")
268
+ end
269
+
270
+ def citation_title(title_text)
271
+ prepositions = ["a","about","across","an","and","before","but","by","for","it","of","the","to","with","without"]
272
+ new_text = []
273
+ title_text.split(" ").each_with_index do |word,index|
274
+ if (index == 0 and word != word.upcase) or (word.length > 1 and word != word.upcase and !prepositions.include?(word))
275
+ # the split("-") will handle the capitalization of hyphenated words
276
+ new_text << word.split("-").map!{|w| w.capitalize }.join("-")
277
+ else
278
+ new_text << word
279
+ end
280
+ end
281
+ new_text.join(" ")
282
+ end
283
+
284
+ def setup_title_info
285
+ text = ''
286
+ title = self.title.first
287
+ unless title.blank?
288
+ title = CGI::escapeHTML(title)
289
+ title_info = clean_end_punctuation(title.strip)
290
+ text << title_info
291
+ end
292
+
293
+ return nil if text.strip.blank?
294
+ clean_end_punctuation(text.strip) + "."
295
+ end
296
+
297
+ def clean_end_punctuation(text)
298
+ if [".",",",":",";","/"].include? text[-1,1]
299
+ return text[0,text.length-1]
300
+ end
301
+ text
302
+ end
303
+
304
+ def get_author_list
305
+ self.creator.map { |author| clean_end_punctuation(CGI::escapeHTML(author)) }.uniq
306
+ end
307
+
308
+ def get_all_authors
309
+ authors = self.creator
310
+ return authors.empty? ? nil : authors.map { |author| CGI::escapeHTML(author) }
311
+ end
312
+
313
+ def abbreviate_name(name)
314
+ abbreviated_name = ''
315
+ name = name.join('') if name.is_a? Array
316
+ # make sure we handle "Cher" correctly
317
+ return name if !name.include?(' ') and !name.include?(',')
318
+ surnames_first = name.include?(',')
319
+ delimiter = surnames_first ? ', ' : ' '
320
+ name_segments = name.split(delimiter)
321
+ given_names = surnames_first ? name_segments.last.split(' ') : name_segments.first.split(' ')
322
+ surnames = surnames_first ? name_segments.first.split(' ') : name_segments.last.split(' ')
323
+ abbreviated_name << surnames.join(' ')
324
+ abbreviated_name << ', '
325
+ abbreviated_name << given_names.map { |n| "#{n[0]}." }.join if given_names.is_a? Array
326
+ abbreviated_name << "#{given_names[0]}." if given_names.is_a? String
327
+ abbreviated_name
328
+ end
329
+
330
+ def name_reverse(name)
331
+ name = clean_end_punctuation(name)
332
+ return name unless name =~ /,/
333
+ temp_name = name.split(", ")
334
+ return temp_name.last + " " + temp_name.first
335
+ end
336
+
337
+ end
338
+ end
339
+ end