active-fedora 11.5.6 → 12.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +4 -0
  3. data/.travis.yml +15 -0
  4. data/Gemfile +1 -3
  5. data/README.md +10 -13
  6. data/active-fedora.gemspec +7 -9
  7. data/lib/active_fedora.rb +3 -5
  8. data/lib/active_fedora/associations/collection_proxy.rb +0 -2
  9. data/lib/active_fedora/attributes/property_builder.rb +3 -1
  10. data/lib/active_fedora/caching_connection.rb +1 -1
  11. data/lib/active_fedora/errors.rb +4 -0
  12. data/lib/active_fedora/fedora.rb +5 -0
  13. data/lib/active_fedora/file.rb +3 -1
  14. data/lib/active_fedora/file/attributes.rb +5 -0
  15. data/lib/active_fedora/file_io.rb +120 -0
  16. data/lib/active_fedora/indexing.rb +6 -1
  17. data/lib/active_fedora/indexing/default_descriptors.rb +128 -0
  18. data/lib/active_fedora/indexing/descendant_fetcher.rb +22 -18
  19. data/lib/active_fedora/indexing/descriptor.rb +44 -0
  20. data/lib/active_fedora/indexing/field_mapper.rb +146 -0
  21. data/lib/active_fedora/indexing/inserter.rb +40 -0
  22. data/lib/active_fedora/indexing/suffix.rb +81 -0
  23. data/lib/active_fedora/indexing_service.rb +2 -2
  24. data/lib/active_fedora/ldp_resource.rb +1 -2
  25. data/lib/active_fedora/railtie.rb +0 -1
  26. data/lib/active_fedora/rdf/field_map_entry.rb +2 -2
  27. data/lib/active_fedora/rdf/indexing_service.rb +6 -6
  28. data/lib/active_fedora/relation.rb +0 -14
  29. data/lib/active_fedora/relation/delegation.rb +1 -2
  30. data/lib/active_fedora/relation/finder_methods.rb +19 -39
  31. data/lib/active_fedora/version.rb +1 -1
  32. data/lib/generators/active_fedora/config/fedora/templates/.fcrepo_wrapper +1 -1
  33. data/lib/generators/active_fedora/config/solr/templates/solr.yml +3 -3
  34. data/lib/generators/active_fedora/config/solr/templates/solr/config/schema.xml +34 -33
  35. data/spec/integration/base_spec.rb +39 -35
  36. data/spec/integration/indexing/descendant_fetcher_spec.rb +64 -0
  37. data/spec/integration/relation_spec.rb +1 -39
  38. data/spec/integration/scoping_spec.rb +17 -11
  39. data/spec/spec_helper.rb +1 -1
  40. data/spec/unit/active_fedora/indexing/inserter_spec.rb +30 -0
  41. data/spec/unit/attributes_spec.rb +3 -7
  42. data/spec/unit/fedora_spec.rb +12 -0
  43. data/spec/unit/file_configurator_spec.rb +0 -9
  44. data/spec/unit/file_io_spec.rb +137 -0
  45. data/spec/unit/file_spec.rb +14 -17
  46. metadata +26 -30
  47. data/.circleci/config.yml +0 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 419ffa1beafe8db1f095d978f5bf68bbc6d9ca821e2f207df12de4eb82a78662
4
- data.tar.gz: '018d793df4de36dd4a207ca6b70af4474d7996acf6a12ec7acac19e019e63ef0'
2
+ SHA1:
3
+ metadata.gz: bedac14828094879a2772f8ab082a5ff0af2ac44
4
+ data.tar.gz: efd5b61d006fd8a7f2c99105d7cd11bf00b7c5b8
5
5
  SHA512:
