blacklight 3.0pre1 → 3.0pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/.gitmodules +0 -6
  2. data/README.rdoc +94 -87
  3. data/blacklight.gemspec +1 -1
  4. data/config/routes.rb +1 -1
  5. data/lib/blacklight.rb +2 -2
  6. data/lib/blacklight/catalog.rb +10 -12
  7. data/lib/blacklight/controller.rb +2 -2
  8. data/lib/blacklight/engine.rb +5 -2
  9. data/lib/blacklight/solr/document.rb +1 -1
  10. data/lib/blacklight/solr/document/marc.rb +1 -16
  11. data/lib/blacklight/solr_helper.rb +43 -14
  12. data/lib/blacklight/version.rb +1 -1
  13. data/lib/generators/blacklight/assets_generator.rb +25 -0
  14. data/lib/generators/blacklight/blacklight_generator.rb +16 -1
  15. data/lib/generators/blacklight/jetty_generator.rb +101 -0
  16. data/lib/generators/blacklight/solr_conf_generator.rb +25 -0
  17. data/lib/generators/blacklight/templates/catalog_controller.rb +0 -1
  18. data/lib/generators/blacklight/templates/config/solr.yml +14 -2
  19. data/lib/generators/blacklight/templates/public/images/{blacklight/bg.png → bg.png} +0 -0
  20. data/lib/generators/blacklight/templates/public/images/{blacklight/border.png → border.png} +0 -0
  21. data/lib/generators/blacklight/templates/public/images/{blacklight/bul_sq_gry.gif → bul_sq_gry.gif} +0 -0
  22. data/lib/generators/blacklight/templates/public/images/{blacklight/checkmark.gif → checkmark.gif} +0 -0
  23. data/lib/generators/blacklight/templates/public/images/{blacklight/logo.png → logo.png} +0 -0
  24. data/lib/generators/blacklight/templates/public/images/{blacklight/magnifying_glass.gif → magnifying_glass.gif} +0 -0
  25. data/lib/generators/blacklight/templates/public/images/{blacklight/remove.gif → remove.gif} +0 -0
  26. data/lib/generators/blacklight/templates/public/images/{blacklight/separator.gif → separator.gif} +0 -0
  27. data/lib/generators/blacklight/templates/public/images/{blacklight/start_over.gif → start_over.gif} +0 -0
  28. data/lib/generators/blacklight/templates/public/javascripts/blacklight.js +5 -0
  29. data/lib/generators/blacklight/templates/public/stylesheets/blacklight.css +9 -3
  30. data/lib/generators/blacklight/templates/solr_conf/schema.xml +339 -0
  31. data/lib/generators/blacklight/templates/solr_conf/solrconfig.xml +578 -0
  32. data/lib/railties/all_tests.rake +11 -0
  33. data/lib/railties/blacklight.rake +0 -52
  34. data/lib/railties/blacklight_cucumber.rake +125 -0
  35. data/lib/railties/blacklight_rspec.rake +128 -0
  36. data/lib/railties/{test_solr_server.rb → jetty_solr_server.rb} +22 -45
  37. data/lib/railties/solr_marc.rake +24 -5
  38. data/test_support/.rspec +1 -0
  39. data/test_support/data/test_data.utf8.mrc +1 -0
  40. data/test_support/features/bookmarks.feature +88 -0
  41. data/test_support/features/did_you_mean.feature +129 -0
  42. data/test_support/features/folder.feature +67 -0
  43. data/test_support/features/librarian_view.feature +17 -0
  44. data/test_support/features/record_view.feature +34 -0
  45. data/test_support/features/saved_searches.feature +49 -0
  46. data/test_support/features/search.feature +86 -0
  47. data/test_support/features/search_filters.feature +121 -0
  48. data/test_support/features/search_history.feature +95 -0
  49. data/test_support/features/search_results.feature +61 -0
  50. data/test_support/features/search_sort.feature +29 -0
  51. data/test_support/features/step_definitions/bookmarks_steps.rb +5 -0
  52. data/test_support/features/step_definitions/error_steps.rb +4 -0
  53. data/test_support/features/step_definitions/folder_steps.rb +26 -0
  54. data/test_support/features/step_definitions/general_steps.rb +49 -0
  55. data/test_support/features/step_definitions/record_view_steps.rb +11 -0
  56. data/test_support/features/step_definitions/saved_searches_steps.rb +21 -0
  57. data/test_support/features/step_definitions/search_facets_steps.rb +28 -0
  58. data/test_support/features/step_definitions/search_history_steps.rb +8 -0
  59. data/test_support/features/step_definitions/search_result_steps.rb +113 -0
  60. data/test_support/features/step_definitions/search_steps.rb +102 -0
  61. data/test_support/features/step_definitions/user_steps.rb +4 -0
  62. data/test_support/features/step_definitions/web_steps.rb +211 -0
  63. data/test_support/features/support/env.rb +49 -0
  64. data/test_support/features/support/paths.rb +55 -0
  65. data/test_support/features/support/selectors.rb +39 -0
  66. data/test_support/features/unapi.feature +30 -0
  67. data/test_support/spec/controllers/application_controller_spec.rb +22 -0
  68. data/test_support/spec/controllers/catalog_controller_spec.rb +480 -0
  69. data/test_support/spec/controllers/folder_controller_spec.rb +40 -0
  70. data/test_support/spec/controllers/search_history_controller_spec.rb +45 -0
  71. data/test_support/spec/data/sample_docs.yml +655 -0
  72. data/test_support/spec/data/test_data.utf8.mrc +1 -0
  73. data/test_support/spec/helpers/blacklight_helper_spec.rb +482 -0
  74. data/test_support/spec/helpers/hash_as_hidden_fields_spec.rb +23 -0
  75. data/test_support/spec/helpers/render_constraints_helper_spec.rb +64 -0
  76. data/test_support/spec/helpers/search_history_helper_spec.rb +11 -0
  77. data/test_support/spec/helpers/solr_helper_spec.rb +873 -0
  78. data/test_support/spec/lib/blacklight_email_spec.rb +23 -0
  79. data/test_support/spec/lib/blacklight_sms_spec.rb +23 -0
  80. data/test_support/spec/lib/blacklight_solr_document_dublin_core_spec.rb +41 -0
  81. data/test_support/spec/lib/blacklight_solr_document_marc_spec.rb +88 -0
  82. data/test_support/spec/lib/blacklight_solr_document_spec.rb +173 -0
  83. data/test_support/spec/lib/blacklight_spec.rb +39 -0
  84. data/test_support/spec/lib/configurable_spec.rb +97 -0
  85. data/test_support/spec/lib/facet_paginator_spec.rb +93 -0
  86. data/test_support/spec/lib/marc_export_spec.rb +444 -0
  87. data/test_support/spec/lib/search_fields_spec.rb +105 -0
  88. data/test_support/spec/lib/tasks/blacklight_task_spec.rb +21 -0
  89. data/test_support/spec/lib/tasks/solr_marc_task_spec.rb +59 -0
  90. data/test_support/spec/models/bookmark_spec.rb +37 -0
  91. data/test_support/spec/models/record_mailer_spec.rb +67 -0
  92. data/test_support/spec/models/search_spec.rb +55 -0
  93. data/test_support/spec/models/solr_docment_spec.rb +111 -0
  94. data/test_support/spec/rcov.opts +3 -0
  95. data/test_support/spec/spec.opts +4 -0
  96. data/test_support/spec/spec_helper.rb +38 -0
  97. data/test_support/spec/support/action_controller.rb +42 -0
  98. data/test_support/spec/support/assert_difference.rb +16 -0
  99. data/test_support/spec/support/include_text.rb +20 -0
  100. data/test_support/spec/views/catalog/_constraints_element.html.erb_spec.rb +59 -0
  101. data/test_support/spec/views/catalog/_document_list.html.erb_spec.rb +8 -0
  102. data/test_support/spec/views/catalog/_facets.html.erb_spec.rb +182 -0
  103. data/test_support/spec/views/catalog/_index_partials/_default.erb_spec.rb +70 -0
  104. data/test_support/spec/views/catalog/_show_partials/_default.html.erb_spec.rb +70 -0
  105. data/test_support/spec/views/catalog/index.atom.builder_spec.rb +141 -0
  106. data/test_support/spec/views/catalog/show.html.erb_spec.rb +100 -0
  107. data/test_support/spec/views/catalog/unapi.xml.builder_spec.rb +45 -0
  108. metadata +95 -98
  109. data/lib/blacklight/marc.rb +0 -46
  110. data/lib/blacklight/marc/citation.rb +0 -251
  111. data/lib/railties/cucumber.rake +0 -53
  112. data/lib/railties/rspec.rake +0 -188
  113. data/spec/helpers/catalog_helper_spec.rb +0 -111
  114. data/spec/views/catalog/_sms_form.html.erb_spec.rb +0 -19
