xbrlware-ce 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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