xbrlware-ce 1.0.4 → 1.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 (56) hide show
  1. data/Rakefile.rb +4 -4
  2. data/Readme.txt +6 -1
  3. data/ReleaseNotes.txt +22 -5
  4. data/doc/classes/Edgar/HTMLFeedDownloader.html +8 -8
  5. data/doc/classes/Edgar/RSSFeedDownloader.html +15 -15
  6. data/doc/classes/Xbrlware.html +22 -0
  7. data/doc/classes/Xbrlware/Context.html +104 -74
  8. data/doc/classes/Xbrlware/Context/Period.html +305 -0
  9. data/doc/classes/Xbrlware/Entity.html +75 -51
  10. data/doc/classes/Xbrlware/Identifier.html +17 -17
  11. data/doc/classes/Xbrlware/Instance.html +165 -137
  12. data/doc/classes/Xbrlware/Item.html +19 -19
  13. data/doc/classes/Xbrlware/Linkbase/CalculationLinkbase/Calculation.html +1 -1
  14. data/doc/classes/Xbrlware/Linkbase/DefinitionLinkbase/Definition.html +2 -2
  15. data/doc/classes/Xbrlware/Linkbase/Linkbase/Link.html +9 -3
  16. data/doc/classes/Xbrlware/Linkbase/Linkbase/Link/Arc.html +4 -4
  17. data/doc/classes/Xbrlware/Linkbase/PresentationLinkbase/Presentation.html +1 -1
  18. data/doc/classes/Xbrlware/Report.html +352 -0
  19. data/doc/classes/Xbrlware/Taxonomy.html +48 -48
  20. data/doc/classes/Xbrlware/TaxonomyDefintion.html +15 -15
  21. data/doc/classes/Xbrlware/Unit.html +6 -6
  22. data/doc/classes/Xbrlware/Unit/Divide.html +6 -6
  23. data/doc/created.rid +1 -1
  24. data/doc/files/Readme_txt.html +9 -1
  25. data/doc/files/lib/xbrlware/context_rb.html +1 -1
  26. data/doc/files/lib/xbrlware/date_util_rb.html +1 -1
  27. data/doc/files/lib/xbrlware/instance_rb.html +1 -1
  28. data/doc/files/lib/xbrlware/linkbase/calculation_linkbase_rb.html +1 -1
  29. data/doc/files/lib/xbrlware/linkbase/definition_linkbase_rb.html +1 -1
  30. data/doc/files/lib/xbrlware/linkbase/linkbase_rb.html +1 -1
  31. data/doc/files/lib/xbrlware/linkbase/presentation_linkbase_rb.html +1 -1
  32. data/doc/files/lib/xbrlware/meta_util_rb.html +1 -1
  33. data/doc/files/lib/xbrlware/report_rb.html +101 -0
  34. data/doc/files/lib/xbrlware/taxonomy_rb.html +1 -1
  35. data/doc/files/lib/xbrlware/version_rb.html +129 -0
  36. data/doc/fr_class_index.html +2 -0
  37. data/doc/fr_file_index.html +2 -0
  38. data/doc/fr_method_index.html +75 -62
  39. data/example/case_study/buy_strategy.rb +1 -1
  40. data/example/case_study/c_sell_strategy.rb +1 -1
  41. data/lib/xbrlware/context.rb +77 -34
  42. data/lib/xbrlware/date_util.rb +16 -6
  43. data/lib/xbrlware/instance.rb +35 -28
  44. data/lib/xbrlware/linkbase/calculation_linkbase.rb +1 -1
  45. data/lib/xbrlware/linkbase/definition_linkbase.rb +2 -2
  46. data/lib/xbrlware/linkbase/linkbase.rb +3 -2
  47. data/lib/xbrlware/linkbase/presentation_linkbase.rb +1 -1
  48. data/lib/xbrlware/meta_util.rb +5 -0
  49. data/lib/xbrlware/report.rb +277 -0
  50. data/lib/xbrlware/taxonomy.rb +13 -10
  51. data/lib/xbrlware/version.rb +22 -0
  52. data/test/lib/xbrlware/47_context_test.rb +13 -4
  53. data/test/lib/xbrlware/date_util_test.rb +10 -2
  54. data/test/lib/xbrlware/instance_test.rb +19 -0
  55. data/test/lib/xbrlware/meta_util_test.rb +21 -1
  56. metadata +10 -4