@@ -1,3 +1,3 @@
1
1
  module Blacklight
2
- VERSION = "3.0pre1"
2
+ VERSION = "3.0pre2"
3
3
  end
@@ -0,0 +1,25 @@
1
+ # Copy Blacklight assets to public folder in current app.
2
+ # If you want to do this on application startup, you can
3
+ # add this next line to your one of your environment files --
4
+ # generally you'd only want to do this in 'development', and can
5
+ # add it to environments/development.rb:
6
+ # require File.join(Blacklight.root, "lib", "generators", "blacklight", "assets_generator.rb")
7
+ # Blacklight::AssetsGenerator.start(["--force", "--quiet"])
8
+
9
+
10
+ # Need the requires here so we can call the generator from environment.rb
11
+ # as suggested above.
12
+ require 'rails/generators'
13
+ require 'rails/generators/base'
14
+ module Blacklight
15
+ class AssetsGenerator < Rails::Generators::Base
16
+ source_root File.expand_path('../templates', __FILE__)
17
+
18
+ def assets
19
+ directory("public/images", "public/images/blacklight")
20
+ directory("public/stylesheets", "public/stylesheets/blacklight")
21
+ directory("public/javascripts", "public/javascripts/blacklight")
22
+ end
23
+
24
+ end
25
+ end
@@ -60,6 +60,18 @@ EOF
60
60
  generate "devise:install"
