xbrlware-ce 1.0.2

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