fbo 0.0.3 → 0.1.0

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -5
  3. data/Gemfile +0 -2
  4. data/Rakefile +8 -1
  5. data/fbo.gemspec +14 -9
  6. data/lib/fbo.rb +7 -38
  7. data/lib/fbo/chunked_file.rb +74 -0
  8. data/lib/fbo/dump.treetop +324 -0
  9. data/lib/fbo/file.rb +17 -1
  10. data/lib/fbo/interpreter.rb +87 -0
  11. data/lib/fbo/node_extensions.rb +173 -0
  12. data/lib/fbo/parser.rb +43 -46
  13. data/lib/fbo/remote_file.rb +4 -4
  14. data/lib/fbo/version.rb +1 -1
  15. data/spec/fbo/chunked_file_spec.rb +22 -0
  16. data/spec/fbo/file_spec.rb +26 -9
  17. data/spec/fbo/interpreter_spec.rb +73 -0
  18. data/spec/fbo/parser_spec.rb +36 -38
  19. data/spec/fbo/remote_file_spec.rb +28 -24
  20. data/spec/fixtures/.keep +0 -0
  21. data/spec/fixtures/FBOFeed20130331 +52 -5529
  22. data/spec/fixtures/FBOFeed20131003 +35126 -0
  23. data/spec/spec_helper.rb +14 -16
  24. metadata +70 -108
  25. data/.rspec +0 -2
  26. data/Gemfile.lock +0 -27
  27. data/lib/fbo/notice.rb +0 -9
  28. data/lib/fbo/notices.rb +0 -6
  29. data/lib/fbo/notices/amendment.rb +0 -13
  30. data/lib/fbo/notices/archive.rb +0 -8
  31. data/lib/fbo/notices/award.rb +0 -14
  32. data/lib/fbo/notices/combined_solicitation.rb +0 -14
  33. data/lib/fbo/notices/fair_opportunity.rb +0 -15
  34. data/lib/fbo/notices/foreign_standard.rb +0 -13
  35. data/lib/fbo/notices/intent_to_bundle.rb +0 -13
  36. data/lib/fbo/notices/justification_approval.rb +0 -18
  37. data/lib/fbo/notices/modification.rb +0 -14
  38. data/lib/fbo/notices/presolicitation.rb +0 -14
  39. data/lib/fbo/notices/sale_of_surplus.rb +0 -13
  40. data/lib/fbo/notices/sources_sought.rb +0 -13
  41. data/lib/fbo/notices/special_notice.rb +0 -13
  42. data/lib/fbo/notices/unarchive.rb +0 -9
  43. data/lib/fbo/notices/unknown.rb +0 -7
  44. data/lib/fbo/parser/amendment_handler.rb +0 -58
  45. data/lib/fbo/parser/archive_handler.rb +0 -41
  46. data/lib/fbo/parser/award_handler.rb +0 -62
  47. data/lib/fbo/parser/combined_solicitation_handler.rb +0 -57
  48. data/lib/fbo/parser/fair_opportunity_handler.rb +0 -61
  49. data/lib/fbo/parser/foreign_standard_handler.rb +0 -57
  50. data/lib/fbo/parser/handler_selector.rb +0 -37
  51. data/lib/fbo/parser/intent_to_bundle_handler.rb +0 -56
  52. data/lib/fbo/parser/justification_approval_handler.rb +0 -60
  53. data/lib/fbo/parser/modification_handler.rb +0 -66
  54. data/lib/fbo/parser/notice_handler.rb +0 -27
  55. data/lib/fbo/parser/parser_helper.rb +0 -315
  56. data/lib/fbo/parser/presolicitation_handler.rb +0 -57
  57. data/lib/fbo/parser/sale_of_surplus_handler.rb +0 -57
  58. data/lib/fbo/parser/sources_sought_handler.rb +0 -57
  59. data/lib/fbo/parser/special_notice_handler.rb +0 -57
  60. data/lib/fbo/parser/unarchive_handler.rb +0 -42
  61. data/lib/fbo/parser/unknown_handler.rb +0 -20
  62. data/spec/fbo/parser/amendment_handler_spec.rb +0 -51
  63. data/spec/fbo/parser/archive_handler_spec.rb +0 -36
  64. data/spec/fbo/parser/award_handler_spec.rb +0 -56
  65. data/spec/fbo/parser/combined_solicitation_handler_spec.rb +0 -51
  66. data/spec/fbo/parser/fair_opportunity_handler_spec.rb +0 -56
  67. data/spec/fbo/parser/foreign_standard_handler_spec.rb +0 -51
  68. data/spec/fbo/parser/handler_selector_spec.rb +0 -40
  69. data/spec/fbo/parser/intent_to_bundle_handler_spec.rb +0 -52
  70. data/spec/fbo/parser/justification_approval_handler_spec.rb +0 -53
  71. data/spec/fbo/parser/modification_handler_spec.rb +0 -52
  72. data/spec/fbo/parser/presolicitation_handler_spec.rb +0 -51
  73. data/spec/fbo/parser/sale_of_surplus_handler_spec.rb +0 -53
  74. data/spec/fbo/parser/sources_sought_handler_spec.rb +0 -51
  75. data/spec/fbo/parser/special_notice_handler_spec.rb +0 -53
  76. data/spec/fbo/parser/unarchive_handler_spec.rb +0 -37
  77. data/spec/fbo/parser/unknown_handler_spec.rb +0 -24
  78. data/spec/fixtures/FBOFeed20130404 +0 -45653
  79. data/spec/fixtures/FBOFeed20130406 +0 -10152
  80. data/spec/fixtures/FBOFeed20130407 +0 -6610
  81. data/spec/fixtures/notices/amdcss +0 -26
  82. data/spec/fixtures/notices/archive +0 -10
  83. data/spec/fixtures/notices/award +0 -31
  84. data/spec/fixtures/notices/combine +0 -29
  85. data/spec/fixtures/notices/fairopp +0 -29
  86. data/spec/fixtures/notices/fstd +0 -24
  87. data/spec/fixtures/notices/itb +0 -19
  88. data/spec/fixtures/notices/ja +0 -30
  89. data/spec/fixtures/notices/mod +0 -28
  90. data/spec/fixtures/notices/notanotice +0 -7
  91. data/spec/fixtures/notices/presol +0 -25
  92. data/spec/fixtures/notices/snote +0 -26
  93. data/spec/fixtures/notices/srcsgt +0 -27
  94. data/spec/fixtures/notices/ssale +0 -24
  95. data/spec/fixtures/notices/unarchive +0 -10