61
61
  generate "devise", model_name.classify
62
62
  generate "devise:views"
63
+
64
+ # add the #to_s to the model.
65
+ insert_into_file("app/models/#{model_name}.rb", :before => /end(\n| )*$/) do
66
+ %{
67
+ # Method added by Blacklight; Blacklight uses #to_s on your
68
+ # user class to get a user-displayable login/identifier for
69
+ # the account.
70
+ def to_s
71
+ email
72
+ end
73
+ }
74
+ end
63
75
  end
64
76
  end
65
77
 
@@ -70,9 +82,12 @@ EOF
70
82
  directory("config/SolrMarc")
71
83
  end
72
84
 
85
+ require File.expand_path('../assets_generator.rb', __FILE__)
73
86
  # Copy all files in templates/public/ directory to public/
87
+ # Call external generator in AssetsGenerator, so we can
88
+ # leave that callable seperately too.
74
89
  def copy_public_assets
75
- directory("public")
90
+ Blacklight::AssetsGenerator.start()
76
91
  end
77
92
 
78
93
  # Setup the database migrations
@@ -0,0 +1,101 @@
1
+
2
+ module Blacklight
3
+ class Jetty < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+
7
+ argument :save_location, :type=>"string", :desc => "where to install the jetty", :default => "./jetty"
8
+ class_option :environment, :aliases => "-e", :type=>"string", :desc => "environment to use jetty with. Will insert into solr.yml, and also offer to index test data in test environment.", :default => Rails.env
9
+ # change this to a different download if you want to peg to a different
10
+ # tagged version of our known-good jetty/solr.
11
+ class_option :download_url, :aliases => "-u", :type=>"string", :default =>"https://github.com/projectblacklight/blacklight-jetty/zipball/v1.4.1-1" , :desc=>"location of zip file including a jetty with solr setup for blacklight."
12
+ class_option :downloaded_package, :aliases => "-d", :type=>"string", :desc => "manual download of BL-jetty zip file"
13
+
14
+
15
+ desc """
16
+ Installs a jetty container with a solr installed in it. A solr setup known
17
+ good with default blacklight setup, including solr conf files for out
18
+ of the box blacklight.
19
+
20
+ Also adds jetty_path key to solr.yml for selected environment, to refer
21
+ to this install.
22
+
23
+ Requires system('unzip... ') to work, probably won't work on Windows.
24
+
25
+ """
26
+
27
+ def download_jetty
28
+ tmp_save_dir = File.join(Rails.root, "tmp", "jetty_generator")
29
+ empty_directory(tmp_save_dir)
30
+
31
+ begin
32
+ unless options[:downloaded_package]
33
+ begin
34
+ say_status("fetching", options[:download_url])
35
+ zip_file = File.join(tmp_save_dir, "bl_jetty.zip")
36
+ get(options[:download_url], zip_file)
37
+ rescue Exception => e
38
+ say_status("error", "Could not download #{options[:download_url]} : #{e}", :red)
39
+ raise Thor::Error.new("Try downloading manually and then using '-d' option?")
40
+ end
41
+ else
42
+ zip_file = options[:downloaded_package]
43
+ end
44
+
45
+
46
+ say_status("unzipping", zip_file)
47
+ "unzip -d #{tmp_save_dir} -qo #{zip_file}".tap do |command|
48
+ system(command) or raise Thor::Error.new("Error executing: #{command}")
49
+ end
50
+ # It unzips into a top_level directory we've got to find by name
51
+ # in the tmp dir, sadly.
52
+ expanded_dir = Dir[File.join(tmp_save_dir, "projectblacklight-blacklight-jetty-*")].first
53
+
54
+ if File.exists?( save_location ) && ! options[:force]
55
+ raise Thor::Error.new("cancelled by user") unless [nil, "", "Y", "y"].include? ask("Copy over existing #{save_location}? [Yn]")
56
+ end
57
+
58
+ directory(expanded_dir, save_location, :verbose => false)
59
+ say_status("installed", save_location )
60
+ ensure
61
+ remove_dir(tmp_save_dir)
62
+ end
63
+ end
64
+
65
+ # the only thing that's REALLY BL-specific is these conf files
66
+ # installed by another generator. We write em on top of the solr we
67
+ # just installed. We "force" it because we're usually writing on top of files
68
+ # we just installed anyway. The user should have said 'no' to overwriting
69
+ # their dir if they already had one!
70
+ #
71
+ # If we later install Solr from somewhere other than BL jetty repo, we'd
72
+ # still want to write these on top, just like this.
73
+ def install_conf_files
74
+ generate("blacklight:solr_conf", "#{File.join(save_location, 'solr', 'conf')} --force")
75
+ end
76
+
77
+ # adds a jetty_path key to solr.yml for the current environment, so
78
+ # rake tasks for automatically starting jetty/solr (as well as
79
+ # for indexing with solrmarc) can find it.
80
+ def add_jetty_path_to_solr_yml
81
+ # inject_into_file no-ops silently if the :after isn't found, we
82
+ # want to be noisy.
83
+ config_file = "config/solr.yml"
84
+ config_file_full_path = File.expand_path(config_file, destination_root)
85
+ after_hook = /#{Regexp.escape(options[:environment])}\:[^\n]*\n/
86
+
87
+ if !(File.exists?(config_file_full_path) && File.binread( config_file_full_path ) =~ after_hook)
88
+ say_status("skipped", "Could not find '#{options[:environment]}' block in #{config_file} to add jetty_path to.", :red)
89
+ elsif File.binread( config_file_full_path ) =~ /#{Regexp.escape(options[:environment])}\:[^\n]*\n.*(?!\n\n).*jetty_path\:/
90
+ say_status("skipped", "#{config_file} '#{options[:environment]}' block already has jetty_path, not overwriting.", :red)
91
+ else
92
+ inject_into_file config_file, :verbose => false, :after => after_hook do
93
+ " jetty_path: '#{save_location}'\n"
94
+ end
95
+ say_status("insert", "#{config_file}: jetty_path key for '#{options[:environment]}' block")
96
+ end
97
+ end
98
+
99
+
100
+ end
101
+ end
@@ -0,0 +1,25 @@
1
+ module Blacklight
2
+ class SolrConf < Rails::Generators::Base
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ argument :target_path, :type=>:string, :default => "."
6
+
7
+ desc """
8
+ Generate solr config files solrconfig.xml and schema.xml
9
+ to directory you specify. (default current dir).
10
+
11
+ Conf files generated are set up to work with out-of-the-box default
12
+ blacklight.
13
+
14
+ You might want to put them into a solr setup, or you might just
15
+ want to look at them.
16
+
17
+ """
18
+
19
+ # this generator used by test jetty generator too.
20
+ def solr_conf_files
21
+ copy_file "solr_conf/schema.xml", File.expand_path("./schema.xml", target_path)
22
+ copy_file "solr_conf/solrconfig.xml", File.expand_path("./solrconfig.xml", target_path)
23
+ end
24
+ end
25
+ end
@@ -2,7 +2,6 @@ require 'blacklight/catalog'
2
2
 