6
- metadata.gz: a5cf6e6c08b021586dbb3a282d2bb91d128a5578e947725c365a239807814f50c4d87067f6e79e68215a9c1870a48b2d41021af51ba7ed65b9778118ce003663
7
- data.tar.gz: 90883925eaaf6601f24cefa301cccb40529b0034100ccf51e92a4da2fbdfa017a405289fb620c5e1352aaa177d9c37c984f5b50dd72bc66ef4ff6024fe7eeb02
6
+ metadata.gz: e56690ae20fd41c22ef507fc89a8c2350ac956cded3bd72d7d46ff43e181ccfe9224e3e40535ab5716b64a34efea98d87bbd7d364fa14c5b9f879cacf65be99f
7
+ data.tar.gz: 18ccc767a70af04dff33580ef2785483adbc3f0e51d8ae382ab65cf49db741b9cca8042c1cf7c59613aa6bcdbe4a0f91839a9a55b6d786c3b08dc74c2bd7f67c
@@ -50,6 +50,8 @@ Metrics/CyclomaticComplexity:
50
50
  - 'lib/active_fedora/file.rb'
51
51
  - 'lib/active_fedora/attribute_methods.rb'
52
52
  - 'lib/active_fedora/scoping/named.rb'
53
+ - 'lib/active_fedora/indexing/field_mapper.rb'
54
+ - 'lib/active_fedora/indexing/suffix.rb'
53
55
  - 'lib/active_fedora/inheritance.rb'
54
56
 
55
57
  Metrics/PerceivedComplexity:
@@ -66,6 +68,7 @@ Metrics/PerceivedComplexity:
66
68
  - 'lib/active_fedora/associations/collection_association.rb'
67
69
  - 'lib/active_fedora/attribute_methods.rb'
68
70
  - 'lib/active_fedora/scoping/named.rb'
71
+ - 'lib/active_fedora/indexing/field_mapper.rb'
69
72
  - 'lib/active_fedora/inheritance.rb'
70
73
 
71
74
  Metrics/ModuleLength:
@@ -127,6 +130,7 @@ Style/PredicateName:
127
130
  - 'lib/active_fedora/association_hash.rb'
128
131
  - 'lib/active_fedora/aggregation/list_source.rb'
129
132
  - 'lib/active_fedora/associations/builder/aggregation.rb'
133
+ - 'lib/active_fedora/indexing/suffix.rb'
130
134
 
131
135
  Style/GuardClause:
132
136
  Exclude:
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ cache: bundler
3
+ sudo: false
4
+ rvm: 2.4.1
5
+ matrix:
6
+ include:
7
+ - rvm: 2.3.4
8
+ env: "RAILS_VERSION=4.2.8"
9
+ - env: "RAILS_VERSION=5.1.1"
10
+ global_env:
11
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
12
+ before_install:
13
+ - gem update --system
14
+ before_script:
15
+ - jdk_switcher use oraclejdk8
data/Gemfile CHANGED
@@ -4,16 +4,14 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec path: File.expand_path('..', __FILE__)
6
6
 
7
- gem 'byebug' unless ENV['CI']
7
+ gem 'byebug' unless ENV['TRAVIS']
8
8
  gem 'pry-byebug' unless ENV['CI']
9
9
 
10
10
  gem 'activemodel', ENV['RAILS_VERSION'] if ENV['RAILS_VERSION']
11
- gem 'rsolr', ENV['RSOLR_VERSION'] if ENV['RSOLR_VERSION']
12
11
 
13
12
  group :test do
14
13
  gem 'simplecov', require: false
15
14
  gem 'coveralls', require: false
16
- gem 'rspec_junit_formatter'
17
15
  end
18
16
 
19
17
  gem 'jruby-openssl', platform: :jruby
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  Description
2
2
  -----------
3
3
 