@@ -21,7 +21,7 @@ end
21
21
 
22
22
  curr_asset, prev_asset=0, 0
23
23
 
24
- if Date.parse(assets[0].context.period) > Date.parse(assets[1].context.period)
24
+ if assets[0].context.period.value > assets[1].context.period.value
25
25
  curr_asset=assets[0].value.to_f
26
26
  prev_asset=assets[1].value.to_f
27
27
  else
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  curr_netincome, prev_netincome=0, 0
16
16
 
17
- if Date.parse(net_incomes[0].context.period["end_date"]) > Date.parse(net_incomes[1].context.period["end_date"])
17
+ if net_incomes[0].context.period.value["end_date"] > net_incomes[1].context.period.value["end_date"]
18
18
  curr_netincome=net_incomes[0].value.to_f
19
19
  prev_netincome=net_incomes[1].value.to_f
20
20
  else
@@ -21,29 +21,66 @@ module Xbrlware
21
21
  # This class represents each context in the XBRL instance file.
22
22
  # Look at {delaing with instance page on xbrlware wiki}[http://code.google.com/p/xbrlware/wiki/InstanceTaxonomy] for more details.
23
23
  class Context
24
- attr_reader :id,:entity,:period, :scenario
24
+ attr_reader :id, :entity, :period, :scenario
25
25
  PERIOD_FOREVER = -1
26
- def initialize(id,entity,period, scenario=nil)
26
+
27
+ class Period
28
+ attr_reader :value
29
+
30
+ def initialize(value)
31
+ @value = value
32
+ end
33
+
34
+ def to_s
35
+ @value.to_s
36
+ end
37
+
38
+ def eql?(o)
39
+ o.is_a?(Period) && @value == o.value
40
+ end
41
+
42
+ def hash
43
+ @value.hash
44
+ end
45
+
46
+ def is_instant?
47
+ @value.is_a?(Date)
48
+ end
49
+
50
+ def is_duration?
51
+ @value.is_a?(Hash)
52
+ end
53
+
54
+ def is_forever?
55
+ @value.is_a?(Fixnum)
56
+ end
57
+ end
58
+
59
+ def initialize(id, entity, period, scenario=nil)
27
60
  @id = id
28
61
  @entity = entity
29
- @period = period
62
+ @period = Period.new(period)
30
63
  @scenario=scenario
31
64
  end
32
-
65
+
66
+ def has_scenario?
67
+ (not @scenario.nil?)
68
+ end
69
+
33
70
  def to_s
34
- "Id [" + id + "], Entity { " + @entity.to_s + " }, period ["+period.to_s+"]"+ (", scenario ["+scenario+"]" unless scenario.nil?).to_s
71
+ "Id [" + id + "], Entity { " + @entity.to_s + " }, period ["+period.to_s+"]"+ (", scenario ["+scenario+"]" unless scenario.nil?).to_s
35
72
  end
36
-
73
+
37
74
  def eql?(o)
38
75
  o.is_a?(Context) && @id == o.id
39
76
  end
40
-
77
+
41
78
  def hash
42
79
  @id.hash
43
80
  end
44
-
81
+
45
82
  def has_explicit_dimensions?(dimensions=[])
46
- return @entity.has_explicit_dimensions?(dimensions) unless @entity.nil?
83
+ return @entity.has_explicit_dimensions?(dimensions) unless @entity.nil?
47
84
  false
48
85
  end
49
86
 
@@ -54,10 +91,10 @@ module Xbrlware
54
91
  end
55
92
 
56
93
  alias_method :dimensions, :explicit_dimensions
57
-
94
+
58
95
  def explicit_domains(dimensions=[])
59
96
  return @entity.explicit_domains(dimensions)
60
- end
97
+ end
61
98
 
62
99
  alias_method :domains, :explicit_domains
63
100
 
@@ -66,37 +103,42 @@ module Xbrlware
66
103
  end
67
104
 
68
105
  alias_method :dimensions_domains, :explicit_dimensions_domains
69
-
106
+
70
107
  end
71
-
108
+
72
109
  class Entity
