xbrlware-ce 1.0.2

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 (194) hide show
  1. data/Copying.txt +13 -0
  2. data/License.txt +13 -0
  3. data/Rakefile.rb +124 -0
  4. data/Readme.txt +15 -0
  5. data/doc/classes/Edgar.html +144 -0
  6. data/doc/classes/Edgar/HTMLFeedDownloader.html +199 -0
  7. data/doc/classes/Edgar/RSSFeedDownloader.html +225 -0
  8. data/doc/classes/Xbrlware.html +350 -0
  9. data/doc/classes/Xbrlware/Context.html +429 -0
  10. data/doc/classes/Xbrlware/Entity.html +323 -0
  11. data/doc/classes/Xbrlware/Identifier.html +191 -0
  12. data/doc/classes/Xbrlware/Instance.html +742 -0
  13. data/doc/classes/Xbrlware/Item.html +278 -0
  14. data/doc/classes/Xbrlware/LBConstants.html +144 -0
  15. data/doc/classes/Xbrlware/Linkbase.html +131 -0
  16. data/doc/classes/Xbrlware/Linkbase/CalculationLinkbase.html +212 -0
  17. data/doc/classes/Xbrlware/Linkbase/CalculationLinkbase/Calculation.html +172 -0
  18. data/doc/classes/Xbrlware/Linkbase/CalculationLinkbase/Calculation/CalculationArc.html +166 -0
  19. data/doc/classes/Xbrlware/Linkbase/DefinitionLinkbase.html +210 -0
  20. data/doc/classes/Xbrlware/Linkbase/DefinitionLinkbase/Definition.html +204 -0
  21. data/doc/classes/Xbrlware/Linkbase/DefinitionLinkbase/Definition/DefinitionArc.html +160 -0
  22. data/doc/classes/Xbrlware/Linkbase/LabelLinkbase.html +239 -0
  23. data/doc/classes/Xbrlware/Linkbase/LabelLinkbase/Label.html +189 -0
  24. data/doc/classes/Xbrlware/Linkbase/Linkbase.html +172 -0
  25. data/doc/classes/Xbrlware/Linkbase/Linkbase/Link.html +217 -0
  26. data/doc/classes/Xbrlware/Linkbase/Linkbase/Link/Arc.html +284 -0
  27. data/doc/classes/Xbrlware/Linkbase/PresentationLinkbase.html +224 -0
  28. data/doc/classes/Xbrlware/Linkbase/PresentationLinkbase/Presentation.html +222 -0
  29. data/doc/classes/Xbrlware/Linkbase/PresentationLinkbase/Presentation/PresentationArc.html +160 -0
  30. data/doc/classes/Xbrlware/Taxonomy.html +369 -0
  31. data/doc/classes/Xbrlware/TaxonomyDefintion.html +177 -0
  32. data/doc/classes/Xbrlware/Unit.html +179 -0
  33. data/doc/classes/Xbrlware/Unit/Divide.html +165 -0
  34. data/doc/created.rid +1 -0
  35. data/doc/files/Readme_txt.html +124 -0
  36. data/doc/files/lib/edgar/edgar_data_downloader_rb.html +129 -0
  37. data/doc/files/lib/edgar/util_rb.html +129 -0
  38. data/doc/files/lib/edgar_rb.html +141 -0
  39. data/doc/files/lib/xbrlware/constants_rb.html +129 -0
  40. data/doc/files/lib/xbrlware/context_rb.html +129 -0
  41. data/doc/files/lib/xbrlware/date_util_rb.html +129 -0
  42. data/doc/files/lib/xbrlware/float_patch_rb.html +129 -0
  43. data/doc/files/lib/xbrlware/hash_util_rb.html +129 -0
  44. data/doc/files/lib/xbrlware/instance_rb.html +129 -0
  45. data/doc/files/lib/xbrlware/item_rb.html +129 -0
  46. data/doc/files/lib/xbrlware/linkbase/calculation_linkbase_rb.html +129 -0
  47. data/doc/files/lib/xbrlware/linkbase/definition_linkbase_rb.html +129 -0
  48. data/doc/files/lib/xbrlware/linkbase/label_linkbase_rb.html +129 -0
  49. data/doc/files/lib/xbrlware/linkbase/linkbase_rb.html +129 -0
  50. data/doc/files/lib/xbrlware/linkbase/presentation_linkbase_rb.html +129 -0
  51. data/doc/files/lib/xbrlware/meta_util_rb.html +129 -0
  52. data/doc/files/lib/xbrlware/taxonomy_rb.html +129 -0
  53. data/doc/files/lib/xbrlware/unit_rb.html +129 -0
  54. data/doc/files/lib/xbrlware/util_rb.html +129 -0
  55. data/doc/files/lib/xbrlware/xml_parser_rb.html +129 -0
  56. data/doc/files/lib/xbrlware_rb.html +163 -0
  57. data/doc/fr_class_index.html +55 -0
  58. data/doc/fr_file_index.html +48 -0
  59. data/doc/fr_method_index.html +104 -0
  60. data/doc/index.html +24 -0
  61. data/doc/rdoc-style.css +208 -0
  62. data/example/benchmark/instance_parser_benchmark.rb +25 -0
  63. data/example/case_study/buy_strategy.rb +34 -0
  64. data/example/case_study/c-20091230.xml +29 -0
  65. data/example/case_study/c_sell_strategy.rb +29 -0
  66. data/example/lang_integration/thrift/rating-client.py +21 -0
  67. data/example/lang_integration/thrift/rating-impl.rb +13 -0
  68. data/example/lang_integration/thrift/rating-server.rb +25 -0
  69. data/example/lang_integration/thrift/rating.thrift +52 -0
  70. data/example/quick_start/foo.rb +10 -0
  71. data/example/quick_start/foo.xml +29 -0
  72. data/example/quick_start/print_item.rb +27 -0
  73. data/lib/edgar.rb +30 -0
  74. data/lib/edgar/edgar_data_downloader.rb +126 -0
  75. data/lib/edgar/util.rb +30 -0
  76. data/lib/xbrlware.rb +65 -0
  77. data/lib/xbrlware/constants.rb +29 -0
  78. data/lib/xbrlware/context.rb +148 -0
  79. data/lib/xbrlware/date_util.rb +35 -0
  80. data/lib/xbrlware/float_patch.rb +26 -0
  81. data/lib/xbrlware/hash_util.rb +175 -0
  82. data/lib/xbrlware/instance.rb +406 -0
  83. data/lib/xbrlware/item.rb +115 -0
  84. data/lib/xbrlware/linkbase/calculation_linkbase.rb +137 -0
  85. data/lib/xbrlware/linkbase/definition_linkbase.rb +186 -0
  86. data/lib/xbrlware/linkbase/label_linkbase.rb +128 -0
  87. data/lib/xbrlware/linkbase/linkbase.rb +170 -0
  88. data/lib/xbrlware/linkbase/presentation_linkbase.rb +160 -0
  89. data/lib/xbrlware/meta_util.rb +45 -0
  90. data/lib/xbrlware/taxonomies/us_gaap_taxonomy_20090131.rb +40365 -0
  91. data/lib/xbrlware/taxonomy.rb +133 -0
  92. data/lib/xbrlware/unit.rb +42 -0
  93. data/lib/xbrlware/util.rb +83 -0
  94. data/lib/xbrlware/xml_parser.rb +122 -0
  95. data/setup.rb +1585 -0
  96. data/test/lib/edgar/edgar_data_downloader_test.rb +35 -0
  97. data/test/lib/edgar/resources/0000930413-09-005485-index.htm +331 -0
  98. data/test/lib/edgar/resources/usgaap.rss.xml +2861 -0
  99. data/test/lib/xbrlware/411_footnotes_test.rb +65 -0
  100. data/test/lib/xbrlware/42_schemaref_test.rb +20 -0
  101. data/test/lib/xbrlware/46_item_test.rb +253 -0
  102. data/test/lib/xbrlware/47_context_test.rb +129 -0
  103. data/test/lib/xbrlware/48_unit_test.rb +45 -0
  104. data/test/lib/xbrlware/49_tuple_test.rb +12 -0
  105. data/test/lib/xbrlware/date_util_test.rb +24 -0
  106. data/test/lib/xbrlware/dimension/context_explicit_dimension_test.rb +40 -0
  107. data/test/lib/xbrlware/dimension/resources/context_explicit_dimension.xml +84 -0
  108. data/test/lib/xbrlware/float_patch_test.rb +10 -0
  109. data/test/lib/xbrlware/hash_util_test.rb +29 -0
  110. data/test/lib/xbrlware/instance_test.rb +250 -0
  111. data/test/lib/xbrlware/linkbase/calculation_linkbase_test.rb +39 -0
  112. data/test/lib/xbrlware/linkbase/definition_linkbase_test.rb +35 -0
  113. data/test/lib/xbrlware/linkbase/label_linkbase_test.rb +22 -0
  114. data/test/lib/xbrlware/linkbase/linkbase_test.rb +36 -0
  115. data/test/lib/xbrlware/linkbase/linkbase_test_util.rb +98 -0
  116. data/test/lib/xbrlware/linkbase/presentation_linkbase_test.rb +33 -0
  117. data/test/lib/xbrlware/linkbase/report.html +62 -0
  118. data/test/lib/xbrlware/linkbase/resources/cal.xml +219 -0
  119. data/test/lib/xbrlware/linkbase/resources/def.xml +186 -0
  120. data/test/lib/xbrlware/linkbase/resources/def_with_multiple_dimension.xml +41 -0
  121. data/test/lib/xbrlware/linkbase/resources/instance.xml +5822 -0
  122. data/test/lib/xbrlware/linkbase/resources/lab.xml +782 -0
  123. data/test/lib/xbrlware/linkbase/resources/pre.xml +485 -0
  124. data/test/lib/xbrlware/linkbase/resources/report_10_q.htm +12327 -0
  125. data/test/lib/xbrlware/linkbase/resources/taxonomy.xsd +178 -0
  126. data/test/lib/xbrlware/linkbase/sample_html_report.html +40 -0
  127. data/test/lib/xbrlware/meta_util_test.rb +23 -0
  128. data/test/lib/xbrlware/resources/411/411_footnotes.xml +66 -0
  129. data/test/lib/xbrlware/resources/42/42_schema_ref_with_base.xml +7 -0
  130. data/test/lib/xbrlware/resources/42/42_schema_ref_without_base.xml +7 -0
  131. data/test/lib/xbrlware/resources/46/46_item_value.xml +61 -0
  132. data/test/lib/xbrlware/resources/47/472_period_forever.xml +29 -0
  133. data/test/lib/xbrlware/resources/47/472_period_instant.xml +24 -0
  134. data/test/lib/xbrlware/resources/47/472_period_start_dt_and_end_dt.xml +30 -0
  135. data/test/lib/xbrlware/resources/47/4731_entity_identifier.xml +29 -0
  136. data/test/lib/xbrlware/resources/47/4732_entity_segment_not_present.xml +24 -0
  137. data/test/lib/xbrlware/resources/47/4732_entity_segment_present.xml +30 -0
  138. data/test/lib/xbrlware/resources/47/474_scenario_not_present.xml +26 -0
  139. data/test/lib/xbrlware/resources/47/474_scenario_present.xml +30 -0
  140. data/test/lib/xbrlware/resources/47/47_multiple_contexts.xml +36 -0
  141. data/test/lib/xbrlware/resources/48/482_unit_measure.xml +32 -0
  142. data/test/lib/xbrlware/resources/48/483_unit_divide.xml +39 -0
  143. data/test/lib/xbrlware/resources/48/48_multiple_units.xml +43 -0
  144. data/test/lib/xbrlware/resources/49/49_tuple.xml +61 -0
  145. data/test/lib/xbrlware/resources/49_tuple.xsd +44 -0
  146. data/test/lib/xbrlware/resources/instance.xml +128 -0
  147. data/test/lib/xbrlware/resources/report_test_xbrl_files/cal.xml +219 -0
  148. data/test/lib/xbrlware/resources/report_test_xbrl_files/def.xml +186 -0
  149. data/test/lib/xbrlware/resources/report_test_xbrl_files/instance.xml +5822 -0
  150. data/test/lib/xbrlware/resources/report_test_xbrl_files/lab.xml +782 -0
  151. data/test/lib/xbrlware/resources/report_test_xbrl_files/pre.xml +485 -0
  152. data/test/lib/xbrlware/resources/report_test_xbrl_files/report/report_index.html +62 -0
  153. data/test/lib/xbrlware/resources/report_test_xbrl_files/taxonomy.xsd +178 -0
  154. data/test/lib/xbrlware/resources/taxonomy_test_files/1/cal.xml +223 -0
  155. data/test/lib/xbrlware/resources/taxonomy_test_files/1/def.xml +190 -0
  156. data/test/lib/xbrlware/resources/taxonomy_test_files/1/lab.xml +786 -0
  157. data/test/lib/xbrlware/resources/taxonomy_test_files/1/pre.xml +489 -0
  158. data/test/lib/xbrlware/resources/taxonomy_test_files/1/taxonomy.xsd +177 -0
  159. data/test/lib/xbrlware/resources/taxonomy_test_files/2/linkbases/cal.xml +223 -0
  160. data/test/lib/xbrlware/resources/taxonomy_test_files/2/linkbases/def.xml +190 -0
  161. data/test/lib/xbrlware/resources/taxonomy_test_files/2/linkbases/lab.xml +786 -0
  162. data/test/lib/xbrlware/resources/taxonomy_test_files/2/linkbases/pre.xml +489 -0
  163. data/test/lib/xbrlware/resources/taxonomy_test_files/2/taxonomy.xsd +175 -0
  164. data/test/lib/xbrlware/resources/taxonomy_test_files/3/taxonomy.xsd +175 -0
  165. data/test/lib/xbrlware/resources/us_gaap_schema.xsd +8 -0
  166. data/test/lib/xbrlware/resources/us_gaap_schema_local.xsd +10 -0
  167. data/test/lib/xbrlware/resources/util_test_xbrl_files/cal.xml +219 -0
  168. data/test/lib/xbrlware/resources/util_test_xbrl_files/def.xml +186 -0
  169. data/test/lib/xbrlware/resources/util_test_xbrl_files/instance.xml +5822 -0
  170. data/test/lib/xbrlware/resources/util_test_xbrl_files/lab.xml +782 -0
  171. data/test/lib/xbrlware/resources/util_test_xbrl_files/pre.xml +485 -0
  172. data/test/lib/xbrlware/resources/util_test_xbrl_files/taxonomy.xsd +178 -0
  173. data/test/lib/xbrlware/resources/xbrl_xsd/dei-2009-01-31.xsd +162 -0
  174. data/test/lib/xbrlware/resources/xbrl_xsd/dei-std-2009-01-31.xsd +23 -0
  175. data/test/lib/xbrlware/resources/xbrl_xsd/negated-2008-03-31.xsd +23 -0
  176. data/test/lib/xbrlware/resources/xbrl_xsd/ref-2006-02-27.xsd +121 -0
  177. data/test/lib/xbrlware/resources/xbrl_xsd/us-gaap-2009-01-31.xsd +13474 -0
  178. data/test/lib/xbrlware/resources/xbrl_xsd/us-roles-2009-01-31.xsd +2283 -0
  179. data/test/lib/xbrlware/resources/xbrl_xsd/us-types-2009-01-31.xsd +368 -0
  180. data/test/lib/xbrlware/resources/xbrl_xsd/xbrl-instance-2003-12-31.xsd +772 -0
  181. data/test/lib/xbrlware/resources/xbrl_xsd/xbrl-linkbase-2003-12-31.xsd +477 -0
  182. data/test/lib/xbrlware/resources/xbrl_xsd/xbrldi-2006.xsd +41 -0
  183. data/test/lib/xbrlware/resources/xbrl_xsd/xbrldt-2005.xsd +53 -0
  184. data/test/lib/xbrlware/resources/xbrl_xsd/xl-2003-12-31.xsd +246 -0
  185. data/test/lib/xbrlware/resources/xbrl_xsd/xlink-2003-12-31.xsd +117 -0
  186. data/test/lib/xbrlware/taxonomy_test.rb +124 -0
  187. data/test/lib/xbrlware/util_test.rb +18 -0
  188. data/test/lib/xbrlware/xml_parser_test.rb +142 -0
  189. data/test/schema_validator_jruby.rb +40 -0
  190. data/test/schema_validator_ruby.rb +7 -0
  191. data/test/scratchpad/block.rb +36 -0
  192. data/test/test_helper.rb +21 -0
  193. data/xbrlware.iml +30 -0
  194. metadata +261 -0