4
- [![Build Status](https://travis-ci.org/projecthydra/active_fedora.png?branch=master)](https://travis-ci.org/projecthydra/active\_fedora)
4
+ [![Build Status](https://travis-ci.org/samvera/active_fedora.png?branch=master)](https://travis-ci.org/samvera/active\_fedora)
5
5
  [![Version](https://badge.fury.io/rb/active-fedora.png)](http://badge.fury.io/rb/active-fedora)
6
- [![Dependencies](https://gemnasium.com/projecthydra/active_fedora.png)](https://gemnasium.com/projecthydra/active\_fedora)
7
- [![Coverage Status](https://img.shields.io/coveralls/projecthydra/active_fedora.svg)](https://coveralls.io/r/projecthydra/active_fedora)
6
+ [![Dependencies](https://gemnasium.com/samvera/active_fedora.png)](https://gemnasium.com/samvera/active\_fedora)
7
+ [![Coverage Status](https://img.shields.io/coveralls/samvera/active_fedora.svg)](https://coveralls.io/r/samvera/active_fedora)
8
8
 
9
9
  ActiveFedora is a Ruby gem for creating and
10
10
  managing objects in the Fedora Repository Architecture
@@ -15,8 +15,8 @@ Getting Help
15
15
  ------------
16
16
 
17
17
  - Community Discussions & Mailing List are located at
18
- [http://groups.google.com/group/hydra-tech](http://groups.google.com/group/hydra-tech)
19
- - Developers hang out on IRC in \#projecthydra on freenet.
18
+ [http://groups.google.com/group/samvera-tech](http://groups.google.com/group/samvera-tech)
19
+ - Developers hang out on [slack.samvera.org](http://slack.samvera.org/)
20
20
 
21
21
  Installation
22
22
  ------------
@@ -30,7 +30,7 @@ gem install active-fedora
30
30
  Getting Started
31
31
  ---------------
32
32
 
33
- The [Dive into Hydra](https://github.com/projecthydra/hydra/wiki/Dive-into-Hydra)
33
+ The [Dive into Hydra](https://github.com/samvera/hydra/wiki/Dive-into-Hydra)
34
34
  gives you a brief tour through ActiveFedora’s features on the command line.
35
35
 
36
36
  Generators
@@ -47,21 +47,18 @@ Testing (this Gem)
47
47
 
48
48
  In order to run the RSpec tests, you need to have a copy of the
49
49
  ActiveFedora source code, and then run bundle install in the source
50
- directory. Testing requires hydra-jetty, which contains version for
51
- Fedora and Solr. Setting up and maintaining hydra-jetty for the purposes
52
- of testing this gem is all accomplished via:
50
+ directory. You can download the source code by doing the following:
53
51
 
54
52
  ```bash
55
- git clone https://github.com/projecthydra/active_fedora.git
56
- cd active_fedora # or whatever directory your clone is in
53
+ git clone https://github.com/samvera/active_fedora.git
54
+ cd active_fedora
57
55
  bundle install
58
56
  ```
59
57
 
60
58
  ### Using the continuous integration server
61
59
 
62
60
  You can test ActiveFedora using the same process as our continuous
63
- integration server. To do that, unzip a copy of hydra-jetty first. This includes copies of Fedora and Solr which are
64
- used during the testing process.
61
+ integration server. This will automatically pull down a copy of Solr and Fedora Content Repository.
65
62
 
66
63
  The `ci` rake task will download solr and fedora, start them,
67
64
  and run the tests for you.
@@ -7,32 +7,31 @@ Gem::Specification.new do |s|
7
7
  s.version = ActiveFedora::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Matt Zumwalt", "McClain Looney", "Justin Coyne"]
10
- s.email = ["matt.zumwalt@yourmediashelf.com"]
10
+ s.email = ["samvera-tech@googlegroups.com"]
11
11
  s.homepage = %q{https://github.com/projecthydra/active_fedora}
12
12
  s.summary = %q{A convenience libary for manipulating documents in the Fedora Repository.}
13
13
  s.description = %q{ActiveFedora provides for creating and managing objects in the Fedora Repository Architecture.}
14
- s.license = "APACHE2"
14
+ s.license = "Apache-2.0"
15
15
  s.required_ruby_version = '~> 2.0'
16
16
 
17
17
  s.add_dependency 'rsolr', '>= 1.1.2', '< 3'
18
18
  s.add_dependency 'solrizer', '>= 3.4', '< 5'
19
- s.add_dependency "activesupport", '>= 4.2.4', '< 5.2'
20
- s.add_dependency "activemodel", '>= 4.2', '< 5.2'
19
+ s.add_dependency "activesupport", '>= 4.2.4', '< 6'
20
+ s.add_dependency "activemodel", '>= 4.2', '< 6'
21
21
  s.add_dependency "active-triples", '>= 0.11.0', '< 2.0.0'
22
22
  s.add_dependency "deprecation"
23
23
  s.add_dependency "ldp", '~> 0.7.0'
24
- s.add_dependency 'rdf-vocab', '< 3.1.5'
25
24
  s.add_dependency "ruby-progressbar", '~> 1.0'
26
25
  s.add_dependency 'faraday', '~> 0.12.1'
27
26
  s.add_dependency 'faraday-encoding', '0.0.4'
28
27
 
29
- s.add_development_dependency "rails", ">= 4.2"
28
+ s.add_development_dependency "rails"
30
29
  s.add_development_dependency "rdoc"
31
30
  s.add_development_dependency "yard"
32
31
  s.add_development_dependency "rake"
33
- s.add_development_dependency "solr_wrapper", "~> 2.0"
32
+ s.add_development_dependency "solr_wrapper", "~> 1.0"
34
33
  s.add_development_dependency 'fcrepo_wrapper', '~> 0.2'
35
- s.add_development_dependency "rspec", "~> 3.0"
34
+ s.add_development_dependency "rspec", "~> 3.5"
36
35
  s.add_development_dependency "rspec-its"
37
36
  s.add_development_dependency "equivalent-xml"
38
37
  s.add_development_dependency "simplecov", '~> 0.8'
@@ -47,5 +46,4 @@ Gem::Specification.new do |s|
47
46
  "README.md"
48
47
  ]
49
48
  s.require_paths = ["lib"]
50
-
51
49
  end
@@ -1,7 +1,6 @@
1
1
  require 'active_support'
2
2
  require 'active_model'
3
3
  require 'ldp'
4
- require 'solrizer'
5
4
  require 'active_fedora/file_configurator'
6
5
  require 'active_support/core_ext/class/attribute'
7
6
  require 'active_support/core_ext/object'
@@ -68,6 +67,7 @@ module ActiveFedora #:nodoc:
68
67
  autoload :FedoraAttributes
69
68
  autoload :File
70
69
  autoload :FileConfigurator
70
+ autoload :FileIO
71
71
  autoload :FilePathBuilder
72
72
  autoload :FilePersistence
73
73
  autoload :FileRelation
@@ -242,16 +242,14 @@ module ActiveFedora #:nodoc:
242
242
  end
243
243
 
244
244
  def index_field_mapper
245
- Solrizer.default_field_mapper
245
+ @index_field_mapper ||= Indexing::FieldMapper.new
246
246
  end
247
247
 
248
248
  def id_field
249
249
  if defined?(SOLR_DOCUMENT_ID) && !SOLR_DOCUMENT_ID.nil?
250
250
  SOLR_DOCUMENT_ID
251
- elsif defined?(Solrizer)
252
- Solrizer.default_field_mapper.id_field
253
251
  else
254
- 'id'.freeze
252
+ ActiveFedora.index_field_mapper.id_field
255
253
  end
256
254
  end
257
255
 
@@ -41,8 +41,6 @@ module ActiveFedora
41
41
  merge! association.scope(nullify: false)
42
42
  end
43
43
 
44
- delegate :each, to: :to_a
45
-
46
44
  def target
47
45
  @association.target
48
46
  end
@@ -13,9 +13,10 @@ module ActiveFedora::Attributes
13
13
  end
14
14
 
15
15
  def self.define_writers(mixin, name)
16
+ # RDF Terms are singular, even if they respond to `#each`
16
17
  mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
17
18
  def #{name}=(value)
18
- if value.present? && !value.respond_to?(:each)
19
+ unless value.nil? || (value.respond_to?(:each) && !(value.respond_to?(:term?) && value.term?))
19
20
  raise ArgumentError, "You attempted to set the property `#{name}' of \#{id} to a scalar value. However, this property is declared as being multivalued."
20
21
  end
21
22
  set_value(:#{name}, value)
@@ -43,6 +44,7 @@ module ActiveFedora::Attributes
43
44
  end
44
45
 
45
46
  def self.define_singular_writers(mixin, name)
47
+ # RDF Terms are singular, even if they respond to `#each`
46
48
  mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
47
49
  def #{name}=(value)
48
50
  if value.respond_to?(:each) && !(value.respond_to?(:term?) && value.term?)
@@ -10,7 +10,7 @@ module ActiveFedora
10
10
  if @cache_enabled
11
11
  cache_resource(url) { super }
12
12
  else
13
- super
13
+ log(url) { super }
14
14
  end
15
15
  end
16
16
 
@@ -40,6 +40,10 @@ module ActiveFedora #:nodoc:
40
40
  class AssociationNotFoundError < ConfigurationError #:nodoc:
41
41
  end
42
42
 
43
+ # Raised when an object is loaded from Fedora by an incompatible class
44
+ class ModelMismatch < ActiveFedoraError
45
+ end
46
+
43
47
  # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
44
48
  # (has_many, has_one) when there is at least 1 child associated instance.
45
49
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
@@ -49,6 +49,10 @@ module ActiveFedora
49
49
  @config[:ssl]
50
50
  end
51
51
 
52
+ def request_options
53
+ @config[:request]
54
+ end
55
+
52
56
  def connection
53
57
  @connection ||= begin
54
58
  build_connection
@@ -86,6 +90,7 @@ module ActiveFedora
86
90
  def authorized_connection
87
91
  options = {}
88
92
  options[:ssl] = ssl_options if ssl_options
93
+ options[:request] = request_options if request_options
89
94
  Faraday.new(host, options) do |conn|
90
95
  conn.response :encoding # use Faraday::Encoding middleware
91
96
  conn.adapter Faraday.default_adapter # net/http
@@ -196,7 +196,9 @@ module ActiveFedora
196
196
  end
197
197
 
198
198
  def local_or_remote_content(ensure_fetch = true)
199
- @content ||= ensure_fetch ? remote_content : @ds_content unless new_record?
199
+ return @content if new_record?
200
+
201
+ @content ||= ensure_fetch ? remote_content : @ds_content
200
202
  @content.rewind if behaves_like_io?(@content)
201
203
  @content
202
204
  end
@@ -49,6 +49,11 @@ module ActiveFedora::File::Attributes
49
49
  created && created.first
50
50
  end
51
51
 
52
+ def modified_date
53
+ modified = metadata.attributes["http://fedora.info/definitions/v4/repository#lastModified"]
54
+ modified && modified.first
55
+ end
56
+
52
57
  private
53
58
 
54
59
  # Fcrepo4.digest was used by Fedora < 4.3, but it was removed
@@ -0,0 +1,120 @@
1
+ module ActiveFedora
2
+ ##
3
+ # IO like object for reading Fedora files.
4
+ # Use ActiveFedora::FileIO.new(fedora_file) to create one. You can then call
5
+ # read on it or use it with IO.copy_stream and the like.
6
+ #
7
+ # @Note The stream will always be in binmode and return ASCII-8BIT content.
8
+ class FileIO
9
+ attr_reader :pos
10
+
11
+ ##
12
+ # @param [ActiveFedora::File] the file which is wrapped in this IO object.
13
+ def initialize(fedora_file)
14
+ @fedora_file = fedora_file
15
+ @closed = false
16
+ rewind # this initialises various variables
17
+ end
18
+
19
+ def size
20
+ @fedora_file.size
21
+ end
22
+
23
+ alias length size
24
+
25
+ def binmode
26
+ # Do nothing, just return self. The stream is essentially always in binmode.
27
+ self
28
+ end
29
+
30
+ def binmode?
31
+ true
32
+ end
33
+
34
+ ##
35
+ # Read bytes from the file. See IO.read for more information.
36
+ # @param [Integer] the number of bytes to read. If nil or omitted, the
37
+ # entire contents will be read.
38
+ # @param [String] a string in which the contents are read. Can be omitted.
39
+ # @return [String] the read bytes. If number of bytes to read was not
40
+ # specified then always returns a String, possibly an empty
41
+ # one. If number of bytes was specified then the returned
42
+ # string will always be at least one byte long. If no bytes
43
+ # are left in the file returns nil instead.
44
+ def read(amount = nil, buf = nil)
45
+ raise(IOError, "closed stream") if @closed
46
+
47
+ buf ||= ''.force_encoding("ASCII-8BIT")
48
+ buf.clear
49
+
50
+ if amount.nil?
51
+ read_to_buf(nil, buf) # read the entire file, returns buf
52
+ elsif amount < 0
53
+ raise(ArgumentError, "negative length #{amount} given")
54
+ elsif amount.zero?
55
+ ''
56
+ else
57
+ read_to_buf(amount, buf)
58
+ # if amount was specified but we reached eof before reading anything
59
+ # then we must return nil
60
+ buf.empty? ? nil : buf
61
+ end
62
+ end
63
+
64
+ ##
65
+ # Rewinds the io object to the beginning. Read will return bytes from the
66
+ # start of the file again.
67
+ def rewind
68
+ raise(IOError, "closed stream") if @closed
69
+ @pos = 0
70
+ @buffer = nil
71
+ @stream_fiber = Fiber.new do
72
+ @fedora_file.stream.each do |chunk|
73
+ Fiber.yield chunk
74
+ end
75
+ @stream_fiber = nil
76
+ # last value from Fiber is the return value of the block which should be nil
77
+ end
78
+ 0
79
+ end
80
+
81
+ ##
82
+ # Closes the file. No further action can be taken on the file.
83
+ def close
84
+ @closed = true
85
+ @stream_fiber = nil
86
+ nil
87
+ end
88
+
89
+ private
90
+
91
+ def read_to_buf(amount, buf)
92
+ while (amount.nil? || buf.length < amount) && fill_buffer
93
+ buf << consume_buffer(amount.nil? ? nil : (amount - buf.length))
94
+ end
95
+ buf
96
+ end
97
+
98
+ def consume_buffer(count = nil)
99
+ if count.nil? || count >= @buffer.length
100
+ @pos += @buffer.length
101
+ @buffer .tap do
102
+ @buffer = nil
103
+ end
104
+ else
105
+ @buffer.slice!(0, count) .tap do |slice|
106
+ @pos += slice.length
107
+ end
108
+ end
109
+ end
110
+
111
+ def fill_buffer
112
+ return true if @buffer.present?
113
+ # Ruby Net library doesn't seem to like it if we modify the returned
114
+ # chunk in any way, hence dup.
115
+ @buffer = @stream_fiber.try(:resume).try(:dup)
116
+ @buffer.try(:force_encoding, 'ASCII-8BIT')
117
+ !@buffer.nil?
118
+ end
119
+ end
120
+ end
@@ -12,8 +12,13 @@ module ActiveFedora
12
12
  extend ActiveSupport::Autoload
13
13
 
14
14
  eager_autoload do
15
- autoload :Map
15
+ autoload :DefaultDescriptors
16
+ autoload :Descriptor
16
17
  autoload :DescendantFetcher
18
+ autoload :FieldMapper
19
+ autoload :Inserter
20
+ autoload :Map
21
+ autoload :Suffix
17
22
  end
18
23
 
19
24
  included do
@@ -0,0 +1,128 @@
1
+ module ActiveFedora
2
+ module Indexing
3
+ class DefaultDescriptors
4
+ # The suffix produced depends on the type parameter -- produces suffixes:
5
+ # _tesim - for strings or text fields
6
+ # _dtsim - for dates
7
+ # _isim - for integers
8
+ def self.stored_searchable
9
+ @stored_searchable ||= Descriptor.new(stored_searchable_field_definition, converter: searchable_converter, requires_type: true)
10
+ end
11
+
12
+ # The suffix produced depends on the type parameter -- produces suffixes:
13
+ # _teim - for strings or text fields
14
+ # _dtim - for dates
15
+ # _iim - for integers
16
+ def self.searchable
17
+ @searchable ||= Descriptor.new(searchable_field_definition, converter: searchable_converter, requires_type: true)
18
+ end
19
+
20
+ # Takes fields which are stored as strings, but we want indexed as dates. (e.g. "November 6th, 2012")
21
+ # produces suffixes:
22
+ # _dtsim - for dates
23
+ def self.dateable
24
+ @dateable ||= Descriptor.new(:date, :stored, :indexed, :multivalued, converter: dateable_converter)
25
+ end
26
+
27
+ # Produces _sim suffix
28
+ def self.facetable
29
+ @facetable ||= Descriptor.new(:string, :indexed, :multivalued)
30
+ end
31
+
32
+ # Produces _ssim suffix
33
+ # This is useful for when you only want to match whole words, such as user/group names from the the rightsMetadata datastream
34
+ def self.symbol
35
+ @symbol ||= Descriptor.new(:string, :stored, :indexed, :multivalued)
36
+ end
37
+
38
+ # The suffix produced depends on the type parameter -- produces suffixes:
39
+ # _tei - for text fields
40
+ # _si - for strings
41
+ # _dti - for dates
42
+ # _ii - for integers
43
+ def self.sortable
44
+ @sortable ||= Descriptor.new(sortable_field_definition, converter: searchable_converter, requires_type: true)
45
+ end
46
+
47
+ # Fields that are both stored and sortable
48
+ # Produces _ssi suffix if field_type is string
49
+ # Produces _dtsi suffix if field_type is date
50
+ def self.stored_sortable
51
+ @stored_sortable ||= Descriptor.new(->(field_type) { [field_type, :stored, :indexed] }, converter: searchable_converter)
52
+ end
53
+
54
+ # Produces _ssm suffix
55
+ def self.displayable
56
+ @displayable ||= Descriptor.new(:string, :stored, :multivalued)
57
+ end
58
+
59
+ # Produces _tim suffix (used to be _unstem)
60
+ def self.unstemmed_searchable
61
+ @unstemmed_searchable ||= Descriptor.new(:text, :indexed, :multivalued)
62
+ end
63
+
64
+ def self.simple
65
+ @simple ||= Descriptor.new(->(field_type) { [field_type, :indexed] })
66
+ end
67
+
68
+ class << self
69
+ def searchable_field_definition
70
+ lambda do |type|
71
+ type = :text_en if [:string, :text].include?(type) # for backwards compatibility with old solr schema
72
+ vals = [type, :indexed, :multivalued]
73
+ vals
74
+ end
75
+ end
76
+
77
+ def stored_searchable_field_definition
78
+ lambda do |type|
79
+ type = :text_en if [:string, :text].include?(type) # for backwards compatibility with old solr schema
80
+ if type == :boolean
81
+ [type, :indexed, :stored]
82
+ else
83
+ [type, :indexed, :stored, :multivalued]
84
+ end
85
+ end
86
+ end
87
+
88
+ def sortable_field_definition
89
+ lambda do |type|
90
+ vals = [type, :indexed]
91
+ vals
92
+ end
93
+ end
94
+
95
+ def searchable_converter
96
+ lambda do |type|
97
+ case type
98
+ when :date, :time
99
+ ->(val) { iso8601_date(val) }
100
+ end
101
+ end
102
+ end
103
+
104
+ def dateable_converter
105
+ lambda do |_type|
106
+ lambda do |val|
107
+ begin
108
+ iso8601_date(Date.parse(val))
109
+ rescue ArgumentError
110
+ nil
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ def iso8601_date(value)
117
+ if value.is_a?(Date) || value.is_a?(Time)
118
+ DateTime.parse(value.to_s).to_time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
119
+ elsif !value.empty?
120
+ DateTime.parse(value).to_time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
121
+ end
122
+ rescue ArgumentError
123
+ raise ArgumentError, "Unable to parse `#{value}' as a date-time object"
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end