73
- attr_reader :identifier,:segment
74
- def initialize(identifier,segment=nil)
110
+ attr_reader :identifier, :segment
111
+
112
+ def initialize(identifier, segment=nil)
75
113
  @identifier = identifier
76
114
  @segment = segment
77
115
  end
78
-
116
+
117
+ def has_segment?
118
+ (not @segment.nil?)
119
+ end
120
+
79
121
  def to_s
80
122
  "Identifier { " + @identifier.to_s + " } " + (", segment [" + segment.to_s + "]" unless segment.nil?).to_s
81
123
  end
82
-
124
+
83
125
  def has_explicit_dimensions?(dimensions=[])
84
126
  dimensions_set=Set.new
85
127
  dimensions_set.merge(dimensions)
86
128
  unless @segment.nil? || @segment["explicitMember"].nil?
87
-
88
- return true if dimensions.size==0
89
-
129
+
130
+ return true if dimensions.size==0
131
+
90
132
  dim = Set.new
91
133
  @segment["explicitMember"].each do |member|
92
134
  dim << member["dimension"]
93
135
  end
94
- return dim.superset?(dimensions_set)
136
+ return dim.superset?(dimensions_set)
95
137
  end
96
-
138
+
97
139
  return false
98
140
  end
99
-
141
+
100
142
  def explicit_dimensions
101
143
  dim = Set.new
102
144
  unless @segment.nil? || @segment["explicitMember"].nil?
@@ -106,7 +148,7 @@ module Xbrlware
106
148
  end
107
149
  return dim.to_a
108
150
  end
109
-
151
+
110
152
  def explicit_domains(dimensions=[])
111
153
  dom = Set.new
112
154
  if has_explicit_dimensions?(dimensions)
@@ -116,33 +158,34 @@ module Xbrlware
116
158
  next unless dim==member["dimension"]
117
159
  dom << member["content"]
118
160
  end
119
- end
161
+ end
120
162
  end
121
163
  return dom.to_a
122
164
  end
123
-
165
+
124
166
  def explicit_dimensions_domains
125
167
  dim_dom={}
126
168
  if has_explicit_dimensions?
127
169
  @segment["explicitMember"].each do |member|
128
170
  dim_dom[member["dimension"]]=[] if dim_dom[member["dimension"]].nil?
129
171
  dim_dom[member["dimension"]] << member["content"]
130
- end
172
+ end
131
173
  end
132
174
  return dim_dom
133
175
  end
134
-
176
+
135
177
  end
136
-
137
- class Identifier
138
- attr_reader :value,:scheme
139
- def initialize(scheme,value)
178
+
179
+ class Identifier
180
+ attr_reader :value, :scheme
181
+
182
+ def initialize(scheme, value)
140
183
  @scheme = scheme
141
184
  @value = value
142
185
  end
143
-
186
+
144
187
  def to_s
145
- "schema [" + @scheme.to_s + "], value [" + @value.to_s + "]"
188
+ "schema [" + @scheme.to_s + "], value [" + @value.to_s + "]"
146
189
  end
147
190
  end
148
191
  end
@@ -21,15 +21,25 @@ module Xbrlware
21
21
  module DateUtil # :nodoc:
22
22
  def self.stringify_date (date)
23
23
  return "" if date.nil?
24
- _date=Date.parse(date) if date.is_a?(String)
25
- _date=date if date.is_a?(Date)
26
- m=Date::ABBR_MONTHNAMES[_date.month]
27
- m + " " + _date.day.to_s + ", " + _date.year.to_s
24
+ begin
25
+ _date=Date.parse(date) if date.is_a?(String)
26
+ _date=date if date.is_a?(Date)
27
+ m=Date::ABBR_MONTHNAMES[_date.month]
28
+ m + " " + _date.day.to_s + ", " + _date.year.to_s
29
+ rescue Exception => e
30
+ ""
31
+ end
28
32
  end
29
33
 
30
34
  def self.months_between(date1=Date.today, date2=Date.today)
31
- (date1 > date2) ? (recent_date, past_date = date1, date2) : (recent_date, past_date = date2, date1)
32
- (recent_date.year - past_date.year) * 12 + (recent_date.month - past_date.month)
35
+ begin
36
+ date1=Date.parse(date1) if date1.is_a?(String)
37
+ date2=Date.parse(date2) if date2.is_a?(String)
38
+ (date1 > date2) ? (recent_date, past_date = date1, date2) : (recent_date, past_date = date2, date1)
39
+ (recent_date.year - past_date.year) * 12 + (recent_date.month - past_date.month) + 1
40
+ rescue Exception => e
41
+ 0
42
+ end
33
43
  end
