woodwing_elvis 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ module WoodWing
2
+ class Elvis
3
+ module Rest
4
+
5
+
6
+ # https://elvis.tenderapp.com/kb/api/rest-create_relation
7
+ def create_relation(options={})
8
+ url = base_url + "create_relation"
9
+ response = get_response(url, options)
10
+ end # create_relation
11
+
12
+
13
+ # https://elvis.tenderapp.com/kb/api/rest-remove_relation
14
+ def remove_relation(options={})
15
+ url = base_url + "remove_relation"
16
+ response = get_response(url, options)
17
+ end # remove_relation
18
+
19
+ alias :delete_relation :remove_relation
20
+
21
+
22
+ end # module Rest
23
+ end # class Elvis
24
+ end # module WoodWing
@@ -0,0 +1,156 @@
1
+ module WoodWing
2
+ class Elvis
3
+ module Rest
4
+
5
+
6
+ # https://elvis.tenderapp.com/kb/api/rest-search
7
+ # Search assets in Elvis using all of the powerful search functions provided
8
+ # by the Elvis search engine. You can execute all possible queries and even
9
+ # use faceted search.
10
+ #
11
+ # Returned information can be formatted as JSON, XML or HTML to support any
12
+ # kind of environment for clients.
13
+ #
14
+ # Apart from all sorts of metadata about the assets, the results returned
15
+ # by a search call also contain ready-to-use URLs to the thumbnail, preview
16
+ # and original file. This makes it extremely easy to display rich visual results.
17
+ #
18
+ # http://yourserver.com/services/search
19
+ # ?q=<query>
20
+ # &start=<first result>
21
+ # &num=<max result hits to return>
22
+ # &sort=<comma-delimited sort fields>
23
+ # &metadataToReturn=<comma-delimited fields>
24
+ # &facets=<comma-delimited fields>
25
+ # &facet.<field>.selection=<comma-delimited values>
26
+ # &format=<json|xml|html>
27
+ # &appendRequestSecret=<true|false>
28
+ #
29
+ # Options
30
+ # q (Required) The query to search for, see the query syntax guide
31
+ # for details. https://elvis.tenderapp.com/kb/technical/query-syntax
32
+ # Recap: supports wildcards: *? logical: AND && OR ||
33
+ # prefix terms with + to require - to remove
34
+ # suffix terms with ~ to include similar (eg. spelling errors)
35
+ # terms seperated by spaces default to an AND condition
36
+ # use "double quotes" to search for phrases.
37
+ # All searches are case insensitive.
38
+ #
39
+ # start First hit to be returned. Starting at 0 for the first hit. Used
40
+ # to skip hits to return 'paged' results. Optional. Default is 0.
41
+ #
42
+ # num Number of hits to return. Specify 0 to return no hits, this can be
43
+ # useful if you only want to fetch facets data. Optional. Default is 50.
44
+ #
45
+ # sort The sort order of returned hits. Comma-delimited list of fields to
46
+ # sort on. By default, date/time fields and number fields are sorted
47
+ # descending. All other fields are sorted ascending. To explicitly
48
+ # specify sort order, append "-desc" or "-asc" to the field.
49
+ # Some examples:
50
+ # sort=name
51
+ # sort=rating
52
+ # sort=fileSize-asc
53
+ # sort=status,assetModified-asc
54
+ # A special sort case is "relevance". This lets the search engine
55
+ # determine sorting based on the relevance of the asset against
56
+ # the search query. Relevance results are always returned descending.
57
+ # Optional. Default is assetCreated-desc.
58
+ #
59
+ # metadataToReturn Comma-delimited list of metadata fields to return in hits.
60
+ # It is good practice to always specify just the metadata
61
+ # fields that you need. This will make the searches faster
62
+ # because less data needs to be transferred over the network.
63
+ # Example: metadataToReturn=name,rating,assetCreated
64
+ # Specify "all", or omit to return all available metadata.
65
+ # Example: metadataToReturn=all
66
+ # metadataToReturn=
67
+ # Optional. Default returns all fields.
68
+ #
69
+ # facets Comma-delimited list fields to return facet for.
70
+ # Example: facets=tags,assetDomain
71
+ # Selected values for a facet must be specified with a
72
+ # "facet.<field>.selection" parameter. Do not add selected items to
73
+ # the query since that will cause incorrect facet filtering.
74
+ # Note: Only fields that are un_tokenized or tokenized with
75
+ # pureLowerCase analyzer can be used for faceted search
76
+ # Optional. Default returns no facets.
77
+ #
78
+ # facet.<field>.selection Comma-delimited list of values that should
79
+ # be 'selected' for a given facet.
80
+ # Example: facet.tags.selection=beach
81
+ # facet.assetDomain.selection=image,video
82
+ # Optional.
83
+ #
84
+ # format Response format to return, either json, xml or html.
85
+ # json format is lightweight and very suitable for consumption
86
+ # using AJAX and JavaScript.
87
+ # html format is the easiest way to embed results in HTML pages,
88
+ # but is heavier and less flexible than using a HitRenderer
89
+ # from our open-source JavaScript library.
90
+ # xml format is the same as returned by the Elvis SOAP webservice
91
+ # search operation. This format is suitable for environments
92
+ # that do not support JSON parsing and work better with XML.
93
+ # When you use format=xml, error responses will also be returned
94
+ # in xml format.
95
+ # Optional. Default is json.
96
+ #
97
+ # appendRequestSecret When set to true will append an encrypted code to
98
+ # the thumbnail, preview and original URLs. This is
99
+ # useful when the search is transformed to HTML by an
100
+ # intermediary (like a PHP or XSLT) and is then served
101
+ # to a web browser that is not authenticated against
102
+ # the server.
103
+ # Optional. Default is false.
104
+ #
105
+ # RETURNED VALUE
106
+ # ==============
107
+ #
108
+ # An array of hits in JSON, XML or HTML format. Each item in the array has
109
+ # the following properties.
110
+ #
111
+ # firstResult Index of the first result that is returned.
112
+ # maxResultHits Maximum number of hits that are returned.
113
+ # totalHits Total hits found by the search.
114
+ #
115
+ # hits
116
+ #
117
+ # id Unique ID of the asset in Elvis.
118
+ # permissions String that indicates the permissions the current user has
119
+ # for the asset.
120
+ # thumbnailUrl A ready to use URL to display the thumbnail of an asset.
121
+ # Only available for assets that have a thumbnail.
122
+ # previewUrl A ready to use URL to display the default preview of an
123
+ # asset. The type of preview depends on the asset type.
124
+ # Only available for assets that have a preview.
125
+ # originalUrl A ready to use URL to download the original asset.
126
+ # This URL will only work if the user has the 'use original'
127
+ # permission for this asset. This can be checked with the
128
+ # 'permissions' property.
129
+ # metadata An object with metadata that was requested to be returned.
130
+ # Some metadata will always be returned.
131
+ #
132
+ # Fields that have date or datetime values and the field fileSize contain
133
+ # both the actual numerical value and a formatted value.
134
+
135
+ def search(options={})
136
+
137
+ Utilities.demand_required_options!( :search, options )
138
+ url = base_url + "search"
139
+
140
+ # NOTE: One element of metadata is 'textContent' for books and
141
+ # large articles that is a LOT of text. The following
142
+ # line changes the default from 'all' to 'status,name'.
143
+ # If you want all metadata then you have to request
144
+ # 'all' in your options.
145
+
146
+ options = { metadataToReturn: 'status,name' }.merge(options)
147
+ response = get_response(url, options)
148
+
149
+ end # search
150
+
151
+ alias :find :search
152
+
153
+
154
+ end # module Rest
155
+ end # class Elvis
156
+ end # module WoodWing
@@ -0,0 +1,11 @@
1
+ module WoodWing
2
+ class Elvis
3
+ module Rest
4
+
5
+
6
+ def stub(); end
7
+
8
+
9
+ end # module Rest
10
+ end # class Elvis
11
+ end # module WoodWing
@@ -0,0 +1,18 @@
1
+ ###################################################
2
+ ###
3
+ ## File: soap.rb
4
+ ## Desc: SOAP API definitions for WoodWing's Elvis
5
+ #
6
+
7
+ module WoodWing
8
+ class Elvis
9
+ module Soap
10
+
11
+ require_relative 'soap/stub'
12
+
13
+ end # module Soap
14
+
15
+ include Soap
16
+
17
+ end # class Elvis
18
+ end # module WoodWing
@@ -0,0 +1,11 @@
1
+ module WoodWing
2
+ class Elvis
3
+ module Soap
4
+
5
+
6
+ def stub(); end
7
+
8
+
9
+ end # module Soap
10
+ end # class Elvis
11
+ end # module WoodWing
@@ -0,0 +1,80 @@
1
+ ###################################################
2
+ ###
3
+ ## File: utilities.rb
4
+ ## Desc: Utilitie methods for working with the REST API
5
+ ## for WoodWing's Elvis product
6
+ #
7
+
8
+ require_relative 'utilities/pmask'
9
+
10
+ module WoodWing
11
+ class Elvis
12
+ class Utilities
13
+ class << self
14
+
15
+ =begin
16
+ # SMELL: Is this really necessary with RestClient ?
17
+ def url_encode_options(options)
18
+ raise "Invalid parameter class: expected Hash" unless Hash == options.class
19
+ a_string = ''
20
+ first_one = true
21
+ options.each_pair do |k, v|
22
+ if first_one
23
+ a_string += '?'
24
+ first_one = false
25
+ else
26
+ a_string += '&'
27
+ end
28
+ # a_string += "#{k}=#{String == v.class ? v.gsub(' ','%20') : v}"
29
+ a_string += "#{k}=#{URI::encode(v)}"
30
+ end # options.each_pair
31
+ #debug_me{:a_string} if debug?
32
+ return a_string
33
+ end # url_encode_options
34
+
35
+ =end
36
+
37
+ # encode the username and password for use on the URL for login
38
+
39
+ # SMELL: This is not necessary with a session-based logon/off system
40
+ # HOWEVER, it might still be useful for some cases. Can this
41
+ # scheme and a session management scheme work together?
42
+
43
+ def encode_login(username='guest', password='guest')
44
+
45
+ {
46
+ authcred: UrlSafeBase64.encode64("#{username}:#{password}"),
47
+ authpersist: 'true',
48
+ authclient: 'api_ruby'
49
+ }
50
+
51
+ end # def encode_login(username='guest', password='guest')
52
+
53
+
54
+ # raise ArgumentError if required options are not present
55
+
56
+ def demand_required_options!(command, options)
57
+
58
+ raise ArgumentError unless Symbol == command.class
59
+ raise ArgumentError unless Hash == options.class
60
+ raise ArgumentError unless WW::Elvis::COMMANDS.include?(command)
61
+
62
+ required_options = WW::Elvis::COMMANDS[command][1]
63
+
64
+ answer = true
65
+
66
+ return(answer) if required_options.empty?
67
+
68
+ required_options.each do |ro|
69
+ answer &&= options.include?(ro)
70
+ end
71
+
72
+ raise "ArgumentError: #{caller.first.split().last} requires #{required_options.join(', ')}" unless answer
73
+
74
+ end # def demand_required_options!(command, options)
75
+
76
+ end # eigenclass
77
+ end # class Utilities
78
+ end # class Elvis
79
+ end # module WoodWing
80
+
@@ -0,0 +1,52 @@
1
+ ###################################################
2
+ ###
3
+ ## File: pmask.rb
4
+ ## Desc: Utility class to check permissions 'mask' for available permissions
5
+ #
6
+
7
+ module WoodWing
8
+ class Elvis
9
+ class Utilities
10
+
11
+ # Utility class to check permissions 'mask' for available permissions.
12
+ # The permissions mask consists of a string with one character for
13
+ # every permission available in Elvis: VPUMERXCD
14
+
15
+ class Pmask
16
+
17
+ PERMISSIONS = {
18
+ 'V' => 'VIEW',
19
+ 'P' => 'VIEW_PREVIEW',
20
+ 'U' => 'USE_ORIGINAL',
21
+ 'M' => 'EDIT_METADATA',
22
+ 'E' => 'EDIT',
23
+ 'R' => 'RENAME',
24
+ 'X' => 'MOVE',
25
+ 'C' => 'CREATE',
26
+ 'D' => 'DELETE',
27
+ }
28
+
29
+ def initialize(pmask='')
30
+ @pmask = pmask
31
+ end
32
+
33
+ def verbose
34
+ v=[]
35
+ @pmask.each_char{|c| v<<PERMISSIONS[c]}
36
+ return v.join(', ')
37
+ end
38
+
39
+ define_method('can_view?') { @pmask.include? 'V' }
40
+ define_method('can_view_preview?') { @pmask.include? 'P' }
41
+ define_method('can_use_original?') { @pmask.include? 'U' }
42
+ define_method('can_edit_metadata?') { @pmask.include? 'M' }
43
+ define_method('can_edit?') { @pmask.include? 'E' }
44
+ define_method('can_rename?') { @pmask.include? 'R' }
45
+ define_method('can_move?') { @pmask.include? 'X' }
46
+ define_method('can_create?') { @pmask.include? 'C' }
47
+ define_method('can_delete?') { @pmask.include? 'D' }
48
+
49
+ end # class Pmask
50
+ end # class Utilities
51
+ end # class Elvis
52
+ end # module WoodWing
@@ -0,0 +1,5 @@
1
+ # TODO: indicate the version of the API
2
+
3
+ module WoodWing
4
+ VERSION = "0.0.1" # This is just the version of this gem.
5
+ end # module WoodWing
@@ -0,0 +1,416 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ ##########################################################
4
+ ###
5
+ ## File: elvis_search.rb
6
+ ## Desc: Search Elvis for stuff
7
+ ## can produce an XML file for use with Carrot2 clustering
8
+ ## By: Dewayne VanHoozer (dvanhoozer@gmail.com)
9
+ #
10
+
11
+ require 'debug_me'
12
+ include DebugMe
13
+
14
+ require 'pathname'
15
+ require_relative '../lib/woodwing'
16
+
17
+
18
+ me = Pathname.new(__FILE__).realpath
19
+ my_dir = me.parent
20
+ my_name = me.basename.to_s
21
+
22
+ $options = {
23
+ verbose: false,
24
+ debug: false,
25
+ show_text: false,
26
+ show_dates: false,
27
+ cluster_results: false,
28
+ cluster_filename: nil,
29
+ cluster_file: nil,
30
+ elvis_api_url: ENV['ELVIS_API_URL'] || 'http://localhost:8080/services/',
31
+ elvis_user: ENV['ELVIS_USER'] || 'guest',
32
+ elvis_pass: ENV['ELVIS_PASS'] || 'guest',
33
+ meta_fields: '',
34
+ query: '' # syntax identical to Elvis UI search box
35
+ }
36
+
37
+ def verbose?
38
+ $options[:verbose]
39
+ end
40
+
41
+ def debug?
42
+ $options[:debug]
43
+ end
44
+
45
+ def show_text?
46
+ $options[:show_text]
47
+ end
48
+
49
+ def show_dates?
50
+ $options[:show_dates]
51
+ end
52
+
53
+ def cluster_results?
54
+ $options[:cluster_results]
55
+ end
56
+
57
+ $KNOWN_MFIELDS = %w[ assetCreator
58
+ assetDomain
59
+ assetFileModifier
60
+ assetModifier
61
+ assetPath
62
+ assetPropertyETag
63
+ assetType
64
+ basicDataETag
65
+ cf_PrayerFocus
66
+ cf_Theme
67
+ cf_TFTD
68
+ cf_LongReading
69
+ cf_Citation
70
+ contentETag
71
+ extension
72
+ filename
73
+ fileSize
74
+ fileType
75
+ folderPath
76
+ indexRevision
77
+ metadataComplete
78
+ mimeType
79
+ name
80
+ previewETag
81
+ previewState
82
+ sceArchived
83
+ sceUsed
84
+ status
85
+ textContent
86
+ versionETag
87
+ versionNumber ]
88
+
89
+ usage = <<EOS
90
+
91
+ Search Elvis for stuff
92
+
93
+ Usage: #{my_name} [options] 'query'
94
+
95
+ Where:
96
+
97
+ options Do This
98
+ -h or --help Display this message
99
+ -v or --verbose Display progress
100
+ -d or --debug Sets $DEBUG
101
+ -m or --meta Display these metadata fields
102
+ field_names+ one of more metadata field
103
+ names seperated by commas
104
+ --dates Shows creation and modification
105
+ dates and users
106
+ --text Shows text around the search term(s)
107
+ for the first "hit" in the document
108
+
109
+ --cluster User document clustering
110
+ out_filename filename into which the search
111
+ results are stored
112
+
113
+ 'query' The search query constrained by
114
+ single quotes.
115
+
116
+ NOTE:
117
+
118
+ The single quotes around the search query are required to
119
+ defeat the command line file glob/wildcard facility.
120
+
121
+ The '-m or --meta' option can be used many times as needed.
122
+ The following list contains the known (case-SENSITIVE)
123
+ metadata fields:
124
+
125
+ #{$KNOWN_MFIELDS.join(', ')}
126
+
127
+ EOS
128
+
129
+ # Check command line for Problems with Parameters
130
+ $errors = []
131
+ $warnings = []
132
+
133
+
134
+ # Get the next ARGV parameter after param_index
135
+ def get_next_parameter(param_index)
136
+ unless Fixnum == param_index.class
137
+ param_index = ARGV.find_index(param_index)
138
+ end
139
+ next_parameter = nil
140
+ if param_index+1 >= ARGV.size
141
+ $errors << "#{ARGV[param_index]} specified without parameter"
142
+ else
143
+ next_parameter = ARGV[param_index+1]
144
+ ARGV[param_index+1] = nil
145
+ end
146
+ ARGV[param_index] = nil
147
+ return next_parameter
148
+ end # def get_next_parameter(param_index)
149
+
150
+
151
+ # Get $options[:out_filename]
152
+ def get_out_filename(param_index)
153
+ filename_str = get_next_parameter(param_index)
154
+ $options[:out_filename] = Pathname.new( filename_str ) unless filename_str.nil?
155
+ end # def get_out_filename(param_index)
156
+
157
+
158
+ # Display global warnings and errors arrays and exit if necessary
159
+ def abort_if_errors
160
+ unless $warnings.empty?
161
+ STDERR.puts
162
+ STDERR.puts "The following warnings were generated:"
163
+ STDERR.puts
164
+ $warnings.each do |w|
165
+ STDERR.puts "\tWarning: #{w}"
166
+ end
167
+ STDERR.print "\nAbort program? (y/N) "
168
+ answer = (gets).chomp.strip.downcase
169
+ $errors << "Aborted by user" if answer.size>0 && 'y' == answer[0]
170
+ end
171
+ unless $errors.empty?
172
+ STDERR.puts
173
+ STDERR.puts "Correct the following errors and try again:"
174
+ STDERR.puts
175
+ $errors.each do |e|
176
+ STDERR.puts "\t#{e}"
177
+ end
178
+ STDERR.puts
179
+ exit(-1)
180
+ end
181
+ end # def abort_if_errors
182
+
183
+
184
+ # Display the usage info
185
+ if ARGV.empty? ||
186
+ ARGV.include?('-h') ||
187
+ ARGV.include?('--help')
188
+ puts usage
189
+ exit
190
+ end
191
+
192
+ %w[ -v --verbose ].each do |param|
193
+ if ARGV.include? param
194
+ $options[:verbose] = true
195
+ ARGV[ ARGV.index(param) ] = nil
196
+ end
197
+ end
198
+
199
+ %w[ -d --debug ].each do |param|
200
+ if ARGV.include? param
201
+ $options[:debug] = true
202
+ $DEBUG = true
203
+ ARGV[ ARGV.index(param) ] = nil
204
+ end
205
+ end
206
+
207
+ %w[ -m --meta ].each do |param|
208
+ while ARGV.include?(param) do
209
+ $options[:meta_fields] += ',' unless $options[:meta_fields].empty?
210
+ $options[:meta_fields] += get_next_parameter(ARGV.index(param))
211
+ end
212
+ end
213
+
214
+ %w[ --dates ].each do |param|
215
+ if ARGV.include? param
216
+ $options[:show_dates] = true
217
+ $options[:meta_fields] += ',' unless $options[:meta_fields].empty?
218
+ $options[:meta_fields] += "assetCreated,assetCreator,assetModified,assetModifier,versionNumber"
219
+ ARGV[ ARGV.index(param) ] = nil
220
+ end
221
+ end
222
+
223
+ %w[ --text ].each do |param|
224
+ if ARGV.include? param
225
+ $options[:show_text] = true
226
+ ARGV[ ARGV.index(param) ] = nil
227
+ end
228
+ end
229
+
230
+ %w[ --cluster ].each do |param|
231
+ if ARGV.include? param
232
+ $options[:cluster_results] = true
233
+ next_param = get_next_parameter(param)
234
+ unless next_param.nil?
235
+ $options[:cluster_filename] = Pathname.new(next_param)
236
+ $warnings << "File already exists: #{$options[:cluster_filename].realpath}" if $options[:cluster_filename].exist?
237
+ end
238
+ end
239
+ end
240
+
241
+
242
+ ARGV.compact!
243
+
244
+ debug_me(){ :ARGV }
245
+
246
+
247
+ if ARGV.empty?
248
+ $errors << "No search query was specified."
249
+ end
250
+
251
+ $options[:query] = ARGV.shift
252
+
253
+ unless ARGV.empty?
254
+ $errors << "The search query is malformed - may not be enclosed in quotes."
255
+ end
256
+
257
+ abort_if_errors
258
+
259
+ max_mfield_size = 0
260
+
261
+ unless $options[:meta_fields].empty?
262
+ $options[:meta_fields] = $options[:meta_fields].split(',')
263
+ $options[:meta_fields].each do |mf|
264
+ max_mfield_size = mf.size if mf.size > max_mfield_size
265
+ end
266
+ max_mfield_size += 2
267
+ end
268
+
269
+
270
+ if cluster_results?
271
+ $options[:cluster_file] = File.new($options[:cluster_filename],'w')
272
+ end
273
+
274
+
275
+ ######################################################
276
+ # Local methods
277
+
278
+
279
+
280
+
281
+ ######################################################
282
+ # Main
283
+
284
+ at_exit do
285
+ begin
286
+ $elvis.logout
287
+ rescue
288
+ # eat it
289
+ end
290
+ puts
291
+ puts "Done."
292
+ puts
293
+ end
294
+
295
+ $elvis = WoodWing::Elvis.new
296
+ $elvis.login
297
+
298
+ if debug?
299
+ puts
300
+ pp $options
301
+ puts
302
+ pp $elvis
303
+ puts
304
+ end
305
+
306
+ options = {
307
+ q: $options[:query],
308
+ appendRequestSecret: 'true'
309
+ }
310
+
311
+ options[:metadataToReturn] = $options[:meta_fields].join(',') unless $options[:meta_fields].empty?
312
+
313
+
314
+ response = $elvis.search options
315
+
316
+ if debug?
317
+ puts "======= Full Response ======="
318
+ pp response
319
+ end
320
+
321
+ puts
322
+
323
+ unless response.include?(:totalHits)
324
+ puts "ERROR: response does not include :totalHits"
325
+ exit
326
+ end
327
+
328
+ puts
329
+ puts "Total Hits: #{response[:totalHits]}"
330
+ puts "First Result: #{response[:firstResult]}"
331
+ puts "Max. Results: #{response[:maxResultHits]}"
332
+ puts
333
+
334
+ if cluster_results?
335
+ $options[:cluster_file].puts <<ENDXML
336
+ <?xml version="1.0" encoding="UTF-8"?>
337
+ <searchresult>
338
+ <query>#{$options[:query]}</query>
339
+ ENDXML
340
+
341
+ end
342
+
343
+ if response[:totalHits] > 0
344
+ result_number = 0
345
+ response[:hits].each do |hit|
346
+
347
+ $options[:cluster_file].puts '<document>' if cluster_results?
348
+
349
+ metadata = hit[:metadata]
350
+ puts
351
+ puts "="*45
352
+ puts "== Result # #{result_number+=1} ID: #{hit[:id]}"
353
+ puts
354
+ puts "originalUrl: #{hit[:originalUrl]}"
355
+ puts "Asset Path: #{metadata[:assetPath]}"
356
+ puts "Status: #{metadata[:status]}"
357
+
358
+ unless $options[:meta_fields].empty?
359
+ puts
360
+ $options[:meta_fields].each do |mf|
361
+ mf_label = "#{mf}:" + ' '*(max_mfield_size-mf.size)
362
+ puts "#{mf_label} #{metadata[mf.to_sym]}"
363
+ end
364
+ end
365
+
366
+ if show_dates?
367
+ puts
368
+ puts "Created on: #{metadata[:assetCreated][:formatted]} by: #{metadata[:assetCreator]}"
369
+ puts "Modified on: #{metadata[:assetModified][:formatted]} by: #{metadata[:assetModifier]} Version Number # #{metadata[:versionNumber]}"
370
+ end
371
+
372
+ if show_text?
373
+ puts
374
+ puts "highlightedText: #{hit[:highlightedText]}"
375
+ end
376
+
377
+ puts
378
+
379
+ if cluster_results?
380
+ $options[:cluster_file].puts <<ENDXML
381
+ <title>#{metadata[:assetPath]}</title>
382
+ <snippet>#{hit[:highlightedText].gsub('<B>','').gsub('</B>','').gsub('<','').gsub('>','')}</snippet>
383
+ <url>http://localhost#{metadata[:assetPath]}</url>
384
+ </document>
385
+ ENDXML
386
+
387
+ end # if cluster_results?
388
+
389
+ end # response[:hits].each do |hit|
390
+ end # if response[:totalHits] > 0
391
+
392
+
393
+ if cluster_results?
394
+ $options[:cluster_file].puts "</searchresult>"
395
+ $options[:cluster_file].close
396
+ # TODO: invokl carrot2 CLI
397
+ # TODO: retrieve carrot2 generated XML file
398
+ # TODO: display document clusters
399
+ end
400
+
401
+ __END__
402
+
403
+ # To interface with Carrot2 document clustering workbench this kind of xml
404
+ # file needs to be generated with 1 document entry for each 'hit' of
405
+ # the query.
406
+
407
+ <?xml version="1.0" encoding="UTF-8"?>
408
+ <searchresult>
409
+ <query>seattle</query>
410
+ <document>
411
+ <title>City of Seattle</title>
412
+ <snippet>Official site featuring a guide to living in Seattle and information on doing business, city services, and visitor's resources.</snippet>
413
+ <url>http://www.seattle.gov/</url>
414
+ </document>
415
+ </searchresult>
416
+