hydra-collections 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.gitmodules +4 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +16 -0
  7. data/Gemfile +12 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +133 -0
  10. data/Rakefile +12 -0
  11. data/app/assets/javascripts/hydra/batch_select.js +41 -0
  12. data/app/assets/javascripts/hydra_collections.js +12 -0
  13. data/app/controllers/collections_controller.rb +18 -0
  14. data/app/helpers/batch_select_helper.rb +25 -0
  15. data/app/helpers/collections_helper.rb +14 -0
  16. data/app/models/collection.rb +16 -0
  17. data/app/views/batch_select/_add_button.html.erb +3 -0
  18. data/app/views/batch_select/_check_all.html.erb +4 -0
  19. data/app/views/batch_select/_tools.html.erb +10 -0
  20. data/app/views/collections/_button_create_collection.html.erb +2 -0
  21. data/app/views/collections/_form.html.erb +36 -0
  22. data/app/views/collections/_form_for_select_collection.html.erb +13 -0
  23. data/app/views/collections/new.html.erb +3 -0
  24. data/app/views/collections/show.html.erb +9 -0
  25. data/config/jetty.yml +6 -0
  26. data/config/routes.rb +3 -0
  27. data/fedora_conf/conf/development/fedora.fcfg +946 -0
  28. data/fedora_conf/conf/test/fedora.fcfg +946 -0
  29. data/hydra-collections.gemspec +27 -0
  30. data/lib/hydra-collections.rb +7 -0
  31. data/lib/hydra/collection.rb +52 -0
  32. data/lib/hydra/collections.rb +12 -0
  33. data/lib/hydra/collections/accepts_batches.rb +55 -0
  34. data/lib/hydra/collections/collectible.rb +24 -0
  35. data/lib/hydra/collections/search_service.rb +58 -0
  36. data/lib/hydra/collections/version.rb +5 -0
  37. data/lib/hydra/collections_controller_behavior.rb +108 -0
  38. data/lib/hydra/datastreams/collection_rdf_datastream.rb +36 -0
  39. data/solr_conf/conf/schema.xml +372 -0
  40. data/solr_conf/conf/solrconfig.xml +163 -0
  41. data/solr_conf/solr.xml +35 -0
  42. data/spec/controllers/accepts_batches_spec.rb +72 -0
  43. data/spec/controllers/collections_controller_spec.rb +93 -0
  44. data/spec/factories.rb +18 -0
  45. data/spec/factories/.gitkeep +0 -0
  46. data/spec/factories/users.rb +31 -0
  47. data/spec/helpers/collections_helper_spec.rb +29 -0
  48. data/spec/lib/collectible_spec.rb +31 -0
  49. data/spec/lib/search_service_spec.rb +41 -0
  50. data/spec/models/collection_spec.rb +100 -0
  51. data/spec/spec_helper.rb +24 -0
  52. data/spec/support/Gemfile +19 -0
  53. data/spec/support/app/models/sample.rb +37 -0
  54. data/spec/support/app/models/solr_document.rb +5 -0
  55. data/spec/support/app/views/catalog/_document_header.html.erb +11 -0
  56. data/spec/support/app/views/catalog/_sort_and_per_page.html.erb +20 -0
  57. data/spec/support/config/initializers/hydra_config.rb +28 -0
  58. data/spec/support/db/migrate/20111101221803_create_searches.rb +16 -0
  59. data/spec/support/lib/generators/test_app_generator.rb +54 -0
  60. data/spec/support/lib/tasks/rspec.rake +9 -0
  61. data/tasks/hydra-collections-dev.rake +68 -0
  62. data/tasks/jetty.rake +40 -0
  63. metadata +194 -0
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hydra/collections/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hydra-collections"
8
+ spec.version = Hydra::Collections::VERSION
9
+ spec.authors = ["Carolyn Cole"]
10
+ spec.email = ["cam156@psu.edu"]
11
+ spec.description = "A rails engine for managing Hydra Collections"
12
+ spec.summary = "A rails engine for managing Hydra Collections"
13
+ spec.homepage = "https://github.com/psu-stewardship/hydra-collections"
14
+ spec.license = "APACHE2"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "blacklight"
22
+ spec.add_dependency "hydra-head"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec-rails"
27
+ end
@@ -0,0 +1,7 @@
1
+ require "hydra/collections"
2
+ require "hydra/collections_controller_behavior"
3
+ require "hydra/collection"
4
+ require "bundler/setup"
5
+ require "blacklight"
6
+ require "hydra/head"
7
+ require "active_fedora"
@@ -0,0 +1,52 @@
1
+ require 'hydra/head'
2
+ require 'hydra/datastreams/collection_rdf_datastream'
3
+
4
+ module Hydra
5
+ module Collection
6
+ extend ActiveSupport::Concern
7
+ extend ActiveSupport::Autoload
8
+ autoload :Permissions
9
+ include Hydra::ModelMethods # for access to apply_depositor_metadata
10
+
11
+ included do
12
+ has_metadata :name => "descMetadata", :type => CollectionRdfDatastream
13
+ has_metadata :name => "properties", :type => Hydra::Datastream::Properties
14
+ has_metadata :name => "rightsMetadata", :type => Hydra::Datastream::RightsMetadata
15
+
16
+ has_and_belongs_to_many :members, :property => :has_collection_member, :class_name => "ActiveFedora::Base"
17
+
18
+ delegate_to :properties, [:depositor], :unique => true
19
+ delegate_to :descMetadata, [:date_uploaded, :date_modified, :related_url,
20
+ :title, :description], :unique => true
21
+
22
+ before_create :set_date_uploaded
23
+ before_save :set_date_modified
24
+ end
25
+
26
+ # TODO: Move this override into ScholarSphere
27
+ #def to_solr(solr_doc={}, opts={})
28
+ # super(solr_doc, opts)
29
+ # solr_doc[Solrizer.solr_name("noid", :sortable, :type => :text)] = noid
30
+ # return solr_doc
31
+ #end
32
+
33
+ def terms_for_editing
34
+ terms_for_display - [:date_modified, :date_uploaded]
35
+ end
36
+
37
+ def terms_for_display
38
+ self.descMetadata.class.config.keys
39
+ end
40
+
41
+ private
42
+
43
+ def set_date_uploaded
44
+ self.date_uploaded = Date.today
45
+ end
46
+
47
+ def set_date_modified
48
+ self.date_modified = Date.today
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,12 @@
1
+ module Hydra
2
+ module Collections
3
+ extend ActiveSupport::Autoload
4
+ autoload :Version
5
+ autoload :Collectible
6
+ autoload :SearchService
7
+ autoload :AcceptsBatches
8
+ class Engine < ::Rails::Engine
9
+ engine_name "collections"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ module Hydra
2
+ module Collections
3
+ module AcceptsBatches
4
+
5
+ def batch
6
+ @batch ||= batch_ids_from_params
7
+ end
8
+
9
+ def batch=(val)
10
+ @batch = val
11
+ end
12
+
13
+ # Callback to be used in before_filter
14
+ def check_for_empty_batch?
15
+ return batch.empty?
16
+ end
17
+
18
+ protected
19
+
20
+ def batch_ids_from_params
21
+ if params["batch_document_ids"].nil? || params["batch_document_ids"].empty?
22
+ return []
23
+ elsif params["batch_document_ids"] == "all"
24
+ return Hydra::Collections::SearchService.new(session, current_user.user_key).last_search_documents.map(&:id)
25
+ else
26
+ return params["batch_document_ids"]
27
+ end
28
+ end
29
+
30
+ def filter_docs_with_read_access!
31
+ filter_docs_with_access!(:read)
32
+ end
33
+
34
+ def filter_docs_with_edit_access!
35
+ filter_docs_with_access!(:edit)
36
+ end
37
+
38
+ def filter_docs_with_access!(access_type=:edit)
39
+ no_permissions = []
40
+ if batch.empty?
41
+ flash[:notice] = "Select something first"
42
+ else
43
+ batch.dup.each do |doc_id|
44
+ unless can?(access_type, doc_id)
45
+ batch.delete(doc_id)
46
+ no_permissions << doc_id
47
+ end
48
+ end
49
+ flash[:notice] = "You do not have permission to edit the documents: #{no_permissions.join(', ')}" unless no_permissions.empty?
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,24 @@
1
+ # This module adds a `has_many :collections` association to any models that you mix it into, using the :has_collection_member property
2
+ # It also provides methods to help you index the information as a facet
3
+ module Hydra::Collections::Collectible
4
+ extend ActiveSupport::Autoload
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ #after_solrize << :index_collection_pids
9
+ has_many :collections, property: :has_collection_member
10
+ end
11
+
12
+ # Add this method to your solrization logic (ie. in to_solr) in order to populate the 'collection' facet
13
+ # with the pids of any collections that contain the current object.
14
+ # @example
15
+ # def to_solr(solr_doc={}, opts={})
16
+ # super(solr_doc, opts)
17
+ # index_collection_pids(solr_doc)
18
+ # return solr_doc
19
+ # end
20
+ def index_collection_pids(solr_doc={})
21
+ solr_doc[Solrizer.solr_name(:collection, :facetable)] = self.collection_ids
22
+ solr_doc
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ module Hydra
2
+ module Collections
3
+ class SearchService
4
+ include Blacklight::Configurable
5
+ include Blacklight::SolrHelper
6
+
7
+ def initialize(session, user_key)
8
+ @session = session
9
+ @user_key = user_key
10
+ self.class.copy_blacklight_config_from(::CatalogController)
11
+ end
12
+
13
+ solr_search_params_logic << :apply_gated_search
14
+
15
+ def last_search_documents
16
+ return [] if @session[:history].blank?
17
+ last_search_id = @session[:history].first
18
+ search = Search.find(last_search_id)
19
+ _, document_list = get_search_results(search.query_params, :fl=>'id', :rows=>1000)
20
+ document_list
21
+ end
22
+
23
+ # filter that sets up access-controlled lucene query in order to provide gated search behavior
24
+ # @param solr_parameters the current solr parameters
25
+ # @param user_parameters the current user-submitted parameters
26
+ def apply_gated_search(solr_parameters, user_parameters)
27
+ solr_parameters[:fq] ||= []
28
+
29
+ # Grant access to public content
30
+ user_access_filters = []
31
+ user_access_filters << "#{solr_access_control_suffix(:group)}:public"
32
+
33
+ # Grant access based on user id & role
34
+ unless @user_key.blank?
35
+ # for roles
36
+ ::RoleMapper.roles(@user_key).each do |role|
37
+ user_access_filters << "#{solr_access_control_suffix(:group)}:#{escape_slashes(role)}"
38
+ end
39
+ # for individual person access
40
+ user_access_filters << "#{solr_access_control_suffix(:individual)}:#{escape_slashes(@user_key)}"
41
+ end
42
+ solr_parameters[:fq] << user_access_filters.join(' OR ')
43
+ solr_parameters
44
+ end
45
+
46
+ def escape_slashes(value)
47
+ value.gsub('/', '\/')
48
+ end
49
+
50
+ # @param [Symbol] key The permission type to return. Must be `:group` or `:individual`
51
+ def solr_access_control_suffix(key)
52
+ raise ArgumentError, "you must provide :group or :individual" unless [:group, :individual].include?(key)
53
+ Hydra.config[:permissions][:edit][key]
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,5 @@
1
+ module Hydra
2
+ module Collections
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,108 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2012 The Pennsylvania State University
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ module Hydra
17
+ module CollectionsControllerBehavior
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ include Hydra::Controller::ControllerBehavior
22
+ include Blacklight::Configurable # comply with BL 3.7
23
+ include Hydra::Collections::AcceptsBatches
24
+
25
+ # This is needed as of BL 3.7
26
+ self.copy_blacklight_config_from(CatalogController)
27
+
28
+ # Catch permission errors
29
+ rescue_from Hydra::AccessDenied, CanCan::AccessDenied do |exception|
30
+ if (exception.action == :edit)
31
+ redirect_to(sufia.url_for({:action=>'show'}), :alert => "You do not have sufficient privileges to edit this document")
32
+ elsif current_user and current_user.persisted?
33
+ redirect_to root_url, :alert => exception.message
34
+ else
35
+ session["user_return_to"] = request.url
36
+ redirect_to new_user_session_url, :alert => exception.message
37
+ end
38
+ end
39
+
40
+ # actions: audit, index, create, new, edit, show, update, destroy, permissions, citation
41
+ before_filter :authenticate_user!, :except => [:show]
42
+ load_and_authorize_resource :except=>[:index]
43
+ end
44
+
45
+ def new
46
+ #@collection = ::Collection.new
47
+ end
48
+
49
+ def edit
50
+ end
51
+
52
+ def create
53
+ @collection.apply_depositor_metadata(current_user.user_key)
54
+ unless batch.empty?
55
+ params[:collection][:members]="add"
56
+ process_member_changes
57
+ end
58
+ respond_to do |format|
59
+ if @collection.save
60
+ format.html { redirect_to collections.collection_path(@collection), notice: 'Collection was successfully created.' }
61
+ format.json { render json: @collection, status: :created, location: @collection }
62
+ else
63
+ format.html { render action: "new" }
64
+ format.json { render json: @collection.errors, status: :unprocessable_entity }
65
+ end
66
+ end
67
+ end
68
+
69
+ def update
70
+ @collection = ::Collection.find(params[:id])
71
+ process_member_changes
72
+ @collection.update_attributes(params[:collection].except(:members))
73
+ respond_to do |format|
74
+ if @collection.save
75
+ format.html { redirect_to collections.collection_path(@collection), notice: 'Collection was successfully created.' }
76
+ format.json { render json: @collection, status: :updated, location: @collection }
77
+ else
78
+ format.html { render action: collections.edit_collection_path(@collection) }
79
+ format.json { render json: @collection.errors, status: :unprocessable_entity }
80
+ end
81
+ end
82
+ end
83
+
84
+ protected
85
+
86
+ def process_member_changes
87
+ unless params[:collection].nil?
88
+ case params[:collection][:members]
89
+ when "add"
90
+ batch.each do |pid|
91
+ @collection.add_relationship(:has_collection_member, "info:fedora/#{pid}")
92
+ end
93
+ when "remove"
94
+ batch.each do |pid|
95
+ @collection.remove_relationship(:has_collection_member, "info:fedora/#{pid}")
96
+ end
97
+ when Array
98
+ @collection.clear_relationship(:has_collection_member)
99
+ params[:collection][:members].each do |pid|
100
+ @collection.add_relationship(:has_collection_member, "info:fedora/#{pid}")
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+
107
+ end # module CollectionsControllerBehavior
108
+ end # module Hydra
@@ -0,0 +1,36 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require 'active_fedora'
15
+
16
+ module Hydra
17
+ class CollectionRdfDatastream < ActiveFedora::NtriplesRDFDatastream
18
+ map_predicates do |map|
19
+ map.title(:in => RDF::DC) do |index|
20
+ index.as :stored_searchable
21
+ end
22
+ map.description(:in => RDF::DC) do |index|
23
+ index.type :text
24
+ index.as :stored_searchable
25
+ end
26
+ map.date_uploaded(:to => "dateSubmitted", :in => RDF::DC) do |index|
27
+ index.type :date
28
+ index.as :stored_sortable
29
+ end
30
+ map.date_modified(:to => "modified", :in => RDF::DC) do |index|
31
+ index.type :date
32
+ index.as :stored_sortable
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,372 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <schema name="Hydra" version="1.5">
3
+ <!-- NOTE: various comments and unused configuration possibilities have been purged
4
+ from this file. Please refer to http://wiki.apache.org/solr/SchemaXml,
5
+ as well as the default schema file included with Solr -->
6
+
7
+ <uniqueKey>id</uniqueKey>
8
+
9
+ <fields>
10
+ <field name="id" type="string" stored="true" indexed="true" multiValued="false" required="true"/>
11
+ <field name="timestamp" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
12
+
13
+ <field name="lat" type="tdouble" stored="true" indexed="true" multiValued="false"/>
14
+ <field name="lng" type="tdouble" stored="true" indexed="true" multiValued="false"/>
15
+
16
+ <!--these fields are hard coded in places in hydra-head -->
17
+ <field name="active_fedora_model_s" type="string" stored="true" indexed="true"/>
18
+ <field name="object_profile_display" type="string" stored="true" indexed="true"/>
19
+ <field name="has_model_s" type="string" stored="true" indexed="true"/>
20
+ <field name="is_governed_by_s" type="string" stored="true" indexed="true"/>
21
+
22
+
23
+ <!--
24
+ These are hard coded in places in hydra-head, but we hope to fix that.
25
+
26
+ <field name="inheritable_discover_access_person_t" type="string" stored="true" indexed="true" multiValued="true"/>
27
+ <field name="inheritable_read_access_person_t" type="string" stored="true" indexed="true" multiValued="true"/>
28
+ <field name="inheritable_edit_access_person_t" type="string" stored="true" indexed="true" multiValued="true"/>
29
+ <field name="inheritable_discover_access_group_t" type="string" stored="true" indexed="true" multiValued="true"/>
30
+ <field name="inheritable_read_access_group_t" type="string" stored="true" indexed="true" multiValued="true"/>
31
+ <field name="inheritable_edit_access_group_t" type="string" stored="true" indexed="true" multiValued="true"/>
32
+ <field name="read_access_person_t" type="string" stored="true" indexed="true" multiValued="true"/>
33
+ <field name="discover_access_person_t" type="string" stored="true" indexed="true" multiValued="true"/>
34
+ <field name="edit_access_person_t" type="string" stored="true" indexed="true" multiValued="true"/>
35
+ <field name="read_access_group_t" type="string" stored="true" indexed="true" multiValued="true"/>
36
+ <field name="edit_access_group_t" type="string" stored="true" indexed="true" multiValued="true"/>
37
+ <field name="discover_access_group_t" type="string" stored="true" indexed="true" multiValued="true"/>
38
+ -->
39
+
40
+
41
+ <!-- NOTE: not all possible Solr field types are represented in the dynamic fields -->
42
+
43
+ <!-- text (_t...) -->
44
+ <dynamicField name="*_ti" type="text" stored="false" indexed="true" multiValued="false"/>
45
+ <dynamicField name="*_tim" type="text" stored="false" indexed="true" multiValued="true"/>
46
+ <dynamicField name="*_ts" type="text" stored="true" indexed="false" multiValued="false"/>
47
+ <dynamicField name="*_tsm" type="text" stored="true" indexed="false" multiValued="true"/>
48
+ <dynamicField name="*_tsi" type="text" stored="true" indexed="true" multiValued="false"/>
49
+ <dynamicField name="*_tsim" type="text" stored="true" indexed="true" multiValued="true"/>
50
+ <dynamicField name="*_tiv" type="text" stored="false" indexed="true" multiValued="false" termVectors="true" termPositions="true" termOffsets="true"/>
51
+ <dynamicField name="*_timv" type="text" stored="false" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
52
+ <dynamicField name="*_tsiv" type="text" stored="true" indexed="true" multiValued="false" termVectors="true" termPositions="true" termOffsets="true"/>
53
+ <dynamicField name="*_tsimv" type="text" stored="true" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
54
+
55
+ <!-- English text (_te...) -->
56
+ <dynamicField name="*_tei" type="text_en" stored="false" indexed="true" multiValued="false"/>
57
+ <dynamicField name="*_teim" type="text_en" stored="false" indexed="true" multiValued="true"/>
58
+ <dynamicField name="*_tes" type="text_en" stored="true" indexed="false" multiValued="false"/>
59
+ <dynamicField name="*_tesm" type="text_en" stored="true" indexed="false" multiValued="true"/>
60
+ <dynamicField name="*_tesi" type="text_en" stored="true" indexed="true" multiValued="false"/>
61
+ <dynamicField name="*_tesim" type="text_en" stored="true" indexed="true" multiValued="true"/>
62
+ <dynamicField name="*_teiv" type="text_en" stored="false" indexed="true" multiValued="false" termVectors="true" termPositions="true" termOffsets="true"/>
63
+ <dynamicField name="*_teimv" type="text_en" stored="false" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
64
+ <dynamicField name="*_tesiv" type="text_en" stored="true" indexed="true" multiValued="false" termVectors="true" termPositions="true" termOffsets="true"/>
65
+ <dynamicField name="*_tesimv" type="text_en" stored="true" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
66
+
67
+ <!-- string (_s...) -->
68
+ <dynamicField name="*_si" type="string" stored="false" indexed="true" multiValued="false"/>
69
+ <dynamicField name="*_sim" type="string" stored="false" indexed="true" multiValued="true"/>
70
+ <dynamicField name="*_ss" type="string" stored="true" indexed="false" multiValued="false"/>
71
+ <dynamicField name="*_ssm" type="string" stored="true" indexed="false" multiValued="true"/>
72
+ <dynamicField name="*_ssi" type="string" stored="true" indexed="true" multiValued="false"/>
73
+ <dynamicField name="*_ssim" type="string" stored="true" indexed="true" multiValued="true"/>
74
+ <dynamicField name="*_ssort" type="alphaSort" stored="false" indexed="true" multiValued="false"/>
75
+
76
+ <!-- integer (_i...) -->
77
+ <dynamicField name="*_ii" type="int" stored="false" indexed="true" multiValued="false"/>
78
+ <dynamicField name="*_iim" type="int" stored="false" indexed="true" multiValued="true"/>
79
+ <dynamicField name="*_is" type="int" stored="true" indexed="false" multiValued="false"/>
80
+ <dynamicField name="*_ism" type="int" stored="true" indexed="false" multiValued="true"/>
81
+ <dynamicField name="*_isi" type="int" stored="true" indexed="true" multiValued="false"/>
82
+ <dynamicField name="*_isim" type="int" stored="true" indexed="true" multiValued="true"/>
83
+
84
+ <!-- trie integer (_it...) (for faster range queries) -->
85
+ <dynamicField name="*_iti" type="tint" stored="false" indexed="true" multiValued="false"/>
86
+ <dynamicField name="*_itim" type="tint" stored="false" indexed="true" multiValued="true"/>
87
+ <dynamicField name="*_its" type="tint" stored="true" indexed="false" multiValued="false"/>
88
+ <dynamicField name="*_itsm" type="tint" stored="true" indexed="false" multiValued="true"/>
89
+ <dynamicField name="*_itsi" type="tint" stored="true" indexed="true" multiValued="false"/>
90
+ <dynamicField name="*_itsim" type="tint" stored="true" indexed="true" multiValued="true"/>
91
+
92
+ <!-- date (_dt...) -->
93
+ <!-- The format for this date field is of the form 1995-12-31T23:59:59Z
94
+ Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z -->
95
+ <dynamicField name="*_dti" type="date" stored="false" indexed="true" multiValued="false"/>
96
+ <dynamicField name="*_dtim" type="date" stored="false" indexed="true" multiValued="true"/>
97
+ <dynamicField name="*_dts" type="date" stored="true" indexed="false" multiValued="false"/>
98
+ <dynamicField name="*_dtsm" type="date" stored="true" indexed="false" multiValued="true"/>
99
+ <dynamicField name="*_dtsi" type="date" stored="true" indexed="true" multiValued="false"/>
100
+ <dynamicField name="*_dtsim" type="date" stored="true" indexed="true" multiValued="true"/>
101
+
102
+ <!-- trie date (_dtt...) (for faster range queries) -->
103
+ <dynamicField name="*_dtti" type="tdate" stored="false" indexed="true" multiValued="false"/>
104
+ <dynamicField name="*_dttim" type="tdate" stored="false" indexed="true" multiValued="true"/>
105
+ <dynamicField name="*_dtts" type="tdate" stored="true" indexed="false" multiValued="false"/>
106
+ <dynamicField name="*_dttsm" type="tdate" stored="true" indexed="false" multiValued="true"/>
107
+ <dynamicField name="*_dttsi" type="tdate" stored="true" indexed="true" multiValued="false"/>
108
+ <dynamicField name="*_dttsim" type="tdate" stored="true" indexed="true" multiValued="true"/>
109
+
110
+ <!-- long (_l...) -->
111
+ <dynamicField name="*_li" type="long" stored="false" indexed="true" multiValued="false"/>
112
+ <dynamicField name="*_lim" type="long" stored="false" indexed="true" multiValued="true"/>
113
+ <dynamicField name="*_ls" type="long" stored="true" indexed="false" multiValued="false"/>
114
+ <dynamicField name="*_lsm" type="long" stored="true" indexed="false" multiValued="true"/>
115
+ <dynamicField name="*_lsi" type="long" stored="true" indexed="true" multiValued="false"/>
116
+ <dynamicField name="*_lsim" type="long" stored="true" indexed="true" multiValued="true"/>
117
+
118
+ <!-- trie long (_lt...) (for faster range queries) -->
119
+ <dynamicField name="*_lti" type="tlong" stored="false" indexed="true" multiValued="false"/>
120
+ <dynamicField name="*_ltim" type="tlong" stored="false" indexed="true" multiValued="true"/>
121
+ <dynamicField name="*_lts" type="tlong" stored="true" indexed="false" multiValued="false"/>
122
+ <dynamicField name="*_ltsm" type="tlong" stored="true" indexed="false" multiValued="true"/>
123
+ <dynamicField name="*_ltsi" type="tlong" stored="true" indexed="true" multiValued="false"/>
124
+ <dynamicField name="*_ltsim" type="tlong" stored="true" indexed="true" multiValued="true"/>
125
+
126
+ <!-- double (_db...) -->
127
+ <dynamicField name="*_dbi" type="double" stored="false" indexed="true" multiValued="false"/>
128
+ <dynamicField name="*_dbim" type="double" stored="false" indexed="true" multiValued="true"/>
129
+ <dynamicField name="*_dbs" type="double" stored="true" indexed="false" multiValued="false"/>
130
+ <dynamicField name="*_dbsm" type="double" stored="true" indexed="false" multiValued="true"/>
131
+ <dynamicField name="*_dbsi" type="double" stored="true" indexed="true" multiValued="false"/>
132
+ <dynamicField name="*_dbsim" type="double" stored="true" indexed="true" multiValued="true"/>
133
+
134
+ <!-- trie double (_dbt...) (for faster range queries) -->
135
+ <dynamicField name="*_dbti" type="tdouble" stored="false" indexed="true" multiValued="false"/>
136
+ <dynamicField name="*_dbtim" type="tdouble" stored="false" indexed="true" multiValued="true"/>
137
+ <dynamicField name="*_dbts" type="tdouble" stored="true" indexed="false" multiValued="false"/>
138
+ <dynamicField name="*_dbtsm" type="tdouble" stored="true" indexed="false" multiValued="true"/>
139
+ <dynamicField name="*_dbtsi" type="tdouble" stored="true" indexed="true" multiValued="false"/>
140
+ <dynamicField name="*_dbtsim" type="tdouble" stored="true" indexed="true" multiValued="true"/>
141
+
142
+ <!-- float (_f...) -->
143
+ <dynamicField name="*_fi" type="float" stored="false" indexed="true" multiValued="false"/>
144
+ <dynamicField name="*_fim" type="float" stored="false" indexed="true" multiValued="true"/>
145
+ <dynamicField name="*_fs" type="float" stored="true" indexed="false" multiValued="false"/>
146
+ <dynamicField name="*_fsm" type="float" stored="true" indexed="false" multiValued="true"/>
147
+ <dynamicField name="*_fsi" type="float" stored="true" indexed="true" multiValued="false"/>
148
+ <dynamicField name="*_fsim" type="float" stored="true" indexed="true" multiValued="true"/>
149
+
150
+ <!-- trie float (_ft...) (for faster range queries) -->
151
+ <dynamicField name="*_fti" type="tfloat" stored="false" indexed="true" multiValued="false"/>
152
+ <dynamicField name="*_ftim" type="tfloat" stored="false" indexed="true" multiValued="true"/>
153
+ <dynamicField name="*_fts" type="tfloat" stored="true" indexed="false" multiValued="false"/>
154
+ <dynamicField name="*_ftsm" type="tfloat" stored="true" indexed="false" multiValued="true"/>
155
+ <dynamicField name="*_ftsi" type="tfloat" stored="true" indexed="true" multiValued="false"/>
156
+ <dynamicField name="*_ftsim" type="tfloat" stored="true" indexed="true" multiValued="true"/>
157
+
158
+ <!-- boolean (_b...) -->
159
+ <dynamicField name="*_bi" type="boolean" stored="false" indexed="true" multiValued="false"/>
160
+ <dynamicField name="*_bs" type="boolean" stored="true" indexed="false" multiValued="false"/>
161
+ <dynamicField name="*_bsi" type="boolean" stored="true" indexed="true" multiValued="false"/>
162
+
163
+ <!-- Type used to index the lat and lon components for the "location" FieldType -->
164
+ <dynamicField name="*_coordinate" type="tdouble" indexed="true" stored="false" />
165
+
166
+ <!-- location (_ll...) -->
167
+ <dynamicField name="*_lli" type="location" stored="false" indexed="true" multiValued="false"/>
168
+ <dynamicField name="*_llim" type="location" stored="false" indexed="true" multiValued="true"/>
169
+ <dynamicField name="*_lls" type="location" stored="true" indexed="false" multiValued="false"/>
170
+ <dynamicField name="*_llsm" type="location" stored="true" indexed="false" multiValued="true"/>
171
+ <dynamicField name="*_llsi" type="location" stored="true" indexed="true" multiValued="false"/>
172
+ <dynamicField name="*_llsim" type="location" stored="true" indexed="true" multiValued="true"/>
173
+
174
+ <!-- you must define copyField source and dest fields explicity or schemaBrowser doesn't work -->
175
+ <field name="all_text_timv" type="text" stored="false" indexed="true" multiValued="true" termVectors="true" termPositions="true" termOffsets="true"/>
176
+
177
+ </fields>
178
+
179
+ <!-- START hydra deprecated items -->
180
+ <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
181
+ <!--
182
+ <solrQueryParser defaultOperator="AND"/>
183
+
184
+ <copyField source="title_t" dest="title_unstem_search"/>
185
+ <copyField source="subtitle_t" dest="subtitle_unstem_search"/>
186
+ <copyField source="title_addl_t" dest="title_addl_unstem_search"/>
187
+ <copyField source="title_added_entry_t" dest="title_added_entry_unstem_search"/>
188
+ <copyField source="title_series_t" dest="title_series_unstem_search"/>
189
+ <copyField source="author_t" dest="author_unstem_search"/>
190
+ <copyField source="author_addl_t" dest="author_addl_unstem_search"/>
191
+ <copyField source="subject_t" dest="subject_unstem_search"/>
192
+ <copyField source="subject_addl_t" dest="subject_addl_unstem_search"/>
193
+ <copyField source="subject_topic_facet" dest="subject_topic_unstem_search"/>
194
+ -->
195
+ <!-- sort fields -->
196
+ <!--
197
+ <copyField source="pub_date" dest="pub_date_sort"/>
198
+ -->
199
+
200
+ <!-- spellcheck fields -->
201
+ <!-- default spell check; should match fields for default request handler -->
202
+ <!-- it won't work with a copy of a copy field -->
203
+ <!--
204
+ <copyField source="*_t" dest="spell"/>
205
+ <copyField source="*_facet" dest="spell"/>
206
+ -->
207
+ <!-- title spell check; should match fields for title request handler -->
208
+ <!--
209
+ <copyField source="title_t" dest="title_spell"/>
210
+ <copyField source="subtitle_t" dest="title_spell"/>
211
+ <copyField source="addl_titles_t" dest="title_spell"/>
212
+ <copyField source="title_added_entry_t" dest="title_spell"/>
213
+ <copyField source="title_series_t" dest="title_spell"/>
214
+ -->
215
+ <!-- author spell check; should match fields for author request handler -->
216
+ <!--
217
+ <copyField source="author_t" dest="author_spell"/>
218
+ <copyField source="author_addl_t" dest="author_spell"/>
219
+ -->
220
+ <!-- subject spell check; should match fields for subject request handler -->
221
+ <!--
222
+ <copyField source="subject_topic_facet" dest="subject_spell"/>
223
+ <copyField source="subject_t" dest="subject_spell"/>
224
+ <copyField source="subject_addl_t" dest="subject_spell"/>
225
+ -->
226
+
227
+ <!-- OpenSearch query field should match request handler search fields -->
228
+ <!--
229
+ <copyField source="title_t" dest="opensearch_display"/>
230
+ <copyField source="subtitle_t" dest="opensearch_display"/>
231
+ <copyField source="addl_titles_t" dest="opensearch_display"/>
232
+ <copyField source="title_added_entry_t" dest="opensearch_display"/>
233
+ <copyField source="title_series_t" dest="opensearch_display"/>
234
+ <copyField source="author_t" dest="opensearch_display"/>
235
+ <copyField source="author_addl_t" dest="opensearch_display"/>
236
+ <copyField source="subject_topic_facet" dest="opensearch_display"/>
237
+ <copyField source="subject_t" dest="opensearch_display"/>
238
+ <copyField source="subject_addl_t" dest="opensearch_display"/>
239
+ -->
240
+
241
+ <!-- Above, multiple source fields are copied to the [text] field.
242
+ Another way to map multiple source fields to the same
243
+ destination field is to use the dynamic field syntax.
244
+ copyField also supports a maxChars to copy setting. -->
245
+
246
+ <!-- <copyField source="*_t" dest="text" maxChars="3000"/> -->
247
+ <!--
248
+ <copyField source="*_s" dest="text"/>
249
+ <copyField source="*_t" dest="text"/>
250
+ <copyField source="*_facet" dest="text"/>
251
+ -->
252
+ <!-- copy name to alphaNameSort, a field designed for sorting by name -->
253
+ <!-- <copyField source="name" dest="alphaNameSort"/> -->
254
+
255
+ <!-- END hydra deprecated items -->
256
+
257
+ <!-- copy fields; note that you must define copyField source and dest fields explicity or schemaBrowser doesn't work -->
258
+ <!--
259
+ <copyField source="some_field" dest="all_text_timv" />
260
+ -->
261
+
262
+ <types>
263
+ <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
264
+ <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
265
+ <fieldType name="rand" class="solr.RandomSortField" omitNorms="true"/>
266
+
267
+ <!-- Default numeric field types. -->
268
+ <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
269
+ <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
270
+ <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
271
+ <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
272
+
273
+ <!-- trie numeric field types for faster range queries -->
274
+ <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
275
+ <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
276
+ <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
277
+ <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
278
+
279
+ <!-- The format for this date field is of the form 1995-12-31T23:59:59Z
280
+ Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
281
+ -->
282
+ <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
283
+ <!-- A Trie based date field for faster date range queries and date faceting. -->
284
+ <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
285
+
286
+
287
+ <!-- This point type indexes the coordinates as separate fields (subFields)
288
+ If subFieldType is defined, it references a type, and a dynamic field
289
+ definition is created matching *___<typename>. Alternately, if
290
+ subFieldSuffix is defined, that is used to create the subFields.
291
+ Example: if subFieldType="double", then the coordinates would be
292
+ indexed in fields myloc_0___double,myloc_1___double.
293
+ Example: if subFieldSuffix="_d" then the coordinates would be indexed
294
+ in fields myloc_0_d,myloc_1_d
295
+ The subFields are an implementation detail of the fieldType, and end
296
+ users normally should not need to know about them.
297
+ -->
298
+ <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
299
+
300
+ <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
301
+ <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
302
+
303
+ <!-- An alternative geospatial field type new to Solr 4. It supports multiValued and polygon shapes.
304
+ For more information about this and other Spatial fields new to Solr 4, see:
305
+ http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
306
+ -->
307
+ <fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
308
+ geo="true" distErrPct="0.025" maxDistErr="0.000009" units="degrees" />
309
+
310
+ <fieldType name="text" class="solr.TextField" omitNorms="false">
311
+ <analyzer>
312
+ <tokenizer class="solr.ICUTokenizerFactory"/>
313
+ <filter class="solr.ICUFoldingFilterFactory"/> <!-- NFKC, case folding, diacritics removed -->
314
+ <filter class="solr.TrimFilterFactory"/>
315
+ </analyzer>
316
+ </fieldType>
317
+
318
+ <!-- A text field that only splits on whitespace for exact matching of words -->
319
+ <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
320
+ <analyzer>
321
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
322
+ <filter class="solr.TrimFilterFactory"/>
323
+ </analyzer>
324
+ </fieldType>
325
+
326
+ <!-- single token analyzed text, for sorting. Punctuation is significant. -->
327
+ <fieldtype name="alphaSort" class="solr.TextField" sortMissingLast="true" omitNorms="true">
328
+ <analyzer>
329
+ <tokenizer class="solr.KeywordTokenizerFactory" />
330
+ <filter class="solr.ICUFoldingFilterFactory"/>
331
+ <filter class="solr.TrimFilterFactory" />
332
+ </analyzer>
333
+ </fieldtype>
334
+
335
+ <!-- A text field with defaults appropriate for English -->
336
+ <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
337
+ <analyzer>
338
+ <tokenizer class="solr.ICUTokenizerFactory"/>
339
+ <filter class="solr.ICUFoldingFilterFactory"/> <!-- NFKC, case folding, diacritics removed -->
340
+ <filter class="solr.EnglishPossessiveFilterFactory"/>
341
+ <!-- EnglishMinimalStemFilterFactory is less aggressive than PorterStemFilterFactory: -->
342
+ <filter class="solr.EnglishMinimalStemFilterFactory"/>
343
+ <!--
344
+ <filter class="solr.PorterStemFilterFactory"/>
345
+ -->
346
+ <filter class="solr.TrimFilterFactory"/>
347
+ </analyzer>
348
+ </fieldType>
349
+
350
+ <!-- queries for paths match documents at that path, or in descendent paths -->
351
+ <fieldType name="descendent_path" class="solr.TextField">
352
+ <analyzer type="index">
353
+ <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
354
+ </analyzer>
355
+ <analyzer type="query">
356
+ <tokenizer class="solr.KeywordTokenizerFactory" />
357
+ </analyzer>
358
+ </fieldType>
359
+
360
+ <!-- queries for paths match documents at that path, or in ancestor paths -->
361
+ <fieldType name="ancestor_path" class="solr.TextField">
362
+ <analyzer type="index">
363
+ <tokenizer class="solr.KeywordTokenizerFactory" />
364
+ </analyzer>
365
+ <analyzer type="query">
366
+ <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
367
+ </analyzer>
368
+ </fieldType>
369
+
370
+ </types>
371
+
372
+ </schema>