34
44
  end
35
45
  end
@@ -58,6 +58,7 @@ module Xbrlware
58
58
  end
59
59
 
60
60
  @taxonomy=Xbrlware::Taxonomy.new(taxonomy_filepath, self)
61
+ @entity_details=Hash.new("UNKNOWN")
61
62
  end
62
63
 
63
64
  # Returns raw content of instance file in the form of Hash
@@ -190,9 +191,9 @@ module Xbrlware
190
191
  # Returns -1 if period is forever
191
192
  def period(period_content)
192
193
  if period_content["startDate"] && period_content["endDate"]
193
- return {"start_date" => period_content["startDate"][0]["content"], "end_date" => period_content["endDate"][0]["content"]}
194
+ return {"start_date" => Date.parse(period_content["startDate"][0]["content"]), "end_date" => Date.parse(period_content["endDate"][0]["content"])}
194
195
  elsif period_content["instant"]
195
- return period_content["instant"][0]["content"]
196
+ return Date.parse(period_content["instant"][0]["content"])
196
197
  elsif period_content["forever"]
197
198
  return Context::PERIOD_FOREVER
198
199
  end
@@ -279,7 +280,7 @@ module Xbrlware
279
280
  all_items.each do |name, item_content|
280
281
  _name=name.upcase
281
282
  next if _name=="CONTEXT" || _name=="UNIT"
282
- items_hash[name.upcase] = item(name)
283
+ items_hash[name.upcase] = item(name)
283
284
  end
284
285
  items_hash
285
286
  end
@@ -348,34 +349,40 @@ module Xbrlware
348
349
  @item_footnote_map
349
350
  end
350
351
 
352
+ def entity_details=(value)
353
+ @entity_details.merge!(value) if value.is_a?(Hash)
354
+ end
351
355
 
352
356
  def entity_details
353
- @entity_details={}
354
357
  if @entity_details.size==0
355
- e_name=item("EntityRegistrantName")[0]
356
- e_ci_key=item("EntityCentralIndexKey")[0]
357
- e_doc_type=item("DocumentType")[0]
358
- e_doc_end_type=item("DocumentPeriodEndDate")[0]
359
-
360
- fedate=item("CurrentFiscalYearEndDate")
361
- e_fiscal_end_date=fedate[0] unless fedate.nil?
362
-
363
- shares_outstanding = item("EntityCommonStockSharesOutstanding")
364
- e_common_shares_outstanding=shares_outstanding[0] unless shares_outstanding.nil?
365
-
366
- @entity_details["name"]=e_name.value unless e_name.nil?
367
- @entity_details["ci_key"]=e_ci_key.value unless e_ci_key.nil?
368
- @entity_details["doc_type"]=e_doc_type.value unless e_doc_type.nil?
369
- @entity_details["doc_end_date"]=e_doc_end_type.value unless e_doc_end_type.nil?
370
- @entity_details["fiscal_end_date"]=e_fiscal_end_date.value unless e_fiscal_end_date.nil?
371
- @entity_details["common_shares_outstanding"]=e_common_shares_outstanding.value unless e_common_shares_outstanding.nil?
372
-
373
- file_name=File.basename(@file_name)
374
- symbol=file_name.split("-")[0]
375
- symbol.upcase!
376
-
377
- @entity_details["symbol"]=symbol unless symbol.nil?
378
-
358
+ begin
359
+ # Specific to US filing
360
+ e_name=item("EntityRegistrantName")[0]
361
+ e_ci_key=item("EntityCentralIndexKey")[0]
362
+ e_doc_type=item("DocumentType")[0]
363
+ e_doc_end_type=item("DocumentPeriodEndDate")[0]
364
+
365
+ fedate=item("CurrentFiscalYearEndDate")
366
+ e_fiscal_end_date=fedate[0] unless fedate.nil?
367
+
368
+ shares_outstanding = item("EntityCommonStockSharesOutstanding")
369
+ e_common_shares_outstanding=shares_outstanding[0] unless shares_outstanding.nil?
370
+
371
+ @entity_details["name"]=e_name.value unless e_name.nil?
372
+ @entity_details["ci_key"]=e_ci_key.value unless e_ci_key.nil?
373
+ @entity_details["doc_type"]=e_doc_type.value unless e_doc_type.nil?
374
+ @entity_details["doc_end_date"]=e_doc_end_type.value unless e_doc_end_type.nil?
375
+ @entity_details["fiscal_end_date"]=e_fiscal_end_date.value unless e_fiscal_end_date.nil?
376
+ @entity_details["common_shares_outstanding"]=e_common_shares_outstanding.value unless e_common_shares_outstanding.nil?
377
+
378
+ file_name=File.basename(@file_name)
379
+ symbol=file_name.split("-")[0]
380
+ symbol.upcase!
381
+
382
+ @entity_details["symbol"]=symbol unless symbol.nil?
383
+ rescue Exception => e
384
+ @entity_details
385
+ end
379
386
  end