@@ -1,56 +0,0 @@
1
- module FBO::Parser::IntentToBundleHandler
2
- TAGS = %w( ITB DATE YEAR CBAC PASSWORD ZIP CLASSCOD NAICS OFFADD AGENCY ) +
3
- %w( OFFICE LOCATION SUBJECT SOLNBR NTYPE ARCHDATE CONTACT DESC AWDNBR ) +
4
- %w( DONBR LINK URL EMAIL ADDRESS \/ITB )
5
-
6
- ANY_ITB_TAG = TAGS.join("|")
7
- INTENT_TO_BUNDLE_PATTERN = /^<ITB>/
8
-
9
-
10
- def is_intent_to_bundle?(text)
11
- text =~ INTENT_TO_BUNDLE_PATTERN
12
- end
13
-
14
- def parse(text)
15
- params = {
16
- date: date(text),
17
- year: year(text),
18
- zip: zip(text),
19
- class_code: classification_code(text),
20
- naics_code: naics_code(text),
21
- agency: agency(text),
22
- office: office(text),
23
- location: location(text),
24
- office_address: office_address(text),
25
- subject: subject(text),
26
- solicitation_number: solicitation_number(text),
27
- archive_date: archive_date(text),
28
- contact_info: contact(text),
29
- description: description(text),
30
- notice_type: notice_type(text),
31
- award_number: award_number(text),
32
- delivery_order_number: delivery_order_number(text),
33
- link_url: link_url(text),
34
- link_description: link_description(text),
35
- email_address: email_address(text),
36
- email_description: email_description(text),
37
- correction: correction?(text)
38
- }
39
- FBO::Notices::IntentToBundle.new(params)
40
- end
41
-
42
-
43
- protected
44
-
45
- # Returns a concatenated list of all tags for the notice
46
- #
47
- # @return [String]
48
- def any_notice_tag
49
- ANY_ITB_TAG
50
- end
51
-
52
-
53
- extend FBO::Parser::NoticeHandler
54
- extend FBO::Parser::ParserHelper
55
- extend self
56
- end
@@ -1,60 +0,0 @@
1
- module FBO::Parser::JustificationApprovalHandler
2
- TAGS = %w( JA DATE YEAR CBAC PASSWORD ZIP CLASSCOD NAICS OFFADD ) +
3
- %w( AGENCY OFFICE LOCATION SUBJECT SOLNBR NTYPE DESC CONTACT AWDNBR ) +
4
- %w( AWDDATE ARCHDATE LINK URL EMAIL ADDRESS STAUTH MODNBR ) +
5
- %w( FILELIST FILE MIMETYPE /FILE /FILELIST CORRECTION /JA )
6
-
7
- ANY_JUSTIFICATION_APPROVAL_TAG = TAGS.join("|")
8
- JA_PATTERN = /^<JA>/
9
-
10
-
11
- def is_justification_approval?(text)
12
- text =~ JA_PATTERN
13
- end
14
-
15
- def parse(text)
16
- params = {
17
- date: date(text),
18
- year: year(text),
19
- zip: zip(text),
20
- class_code: classification_code(text),
21
- naics_code: naics_code(text),
22
- agency: agency(text),
23
- office: office(text),
24
- location: location(text),
25
- office_address: office_address(text),
26
- subject: subject(text),
27
- solicitation_number: solicitation_number(text),
28
- notice_type: notice_type(text),
29
- description: description(text),
30
- contact_info: contact(text),
31
- statutory_authority: statutory_authority(text),
32
- award_number: award_number(text),
33
- modification_number: modification_number(text),
34
- award_date: award_date(text),
35
- archive_date: archive_date(text),
36
- link_url: link_url(text),
37
- link_description: link_description(text),
38
- email_address: email_address(text),
39
- email_description: email_description(text),
40
- file_list: file_list(text),
41
- correction: correction?(text)
42
- }
43
- FBO::Notices::JustificationApproval.new(params)
44
- end
45
-
46
-
47
- protected
48
-
49
- # Returns a concatenated list of all tags for the notice
50
- #
51
- # @return [String]
52
- def any_notice_tag
53
- ANY_JUSTIFICATION_APPROVAL_TAG
54
- end
55
-
56
-
57
- extend FBO::Parser::NoticeHandler
58
- extend FBO::Parser::ParserHelper
59
- extend self
60
- end
@@ -1,66 +0,0 @@
1
- module FBO::Parser::ModificationHandler
2
- TAGS = %w( MOD DATE YEAR CBAC PASSWORD ZIP CLASSCOD NAICS OFFADD AGENCY) +
3
- %w( OFFICE LOCATION SUBJECT SOLNBR NTYPE RESPDATE ARCHDATE CONTACT DESC ) +
4
- %w( LINK URL EMAIL ADDRESS SETASIDE POPADDRESS POPZIP POPCOUNTRY \/MOD )
5
-
6
- ANY_MOD_TAG = TAGS.join("|")
7
- MODIFICATION_PATTERN = /^<MOD>/
8
-
9
-
10
- def is_modification?(text)
11
- text =~ MODIFICATION_PATTERN
12
- end
13
-
14
- def parse(text)
15
- params = {
16
- date: date(text),
17
- year: year(text),
18
- zip: zip(text),
19
- class_code: classification_code(text),
20
- naics_code: naics_code(text),
21
- agency: agency(text),
22
- office: office(text),
23
- location: location(text),
24
- office_address: office_address(text),
25
- subject: subject(text),
26
- solicitation_number: solicitation_number(text),
27
- notice_type: notice_type(text),
28
- response_date: response_date(text),
29
- archive_date: archive_date(text),
30
- contact_info: contact(text),
31
- description: description(text),
32
- link_url: link_url(text),
33
- link_description: link_description(text),
34
- email_address: email_address(text),
35
- email_description: email_description(text),
36
- setaside: set_aside(text),
37
- pop_address: pop_address(text),
38
- pop_zip: pop_zip_code(text),
39
- pop_country: pop_country(text)
40
- }
41
- FBO::Notices::Modification.new(params)
42
- end
43
-
44
-
45
- protected
46
-
47
- # Returns a concatenated list of all tags for the notice
48
- #
49
- # @return [String]
50
- def any_notice_tag
51
- ANY_MOD_TAG
52
- end
53
-
54
- # Get the notice type that this modification is affecting.
55
- #
56
- # @param text [String] the full text of the notice
57
- # @return [Date] the notice type
58
- def notice_type(text)
59
- simple_tag_contents(text, "NTYPE")
60
- end
61
-
62
-
63
- extend FBO::Parser::NoticeHandler
64
- extend FBO::Parser::ParserHelper
65
- extend self
66
- end
@@ -1,27 +0,0 @@
1
- module FBO::Parser::NoticeHandler
2
-
3
- protected
4
-
5
- # Returns a concatenated list of all tags for the notice
6
- #
7
- # @return [String]
8
- def any_notice_tag
9
- ""
10
- end
11
-
12
- # Given a tag string, return the data associated with it as a String object
13
- # or nil if not present.
14
- #
15
- # @param text [String] the full text of the notice
16
- # @param tag [String] the tag that should be searched for
17
- # @return [String] contents or nil if not present
18
- def simple_tag_contents(text, tag)
19
- regexp = (tag.is_a?(Regexp) ? tag : /<#{ tag }>/)
20
- match = text.match(regexp)
21
- return nil unless match
22
- match2 = match.post_match.match(/<(?:#{ any_notice_tag })>/)
23
- prematch = match2.pre_match if match2
24
- prematch ? prematch.strip : nil
25
- end
26
-
27
- end
@@ -1,315 +0,0 @@
1
- require "date"
2
-
3
- module FBO::Parser::ParserHelper
4
- extend FBO::Parser::NoticeHandler
5
-
6
- protected
7
-
8
- # Get the date of the notice.
9
- #
10
- # @param text [String] the full text of the notice
11
- # @return [Date] the date that the notice was posted
12
- def date(text)
13
- date_string = simple_tag_contents(text, "DATE")
14
- Date.parse("#{ year(text) }#{ date_string }")
15
- end
16
-
17
- # Get the year from the notice or assume the current year.
18
- #
19
- # @param [text] the whole notice text
20
- # @return [Fixnum] the year of the notice
21
- def year(text)
22
- year_string = simple_tag_contents(text, "YEAR")
23
- "20#{ year_string }".to_i
24
- end
25
-
26
- # Get the zip code of the contracting office.
27
- #
28
- # @param text [String] the full text of the notice
29
- # @return [String] the zip code of the contracting office
30
- def zip(text)
31
- simple_tag_contents(text, "ZIP")
32
- end
33
-
34
- # Get the two-digit or single alphabetic code for classifying the notice.
35
- #
36
- # @param text [String] the full text of the notice
37
- # @return [String] the classification code as a string
38
- def classification_code(text)
39
- simple_tag_contents(text, "CLASSCOD")
40
- end
41
-
42
- # Get the NAICS code that should be referenced with this notice.
43
- #
44
- # @param text [String] the full text of the notice
45
- # @return [String] the relevant NAICS code
46
- def naics_code(text)
47
- simple_tag_contents(text, "NAICS")
48
- end
49
-
50
- # Get the agency name for this notice.
51
- #
52
- # @param text [String] the full text of the notice
53
- # @return [String] the name of the agency
54
- def agency(text)
55
- simple_tag_contents(text, "AGENCY")
56
- end
57
-
58
- # Get the agency office name for this notice.
59
- #
60
- # @param text [String] the full text of the notice
61
- # @return [String] the name of the agency office
62
- def office(text)
63
- simple_tag_contents(text, "OFFICE")
64
- end
65
-
66
- # Get the location of the office issuing the notice (often used for department).
67
- #
68
- # @param text [String] the full text of the notice
69
- # @return [String] the location text
70
- def location(text)
71
- simple_tag_contents(text, "LOCATION")
72
- end
73
-
74
- # Get the office address from which the notice is issued.
75
- #
76
- # @param text [String] the full text of the notice
77
- # @return [String] the office address
78
- def office_address(text)
79
- simple_tag_contents(text, "OFFADD")
80
- end
81
-
82
- # Get the subject of the notice.
83
- #
84
- # @param text [String] the full text of the notice
85
- # @return [String] the subject address
86
- def subject(text)
87
- simple_tag_contents(text, "SUBJECT")
88
- end
89
-
90
- # Get the solicitation number for the notice.
91
- #
92
- # @param text [String] the full text of the notice
93
- # @return [String] the solicitation number
94
- def solicitation_number(text)
95
- simple_tag_contents(text, "SOLNBR")
96
- end
97
-
98
- # Get the type of the related notice in the case of dependent notices.
99
- #
100
- # @param text [String] the full text of the notice
101
- # @return [String] the notice type
102
- def notice_type(text)
103
- simple_tag_contents(text, "NTYPE")
104
- end
105
-
106
- # Get the deadline for responding to the notice.
107
- #
108
- # @param text [String] the full text of the notice
109
- # @return [Date] the response date
110
- def response_date(text)
111
- date_string = simple_tag_contents(text, "RESPDATE")
112
- date_string ? Date.strptime(date_string, "%m%d%y") : nil
113
- end
114
-
115
- # Get the date when the notice will be archived.
116
- #
117
- # @param text [String] the full text of the notice
118
- # @return [Date] the archive date
119
- def archive_date(text)
120
- date_string = simple_tag_contents(text, "ARCHDATE")
121
- date_string ? Date.strptime(date_string, "%m%d%Y") : nil
122
- end
123
-
124
- # Get the contact information for responding to the notice.
125
- #
126
- # @param text [String] the full text of the notice
127
- # @return [String] the contact info
128
- def contact(text)
129
- simple_tag_contents(text, "CONTACT")
130
- end
131
-
132
- # Get the full description of the notice.
133
- # This implementation accounts for the fact that there may be more than one
134
- # DESC tag in the notice and that the one we want will be the first one.
135
- #
136
- # @param text [String] the full text of the notice
137
- # @return [String] the description
138
- def description(text)
139
- match = text.match(/<DESC>/)
140
- match2 = match.post_match.match(/<(?:#{ any_notice_tag })>/)
141
- prematch = match2.pre_match
142
- prematch ? prematch.strip : nil
143
- end
144
-
145
- # Get the link URL.
146
- #
147
- # @param text [String] the full text of the notice
148
- # @return [String] the URL
149
- def link_url(text)
150
- match = text.match(/<LINK>/)
151
- simple_tag_contents(match.post_match, "URL") if match
152
- end
153
-
154
- # Get the link description / text.
155
- #
156
- # @param text [String] the full text of the notice
157
- # @return [String] the link description
158
- def link_description(text)
159
- match = text.match(/<LINK>/)
160
- description(match.post_match) if match
161
- end
162
-
163
- # Get the contact email address.
164
- #
165
- # @param text [String] the full text of the notice
166
- # @return [String] the email address
167
- def email_address(text)
168
- match = text.match(/<EMAIL>/)
169
- simple_tag_contents(match.post_match, "(EMAIL|ADDRESS)") if match
170
- end
171
-
172
- # Get the contact email description (link text).
173
- #
174
- # @param text [String] the full text of the notice
175
- # @return [String] the email description
176
- def email_description(text)
177
- match = text.match(/<EMAIL>/)
178
- description(match.post_match) if match
179
- end
180
-
181
- # Get the set-aside identifier for the notice.
182
- #
183
- # @param text [String] the full text of the notice
184
- # @return [String] the set-aside
185
- def set_aside(text)
186
- simple_tag_contents(text, "SETASIDE")
187
- end
188
-
189
- # Get the address of the "place of performance".
190
- #
191
- # @param text [String] the full text of the notice
192
- # @return [String] the address
193
- def pop_address(text)
194
- simple_tag_contents(text, "POPADDRESS")
195
- end
196
-
197
- # Get the zip code of the "place of performance".
198
- #
199
- # @param text [String] the full text of the notice
200
- # @return [String] the zip code
201
- def pop_zip_code(text)
202
- simple_tag_contents(text, "POPZIP")
203
- end
204
-
205
- # Get the country of the "place of performance".
206
- #
207
- # @param text [String] the full text of the notice
208
- # @return [String] the country
209
- def pop_country(text)
210
- simple_tag_contents(text, "POPCOUNTRY")
211
- end
212
-
213
- # Get the award number with which the notice is associated.
214
- #
215
- # @param text [String] the full text of the notice
216
- # @return [String] the award number
217
- def award_number(text)
218
- simple_tag_contents(text, "AWDNBR")
219
- end
220
-
221
- # Get the amount of the award with which the notice is associated.
222
- #
223
- # @param text [String] the full text of the notice
224
- # @return [Float] the award amount (in dollars)
225
- def award_amount(text)
226
- amount_string = simple_tag_contents(text, "AWDAMT")
227
- amount_string.gsub(/[^\d\.]/, "").to_f
228
- end
229
-
230
- # Get the line number of the contract with which the award is associated.
231
- #
232
- # @param text [String] the full text of the notice
233
- # @return [String] the line number (which might not be a Fixnum)
234
- def line_number(text)
235
- simple_tag_contents(text, "LINENBR")
236
- end
237
-
238
- # Get the date of the award.
239
- #
240
- # @param text [String] the full text of the notice
241
- # @return [Date] the date that the award was given
242
- def award_date(text)
243
- date_string = simple_tag_contents(text, "AWDDATE")
244
- Date.strptime(date_string, "%m%d%y")
245
- end
246
-
247
- # Get the name of the awardee.
248
- #
249
- # @param text [String] the full text of the notice
250
- # @return [String] the awardee's name
251
- def awardee(text)
252
- simple_tag_contents(text, "AWARDEE")
253
- end
254
-
255
- # Get the DUNS number for the awardee.
256
- #
257
- # @param text [String] the full text of the notice
258
- # @return [String] the awardee's DUNS number
259
- def awardee_duns(text)
260
- simple_tag_contents(text, "AWARDEEDUNS")
261
- end
262
-
263
- # If the notice is a correction of a previous notice, return true; otherwise, false.
264
- #
265
- # @param text [String] the full text of the notice
266
- # @return [boolean]
267
- def correction?(text)
268
- correction_string = simple_tag_contents(text, "CORRECTION")
269
- if correction_string && correction_string =~ /^y/i
270
- return true
271
- end
272
- false
273
- end
274
-
275
- # Get the file list associated with the notice.
276
- #
277
- # @param text [String] the full text of the notice
278
- # @return [Array] the file list
279
- def file_list(text)
280
- []
281
- end
282
-
283
- # Get the statutory authority.
284
- #
285
- # @param text [String] the full text of the notice
286
- # @return [String] the name of the statutory authority
287
- def statutory_authority(text)
288
- simple_tag_contents(text, "STAUTH")
289
- end
290
-
291
- # Get the modification number.
292
- #
293
- # @param text [String] the full text of the notice
294
- # @return [String] the modification number
295
- def modification_number(text)
296
- simple_tag_contents(text, "MODNBR")
297
- end
298
-
299
- # Get the delivery order number.
300
- #
301
- # @param text [String] the full text of the notice
302
- # @return [String] the delivery order number
303
- def delivery_order_number(text)
304
- simple_tag_contents(text, "DONBR")
305
- end
306
-
307
- # Get the justification authority (reason).
308
- #
309
- # @param text [String] the full text of the notice
310
- # @return [String] the judstification authority
311
- def justification_authority(text)
312
- simple_tag_contents(text, "FOJA")
313
- end
314
-
315
- end