3
3
  class CatalogController < ApplicationController
4
4
 
5
- include Blacklight::SolrHelper
6
5
  include Blacklight::Catalog
7
6
 
8
7
  end
@@ -1,6 +1,18 @@
1
+ # = jetty_path key
2
+ # each environment can have a jetty_path with absolute or relative
3
+ # (to app root) path to a jetty/solr install. This is used
4
+ # by the rake tasks that start up solr automatically for testing
5
+ # and by rake solr:marc:index.
6
+ #
7
+ # jetty_path is not used by a running Blacklight application
8
+ # at all. In general you do NOT need to deploy solr in Jetty, you can deploy it
9
+ # however you want.
10
+ # jetty_path is only required for rake tasks that need to know
11
+ # how to start up solr, generally for automated testing.
12
+
1
13
  development:
2
14
  url: http://127.0.0.1:8983/solr
3
- test:
15
+ test: &test
4
16
  url: http://127.0.0.1:8888/solr
5
17
  cucumber:
6
- url: http://127.0.0.1:8888/solr
18
+ <<: *test
@@ -1,3 +1,8 @@
1
+ /* This file is generated by Blacklight. You probably don't want to edit
2
+ this file directly, or you'll have to manually merge your changes if later
3
+ versions of Blacklight change this file. Instead, use your own JS file
4
+ which over-rides things in this JS file, as described below: */
5
+
1
6
  /* Blacklight has a Javascript setup meant to support local disabling,
2
7
  modification, and use of Blacklight behaviors.
3
8
 
@@ -1,3 +1,9 @@
1
+ /* This file is generated by Blacklight. You probably don't want to edit
2
+ this file directly, or you'll have to manually merge your changes if later
3
+ versions of Blacklight change this file. Instead, use your own CSS file
4
+ which over-rides things in this file. Or of course you can choose
5
+ not to use the Blacklight CSS file at all in your local app. */
6
+
1
7
  /* Global */