380
387
  @entity_details
381
388
  end
@@ -116,7 +116,7 @@ module Xbrlware
116
116
  attr_reader :contexts, :entity_details
117
117
 
118
118
  def initialize(entity_details, title, role, href=nil, arcs=nil, contexts=nil)
119
- super(title, role, href, arcs)
119
+ super("Calculation", title, role, href, arcs)
120
120
  @contexts=contexts
121
121
  @entity_details=entity_details
122
122
  end
@@ -151,7 +151,7 @@ module Xbrlware
151
151
  attr_reader :primary_items
152
152
 
153
153
  def initialize(title, role, href=nil, primary_items=nil)
154
- super(title, role, href, primary_items)
154
+ super("Definition", title, role, href, primary_items)
155
155
  @primary_items=primary_items
156
156
  end
157
157
 
@@ -164,7 +164,7 @@ module Xbrlware
164
164
  dimension.domains.each do |domain|
165
165
  domains << domain.href.sub("_", ":")
166
166
  end
167
- dim_dom_map[dimension.href.sub("_", ":")]=domains
167
+ dim_dom_map[dimension.href.sub("_", ":")]=domains if domains.size > 0
168
168
  end
169
169
  end
170
170
  end unless @primary_items.nil?
@@ -95,9 +95,10 @@ module Xbrlware
95
95
 
96
96
  class Link
97
97
 
98
- attr_reader :title, :role, :href, :arcs
98
+ attr_reader :link_type, :title, :role, :href, :arcs
99
99
 
100
- def initialize(title, role, href, arcs=nil)
100
+ def initialize(link_type, title, role, href, arcs=nil)
101
+ @link_type=link_type
101
102
  @role = role
102
103
  @href = href
103
104
 
@@ -133,7 +133,7 @@ module Xbrlware
133
133
  attr_reader :contexts, :definition, :instance, :timelines, :dimensions, :entity_details
134
134
 
135
135
  def initialize(entity_details, title, role, href=nil, contexts=nil, arcs=nil, definition=nil, instance=nil, dimensions=[])
136
- super(title, role, href, arcs)
136
+ super("Presentation", title, role, href, arcs)
137
137
  @entity_details=entity_details
138
138
  @contexts=contexts
139
139
  @definition=definition
@@ -41,5 +41,10 @@ module Xbrlware
41
41
  alias :#{alias_name} :#{actual_name}
42
42
  }
43
43
  end
44
+
45
+ def self.eval_on_instance(o, method_block)
46
+ p "#{o.class}"
47
+ o.instance_eval method_block
48
+ end
44
49
  end
45
50
  end