@@ -0,0 +1,406 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Author:: xbrlware@bitstat.com
4
+ #
5
+ # Copyright:: 2009, 2010 bitstat (http://www.bitstat.com). All Rights Reserved.
6
+ #
7
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16
+ # implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ module Xbrlware
21
+
22
+ # Class to deal with valid, well-formatted XBRl instance file.
23
+ # This class provides methods to deal with instance file.
24
+ # Look at {delaing with instance page on xbrlware wiki}[http://code.google.com/p/xbrlware/wiki/InstanceTaxonomy] for more details.
25
+ class Instance
26
+
27
+ attr_reader :taxonomy
28
+
29
+ # Creates an Instance.
30
+ #
31
+ # instance_filepath:: XBRL Instance source. Tries to load and parse instance file from the path.
32
+ #
33
+ # taxonomy_filepath::
34
+ # optional parameter, XBRL Taxonomy source. Tries to load and parse taxonomy file from path.
35
+ # If this param is specified, taxonomy file in the instance document will be ignored
36
+ #
37
+ # Expects instance source is well-formatted and valid
38
+ # Sometimes instance document contains large chunk of HTML content with new lines in-between,
39
+ # which will cause parsing error. Hence any exceptions during instance source parsing, will trigger re-parsing of
40
+ # the entire instnace file with new lines replaced.
41
+ # Look at {delaing with instance page on xbrlware wiki}[http://code.google.com/p/xbrlware/wiki/InstanceTaxonomy] for details.
42
+ def initialize(instance_filepath, taxonomy_filepath=nil)
43
+ m=Benchmark.measure do
44
+ begin
45
+ @file_name=instance_filepath
46
+ @xbrl_content = XmlParser.xml_in(instance_filepath, {'ForceContent' => true})
47
+ rescue Exception
48
+ $LOG.warn "File ["+instance_filepath+"] is not well formed. Starting reparsing after removing new lines."
49
+ @xbrl_content = XmlParser.xml_in(File.open(instance_filepath).read.gsub("\n", ""), {'ForceContent' => true})
50
+ end
51
+ end
52
+ bm("Parsing [" + instance_filepath + "] took", m)
53
+
54
+ # if taxonomy file is not supplied, get it from instance schema_ref
55
+ if taxonomy_filepath.nil?
56
+ taxonomy_file_location=File.dirname(instance_filepath)+File::Separator+schema_ref
57
+ taxonomy_filepath = taxonomy_file_location if File.exist?(taxonomy_file_location) && (not File.directory?(taxonomy_file_location))
58
+ end
59
+
60
+ @taxonomy=Xbrlware::Taxonomy.new(taxonomy_filepath, self)
61
+ end
62
+
63
+ # Returns raw content of instance file in the form of Hash
64
+ def raw
65
+ @xbrl_content
66
+ end
67
+
68
+ # Returns schemaRef element of instance file. schemaRef holds path to taxonomy file for the instance file.
69
+ def schema_ref
70
+ base = @xbrl_content["schemaRef"][0]["xml:base"]
71
+ href = @xbrl_content["schemaRef"][0]["xlink:href"]
72
+ return base + href if base
73
+ href
74
+ end
75
+
76
+ # Takes optional context_id as string and dimensions as array
77
+ # Returns all contexts when context_id is nil
78
+ # Returns instance of Context object if context_id or dimensions is passed and matching context exist
79
+ # Returns nil if context_id or dimensions is passed and no matching context exist
80
+ def context(context_id=nil, dimensions=[])
81
+ all_contexts= context_by_id(context_id)
82
+
83
+ return all_contexts if dimensions.size==0
84
+
85
+ contexts=[]
86
+
87
+ all_contexts=[all_contexts] unless all_contexts.is_a?(Array)
88
+ all_contexts.each do |ctx|
89
+ next unless ctx.has_explicit_dimensions?(dimensions)
90
+ contexts << ctx
91
+ end
92
+
93
+ return contexts[0] unless context_id.nil?
94
+ contexts
95
+ end
96
+
97
+ # Returns contexts grouped by dimension as map. Map contains dimension as key and corresponding contexts as value
98
+ def ctx_groupby_dim
99
+ dim_group={}
100
+ all_contexts= context
101
+ all_contexts=[all_contexts] unless all_contexts.is_a?(Array)
102
+ all_contexts.each do |ctx|
103
+ ctx.explicit_dimensions.each do |dim|
104
+ dim_group[dim] = [] if dim_group[dim].nil?
105
+ dim_group[dim] << ctx
106
+ end
107
+ end
108
+ dim_group
109
+ end
110
+
111
+ # Takes optional dimensions as array
112
+ # Returns contexts group by domain as map. Map contains domain as key and corresponding contexts as value
113
+ def ctx_groupby_dom(dimensions=[])
114
+ dom_group={}
115
+ all_contexts= context(nil, dimensions)
116
+ all_contexts=[all_contexts] unless all_contexts.is_a?(Array)
117
+ all_contexts.each do |ctx|
118
+ ctx.explicit_domains(dimensions).each do |dom|
119
+ dom_group[dom] = [] if dom_group[dom].nil?
120
+ dom_group[dom] << ctx
121
+ end
122
+ end
123
+ dom_group
124
+ end
125
+
126
+ # Takes optional dimensions as array
127
+ # Returns contexts group by period as map. Map contains period as key and corresponding contexts as value
128
+ def ctx_groupby_period(dimensions=[])
129
+ period_group={}
130
+ all_contexts= context(nil, dimensions)
131
+ all_contexts=[all_contexts] unless all_contexts.is_a?(Array)
132
+ all_contexts.each do |ctx|
133
+ period_group[ctx.period.to_s] = [] if period_group[ctx.period.to_s].nil?
134
+ period_group[ctx.period.to_s] << ctx
135
+ end
136
+ period_group
137
+ end
138
+
139
+ # Prints dimension -> domain -> context relationship for all contexts in the console.
140
+ def ctx_groupby_dim_dom_print
141
+ group_dim=ctx_groupby_dim
142
+ group_dim.keys.each do |dimension|
143
+ puts " dimension :: " + dimension
144
+ group_dom=ctx_groupby_dom(dimension)
145
+ group_dom.keys.each do |domain|
146
+ puts " \t domain :: " + domain
147
+ group_dom[domain].each do |ctx|
148
+ puts " \t\t ctx :: " + ctx.id
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ private
155
+ # Takes optional context_id
156
+ # Returns all contexts if context_id is nil
157
+ # Returns matching context as Context object if context_id is given and matching context found
158
+ # Returns nil if context_id is given and no matching context found
159
+ def context_by_id(context_id=nil)
160
+ if context_id.nil?
161
+ contexts=[]
162
+ @xbrl_content["context"].each {|c| contexts << to_ctx_obj(c) }
163
+ return contexts
164
+ end
165
+
166
+ ctx_content=nil
167
+ @xbrl_content["context"].each { |ctx| ctx_content=ctx if ctx["id"]==context_id}
168
+ $LOG.warn " unable to find context for id [" + context_id+"]" if ctx_content.nil?
169
+ return nil if ctx_content.nil?
170
+ return to_ctx_obj(ctx_content)
171
+
172
+ end
173
+
174
+ # Creates Context object from context content of XBRL instance file
175
+ def to_ctx_obj (ctx_content)
176
+ id=ctx_content["id"]
177
+
178
+ entity_content = ctx_content["entity"][0]
179
+ e = entity(entity_content)
180
+
181
+ period_content = ctx_content["period"][0]
182
+ p = period(period_content)
183
+
184
+ s = scenario(ctx_content)
185
+ return Context.new(id, e, p, s)
186
+ end
187
+
188
+ # Returns map if period is duration. Map has key with name "start_date" and "end_date"
189
+ # Returns string if period is instant
190
+ # Returns -1 if period is forever
191
+ def period(period_content)
192
+ if period_content["startDate"] && period_content["endDate"]
193
+ return {"start_date" => period_content["startDate"][0]["content"], "end_date" => period_content["endDate"][0]["content"]}
194
+ elsif period_content["instant"]
195
+ return period_content["instant"][0]["content"]
196
+ elsif period_content["forever"]
197
+ return Context::PERIOD_FOREVER
198
+ end
199
+ end
200
+
201
+ # Returns Entity object
202
+ def entity(entity_content)
203
+ entity_identifier = Identifier.new(entity_content["identifier"][0]["scheme"], entity_content["identifier"][0]["content"].strip!)
204
+
205
+ entity_segment_content=entity_content["segment"]
206
+ entity_segment=nil
207
+ unless entity_segment_content.nil?
208
+ entity_segment=entity_segment_content[0]
209
+ end
210
+
211
+ return Entity.new(entity_identifier, entity_segment)
212
+ end
213
+
214
+ # Returns scenario content
215
+ def scenario(ctx_content)
216
+ s=nil
217
+ unless ctx_content["scenario"].nil?
218
+ s = ctx_content["scenario"][0]
219
+ end
220
+ return s
221
+ end
222
+
223
+ public
224
+ # Takes optional unit_id
225
+ # Returns all units if unit_id is nil
226
+ # Returns matching unit as Unit object if unit_id is given and matching unit found
227
+ # Returns nil if unit_id is given and no matching unit found
228
+ def unit(unit_id=nil)
229
+ unit_content = @xbrl_content["unit"]
230
+ return nil if unit_content.nil?
231
+
232
+ units=[]
233
+
234
+ l = lambda {|measure_list| measures=[]; measure_list.each { |measure| measures << measure["content"]}; return measures}
235
+ unit_content.each do |unit|
236
+
237
+ next unless unit_id.nil? || unit["id"].to_s == unit_id
238
+
239
+ unless unit["measure"].nil?
240
+ units << Unit.new(unit["id"], l.call(unit["measure"]))
241
+ else
242
+ divide_content = unit["divide"][0]
243
+
244
+ numerator = l.call(divide_content["unitNumerator"][0]["measure"])
245
+ denominator = l.call(divide_content["unitDenominator"][0]["measure"])
246
+
247
+ divide=Unit::Divide.new(numerator, denominator)
248
+ units << Unit.new(unit["id"], divide)
249
+ end
250
+ end
251
+ return units[0] unless unit_id.nil?
252
+ units
253
+ end
254
+
255
+ # Takes name and optional context_ref and unit_ref
256
+ # Returns array of Item for given name, context_ref and unit_ref
257
+ # Returns empty array if item is not found
258
+ def item(name, context_ref=nil, unit_ref=nil)
259
+
260
+ item_content = @xbrl_content[name]
261
+
262
+ return nil if item_content.nil?
263
+
264
+ items=[]
265
+
266
+ item_content.each do |item|
267
+
268
+ next unless context_ref.nil? || context_ref == item["contextRef"]
269
+ next unless unit_ref.nil? || unit_ref == item["unitRef"]
270
+
271
+ context = context(item["contextRef"])
272
+ value = item["content"]
273
+
274
+ unit, precision, decimals, _footnotes=nil
275
+
276
+ unit = unit(item["unitRef"]) unless item["unitRef"].nil?
277
+ precision = item["precision"] unless item["precision"].nil?
278
+ decimals = item["decimals"] unless item["decimals"].nil?
279
+
280
+ _footnotes = footnotes(item["id"]) unless item["id"].nil?
281
+ item=Item.new(name, context, value, unit, precision, decimals, _footnotes)
282
+ item.def=@taxonomy.definition(name)
283
+ items << item
284
+ end
285
+ items
286
+ end
287
+
288
+ # Takes item name
289
+ # Returns array of contexts for given item name
290
+ # Returns empty array if no item with given name found
291
+ def context_for_item(item_name)
292
+ contexts=[]
293
+ items = item(item_name)
294
+ items.each {|item| contexts << item.context}
295
+ return contexts
296
+ end
297
+
298
+
299
+ # Takes item name and filter block
300
+ # Fetches item with name and invokes filter block with item context
301
+ # Returns matched items.
302
+ def item_ctx_filter(name, &context_filter_block)
303
+ items=item(name)
304
+ return items if context_filter_block.nil?
305
+ filtered_items=[]
306
+ items.each do |item|
307
+ filtered_items << item if yield(item.context)
308
+ end
309
+ filtered_items
310
+ end
311
+
312
+ public
313
+ # Takes optional item id and language
314
+ # Every item in XBRL instance file may contain optional id element.
315
+ # Footnotes is associated with id of the item. Footnotes may be in different languages.
316
+ # Returns Map with lang as key and corresponding footnotes in array as value if item_id is givien
317
+ # Returns Map with item_id as key and another Map as value.
318
+ # Second map has lang as key and corresponding footnotes in array as value if item_id is givien
319
+ # Returns nil if no match found for item_it or footnotes not exist
320
+ def footnotes (item_id=nil, lang=nil)
321
+ @item_footnote_map=nil
322
+ raise " lang can't be passed when item id is nil" if item_id.nil? && (not lang.nil?)
323
+ @item_footnote_map = compute_footnotes if @item_footnote_map.nil?
324
+ return nil if @item_footnote_map.nil?
325
+ return @item_footnote_map[item_id] if (not item_id.nil?) && lang.nil?
326
+ return @item_footnote_map[item_id][lang] unless item_id.nil? || lang.nil?
327
+ @item_footnote_map
328
+ end
329
+
330
+
331
+ def entity_details
332
+ @entity_details={}
333
+ if @entity_details.size==0
334
+ e_name=item("EntityRegistrantName")[0]
335
+ e_ci_key=item("EntityCentralIndexKey")[0]
336
+ e_doc_type=item("DocumentType")[0]
337
+ e_doc_end_type=item("DocumentPeriodEndDate")[0]
338
+
339
+ fedate=item("CurrentFiscalYearEndDate")
340
+ e_fiscal_end_date=fedate[0] unless fedate.nil?
341
+
342
+ shares_outstanding = item("EntityCommonStockSharesOutstanding")
343
+ e_common_shares_outstanding=shares_outstanding[0] unless shares_outstanding.nil?
344
+
345
+ @entity_details["name"]=e_name.value unless e_name.nil?
346
+ @entity_details["ci_key"]=e_ci_key.value unless e_ci_key.nil?
347
+ @entity_details["doc_type"]=e_doc_type.value unless e_doc_type.nil?
348
+ @entity_details["doc_end_date"]=e_doc_end_type.value unless e_doc_end_type.nil?
349
+ @entity_details["fiscal_end_date"]=e_fiscal_end_date.value unless e_fiscal_end_date.nil?
350
+ @entity_details["common_shares_outstanding"]=e_common_shares_outstanding.value unless e_common_shares_outstanding.nil?
351
+
352
+ file_name=File.basename(@file_name)
353
+ symbol=file_name.split("-")[0]
354
+ symbol.upcase!
355
+
356
+ @entity_details["symbol"]=symbol unless symbol.nil?
357
+
358
+ end
359
+ @entity_details
360
+ end
361
+
362
+ private
363
+ def compute_footnotes()
364
+ return nil if @xbrl_content["footnoteLink"].nil?
365
+ item_map={}
366
+ @xbrl_content["footnoteLink"][0]["loc"].each do |loc|
367
+ item_map[loc["xlink:label"]]=[] if item_map[loc["xlink:label"]].nil?
368
+ item_map[loc["xlink:label"]] << loc["xlink:href"].split("#")[-1]
369
+ end
370
+
371
+ footnote_map = {}
372
+ @xbrl_content["footnoteLink"][0]["footnote"].each do |fn|
373
+ label=fn["xlink:label"]
374
+ lang=fn["xml:lang"]
375
+ content=fn["content"]
376
+
377
+ footnote_map[label]={} if footnote_map[label].nil?
378
+ footnote_map[label][lang]=content
379
+ end
380
+
381
+ label_to_footnote_map = {}
382
+ @xbrl_content["footnoteLink"][0]["footnoteArc"].each do |fn_arc|
383
+ label_to_footnote_map[fn_arc["xlink:from"]] = [] if label_to_footnote_map[fn_arc["xlink:from"]].nil?
384
+ label_to_footnote_map[fn_arc["xlink:from"]] << fn_arc["xlink:to"]
385
+ end
386
+
387
+ item_footnote_map ={}
388
+ label_to_footnote_map.each do |item_label, fn_labels|
389
+ item_ids=item_map[item_label]
390
+ item_ids.each do |item_id|
391
+ item_footnote_map[item_id] = {} if item_footnote_map[item_id].nil?
392
+ map=item_footnote_map[item_id]
393
+ fn_labels.each do |fn_lab|
394
+ fn=footnote_map[fn_lab]
395
+ fn.each do |lang, content|
396
+ map[lang]=[] if map[lang].nil?
397
+ map[lang] << content
398
+ end
399
+ end unless fn_labels.nil?
400
+ end unless item_ids.nil?
401
+ end
402
+ item_footnote_map
403
+ end
404
+
405
+ end
406
+ end
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Author:: xbrlware@bitstat.com
4
+ #
5
+ # Copyright:: 2009, 2010 bitstat (http://www.bitstat.com). All Rights Reserved.
6
+ #
7
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16
+ # implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ module Xbrlware
21
+
22
+ # This class represents each item in the XBRL instance file.
23
+ # Taxonomy definition of a item can be retrieved using def or meta methods.
24
+ # Look at {delaing with instance page on xbrlware wiki}[http://code.google.com/p/xbrlware/wiki/InstanceTaxonomy] for more details.
25
+ class Item
26
+ attr_reader :name, :context,:unit,:precision,:decimals, :footnotes
27
+ attr_accessor :def
28
+
29
+ # Constructs item
30
+ # value is normalized based on precision and decimals passed as per XBRL specification
31
+ def initialize(name, context, value, unit=nil,precision=nil,decimals=nil, footnotes=nil)
32
+ @name=name
33
+ @context = context
34
+ @precision=precision
35
+ @decimals=decimals
36
+ @footnotes=footnotes
37
+ @value = ItemValue.new(value, precision, decimals).value
38
+ @unit = unit
39
+ end
40
+
41
+ def value
42
+ return yield(@value) if block_given?
43
+ @value
44
+ end
45
+
46
+ alias_method :meta, :def
47
+
48
+ def balance
49
+ _balance=meta["xbrli:balance"] unless meta.nil?
50
+ _balance.nil? ? "" : _balance
51
+ end
52
+
53
+ class ItemValue # :nodoc:
54
+
55
+ attr_reader :item_value
56
+
57
+ def initialize(item_value,precision=nil,decimals=nil)
58
+ @item_value=item_value
59
+ @precision=precision
60
+ @decimals=decimals
61
+ end
62
+
63
+ def value()
64
+ return precision() unless @precision.nil?
65
+ return decimals() unless @decimals.nil?
66
+ return @item_value
67
+ end
68
+
69
+ # returns BigDecimal float representation as String
70
+ def precision()
71
+ return @item_value if @precision=="INF"
72
+
73
+ precision_i=@precision.to_i
74
+ new_value=BigDecimal(@item_value)
75
+
76
+ is_value_integer = new_value==@item_value.to_i
77
+
78
+
79
+ return to_precision_from_integer(@item_value.to_i, precision_i) if is_value_integer
80
+
81
+ index_of_dot = new_value.abs.to_s("F").index(".")
82
+
83
+ # When mod value is greater than 1 and float number
84
+ if new_value.abs > 1
85
+ #Precision is less than number of digits before decimal
86
+ return to_precision_from_integer(new_value.to_i, precision_i) if precision_i <= index_of_dot
87
+
88
+ #Precision is greater than number of digits before decimal
89
+ return new_value.round(precision_i-index_of_dot).to_s("F")
90
+ else
91
+ new_value_s = new_value.abs.to_s("F")
92
+ no_of_zeroes = new_value_s.split(/[1-9].*/).join.length - new_value_s.index(".")-1
93
+ return new_value.round(no_of_zeroes + precision_i).to_s("F")
94
+ end
95
+ end
96
+
97
+ # returns BigDecimal float representation as String
98
+ def decimals
99
+ return BigDecimal(@item_value).round(@decimals.to_i).to_s("F")
100
+ end
101
+
102
+ private
103
+ def to_precision_from_integer(new_value, precision_i)
104
+ factor=10 **(new_value.abs.to_s.length - precision_i)
105
+ return to_big_decimal_float_str(((BigDecimal(new_value.to_s) / factor).to_i * factor).to_s)
106
+ end
107
+
108
+ def to_big_decimal_float_str(value)
109
+ return BigDecimal(value).to_s("F")
110
+ end
111
+
112
+ end
113
+ end
114
+
115
+ end