2
8
  html {background: #707070;}
3
9
 
@@ -6,7 +12,7 @@ html {background: #707070;}
6
12
  an accident. */
7
13
  .ui-dialog-content { text-align: left; }
8
14
 
9
- body {background: url('../images/blacklight/bg.png') repeat-x top left; font: 0.7em Verdana, "Lucida Grande", "Lucida Sans Unicode", "Arial Unicode MS", Arial, sans-serif; line-height: 1.4; color:#333; margin: 0px; padding: 15px;}
15
+ body {background: url('../../images/blacklight/bg.png') repeat-x top left; font: 0.7em Verdana, "Lucida Grande", "Lucida Sans Unicode", "Arial Unicode MS", Arial, sans-serif; line-height: 1.4; color:#333; margin: 0px; padding: 15px;}
10
16
 
11
17
  select,input,button,textarea {font: 1em Verdana, "Lucida Grande", "Lucida Sans Unicode", "Arial Unicode MS", Arial, sans-serif;}
12
18
 
@@ -32,7 +38,7 @@ a:hover {color: #029;}
32
38
  #hd {margin: 0em 2em 0 2em; padding: 2em 0 2em 0; }
33
39
  #hd .yui-g {text-align: right;}
34
40
  #hd .yui-g .first {text-align: left;}
35
- #doc, #doc2, #doc3, #doc4 {background: #fff url('../images/blacklight/border.png') repeat-x top left; border-bottom: 2px solid #555; margin: 0px auto;}
41
+ #doc, #doc2, #doc3, #doc4 {background: #fff url('../../images/blacklight/border.png') repeat-x top left; border-bottom: 2px solid #555; margin: 0px auto;}
36
42
  /* border-top: 10px solid #548cd8; -moz-border-top-colors: #548cd8 #5188d3 #4e84d0 #4b81cd #497dc9 #457ac6 #4376c2 #4173be #3e71bc #3d6fba; */
37
43
 
38
44
  /* Body Container Layout */
@@ -43,7 +49,7 @@ a:hover {color: #029;}
43
49
  .sidebar p {padding-top: 2em;}
44
50
 
45
51
  /* Top Banner */
46
- h1.site_title {background: transparent url('../images/blacklight/logo.png') no-repeat top left; margin: 2em 0px 0px 1em; height: 35px; width: 120px;}
52
+ h1.site_title {background: transparent url('../../images/blacklight/logo.png') no-repeat top left; margin: 2em 0px 0px 1em; height: 35px; width: 120px;}
47
53
  .first h1 {margin: 0px; padding: 0px;}
48
54
  h1.site_title a {display:block; height: 35px; width:120px; text-indent: -9999px; overflow: hidden; text-decoration: none; border: 0px;}
49
55
  h1.site_title a:link, h1.site_title a:visited, h1.site_title a:hover, h1.site_title a:active {border: 0px;}
@@ -0,0 +1,339 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <!--
3
+ For information on how to customize this file, please see
4
+ http://wiki.apache.org/solr/SchemaXml. The page also has a link to an
5
+ extensively commented version of this file.
6
+ -->
7
+ <schema name="Blacklight Demo Index" version="1.2">
8
+ <!-- attribute "name" is the name of this schema and is only used for display purposes.
9
+ Applications should change this to reflect the nature of the search collection.
10
+ version="1.2" is Solr's version number for the schema syntax and semantics. It should
11
+ not normally be changed by applications.
12
+ 1.0: multiValued attribute did not exist, all fields are multiValued by nature
13
+ 1.1: multiValued attribute introduced, false by default
14
+ 1.2: omitTermFreqAndPositions attribute introduced, true by default except for text fields.
15
+ 1.3: removed optional field compress feature
16
+ -->
17
+ <types>
18
+ <!-- The StrField type is not analyzed, but indexed/stored verbatim. -->
19
+ <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
20
+ <!-- boolean type: "true" or "false" -->
21
+ <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
22
+ <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
23
+ <fieldtype name="binary" class="solr.BinaryField"/>
24
+
25
+ <!-- The optional sortMissingLast and sortMissingFirst attributes are
26
+ currently supported on types that are sorted internally as strings.
27
+ This includes "string","boolean","sint","slong","sfloat","sdouble","pdate"
28
+ - If sortMissingLast="true", then a sort on this field will cause documents
29
+ without the field to come after documents with the field,
30
+ regardless of the requested sort order (asc or desc).
31
+ - If sortMissingFirst="true", then a sort on this field will cause documents
32
+ without the field to come before documents with the field,
33
+ regardless of the requested sort order.
34
+ - If sortMissingLast="false" and sortMissingFirst="false" (the default),
35
+ then default lucene sorting will be used which places docs without the
36
+ field first in an ascending sort and last in a descending sort.
37
+ -->
38
+
39
+ <!--
40
+ Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
41
+ -->
42
+ <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
43
+ <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
44
+ <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
45
+ <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
46
+
47
+ <!-- included for backwards compat, same as "pint" below. For backwards
48
+ compat only, see notes at "pint" -->
49
+ <fieldType name="integer" class="solr.IntField" omitNorms="true"/>
50
+
51
+ <!--
52
+ Numeric field types that index each value at various levels of precision
53
+ to accelerate range queries when the number of values between the range
54
+ endpoints is large. See the javadoc for NumericRangeQuery for internal
55
+ implementation details.
56
+
57
+ Smaller precisionStep values (specified in bits) will lead to more tokens
58
+ indexed per value, slightly larger index size, and faster range queries.
59
+ A precisionStep of 0 disables indexing at different precision levels.
60
+ -->
61
+ <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
62
+ <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
63
+ <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
64
+ <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
65
+
66
+ <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
67
+ is a more restricted form of the canonical representation of dateTime
68
+ http://www.w3.org/TR/xmlschema-2/#dateTime
69
+ The trailing "Z" designates UTC time and is mandatory.
70
+ Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
71
+ All other components are mandatory.
72
+
73
+ Expressions can also be used to denote calculations that should be
74
+ performed relative to "NOW" to determine the value, ie...
75
+
76
+ NOW/HOUR
77
+ ... Round to the start of the current hour
78
+ NOW-1DAY
79
+ ... Exactly 1 day prior to now
80
+ NOW/DAY+6MONTHS+3DAYS
81
+ ... 6 months and 3 days in the future from the start of
82
+ the current day
83
+
84
+ Consult the DateField javadocs for more information.
85
+
86
+ Note: For faster range queries, consider the tdate type
87
+ -->
88
+ <fieldType name="date" class="solr.TrieDateField" omitNorms="true" precisionStep="0" positionIncrementGap="0"/>
89
+
90
+ <!-- A Trie based date field for faster date range queries and date faceting. -->
91
+ <fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" precisionStep="6" positionIncrementGap="0"/>
92
+
93
+ <!--
94
+ Note:
95
+ These should only be used for compatibility with existing indexes (created with older Solr versions)
96
+ or if "sortMissingFirst" or "sortMissingLast" functionality is needed. Use Trie based fields instead.
97
+
98
+ Plain numeric field types that store and index the text
99
+ value verbatim (and hence don't support range queries, since the
100
+ lexicographic ordering isn't equal to the numeric ordering)
101
+ -->
102
+ <fieldType name="pint" class="solr.IntField" omitNorms="true"/>
103
+ <fieldType name="plong" class="solr.LongField" omitNorms="true"/>
104
+ <fieldType name="pfloat" class="solr.FloatField" omitNorms="true"/>
105
+ <fieldType name="pdouble" class="solr.DoubleField" omitNorms="true"/>
106
+ <fieldType name="pdate" class="solr.DateField" sortMissingLast="true" omitNorms="true"/>
107
+
108
+ <!--
109
+ Note:
110
+ These should only be used for compatibility with existing indexes (created with older Solr versions)
111
+ or if "sortMissingFirst" or "sortMissingLast" functionality is needed. Use Trie based fields instead.
112
+
113
+ Numeric field types that manipulate the value into
114
+ a string value that isn't human-readable in its internal form,
115
+ but with a lexicographic ordering the same as the numeric ordering,
116
+ so that range queries work correctly.
117
+ -->
118
+ <fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
119
+ <fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
120
+ <fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
121
+ <fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
122
+
123
+ <!-- The "RandomSortField" is not used to store or search any
124
+ data. You can declare fields of this type it in your schema
125
+ to generate pseudo-random orderings of your docs for sorting
126
+ purposes. The ordering is generated based on the field name
127
+ and the version of the index, As long as the index version
128
+ remains unchanged, and the same field name is reused,
129
+ the ordering of the docs will be consistent.
130
+ If you want different psuedo-random orderings of documents,
131
+ for the same version of the index, use a dynamicField and
132
+ change the name
133
+ -->
134
+ <fieldType name="random" class="solr.RandomSortField" indexed="true" />
135
+
136
+
137
+ <!-- solr.TextField allows the specification of custom text analyzers
138
+ specified as a tokenizer and a list of token filters. Different
139
+ analyzers may be specified for indexing and querying.
140
+
141
+ The optional positionIncrementGap puts space between multiple fields of
142
+ this type on the same document, with the purpose of preventing false phrase
143
+ matching across fields.
144
+
145
+ For more info on customizing your analyzer chain, please see
146
+ http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
147
+ -->
148
+ <fieldType name="text" class="solr.TextField" positionIncrementGap="100">
149
+ <analyzer type="index">
150
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
151
+ <!-- custom filter from bob@umich -->
152
+ <filter class="schema.UnicodeNormalizationFilterFactory" version="icu4j" composed="false" remove_diacritics="true" remove_modifiers="true" fold="true" />
153
+ <!-- cusotm filter from bob@umich, tokenizes CJK char-by-char. Not
154
+ sure how good that is, but it's probably better than tokenizing
155
+ only at whitespace. -->
156
+ <filter class="schema.CJKFilterFactory" bigrams="false"/>
157
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
158
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
159
+ <filter class="solr.LowerCaseFilterFactory"/>
160
+ <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
161
+ </analyzer>
162
+ <analyzer type="query">
163
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
164
+ <filter class="schema.UnicodeNormalizationFilterFactory" version="icu4j" composed="false" remove_diacritics="true" remove_modifiers="true" fold="true" />
165
+ <filter class="schema.CJKFilterFactory" bigrams="false"/>
166
+ <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
167
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
168
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
169
+ <filter class="solr.LowerCaseFilterFactory"/>
170
+ <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
171
+ </analyzer>
172
+ </fieldType>
173
+
174
+ <!-- Analyzed Text, no Stemming or Synonyms -->
175
+ <fieldtype name="textNoStem" class="solr.TextField" positionIncrementGap="100">
176
+ <analyzer type="index">
177
+ <tokenizer class="solr.WhitespaceTokenizerFactory" />
178
+ <filter class="schema.UnicodeNormalizationFilterFactory" version="icu4j" composed="false" remove_diacritics="true" remove_modifiers="true" fold="true" />
179
+ <filter class="schema.CJKFilterFactory" bigrams="false"/>
180
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
181
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" />
182
+ <filter class="solr.LowerCaseFilterFactory" />
183
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory" />
184
+ </analyzer>
185
+ <analyzer type="query">
186
+ <tokenizer class="solr.WhitespaceTokenizerFactory" />
187
+ <filter class="schema.UnicodeNormalizationFilterFactory" version="icu4j" composed="false" remove_diacritics="true" remove_modifiers="true" fold="true" />
188
+ <filter class="schema.CJKFilterFactory" bigrams="false"/>
189
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
190
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1" />
191
+ <filter class="solr.LowerCaseFilterFactory" />
192
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory" />
193
+ </analyzer>
194
+ </fieldtype>
195
+
196
+ <!-- Less flexible matching, but less false matches. Probably not ideal for product names, but may be good for SKUs. Can insert dashes in the wrong place and still match. -->
197
+ <fieldType name="textTight" class="solr.TextField" positionIncrementGap="100" >
198
+ <analyzer>
199
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
200
+ <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
201
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
202
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
203
+ <filter class="solr.LowerCaseFilterFactory"/>
204
+ <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
205
+ <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
206
+ possible with WordDelimiterFilter in conjuncton with stemming. -->
207
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
208
+ </analyzer>
209
+ </fieldType>
210
+
211
+ <fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100" >
212
+ <analyzer>
213
+ <tokenizer class="solr.StandardTokenizerFactory"/>
214
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
215
+ <filter class="solr.StandardFilterFactory"/>
216
+ <filter class="solr.LowerCaseFilterFactory"/>
217
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
218
+ </analyzer>
219
+ </fieldType>
220
+
221
+ <fieldType name="alphaOnlySort" class="solr.TextField" sortMissingLast="true" omitNorms="true">
222
+ <analyzer>
223
+ <!-- KeywordTokenizer does no actual tokenizing, so the entire
224
+ input string is preserved as a single token
225
+ -->
226
+ <tokenizer class="solr.KeywordTokenizerFactory"/>
227
+ <filter class="schema.UnicodeNormalizationFilterFactory" version="icu4j" composed="false" remove_diacritics="true" remove_modifiers="true" fold="true" />
228
+ <filter class="solr.LowerCaseFilterFactory" />
229
+ <filter class="solr.TrimFilterFactory" />
230
+ <!--
231
+ <filter class="solr.PatternReplaceFilterFactory" pattern="([^a-z\d])" replacement="" replace="all" />
232
+ -->
233
+ </analyzer>
234
+ </fieldType>
235
+ </types>
236
+
237
+ <fields>
238
+ <!-- NOTE: this is not a full list of fields in the index; dynamic fields are also used -->
239
+ <field name="id" type="string" indexed="true" stored="true" required="true" />
240
+ <field name="timestamp" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
241
+ <!-- default, catch all search field -->
242
+ <field name="text" type="text" indexed="true" stored="false" multiValued="true"/>
243
+
244
+ <!-- these display fields are NOT multi-valued -->
245
+ <field name="marc_display" type="string" indexed="false" stored="true" multiValued="false"/>
246
+ <field name="title_display" type="string" indexed="false" stored="true" multiValued="false"/>
247
+ <field name="title_vern_display" type="string" indexed="false" stored="true" multiValued="false"/>
248
+ <field name="subtitle_display" type="string" indexed="false" stored="true" multiValued="false"/>
249
+ <field name="subtitle_vern_display" type="string" indexed="false" stored="true" multiValued="false"/>
250
+ <field name="author_display" type="string" indexed="false" stored="true" multiValued="false"/>
251
+ <field name="author_vern_display" type="string" indexed="false" stored="true" multiValued="false"/>
252
+
253
+ <!-- these fields are also used for display, so they must be stored -->
254
+ <field name="isbn_t" type="text" indexed="true" stored="true" multiValued="true"/>
255
+ <field name="language_facet" type="string" indexed="true" stored="true" multiValued="true" />
256
+ <field name="subject_topic_facet" type="string" indexed="true" stored="true" multiValued="true" />
257
+ <field name="subject_era_facet" type="string" indexed="true" stored="true" multiValued="true" />
258
+ <field name="subject_geo_facet" type="string" indexed="true" stored="true" multiValued="true" />
259
+ <!-- pub_date is used for facet and display so it must be indexed and stored -->
260
+ <field name="pub_date" type="string" indexed="true" stored="true" multiValued="true"/>
261
+ <!-- pub_date sort uses new trie-based int fields, which are recommended for any int and are displayable, sortable, and range-query-able. In addition,
262
+ we use 'tint' for faster range-queries. -->
263
+ <field name="pub_date_sort" type="tint" indexed="true" stored="true" multiValued="false"/>
264
+
265
+ <!-- format is used for facet, display, and choosing which partial to use for the show view, so it must be stored and indexed -->
266
+ <field name="format" type="string" indexed="true" stored="true"/>
267
+
268
+ <dynamicField name="*_i" type="int" indexed="true" stored="true"/>
269
+ <dynamicField name="*_s" type="string" indexed="true" stored="true" multiValued="true"/>
270
+ <dynamicField name="*_l" type="long" indexed="true" stored="true"/>
271
+ <dynamicField name="*_t" type="text" indexed="true" stored="false" multiValued="true"/>
272
+ <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
273
+ <dynamicField name="*_f" type="float" indexed="true" stored="true"/>
274
+ <dynamicField name="*_d" type="double" indexed="true" stored="true"/>
275
+ <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
276
+ <dynamicField name="random*" type="random" />
277
+
278
+ <dynamicField name="*_facet" type="string" indexed="true" stored="false" multiValued="true" />
279
+ <dynamicField name="*_display" type="string" indexed="false" stored="true" multiValued="true" />
280
+ <dynamicField name="*_sort" type="alphaOnlySort" indexed="true" stored="false"/>
281
+ <dynamicField name="*_unstem_search" type="textNoStem" indexed="true" stored="false" multiValued="true" />
282
+ <dynamicField name="*spell" type="textSpell" indexed="true" stored="false" multiValued="true"/>
283
+
284
+ </fields>
285
+
286
+ <uniqueKey>id</uniqueKey>
287
+ <defaultSearchField>text</defaultSearchField>
288
+ <solrQueryParser defaultOperator="OR"/>
289
+
290
+ <!-- Copy Fields -->
291
+
292
+ <!-- unstemmed fields -->
293
+ <copyField source="title_t" dest="title_unstem_search"/>
294
+ <copyField source="subtitle_t" dest="subtitle_unstem_search"/>
295
+ <copyField source="title_addl_t" dest="title_addl_unstem_search"/>
296
+ <copyField source="title_added_entry_t" dest="title_added_entry_unstem_search"/>
297
+ <copyField source="title_series_t" dest="title_series_unstem_search"/>
298
+ <copyField source="author_t" dest="author_unstem_search"/>
299
+ <copyField source="author_addl_t" dest="author_addl_unstem_search"/>
300
+ <copyField source="subject_t" dest="subject_unstem_search"/>
301
+ <copyField source="subject_addl_t" dest="subject_addl_unstem_search"/>
302
+ <copyField source="subject_topic_facet" dest="subject_topic_unstem_search"/>
303
+
304
+ <!-- sort fields -->
305
+ <copyField source="pub_date" dest="pub_date_sort"/>
306
+
307
+
308
+ <!-- spellcheck fields -->
309
+ <!-- default spell check; should match fields for default request handler -->
310
+ <!-- it won't work with a copy of a copy field -->
311
+ <copyField source="*_t" dest="spell"/>
312
+ <copyField source="*_facet" dest="spell"/>
313
+ <!-- title spell check; should match fields for title request handler -->
314
+ <copyField source="title_t" dest="title_spell"/>
315
+ <copyField source="subtitle_t" dest="title_spell"/>
316
+ <copyField source="addl_titles_t" dest="title_spell"/>
317
+ <copyField source="title_added_entry_t" dest="title_spell"/>
318
+ <copyField source="title_series_t" dest="title_spell"/>
319
+ <!-- author spell check; should match fields for author request handler -->
320
+ <copyField source="author_t" dest="author_spell"/>
321
+ <copyField source="author_addl_t" dest="author_spell"/>
322
+ <!-- subject spell check; should match fields for subject request handler -->
323
+ <copyField source="subject_topic_facet" dest="subject_spell"/>
324
+ <copyField source="subject_t" dest="subject_spell"/>
325
+ <copyField source="subject_addl_t" dest="subject_spell"/>
326
+
327
+ <!-- OpenSearch query field should match request handler search fields -->
328
+ <copyField source="title_t" dest="opensearch_display"/>
329
+ <copyField source="subtitle_t" dest="opensearch_display"/>
330
+ <copyField source="addl_titles_t" dest="opensearch_display"/>
331
+ <copyField source="title_added_entry_t" dest="opensearch_display"/>
332
+ <copyField source="title_series_t" dest="opensearch_display"/>
333
+ <copyField source="author_t" dest="opensearch_display"/>
334
+ <copyField source="author_addl_t" dest="opensearch_display"/>
335
+ <copyField source="subject_topic_facet" dest="opensearch_display"/>
336
+ <copyField source="subject_t" dest="opensearch_display"/>
337
+ <copyField source="subject_addl_t" dest="opensearch_display"/>
338
+
339
+ </schema>