@@ -0,0 +1,277 @@
1
+ module Xbrlware
2
+
3
+ #This class defines methods to generate HTML reports from XBRL documents.
4
+ class Report
5
+
6
+ PREF={}
7
+
8
+ def initialize(entity_details={}, pref={})
9
+ PREF.merge!(pref)
10
+ PREF["ITEM_FORMAT"]=lambda{|val| (BigDecimal(val)/1000000).round(4).to_s("F")} if PREF["ITEM_FORMAT"].nil?
11
+ PREF["ITEM_FORMAT_DESC"]=" in millions " if PREF["ITEM_FORMAT_DESC"].nil?
12
+ PREF["ITEM_FORMAT_EXCLUDE"] = ["EntityRegistrantName", "EntityCentralIndexKey", "DocumentType", "DocumentPeriodEndDate", "CurrentFiscalYearEndDate", "EntityCommonStockSharesOutstanding"] if PREF["ITEM_EXCLUDE"].nil?
13
+ @entity_details=entity_details
14
+ end
15
+
16
+ @@html_template = %{
17
+ <html>
18
+ <head>
19
+ <% if defined? reports_map && (not reports_map.nil?) %>
20
+ <title>
21
+ <%=reports_map["entity_details"]["symbol"].to_s + " :: " + reports_map["entity_details"]["doc_type"].to_s + " :: " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"]) + " :: Presentation & Calculation Reports"%>
22
+ </title>
23
+ <meta name="title" content="<%=reports_map["entity_details"]["symbol"].to_s + " :: " + reports_map["entity_details"]["doc_type"].to_s + " :: " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"]) + " :: Presentation & Calculation Reports"%>" />
24
+ <meta name="description" content="<%=reports_map["entity_details"]["name"].to_s + " ( " + reports_map["entity_details"]["symbol"].to_s + " ) :: " + reports_map["entity_details"]["doc_type"].to_s + " :: " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"]) + " :: Presentation & Calculation Reports" %>" />
25
+ <link rel="image_src" href="/static/<%=reports_map["entity_details"]["ci_key"].to_s + ".png"%>" / >
26
+ <% end %>
27
+ <meta name="Author" content="xbrlware (bitstat technologies)"/>
28
+ <style>
29
+ table, td {
30
+ border-color: #000000;
31
+ border-style: solid;
32
+ }
33
+
34
+ table {
35
+ border-width: 0 0 1px 1px;
36
+ border-spacing: 0;
37
+ border-collapse: collapse;
38
+ }
39
+
40
+ tr {
41
+ background-color: #FFC;
42
+ }
43
+
44
+ .tr_white_bg {
45
+ background-color: #FFFFFF;
46
+ }
47
+
48
+ td {
49
+ margin: 0;
50
+ padding: 4px;
51
+ border-width: 1px 1px 0 0;
52
+
53
+ font-family: 'Times New Roman','Times serif';
54
+ font-size: 10pt;
55
+ }
56
+ </style>
57
+ </head>
58
+ <body>
59
+ <table border="1">
60
+ <tr class="tr_white_bg">
61
+ <td><b>Entity</b></td>
62
+ <td><b>Presentation Reports</b></td>
63
+ <td><b>Calculation Reports</b></td>
64
+ </tr>
65
+ <% count=0 %>
66
+ <% @ins_report_map.each do |ins, reports_map| %>
67
+ <% if count % 2 == 0%>
68
+ <tr>
69
+ <% else %>
70
+ <tr class="tr_white_bg">
71
+ <% end %>
72
+ <% count=count+1 %>
73
+ <td>
74
+ <%=reports_map["entity_details"]["name"]%>&nbsp;(<%=reports_map["entity_details"]["symbol"]%>) &nbsp;
75
+ <br><%=reports_map["entity_details"]["doc_type"] + " : " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"])%>
76
+ </td>
77
+ <td valign="top">
78
+ <%=create_report_html(reports_map["pre"])%>
79
+ </td>
80
+ <td valign="top">
81
+ <%=create_report_html(reports_map["cal"])%>
82
+ </td>
83
+ </tr>
84
+ <% end %>
85
+ </table>
86
+ </body>
87
+ </html>
88
+ } # :nodoc:
89
+
90
+ private
91
+ def create_report_html(reports) # :nodoc:
92
+ return "" if reports.nil?
93
+ html_snipet=StringIO.new
94
+ reports.each do |title, report_files|
95
+ next if report_files.size==0
96
+ html_snipet << title << " &nbsp; &nbsp;"
97
+ report_files.each do |report_file|
98
+ html_snipet << "<a href='" << report_file << "'>"
99
+ html_snipet << File.extname(report_file).sub(".", "") << "</a>&nbsp;|&nbsp;"
100
+ end
101
+ html_snipet << "</br>"
102
+ end
103
+ html_snipet.string
104
+ end
105
+
106
+ public
107
+ # Takes path to folder that contains xbrl documents of entities. If the folder contains xbrl documents of single entity
108
+ # then HTML reports are generated for that entity. If there is need to generate reports for multiple entities then
109
+ # 1. Create root folder
110
+ # 2. Create subfolder for each entity inside root folder
111
+ # 3. The sub folders contains xbrl documents of the entity
112
+ # 4. File names of xbrl documents has to be in the following convention (if files are not in the convention mentioned below, you have to use gen_for method to generate reports)
113
+ # calculation linkbase document must end with _cal.xml
114
+ # definition linkbase document must end with _def.xml
115
+ # presentation linkbase document must end with _pre.xml
116
+ # label linkbase document must end with _lab.xml
117
+ # taxonomy file must end with .xsd
118
+ # instance document must end with .xml
119
+ # calling "gen" with root folder, will create reports for all entities under root folder
120
+ # detailed reports are stored under "reports" folder of the entity. If the "reports" doesn't exist, it
121
+ # will be created. Consolidated report of all generated reports is stored under root folder with name "edgar_report_index.html"
122
+ def gen(path_to_data_folder=".", report_for="pre|cal", report_type="html|xls|xml|json", verbose_flag="q")
123
+ @ins_report_map={}
124
+ files=xbrl_files(path_to_data_folder)
125
+ $LOG.info " Filtering xbrl files from folder [" + path_to_data_folder + "] done"
126
+ files.each do |file_map|
127
+ begin
128
+ @ins_report_map[file_map["ins"]]=gen_for(file_map, report_for, report_type, verbose_flag)
129
+ $LOG.info "Report generation for ["+file_map["ins"]+"] completed."
130
+ rescue Exception => e:
131
+ $LOG.fatal e.to_s
132
+ end
133
+ end
134
+
135
+ erb = ERB.new(@@html_template)
136
+ index_content=erb.result(get_binding)
137
+ File.open("master_report_index.html", 'w') {|f| f.write(index_content) }
138
+
139
+ rescue Exception => e:
140
+ $LOG.fatal e.to_s
141
+ end
142
+
143
+ private
144
+ def get_binding
145
+ binding
146
+ end
147
+
148
+ private
149
+ def xbrl_files(folder_path)
150
+ files=[]
151
+ presentation_files=Dir[folder_path+File::Separator+"**"+File::Separator+"*pre.xml"]
152
+ presentation_files.each do |pre_file|
153
+ files << Xbrlware::file_grep(File.dirname(pre_file))
154
+ end
155
+ files
156
+ end
157
+
158
+ private
159
+ def reports_content (link, report_type, verbose_flag)
160
+ reports_content={}
161
+
162
+ reports_content["html"]=link.to_html(verbose_flag) if report_type =~ /html|HTML/
163
+ reports_content["xls"]=link.to_xls if report_type =~ /xls|XLS/
164
+ reports_content["xml"]=link.to_xml if report_type =~ /xml|XML/
165
+ reports_content["json"]=link.to_json if report_type =~ /json|JSON/
166
+ reports_content["hash"]=link.to_hash if report_type =~ /hash|HASH/
167
+
168
+ return reports_content
169
+ end
170
+
171
+ private
172
+ def write_reports (links, report_dir, report_type, verbose_flag)
173
+ reports=HashUtil::OHash.new
174
+ links.each do |link|
175
+ reports_content=reports_content(link, report_type, verbose_flag)
176
+ report_name=link.title.gsub(/[^a-zA-Z0-9]/, "_")
177
+ report_files=[]
178
+ reports_content.each do |rtype, rcontent|
179
+ next if rcontent.nil?
180
+ extension = "." + rtype
181
+ report_dir = report_dir +File::Separator unless report_dir.end_with?(File::Separator)
182
+ report_file = report_dir+report_name+extension
183
+ File.open(report_file, 'w') {|f| f.write(rcontent) }
184
+ report_files << report_file
185
+ end
186
+ reports[link.title] = report_files
187
+ end
188
+ return reports
189
+ end
190
+
191
+ public
192
+ # Generates HTML reports from given Hash that contains files for instance, taxonomy, calculation, presentation, label, definition.
193
+ # Example of populating hash,
194
+ # files={}
195
+ # files["ins"] = "<instnace_file_path>"
196
+ # files["tax"] = "<taxonomy_file_path>"
197
+ # files["cal"] = "<calculation_linkbase_file_path>"
198
+ # files["pre"] = "<presentation_linkbase_file_path>"
199
+ # files["lab"] = "<label_linkbase_file_path>"
200
+ # files["def"] = "<definition_linkbase_file_path>"
201
+ # Generated HTML reports will be stored under "reports" folder of current dir. If the "reports" doesn't exist, it
202
+ # will be created. If "cal" is passed as null, calculation linkbase path from taxonomy will be used. Same for other
203
+ # linkbases too (ie, "pre", "lab" and "def".)
204
+ def gen_for (file_map, report_for="pre|cal", report_type="html|xls|xml|json", verbose_flag="q", report_dir=nil, meta_gen=true)
205
+ ins_file=file_map["ins"]
206
+ tax_file=file_map["tax"]
207
+ cal_file=file_map["cal"]
208
+ pre_file=file_map["pre"]
209
+ lab_file=file_map["lab"]
210
+ def_file=file_map["def"]
211
+
212
+ reports_map={}
213
+
214
+ instance=nil
215
+ m=Benchmark.measure do
216
+ instance = Instance.new(ins_file, tax_file)
217
+ taxonomy=instance.taxonomy
218
+ taxonomy.init_all_lb(cal_file, pre_file, lab_file, def_file)
219
+ end
220
+ bm(" Initializing xbrl took", m)
221
+
222
+ instance.entity_details=@entity_details
223
+ reports_map["entity_details"]=instance.entity_details
224
+ reports_map["instance"]=instance
225
+
226
+ report_dir = (File.expand_path(File.dirname(ins_file)) + File::Separator + "report" + File::Separator) if report_dir.nil?
227
+ File.makedirs(report_dir) unless File.directory?(report_dir)
228
+
229
+ if report_for =~ /pre/ && (not instance.taxonomy.prelb.nil?)
230
+ links=instance.taxonomy.prelb.presentation
231
+ pre_dir = report_dir + "pre"
232
+ File.makedirs(pre_dir) unless File.directory?(pre_dir)
233
+ reports_map["pre"]=write_reports(links, pre_dir, report_type, verbose_flag)
234
+ end
235
+
236
+ if report_for =~ /cal/ && (not instance.taxonomy.callb.nil?)
237
+ links=instance.taxonomy.callb.calculation
238
+ cal_dir = report_dir + "cal"
239
+ File.makedirs(cal_dir) unless File.directory?(cal_dir)
240
+ reports_map["cal"]=write_reports(links, cal_dir, report_type, verbose_flag)
241
+ end
242
+
243
+ _tmp = @ins_report_map
244
+
245
+ erb = ERB.new(@@html_template)
246
+ index_content=erb.result(lambda do
247
+ @ins_report_map={}
248
+ @ins_report_map[file_map["ins"]]=reports_map
249
+ lambda {}
250
+ end.call)
251
+
252
+ @ins_report_map = _tmp
253
+
254
+ # str_ci_key=reports_map["entity_details"]["ci_key"]
255
+ # str_doc_end_date=reports_map["entity_details"]["doc_end_date"]
256
+ # str_doc_end_date="" if str_doc_end_date.nil?
257
+ # str_doc_end_date.gsub!("-", "")
258
+ # report_index_file = report_dir + str_ci_key+"_"+str_doc_end_date+"_report.html"
259
+
260
+ report_index_file = report_dir + "report_index.html"
261
+ File.open( report_index_file, 'w') {|f| f.write(index_content) }
262
+
263
+ reports_map["report_index_file"]=report_index_file
264
+
265
+ if meta_gen
266
+ meta_file_name = report_dir + "meta.json"
267
+ meta_gen_content = reports_map.reject {|k, v| k=="instance"}.to_json.to_s
268
+ File.open( meta_file_name, 'w') {|f| f.write(meta_gen_content) }
269
+ reports_map["report_meta_file"]=meta_file_name
270
+ end
271
+
272
+ reports_map
273
+ rescue Exception => e
274
+ raise " Report generation failed for instance " + ins_file + "\n #{e.to_s + "\n" + e.backtrace.join("\n ")}"
275
+ end
276
+ end
277
+ end