arelle-release 2.37.46__py3-none-any.whl → 2.38.0__py3-none-any.whl

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 (204) hide show
  1. arelle/BetaFeatures.py +0 -21
  2. arelle/Cntlr.py +15 -8
  3. arelle/CntlrCmdLine.py +121 -56
  4. arelle/CntlrWinMain.py +143 -70
  5. arelle/DialogFind.py +1 -1
  6. arelle/DialogPluginManager.py +6 -4
  7. arelle/DisclosureSystem.py +7 -0
  8. arelle/ErrorManager.py +21 -6
  9. arelle/FileSource.py +11 -4
  10. arelle/FunctionIxt.py +16 -11
  11. arelle/HtmlUtil.py +5 -4
  12. arelle/LeiUtil.py +63 -43
  13. arelle/ModelDocument.py +20 -15
  14. arelle/ModelDtsObject.py +8 -0
  15. arelle/ModelInstanceObject.py +1 -1
  16. arelle/ModelObject.py +16 -18
  17. arelle/ModelObjectFactory.py +35 -17
  18. arelle/ModelXbrl.py +28 -11
  19. arelle/PluginManager.py +130 -105
  20. arelle/RuntimeOptions.py +1 -0
  21. arelle/UrlUtil.py +14 -0
  22. arelle/Validate.py +17 -12
  23. arelle/ValidateDuplicateFacts.py +3 -1
  24. arelle/ValidateFileSource.py +38 -0
  25. arelle/ValidateFilingText.py +3 -3
  26. arelle/ValidateXbrl.py +5 -2
  27. arelle/ValidateXbrlCalcs.py +210 -186
  28. arelle/ValidateXbrlDTS.py +1 -1
  29. arelle/ViewFile.py +1 -0
  30. arelle/ViewFileFactTable.py +2 -2
  31. arelle/ViewWinDTS.py +4 -1
  32. arelle/WebCache.py +28 -24
  33. arelle/XbrlConst.py +22 -0
  34. arelle/XmlUtil.py +16 -21
  35. arelle/XmlValidate.py +6 -9
  36. arelle/_version.py +16 -3
  37. arelle/api/Session.py +11 -2
  38. arelle/config/disclosuresystems.xsd +2 -0
  39. arelle/config/rosettaEntitlements.plist +8 -0
  40. arelle/conformance/CSVTestcaseLoader.py +1 -1
  41. arelle/formula/XPathContext.py +3 -3
  42. arelle/logging/formatters/LogFormatter.py +3 -1
  43. arelle/packages/report/ReportPackage.py +26 -13
  44. arelle/packages/report/ReportPackageConst.py +0 -1
  45. arelle/plugin/inlineXbrlDocumentSet.py +19 -5
  46. arelle/plugin/validate/DBA/DisclosureSystems.py +19 -1
  47. arelle/plugin/validate/DBA/PluginValidationDataExtension.py +2 -4
  48. arelle/plugin/validate/DBA/ValidationPluginExtension.py +2 -1
  49. arelle/plugin/validate/DBA/resources/config.xml +5 -0
  50. arelle/plugin/validate/DBA/rules/__init__.py +2 -2
  51. arelle/plugin/validate/DBA/rules/fr.py +19 -2
  52. arelle/plugin/validate/DBA/rules/tc.py +2 -0
  53. arelle/plugin/validate/DBA/rules/th.py +6 -0
  54. arelle/plugin/validate/DBA/rules/tm.py +18 -5
  55. arelle/plugin/validate/DBA/rules/tr.py +11 -5
  56. arelle/plugin/validate/EDINET/Constants.py +193 -9
  57. arelle/plugin/validate/EDINET/ContextRequirement.py +58 -0
  58. arelle/plugin/validate/EDINET/ControllerPluginData.py +220 -1
  59. arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
  60. arelle/plugin/validate/EDINET/DeiRequirements.py +118 -0
  61. arelle/plugin/validate/EDINET/FilingFormat.py +275 -0
  62. arelle/plugin/validate/EDINET/FormType.py +134 -0
  63. arelle/plugin/validate/EDINET/ManifestInstance.py +72 -5
  64. arelle/plugin/validate/EDINET/NamespaceConfig.py +50 -0
  65. arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +493 -132
  66. arelle/plugin/validate/EDINET/{InstanceType.py → ReportFolderType.py} +72 -15
  67. arelle/plugin/validate/EDINET/Statement.py +139 -0
  68. arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +595 -0
  69. arelle/plugin/validate/EDINET/UploadContents.py +48 -0
  70. arelle/plugin/validate/EDINET/ValidationPluginExtension.py +20 -2
  71. arelle/plugin/validate/EDINET/__init__.py +31 -6
  72. arelle/plugin/validate/EDINET/resources/config.xml +8 -1
  73. arelle/plugin/validate/EDINET/resources/cover-item-requirements.json +793 -0
  74. arelle/plugin/validate/EDINET/resources/dei-requirements.csv +27 -0
  75. arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml +2 -0
  76. arelle/plugin/validate/EDINET/rules/contexts.py +375 -14
  77. arelle/plugin/validate/EDINET/rules/edinet.py +1934 -45
  78. arelle/plugin/validate/EDINET/rules/frta.py +122 -3
  79. arelle/plugin/validate/EDINET/rules/gfm.py +1907 -11
  80. arelle/plugin/validate/EDINET/rules/upload.py +989 -141
  81. arelle/plugin/validate/ESEF/Const.py +3 -1
  82. arelle/plugin/validate/ESEF/ESEF_2021/DTS.py +5 -0
  83. arelle/plugin/validate/ESEF/ESEF_2021/Image.py +2 -2
  84. arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +23 -20
  85. arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +47 -14
  86. arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +100 -25
  87. arelle/plugin/validate/ESEF/__init__.py +20 -6
  88. arelle/plugin/validate/ESEF/resources/authority-validations.json +76 -9
  89. arelle/plugin/validate/ESEF/resources/config.xml +20 -0
  90. arelle/plugin/validate/NL/DisclosureSystems.py +22 -0
  91. arelle/plugin/validate/NL/PluginValidationDataExtension.py +27 -9
  92. arelle/plugin/validate/NL/ValidationPluginExtension.py +51 -7
  93. arelle/plugin/validate/NL/resources/config.xml +18 -0
  94. arelle/plugin/validate/NL/rules/br_kvk.py +17 -61
  95. arelle/plugin/validate/NL/rules/fg_nl.py +7 -38
  96. arelle/plugin/validate/NL/rules/fr_kvk.py +7 -42
  97. arelle/plugin/validate/NL/rules/fr_nl.py +31 -147
  98. arelle/plugin/validate/NL/rules/nl_kvk.py +142 -28
  99. arelle/plugin/validate/ROS/PluginValidationDataExtension.py +2 -0
  100. arelle/plugin/validate/ROS/ValidationPluginExtension.py +4 -1
  101. arelle/plugin/validate/ROS/rules/ros.py +41 -9
  102. arelle/plugin/validate/UK/ValidateUK.py +130 -66
  103. arelle/plugin/validate/UK/__init__.py +89 -103
  104. arelle/utils/EntryPointDetection.py +79 -13
  105. arelle/utils/PluginHooks.py +125 -0
  106. arelle/utils/validate/ESEFImage.py +6 -6
  107. arelle/utils/validate/Validation.py +18 -0
  108. arelle/utils/validate/ValidationPlugin.py +76 -11
  109. arelle/utils/validate/ValidationUtil.py +35 -3
  110. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/METADATA +30 -20
  111. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/RECORD +115 -191
  112. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/licenses/LICENSE.md +0 -3
  113. arelle/archive/CustomLogger.py +0 -43
  114. arelle/archive/LoadEFMvalidate.py +0 -32
  115. arelle/archive/LoadSavePreLbCsv.py +0 -26
  116. arelle/archive/LoadValidate.cs +0 -31
  117. arelle/archive/LoadValidate.py +0 -36
  118. arelle/archive/LoadValidateCmdLine.java +0 -69
  119. arelle/archive/LoadValidatePostedZip.java +0 -57
  120. arelle/archive/LoadValidateWebService.java +0 -34
  121. arelle/archive/SaveTableToExelle.py +0 -140
  122. arelle/archive/TR3toTR4.py +0 -88
  123. arelle/archive/plugin/ESEF_2022/__init__.py +0 -47
  124. arelle/archive/plugin/bigInstance.py +0 -394
  125. arelle/archive/plugin/cmdWebServerExtension.py +0 -43
  126. arelle/archive/plugin/crashTest.py +0 -38
  127. arelle/archive/plugin/functionsXmlCreation.py +0 -106
  128. arelle/archive/plugin/hello_i18n.pot +0 -26
  129. arelle/archive/plugin/hello_i18n.py +0 -32
  130. arelle/archive/plugin/importTestChild1.py +0 -21
  131. arelle/archive/plugin/importTestChild2.py +0 -22
  132. arelle/archive/plugin/importTestGrandchild1.py +0 -21
  133. arelle/archive/plugin/importTestGrandchild2.py +0 -21
  134. arelle/archive/plugin/importTestImported1.py +0 -23
  135. arelle/archive/plugin/importTestImported11.py +0 -22
  136. arelle/archive/plugin/importTestParent.py +0 -48
  137. arelle/archive/plugin/instanceInfo.py +0 -306
  138. arelle/archive/plugin/loadFromOIM-2018.py +0 -1282
  139. arelle/archive/plugin/locale/fr/LC_MESSAGES/hello_i18n.po +0 -25
  140. arelle/archive/plugin/objectmaker.py +0 -285
  141. arelle/archive/plugin/packagedImportTest/__init__.py +0 -47
  142. arelle/archive/plugin/packagedImportTest/importTestChild1.py +0 -21
  143. arelle/archive/plugin/packagedImportTest/importTestChild2.py +0 -22
  144. arelle/archive/plugin/packagedImportTest/importTestGrandchild1.py +0 -21
  145. arelle/archive/plugin/packagedImportTest/importTestGrandchild2.py +0 -21
  146. arelle/archive/plugin/packagedImportTest/importTestImported1.py +0 -24
  147. arelle/archive/plugin/packagedImportTest/importTestImported11.py +0 -21
  148. arelle/archive/plugin/packagedImportTest/subdir/importTestImported111.py +0 -21
  149. arelle/archive/plugin/packagedImportTest/subdir/subsubdir/importTestImported1111.py +0 -21
  150. arelle/archive/plugin/sakaCalendar.py +0 -215
  151. arelle/archive/plugin/saveInstanceInfoset.py +0 -121
  152. arelle/archive/plugin/sphinx/FormulaGenerator.py +0 -823
  153. arelle/archive/plugin/sphinx/SphinxContext.py +0 -404
  154. arelle/archive/plugin/sphinx/SphinxEvaluator.py +0 -783
  155. arelle/archive/plugin/sphinx/SphinxMethods.py +0 -1287
  156. arelle/archive/plugin/sphinx/SphinxParser.py +0 -1093
  157. arelle/archive/plugin/sphinx/SphinxValidator.py +0 -163
  158. arelle/archive/plugin/sphinx/US-GAAP Ratios Example.xsr +0 -52
  159. arelle/archive/plugin/sphinx/__init__.py +0 -285
  160. arelle/archive/plugin/streamingExtensions.py +0 -335
  161. arelle/archive/plugin/updateTableLB.py +0 -242
  162. arelle/archive/plugin/validate/SBRnl/CustomLoader.py +0 -19
  163. arelle/archive/plugin/validate/SBRnl/DTS.py +0 -305
  164. arelle/archive/plugin/validate/SBRnl/Dimensions.py +0 -357
  165. arelle/archive/plugin/validate/SBRnl/Document.py +0 -799
  166. arelle/archive/plugin/validate/SBRnl/Filing.py +0 -467
  167. arelle/archive/plugin/validate/SBRnl/__init__.py +0 -75
  168. arelle/archive/plugin/validate/SBRnl/config.xml +0 -26
  169. arelle/archive/plugin/validate/SBRnl/sbr-nl-taxonomies.xml +0 -754
  170. arelle/archive/plugin/validate/USBestPractices.py +0 -570
  171. arelle/archive/plugin/validate/USCorpAction.py +0 -557
  172. arelle/archive/plugin/validate/USSecTagging.py +0 -337
  173. arelle/archive/plugin/validate/XDC/__init__.py +0 -77
  174. arelle/archive/plugin/validate/XDC/config.xml +0 -20
  175. arelle/archive/plugin/validate/XFsyntax/__init__.py +0 -64
  176. arelle/archive/plugin/validate/XFsyntax/xf.py +0 -2227
  177. arelle/archive/plugin/validate/calc2.py +0 -536
  178. arelle/archive/plugin/validateSchemaLxml.py +0 -156
  179. arelle/archive/plugin/validateTableInfoset.py +0 -52
  180. arelle/archive/us-gaap-dei-docType-extraction-frm.xml +0 -90
  181. arelle/archive/us-gaap-dei-ratio-cash-frm.xml +0 -150
  182. arelle/examples/plugin/formulaSuiteConverter.py +0 -212
  183. arelle/examples/plugin/functionsCustom.py +0 -59
  184. arelle/examples/plugin/hello_dolly.py +0 -64
  185. arelle/examples/plugin/multi.py +0 -58
  186. arelle/examples/plugin/rssSaveOim.py +0 -96
  187. arelle/examples/plugin/validate/XYZ/DisclosureSystems.py +0 -2
  188. arelle/examples/plugin/validate/XYZ/PluginValidationDataExtension.py +0 -10
  189. arelle/examples/plugin/validate/XYZ/ValidationPluginExtension.py +0 -49
  190. arelle/examples/plugin/validate/XYZ/__init__.py +0 -75
  191. arelle/examples/plugin/validate/XYZ/resources/config.xml +0 -16
  192. arelle/examples/plugin/validate/XYZ/rules/__init__.py +0 -0
  193. arelle/examples/plugin/validate/XYZ/rules/rules01.py +0 -110
  194. arelle/examples/plugin/validate/XYZ/rules/rules02.py +0 -59
  195. arelle/model/CommentBase.py +0 -9
  196. arelle/model/ElementBase.py +0 -11
  197. arelle/model/PIBase.py +0 -10
  198. arelle/model/__init__.py +0 -15
  199. arelle/scripts-macOS/startWebServer.command +0 -3
  200. arelle/scripts-unix/startWebServer.sh +0 -1
  201. arelle/scripts-windows/startWebServer.bat +0 -5
  202. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/WHEEL +0 -0
  203. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/entry_points.txt +0 -0
  204. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/top_level.txt +0 -0
@@ -3,15 +3,19 @@ See COPYRIGHT.md for copyright information.
3
3
  """
4
4
  from __future__ import annotations
5
5
 
6
+ import contextlib
6
7
  from collections import defaultdict
7
8
  from datetime import timedelta
8
9
  from typing import Any, cast, Iterable
9
10
 
10
11
  import regex
11
12
 
12
- from arelle import XbrlConst, XmlUtil
13
- from arelle.ModelInstanceObject import ModelFact
14
- from arelle.ModelObject import ModelObject
13
+ from arelle import ModelDocument, UrlUtil, XbrlConst, XmlUtil
14
+ from arelle.HtmlUtil import attrValue
15
+ from arelle.LinkbaseType import LinkbaseType
16
+ from arelle.ModelDtsObject import ModelConcept, ModelResource
17
+ from arelle.ModelInstanceObject import ModelFact, ModelInlineFootnote
18
+ from arelle.ModelObject import ModelObject, ModelComment
15
19
  from arelle.ModelValue import QName
16
20
  from arelle.PrototypeDtsObject import LocPrototype, ArcPrototype
17
21
  from arelle.UrlUtil import isHttpUrl, splitDecodeFragment
@@ -25,12 +29,15 @@ from arelle.utils.PluginHooks import ValidationHook
25
29
  from arelle.utils.Units import getDuplicateUnitGroups
26
30
  from arelle.utils.validate.Decorator import validation
27
31
  from arelle.utils.validate.Validation import Validation
28
- from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
32
+ from ..Constants import JAPAN_LANGUAGE_CODES, NUMERIC_LABEL_ROLES, domainItemTypeQname, LC3_NAME_PATTERN, HALF_KANA
29
33
  from ..DisclosureSystems import (DISCLOSURE_SYSTEM_EDINET)
30
34
  from ..PluginValidationDataExtension import PluginValidationDataExtension
31
35
 
36
+
32
37
  _: TypeGetText
33
38
 
39
+ DISALLOWED_LABEL_WHITE_SPACE_CHARACTERS = regex.compile(r'\s{2,}')
40
+ XBRLI_IDENTIFIER_PATTERN = regex.compile(r"^[A-Z]\d{5}-\d{3}$")
34
41
  GFM_CONTEXT_DATE_PATTERN = regex.compile(r"^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$")
35
42
  GFM_RECOMMENDED_NAMESPACE_PREFIXES = {
36
43
  XbrlConst.xbrli: ("xbrli",),
@@ -80,9 +87,14 @@ def rule_gfm_1_1_3(
80
87
  for elt in rootElt.iterdescendants(XbrlConst.qnLinkLinkbase.clarkNotation):
81
88
  uri = elt.attrib.get(XbrlConst.qnXsiSchemaLocation.clarkNotation)
82
89
  values.append((modelDocument, elt, uri))
90
+ for elt in rootElt.iterdescendants(XbrlConst.qnLinkLinkbaseRef.clarkNotation):
91
+ uri = elt.attrib.get(XbrlConst.qnXlinkHref.clarkNotation)
92
+ values.append((modelDocument, elt, uri))
83
93
  for modelDocument, elt, uri in values:
84
94
  if uri is None:
85
95
  continue
96
+ if uri in val.modelXbrl.urlUnloadableDocs:
97
+ continue # Already blocked, error fired.
86
98
  if not isHttpUrl(uri):
87
99
  if '/' not in uri:
88
100
  continue # Valid relative path
@@ -106,6 +118,33 @@ def rule_gfm_1_1_3(
106
118
  )
107
119
 
108
120
 
121
+ @validation(
122
+ hook=ValidationHook.XBRL_FINALLY,
123
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
124
+ )
125
+ def rule_gfm_1_1_6(
126
+ pluginData: PluginValidationDataExtension,
127
+ val: ValidateXbrl,
128
+ *args: Any,
129
+ **kwargs: Any,
130
+ ) -> Iterable[Validation]:
131
+ """
132
+ EDINET.EC5700W: [GFM 1.1.6] Filing must have one or more submitter specific(extension) taxonomies
133
+ """
134
+ if not hasattr(val, 'hasExtensionSchema'):
135
+ val.hasExtensionSchema = False
136
+ for modelDocument in val.modelXbrl.urlDocs.values():
137
+ if pluginData.isExtensionUri(modelDocument.uri, val.modelXbrl) and modelDocument.type == ModelDocument.Type.SCHEMA:
138
+ val.hasExtensionSchema = True
139
+ break
140
+ if not val.hasExtensionSchema:
141
+ yield Validation.warning(
142
+ codes='EDINET.EC5700W.GFM.1.1.6',
143
+ msg=_("Filing is missing an extension taxonomy."),
144
+ modelObject=val.modelXbrl,
145
+ )
146
+
147
+
109
148
  @validation(
110
149
  hook=ValidationHook.XBRL_FINALLY,
111
150
  disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
@@ -124,7 +163,7 @@ def rule_gfm_1_1_7(
124
163
  """
125
164
  baseElements = []
126
165
  for rootElt in val.modelXbrl.ixdsHtmlElements:
127
- for uncast_elt, depth in etreeIterWithDepth(rootElt):
166
+ for uncast_elt in rootElt.iter():
128
167
  elt = cast(Any, uncast_elt)
129
168
  if elt.get(xmlBaseIdentifier) is not None:
130
169
  baseElements.append(elt)
@@ -138,6 +177,54 @@ def rule_gfm_1_1_7(
138
177
  )
139
178
 
140
179
 
180
+ @validation(
181
+ hook=ValidationHook.XBRL_FINALLY,
182
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
183
+ )
184
+ def rule_gfm_1_2_1(
185
+ pluginData: PluginValidationDataExtension,
186
+ val: ValidateXbrl,
187
+ *args: Any,
188
+ **kwargs: Any,
189
+ ) -> Iterable[Validation]:
190
+ """
191
+ EDINET.EC5700W: [GFM 1.2.1] The scheme of the entity identifier must be http://disclosure.edinet-fsa.go.jp
192
+ """
193
+ entityIdentifierValues = val.modelXbrl.entityIdentifiersInDocument()
194
+ for entityId in entityIdentifierValues:
195
+ if entityId[0] != 'http://disclosure.edinet-fsa.go.jp':
196
+ yield Validation.warning(
197
+ codes='EDINET.EC5700W.GFM.1.2.1',
198
+ msg=_("The scheme of the entity identifier is: '%(scheme)s' but it must be 'http://disclosure.edinet-fsa.go.jp'."),
199
+ scheme=entityId[0],
200
+ modelObject=entityId,
201
+ )
202
+
203
+
204
+ @validation(
205
+ hook=ValidationHook.XBRL_FINALLY,
206
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
207
+ )
208
+ def rule_gfm_1_2_2(
209
+ pluginData: PluginValidationDataExtension,
210
+ val: ValidateXbrl,
211
+ *args: Any,
212
+ **kwargs: Any,
213
+ ) -> Iterable[Validation]:
214
+ """
215
+ EDINET.EC5700W: [GFM 1.2.2] The entity identifier element must match the following: X00000-000
216
+ """
217
+ entityIdentifierValues = val.modelXbrl.entityIdentifiersInDocument()
218
+ for entityId in entityIdentifierValues:
219
+ if not XBRLI_IDENTIFIER_PATTERN.match(entityId[1]):
220
+ yield Validation.warning(
221
+ codes='EDINET.EC5700W.GFM.1.2.2',
222
+ msg=_("The entity identifier element: '%(element)s' is incorrect. It must take the form of 'X00000-000'."),
223
+ element=entityId[1],
224
+ modelObject=entityId,
225
+ )
226
+
227
+
141
228
  @validation(
142
229
  hook=ValidationHook.XBRL_FINALLY,
143
230
  disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
@@ -254,13 +341,14 @@ def rule_gfm_1_2_8(
254
341
  EDINET.EC5700W: [GFM 1.2.8] Every xbrli:context element must appear in at least one
255
342
  contextRef attribute in the same instance.
256
343
  """
257
- unused_contexts = list(set(val.modelXbrl.contexts.values()) - set(val.modelXbrl.contextsInUse))
258
- unused_contexts.sort(key=lambda x: x.id)
259
- for context in unused_contexts:
344
+ unusedContexts = list(set(val.modelXbrl.contexts.values()) - set(val.modelXbrl.contextsInUse))
345
+ unusedContexts.extend(val.modelXbrl.ixdsUnmappedContexts.values())
346
+ unusedContexts.sort(key=lambda x: x.id if x.id is not None else "")
347
+ for context in unusedContexts:
260
348
  yield Validation.warning(
261
349
  codes='EDINET.EC5700W.GFM.1.2.8',
262
350
  msg=_('If you are not using a context, delete it if it is not needed.'),
263
- modelObject = context
351
+ modelObject=context
264
352
  )
265
353
 
266
354
 
@@ -349,6 +437,31 @@ def rule_gfm_1_2_13(
349
437
  )
350
438
 
351
439
 
440
+ @validation(
441
+ hook=ValidationHook.XBRL_FINALLY,
442
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
443
+ )
444
+ def rule_gfm_1_2_14(
445
+ pluginData: PluginValidationDataExtension,
446
+ val: ValidateXbrl,
447
+ *args: Any,
448
+ **kwargs: Any,
449
+ ) -> Iterable[Validation]:
450
+ """
451
+ EDINET.EC5700W: [GFM.1.2.14] The content of an element with a data type of nonnum:textBlockItemType is not well-formed XML
452
+ (a format that conforms to XML grammar, such as all start and end tags being paired, and the end tag of a nested tag not coming after the end tag of its parent tag, etc.).
453
+ Please modify it so that it is well-formed.
454
+ """
455
+ problematicFacts = pluginData.getProblematicTextBlocks(val.modelXbrl)
456
+ if len(problematicFacts) > 0:
457
+ yield Validation.warning(
458
+ codes='EDINET.EC5700W.GFM.1.2.14',
459
+ msg=_('The content of an element with a data type of nonnum:textBlockItemType is not well-formed XML (a format that conforms to XML grammar, '
460
+ 'such as all start and end tags being in pairs, and the end tag of a nested tag not coming after the end tag of its parent tag). '
461
+ 'Correct the content so that it is well-formed.'),
462
+ modelObject = problematicFacts
463
+ )
464
+
352
465
 
353
466
  @validation(
354
467
  hook=ValidationHook.XBRL_FINALLY,
@@ -517,12 +630,14 @@ def rule_gfm_1_2_27(
517
630
  EDINET.EC5700W: [GFM 1.2.27] An instance must not contain unused units.
518
631
  """
519
632
  # TODO: Consolidate validations involving unused units
520
- unusedUnits = set(val.modelXbrl.units.values()) - {fact.unit for fact in val.modelXbrl.facts if fact.unit is not None}
633
+ unusedUnits = list(set(val.modelXbrl.units.values()) - set(val.modelXbrl.unitsInUse))
634
+ unusedUnits.extend(val.modelXbrl.ixdsUnmappedUnits.values())
635
+ unusedUnits.sort(key=lambda x: x.hash)
521
636
  if len(unusedUnits) > 0:
522
637
  yield Validation.warning(
523
638
  codes='EDINET.EC5700W.GFM.1.2.27',
524
639
  msg=_("Delete unused units from the instance."),
525
- modelObject=list(unusedUnits)
640
+ modelObject=unusedUnits
526
641
  )
527
642
 
528
643
 
@@ -583,3 +698,1784 @@ def rule_gfm_1_2_30(
583
698
  msg=_("A context must not contain the xbrli:forever element."),
584
699
  modelObject=errors
585
700
  )
701
+
702
+
703
+ @validation(
704
+ hook=ValidationHook.XBRL_FINALLY,
705
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
706
+ )
707
+ def rule_gfm_1_3_1(
708
+ pluginData: PluginValidationDataExtension,
709
+ val: ValidateXbrl,
710
+ *args: Any,
711
+ **kwargs: Any,
712
+ ) -> Iterable[Validation]:
713
+ """
714
+ EDINET.EC5700W: [GFM 1.3.1] The submitter-specific taxonomy contains include elements.
715
+ """
716
+ warnings = []
717
+ for modelDocument in val.modelXbrl.urlDocs.values():
718
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
719
+ continue
720
+ rootElt = modelDocument.xmlRootElement
721
+ for elt in rootElt.iterdescendants(XbrlConst.qnXsdInclude.clarkNotation):
722
+ warnings.append(elt)
723
+ if len(warnings) > 0:
724
+ yield Validation.warning(
725
+ codes='EDINET.EC5700W.GFM.1.3.1',
726
+ msg=_("The submitter-specific taxonomy contains include elements."),
727
+ modelObject=warnings
728
+ )
729
+
730
+
731
+ @validation(
732
+ hook=ValidationHook.XBRL_FINALLY,
733
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
734
+ )
735
+ def rule_gfm_1_3_2(
736
+ pluginData: PluginValidationDataExtension,
737
+ val: ValidateXbrl,
738
+ *args: Any,
739
+ **kwargs: Any,
740
+ ) -> Iterable[Validation]:
741
+ """
742
+ EDINET.EC5700W: [GFM 1.3.2] The schemaLocation attribute of the xsd:import element specifying the EDINET taxonomy does not point to a valid location.
743
+
744
+ GFM-1.3.2: If an xsd:import element has a namespace attribute equal to a standard taxonomy
745
+ schema, then its schemaLocation attribute must be the standard taxonomy assigned
746
+ to that namespace.
747
+ """
748
+ for document in val.modelXbrl.urlDocs.values():
749
+ if not pluginData.isExtensionUri(document.uri, val.modelXbrl) or not document.type == ModelDocument.Type.SCHEMA:
750
+ continue
751
+ for refDoc in document.referencesDocument.values():
752
+ if 'import' not in refDoc.referenceTypes:
753
+ continue
754
+ namespace = refDoc.referringModelObject.attrib.get('namespace')
755
+ schemaLocation = refDoc.referringModelObject.attrib.get('schemaLocation')
756
+ if not namespace or not schemaLocation:
757
+ continue
758
+ expectedXSDLocationSet = val.disclosureSystem.standardTaxonomiesDict.get(namespace)
759
+ if expectedXSDLocationSet is not None and schemaLocation not in expectedXSDLocationSet:
760
+ yield Validation.warning(
761
+ codes='EDINET.EC5700W.GFM.1.3.2',
762
+ msg=_("The schemaLocation attribute of the xsd:import element specifying the EDINET taxonomy does not point to a valid location. "
763
+ "The schemaLocation attribute value '%(schemaLocation)s'."),
764
+ schemaLocation = schemaLocation,
765
+ modelObject = refDoc.referringModelObject
766
+ )
767
+
768
+
769
+ @validation(
770
+ hook=ValidationHook.XBRL_FINALLY,
771
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
772
+ )
773
+ def rule_gfm_1_3_8(
774
+ pluginData: PluginValidationDataExtension,
775
+ val: ValidateXbrl,
776
+ *args: Any,
777
+ **kwargs: Any,
778
+ ) -> Iterable[Validation]:
779
+ """
780
+ EDINET.EC5700W: [GFM 1.3.8] TThe submitter-specific taxonomy has an embedded linkbase.
781
+ """
782
+ embeddedElements = []
783
+ for modelDocument in val.modelXbrl.urlDocs.values():
784
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
785
+ continue
786
+ rootElt = modelDocument.xmlRootElement
787
+ for elt in rootElt.iterdescendants(XbrlConst.qnLinkLinkbaseRef.clarkNotation):
788
+ if elt.attrib.get(XbrlConst.qnXlinkType.clarkNotation) in ('extended', 'arc', 'resource', 'locator'):
789
+ embeddedElements.append(elt)
790
+ if len(embeddedElements) > 0:
791
+ yield Validation.warning(
792
+ codes='EDINET.EC5700W.GFM.1.3.8',
793
+ msg=_("The submitter-specific taxonomy has an embedded linkbase."),
794
+ modelObject=embeddedElements
795
+ )
796
+
797
+
798
+ @validation(
799
+ hook=ValidationHook.XBRL_FINALLY,
800
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
801
+ )
802
+ def rule_gfm_1_3_10(
803
+ pluginData: PluginValidationDataExtension,
804
+ val: ValidateXbrl,
805
+ *args: Any,
806
+ **kwargs: Any,
807
+ ) -> Iterable[Validation]:
808
+ """
809
+ EDINET.EC5700W: [GFM 1.3.10] Remove the duplicate link:roleType element.
810
+ """
811
+ for modelRoleTypes in val.modelXbrl.roleTypes.values():
812
+ if modelRoleTypes and len(modelRoleTypes) > 1:
813
+ yield Validation.warning(
814
+ codes='EDINET.EC5700W.GFM.1.3.10',
815
+ msg=_("Remove the duplicate link:roleType element. Duplicate roleURI: %(roleURI)s"),
816
+ roleURI=modelRoleTypes[0].roleURI,
817
+ modelObject=modelRoleTypes
818
+ )
819
+
820
+
821
+ @validation(
822
+ hook=ValidationHook.XBRL_FINALLY,
823
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
824
+ )
825
+ def rule_gfm_1_3_11(
826
+ pluginData: PluginValidationDataExtension,
827
+ val: ValidateXbrl,
828
+ *args: Any,
829
+ **kwargs: Any,
830
+ ) -> Iterable[Validation]:
831
+ """
832
+ EDINET.EC5700W: [GFM 1.3.11] The usedOn attribute of the extended link role should be set to include all of link:presentationLink, link:calculationLink, and link:definitionLink.
833
+ """
834
+ requiredUsedOns = {XbrlConst.qnLinkPresentationLink,
835
+ XbrlConst.qnLinkCalculationLink,
836
+ XbrlConst.qnLinkDefinitionLink}
837
+ for modelRoleTypes in val.modelXbrl.roleTypes.values():
838
+ if len(modelRoleTypes) > 0:
839
+ modelRoleType = modelRoleTypes[0]
840
+ usedOns = modelRoleType.usedOns
841
+ if not usedOns.isdisjoint(requiredUsedOns) and len(requiredUsedOns - usedOns) > 0:
842
+ yield Validation.warning(
843
+ codes='EDINET.EC5700W.GFM.1.3.11',
844
+ msg=_("The usedOn attribute of the extended link role should be set to include all of link:presentationLink, link:calculationLink, and link:definitionLink. "
845
+ "Extended link role roleURI: %(roleURI)s is missing %(usedOn)s."),
846
+ roleURI=modelRoleType.roleURI,
847
+ modelObject=modelRoleType
848
+ )
849
+
850
+
851
+ @validation(
852
+ hook=ValidationHook.XBRL_FINALLY,
853
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
854
+ )
855
+ def rule_gfm_1_3_13(
856
+ pluginData: PluginValidationDataExtension,
857
+ val: ValidateXbrl,
858
+ *args: Any,
859
+ **kwargs: Any,
860
+ ) -> Iterable[Validation]:
861
+ """
862
+ EDINET.EC5700W: [GFM 1.3.13] Remove any leading or trailing XML whitespace and newline
863
+ characters from the "link:definition" of your extended link role.
864
+ """
865
+ for modelRoleTypes in val.modelXbrl.roleTypes.values():
866
+ if len(modelRoleTypes) > 0:
867
+ modelRoleType = modelRoleTypes[0]
868
+ if (
869
+ modelRoleType.definition and modelRoleType.definitionNotStripped
870
+ and modelRoleType.definition != modelRoleType.definitionNotStripped
871
+ ):
872
+ yield Validation.warning(
873
+ codes='EDINET.EC5700W.GFM.1.3.13',
874
+ msg=_("Remove any leading or trailing XML whitespace and newline characters from "
875
+ "the `link:definition` of your extended link role. Definition: %(definition)s"),
876
+ definition=modelRoleTypes[0].definitionNotStripped,
877
+ modelObject=modelRoleTypes[0]
878
+ )
879
+
880
+
881
+ @validation(
882
+ hook=ValidationHook.XBRL_FINALLY,
883
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
884
+ )
885
+ def rule_gfm_1_3_16(
886
+ pluginData: PluginValidationDataExtension,
887
+ val: ValidateXbrl,
888
+ *args: Any,
889
+ **kwargs: Any,
890
+ ) -> Iterable[Validation]:
891
+ """
892
+ EDINET.EC5700W: [GFM 1.3.16] Remove the duplicate link:arcroleType element.
893
+ """
894
+ for modelArcRoleTypes in val.modelXbrl.arcroleTypes.values():
895
+ if len(modelArcRoleTypes) > 1:
896
+ yield Validation.warning(
897
+ codes='EDINET.EC5700W.GFM.1.3.16',
898
+ msg=_("Remove the duplicate link:arcroleType element. Duplicate arcroleURI: %(arcroleURI)s"),
899
+ arcroleURI=modelArcRoleTypes[0].arcroleURI,
900
+ modelObject=modelArcRoleTypes
901
+ )
902
+
903
+
904
+ @validation(
905
+ hook=ValidationHook.XBRL_FINALLY,
906
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
907
+ )
908
+ def rule_gfm_1_3_17(
909
+ pluginData: PluginValidationDataExtension,
910
+ val: ValidateXbrl,
911
+ *args: Any,
912
+ **kwargs: Any,
913
+ ) -> Iterable[Validation]:
914
+ """
915
+ EDINET.EC5700W: [GFM 1.3.17] Add a link:definition to the link:arcroleType element.
916
+ """
917
+ for modelArcRoleTypes in val.modelXbrl.arcroleTypes.values():
918
+ modelArcRoleType = modelArcRoleTypes[0]
919
+ if not modelArcRoleType.definition:
920
+ yield Validation.warning(
921
+ codes='EDINET.EC5700W.GFM.1.3.17',
922
+ msg=_("Add a link:definition to the link:arcroleType element. ArcroleURI: %(arcroleURI)s"),
923
+ arcroleURI=modelArcRoleType.arcroleURI,
924
+ modelObject=modelArcRoleType
925
+ )
926
+
927
+
928
+ @validation(
929
+ hook=ValidationHook.XBRL_FINALLY,
930
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
931
+ )
932
+ def rule_gfm_1_3_18(
933
+ pluginData: PluginValidationDataExtension,
934
+ val: ValidateXbrl,
935
+ *args: Any,
936
+ **kwargs: Any,
937
+ ) -> Iterable[Validation]:
938
+ """
939
+ EDINET.EC5700W: [GFM 1.3.18] The submitter's taxonomy contains an element whose name matches an element in the EDINET taxonomy.
940
+ Modify the element name so that it does not match the EDINET taxonomy, or use the element in the EDINET taxonomy and delete the
941
+ element added in the submitter's taxonomy.
942
+ """
943
+ for extensionConcept in pluginData.getExtensionConcepts(val.modelXbrl):
944
+ name = extensionConcept.get("name")
945
+ if name is not None:
946
+ concepts = val.modelXbrl.nameConcepts.get(name, [])
947
+ for concept in concepts:
948
+ if not pluginData.isExtensionUri(concept.document.uri, val.modelXbrl):
949
+ yield Validation.warning(
950
+ codes='EDINET.EC5700W.GFM.1.3.18',
951
+ msg=_("Your extension taxonomy contains an element, %(concept)s, which has the same name as an element "
952
+ "in the base taxonomy, %(standardConcept)s. Please ensure that this extension is appropriate and "
953
+ "if so, please change the extension concept."),
954
+ concept=name,
955
+ standardConcept=concept
956
+ )
957
+
958
+
959
+ @validation(
960
+ hook=ValidationHook.XBRL_FINALLY,
961
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
962
+ )
963
+ def rule_gfm_1_3_19(
964
+ pluginData: PluginValidationDataExtension,
965
+ val: ValidateXbrl,
966
+ *args: Any,
967
+ **kwargs: Any,
968
+ ) -> Iterable[Validation]:
969
+ """
970
+ EDINET.EC5700W: [GFM 1.3.19] The id attribute of the element defined in the submitter-specific taxonomy
971
+ should be set in the following format:{namespace prefix}_{element name}.
972
+ """
973
+ improperlyFormattedIds = set()
974
+ for concept in pluginData.getExtensionConcepts(val.modelXbrl):
975
+ prefix = concept.qname.prefix or ""
976
+ name = concept.qname.localName
977
+ requiredId = f"{prefix}_{name}"
978
+ if concept.id != requiredId or not prefix:
979
+ improperlyFormattedIds.add(concept)
980
+ if len(improperlyFormattedIds) > 0:
981
+ yield Validation.warning(
982
+ codes='EDINET.EC5700W.GFM.1.3.19',
983
+ msg=_("The id attribute of the element defined in the submitter-specific taxonomy should be set in the following format: {namespace prefix}_{element name}"),
984
+ modelObject=improperlyFormattedIds
985
+ )
986
+
987
+
988
+ @validation(
989
+ hook=ValidationHook.XBRL_FINALLY,
990
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
991
+ )
992
+ def rule_gfm_1_3_20(
993
+ pluginData: PluginValidationDataExtension,
994
+ val: ValidateXbrl,
995
+ *args: Any,
996
+ **kwargs: Any,
997
+ ) -> Iterable[Validation]:
998
+ """
999
+ EDINET.EC5700W: [GFM 1.3.20] Set the nillable attribute value to "true".
1000
+
1001
+ GFM 1.3.20 The nillable attribute value of an xsd:element must equal "true".
1002
+ """
1003
+ nonNillableElements = set()
1004
+ for concept in val.modelXbrl.qnameConcepts.values():
1005
+ if concept.namespaceURI == XbrlConst.xsd:
1006
+ if concept.get("nillable") == "false":
1007
+ nonNillableElements.add(concept)
1008
+ if len(nonNillableElements) > 0:
1009
+ yield Validation.warning(
1010
+ codes='EDINET.EC5700W.GFM.1.3.20',
1011
+ msg=_("Set the nillable attribute value to 'true'."),
1012
+ modelObject=nonNillableElements
1013
+ )
1014
+
1015
+
1016
+ @validation(
1017
+ hook=ValidationHook.XBRL_FINALLY,
1018
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1019
+ )
1020
+ def rule_gfm_1_3_21(
1021
+ pluginData: PluginValidationDataExtension,
1022
+ val: ValidateXbrl,
1023
+ *args: Any,
1024
+ **kwargs: Any,
1025
+ ) -> Iterable[Validation]:
1026
+ """
1027
+ EDINET.EC5700W: [GFM 1.3.21] Remove the tuple definition.
1028
+ """
1029
+ tupleConcepts = [
1030
+ concept for concept in pluginData.getExtensionConcepts(val.modelXbrl)
1031
+ if concept.isTuple
1032
+ ]
1033
+ if len(tupleConcepts) > 0:
1034
+ yield Validation.warning(
1035
+ codes='EDINET.EC5700W.GFM.1.3.21',
1036
+ msg=_("Remove the tuple definition."),
1037
+ modelObject=tupleConcepts
1038
+ )
1039
+
1040
+
1041
+ @validation(
1042
+ hook=ValidationHook.XBRL_FINALLY,
1043
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1044
+ )
1045
+ def rule_gfm_1_3_22(
1046
+ pluginData: PluginValidationDataExtension,
1047
+ val: ValidateXbrl,
1048
+ *args: Any,
1049
+ **kwargs: Any,
1050
+ ) -> Iterable[Validation]:
1051
+ """
1052
+ EDINET.EC5700W: [GFM 1.3.22] Do not set the xbrldt:typedDomainRef attribute on elements defined in submitter-specific taxonomies.
1053
+ """
1054
+ typedDomainConcepts = [
1055
+ concept for concept in pluginData.getExtensionConcepts(val.modelXbrl)
1056
+ if concept.isTypedDimension
1057
+ ]
1058
+
1059
+ if len(typedDomainConcepts) > 0:
1060
+ yield Validation.warning(
1061
+ codes='EDINET.EC5700W.GFM.1.3.22',
1062
+ msg=_("Do not set the xbrldt:typedDomainRef attribute on elements defined in submitter-specific taxonomies."),
1063
+ modelObject=typedDomainConcepts
1064
+ )
1065
+
1066
+
1067
+ @validation(
1068
+ hook=ValidationHook.XBRL_FINALLY,
1069
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1070
+ )
1071
+ def rule_gfm_1_3_23(
1072
+ pluginData: PluginValidationDataExtension,
1073
+ val: ValidateXbrl,
1074
+ *args: Any,
1075
+ **kwargs: Any,
1076
+ ) -> Iterable[Validation]:
1077
+ """
1078
+ EDINET.EC5700W: [GFM 1.3.23] Set the periodType attribute to "duration".
1079
+
1080
+ GFM 1.3.23 If the abstract attribute of xsd:element is "true", then the
1081
+ xbrli:periodType attribute must be "duration".
1082
+ """
1083
+ instantAbstractElements = set()
1084
+ for concept in val.modelXbrl.qnameConcepts.values():
1085
+ if concept.abstract == "true" and concept.periodType == "instant":
1086
+ instantAbstractElements.add(concept)
1087
+ if len(instantAbstractElements) > 0:
1088
+ yield Validation.warning(
1089
+ codes='EDINET.EC5700W.GFM.1.3.23',
1090
+ msg=_("Set the periodType attribute to 'duration'."),
1091
+ modelObject=instantAbstractElements
1092
+ )
1093
+
1094
+
1095
+ @validation(
1096
+ hook=ValidationHook.XBRL_FINALLY,
1097
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1098
+ )
1099
+ def rule_gfm_1_3_25(
1100
+ pluginData: PluginValidationDataExtension,
1101
+ val: ValidateXbrl,
1102
+ *args: Any,
1103
+ **kwargs: Any,
1104
+ ) -> Iterable[Validation]:
1105
+ """
1106
+ EDINET.EC5700W: [GFM 1.3.25] Correct the element name so that it does not end with "Axis", or correct the
1107
+ substitutionGroup to "xbrldt:dimensionItem".
1108
+
1109
+ GFM 1.3.25: The xsd:element substitutionGroup attribute must equal "xbrldt:dimensionItem" if
1110
+ and only if the name attribute ends with "Axis".
1111
+ """
1112
+ for concept in pluginData.getExtensionConcepts(val.modelXbrl):
1113
+ if concept.qname.localName.endswith("Axis") != (concept.substitutionGroupQname == XbrlConst.qnXbrldtDimensionItem):
1114
+ yield Validation.warning(
1115
+ codes='EDINET.EC5700W.GFM.1.3.25',
1116
+ msg=_("Modify the element name, '%(conceptName)s', so that it does not end with 'Axis', or modify the substitutionGroup to 'xbrldt:dimensionItem'."),
1117
+ conceptName=concept.qname.localName,
1118
+ modelObject=concept,
1119
+ )
1120
+
1121
+
1122
+ @validation(
1123
+ hook=ValidationHook.XBRL_FINALLY,
1124
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1125
+ )
1126
+ def rule_gfm_1_3_26(
1127
+ pluginData: PluginValidationDataExtension,
1128
+ val: ValidateXbrl,
1129
+ *args: Any,
1130
+ **kwargs: Any,
1131
+ ) -> Iterable[Validation]:
1132
+ """
1133
+ EDINET.EC5700W: [GFM 1.3.26] Correct the element name so that it does not end with "Table", or correct the
1134
+ substitutionGroup to "xbrldt:hypercubeItem".
1135
+
1136
+ GFM 1.3.26: The xsd:element name attribute must ends with "Table" if and only if
1137
+ substitutionGroup attribute equals "xbrldt:hypercubeItem".
1138
+ """
1139
+ for concept in pluginData.getExtensionConcepts(val.modelXbrl):
1140
+ if concept.qname.localName.endswith("Table") != (concept.substitutionGroupQname == XbrlConst.qnXbrldtHypercubeItem):
1141
+ yield Validation.warning(
1142
+ codes='EDINET.EC5700W.GFM.1.3.26',
1143
+ msg=_("The substitution group 'xbrldt:hypercubeItem' is only allowed with an element name that ends with 'Table'."
1144
+ "Please change %(conceptName)s or change the substitutionGroup."),
1145
+ conceptName=concept.qname.localName,
1146
+ modelObject=concept
1147
+ )
1148
+
1149
+
1150
+ @validation(
1151
+ hook=ValidationHook.XBRL_FINALLY,
1152
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1153
+ )
1154
+ def rule_gfm_1_3_28(
1155
+ pluginData: PluginValidationDataExtension,
1156
+ val: ValidateXbrl,
1157
+ *args: Any,
1158
+ **kwargs: Any,
1159
+ ) -> Iterable[Validation]:
1160
+ """
1161
+ EDINET.EC5700W: [GFM 1.3.28] If the element name of an element extended by a submitter-specific taxonomy ends with "LineItems",
1162
+ set the abstract attribute to "true".
1163
+ """
1164
+ for concept in pluginData.getExtensionConcepts(val.modelXbrl):
1165
+ if concept.qname.localName.endswith("LineItems") and not concept.isAbstract:
1166
+ yield Validation.warning(
1167
+ codes='EDINET.EC5700W.GFM.1.3.28',
1168
+ msg=_("If the element name of an element extended by a submitter-specific taxonomy ends with 'LineItems', "
1169
+ "set the abstract attribute to 'true'. For the element, '%(conceptName)s', the abstract attribute is 'false'."),
1170
+ conceptName=concept.qname.localName,
1171
+ modelObject=concept
1172
+ )
1173
+
1174
+
1175
+ @validation(
1176
+ hook=ValidationHook.XBRL_FINALLY,
1177
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1178
+ )
1179
+ def rule_gfm_1_3_29(
1180
+ pluginData: PluginValidationDataExtension,
1181
+ val: ValidateXbrl,
1182
+ *args: Any,
1183
+ **kwargs: Any,
1184
+ ) -> Iterable[Validation]:
1185
+ """
1186
+ EDINET.EC5700W: [GFM 1.3.29] If the element name of an element extended by the submitter-specific taxonomy ends with
1187
+ "Domain" or "Member", please set the type attribute to "nonnum:domainItemType".
1188
+
1189
+ GFM 1.3.29: The xsd:element name attribute must end with "Domain" or "Member" if and only
1190
+ if the type attribute equals "nonnum:domainItemType".
1191
+ """
1192
+ for concept in pluginData.getExtensionConcepts(val.modelXbrl):
1193
+ isConceptDomain = concept.type.isDomainItemType if concept.type is not None else False
1194
+ if ((concept.qname.localName.endswith("Domain") or concept.qname.localName.endswith("Member")) != isConceptDomain):
1195
+ yield Validation.warning(
1196
+ codes='EDINET.EC5700W.GFM.1.3.29',
1197
+ msg=_("The type 'us-types:domainItemType' is only allowed with an element name that ends with 'Domain' or 'Member'. "
1198
+ "Please change %(conceptName)s or change the type."),
1199
+ conceptName=concept.qname.localName,
1200
+ modelObject=concept
1201
+ )
1202
+
1203
+
1204
+ @validation(
1205
+ hook=ValidationHook.XBRL_FINALLY,
1206
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1207
+ )
1208
+ def rule_gfm_1_3_30(
1209
+ pluginData: PluginValidationDataExtension,
1210
+ val: ValidateXbrl,
1211
+ *args: Any,
1212
+ **kwargs: Any,
1213
+ ) -> Iterable[Validation]:
1214
+ """
1215
+ EDINET.EC5700W: [GFM 1.3.30] Set the periodType attribute to "duration".
1216
+
1217
+ GFM 1.3.30 If xsd:element type attribute equals "nonnum:domainItemType" then
1218
+ the xbrli:periodType attribute must equal "duration".
1219
+ """
1220
+ instantDomainElements = set()
1221
+ for concept in val.modelXbrl.qnameConcepts.values():
1222
+ if concept.type is not None and concept.type.isDomainItemType and concept.periodType == "instant":
1223
+ instantDomainElements.add(concept)
1224
+ if len(instantDomainElements) > 0:
1225
+ yield Validation.warning(
1226
+ codes='EDINET.EC5700W.GFM.1.3.30',
1227
+ msg=_("Set the periodType attribute to 'duration'."),
1228
+ modelObject=instantDomainElements
1229
+ )
1230
+
1231
+ @validation(
1232
+ hook=ValidationHook.XBRL_FINALLY,
1233
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1234
+ )
1235
+ def rule_gfm_1_3_31(
1236
+ pluginData: PluginValidationDataExtension,
1237
+ val: ValidateXbrl,
1238
+ *args: Any,
1239
+ **kwargs: Any,
1240
+ ) -> Iterable[Validation]:
1241
+ """
1242
+ EDINET.EC5700W: [GFM 1.3.31] Set the abstract attribute to "true".
1243
+
1244
+ GFM 1.3.31: If xsd:element type attribute equals "nonnum:domainItemType" then
1245
+ the abstract attribute must equal to "true".
1246
+ """
1247
+ nonAbstractDomainElements = set()
1248
+ for concept in val.modelXbrl.qnameConcepts.values():
1249
+ if concept.type is not None and concept.type.isDomainItemType and concept.abstract != "true":
1250
+ nonAbstractDomainElements.add(concept)
1251
+ if len(nonAbstractDomainElements) > 0:
1252
+ yield Validation.warning(
1253
+ codes='EDINET.EC5700W.GFM.1.3.31',
1254
+ msg=_("Set the abstract attribute to 'true'."),
1255
+ modelObject=nonAbstractDomainElements
1256
+ )
1257
+
1258
+
1259
+ @validation(
1260
+ hook=ValidationHook.XBRL_FINALLY,
1261
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1262
+ )
1263
+ def rule_gfm_1_4_4(
1264
+ pluginData: PluginValidationDataExtension,
1265
+ val: ValidateXbrl,
1266
+ *args: Any,
1267
+ **kwargs: Any,
1268
+ ) -> Iterable[Validation]:
1269
+ """
1270
+ EDINET.EC5700W: [GFM 1.4.4] If the type attribute is "extended" or "resource", set the xlink:role attribute to the extended link role.
1271
+
1272
+ GFM 1.4.4: The xlink:role attribute of an element with a type="extended" attribute or a
1273
+ type="resource" attribute must be present and must not be empty.
1274
+ """
1275
+ for modelDocument in val.modelXbrl.urlDocs.values():
1276
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
1277
+ continue
1278
+ rootElt = modelDocument.xmlRootElement
1279
+ ns = {'xlink': 'http://www.w3.org/1999/xlink'}
1280
+ for elt in rootElt.xpath('//*[@xlink:type="extended" or @xlink:type="resource"]', namespaces=ns):
1281
+ xlinkRole = elt.get(XbrlConst.qnXlinkRole.clarkNotation)
1282
+ if not xlinkRole:
1283
+ yield Validation.warning(
1284
+ codes='EDINET.EC5700W.GFM.1.4.4',
1285
+ msg=_("If the type attribute is 'extended' or 'resource', set the xlink:role attribute to the extended link role."
1286
+ "%(element)s is missing an xlink:role"),
1287
+ modelObject=elt, element=elt.qname
1288
+ )
1289
+
1290
+
1291
+ @validation(
1292
+ hook=ValidationHook.XBRL_FINALLY,
1293
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1294
+ )
1295
+ def rule_gfm_1_4_6(
1296
+ pluginData: PluginValidationDataExtension,
1297
+ val: ValidateXbrl,
1298
+ *args: Any,
1299
+ **kwargs: Any,
1300
+ ) -> Iterable[Validation]:
1301
+ """
1302
+ EDINET.EC5700W: [GFM 1.4.6] Please correct the value of the link:arcroleRef attribute to
1303
+ one specified in the XBRL 2.1 specification or the EDINET taxonomy.
1304
+ GFM 1.4.6: The text preceding a sharp sign "#" in an xlink:href attribute of link:arcroleRef must
1305
+ be a standard taxonomy or in a file recognised in the disclosure system.
1306
+ """
1307
+
1308
+ for modelDocument in val.modelXbrl.urlDocs.values():
1309
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
1310
+ continue
1311
+ rootElt = modelDocument.xmlRootElement
1312
+ for elt in rootElt.iter(XbrlConst.qnLinkArcroleRef.clarkNotation):
1313
+ refUri = elt.get("arcroleURI")
1314
+ hrefAttr = elt.get(XbrlConst.qnXlinkHref.clarkNotation)
1315
+ hrefUri, hrefId = UrlUtil.splitDecodeFragment(hrefAttr)
1316
+ if hrefUri not in val.disclosureSystem.standardTaxonomiesDict:
1317
+ yield Validation.warning(
1318
+ codes='EDINET.EC5700W.GFM.1.4.6',
1319
+ msg=_("Please correct the value of the link:arcroleRef attribute to one specified in the XBRL 2.1 specification or the EDINET taxonomy."
1320
+ " link:arcroleRef: %(xlinkHref)s, arcrole: %(refURI)s,"),
1321
+ modelObject=elt,
1322
+ refURI=refUri,
1323
+ xlinkHref=hrefUri
1324
+ )
1325
+
1326
+
1327
+ @validation(
1328
+ hook=ValidationHook.XBRL_FINALLY,
1329
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1330
+ )
1331
+ def rule_gfm_1_4_8(
1332
+ pluginData: PluginValidationDataExtension,
1333
+ val: ValidateXbrl,
1334
+ *args: Any,
1335
+ **kwargs: Any,
1336
+ ) -> Iterable[Validation]:
1337
+ """
1338
+ EDINET.EC5700W: [GFM 1.4.8] Correct the priority attribute value so that it is less than 10.
1339
+ """
1340
+
1341
+ for modelDocument in val.modelXbrl.urlDocs.values():
1342
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
1343
+ continue
1344
+ rootElt = modelDocument.xmlRootElement
1345
+ ns = {'xlink': 'http://www.w3.org/1999/xlink'}
1346
+ for elt in rootElt.xpath('//*[@xlink:type="arc"][@priority]', namespaces=ns):
1347
+ priority = elt.get("priority")
1348
+ with contextlib.suppress(ValueError, TypeError):
1349
+ if int(priority) >= 10:
1350
+ yield Validation.warning(
1351
+ codes='EDINET.EC5700W.GFM.1.4.8',
1352
+ msg=_("Correct the priority attribute value so that it is less than 10. Arc element: %(arcName)s, priority: %(priority)s"),
1353
+ arcName=elt.qname,
1354
+ modelObject=elt,
1355
+ priority=priority,
1356
+ )
1357
+
1358
+
1359
+ @validation(
1360
+ hook=ValidationHook.XBRL_FINALLY,
1361
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1362
+ )
1363
+ def rule_gfm_1_5_1(
1364
+ pluginData: PluginValidationDataExtension,
1365
+ val: ValidateXbrl,
1366
+ *args: Any,
1367
+ **kwargs: Any,
1368
+ ) -> Iterable[Validation]:
1369
+ """
1370
+ EDINET.EC5700W: [GFM 1.5.1] An element used in a fact or xbrldi:explicitMember in an instance must have a Japanese
1371
+ language standard label in the DTS of that instance.
1372
+ """
1373
+ usedConcepts = pluginData.getUsedConcepts(val.modelXbrl)
1374
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1375
+ if labelRelationshipSet is None:
1376
+ return
1377
+ for concept in usedConcepts:
1378
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1379
+ labelExists = False
1380
+ for rel in labelRels:
1381
+ label = rel.toModelObject
1382
+ if (label is not None and
1383
+ label.role == XbrlConst.standardLabel and
1384
+ label.xmlLang in JAPAN_LANGUAGE_CODES):
1385
+ labelExists = True
1386
+ break
1387
+ if not labelExists:
1388
+ yield Validation.warning(
1389
+ codes='EDINET.EC5700W.GFM.1.5.1',
1390
+ msg=_("The used concept of '%(concept)s' is missing a standard label in Japanese"),
1391
+ concept=concept.qname.localName,
1392
+ modelObject=concept
1393
+ )
1394
+
1395
+
1396
+ @validation(
1397
+ hook=ValidationHook.XBRL_FINALLY,
1398
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1399
+ )
1400
+ def rule_gfm_1_5_2(
1401
+ pluginData: PluginValidationDataExtension,
1402
+ val: ValidateXbrl,
1403
+ *args: Any,
1404
+ **kwargs: Any,
1405
+ ) -> Iterable[Validation]:
1406
+ """
1407
+ EDINET.EC5700W: [GFM 1.5.2] An element used in a fact or xbrldi:explicitMember in an instance must have at most one
1408
+ label for any combination of the xlink:role attribute and the xml:lang attribute in the
1409
+ DTS of that instance.
1410
+ """
1411
+ usedConcepts = pluginData.getUsedConcepts(val.modelXbrl)
1412
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1413
+ if labelRelationshipSet is None:
1414
+ return
1415
+ for concept in usedConcepts:
1416
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1417
+ labelsByRoleAndLang = defaultdict(list)
1418
+ for rel in labelRels:
1419
+ label = rel.toModelObject
1420
+ if label is None:
1421
+ continue
1422
+ labelsByRoleAndLang[(label.role, label.xmlLang)].append(label)
1423
+ warningLabels = []
1424
+ for key, labels in labelsByRoleAndLang.items():
1425
+ if len(labels) > 1:
1426
+ warningLabels.append(key)
1427
+ if len(warningLabels) > 0:
1428
+ yield Validation.warning(
1429
+ codes='EDINET.EC5700W.GFM.1.5.2',
1430
+ msg=_("The used concept of '%(concept)s' has more than one label for the given role/lang pairs: %(pairs)s."),
1431
+ concept=concept.qname.localName,
1432
+ pairs=warningLabels,
1433
+ modelObject=concept
1434
+ )
1435
+
1436
+
1437
+ @validation(
1438
+ hook=ValidationHook.XBRL_FINALLY,
1439
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1440
+ )
1441
+ def rule_gfm_1_5_3(
1442
+ pluginData: PluginValidationDataExtension,
1443
+ val: ValidateXbrl,
1444
+ *args: Any,
1445
+ **kwargs: Any,
1446
+ ) -> Iterable[Validation]:
1447
+ """
1448
+ EDINET.EC5700W: [GFM 1.5.3] If an element used in an instance is assigned a label in the DTS whose xml:lang
1449
+ attribute does not reflect the default language, then the DTS must also contain a
1450
+ link:label for the same element and all other attributes with an xml:lang attribute
1451
+ reflecting the default language.
1452
+ """
1453
+ usedConcepts = pluginData.getUsedConcepts(val.modelXbrl)
1454
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1455
+ if labelRelationshipSet is None:
1456
+ return
1457
+ for concept in usedConcepts:
1458
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1459
+ labelsByRole = defaultdict(list)
1460
+ for rel in labelRels:
1461
+ label = rel.toModelObject
1462
+ if label is None:
1463
+ continue
1464
+ labelsByRole[label.role].append(label)
1465
+ warningRoles = []
1466
+ for role, labels in labelsByRole.items():
1467
+ if len([label for label in labels if label.xmlLang in JAPAN_LANGUAGE_CODES]) == 0:
1468
+ warningRoles.append(role)
1469
+ if len(warningRoles) > 0:
1470
+ yield Validation.warning(
1471
+ codes='EDINET.EC5700W.GFM.1.5.3',
1472
+ msg=_("The used concept of '%(concept)s' is missing a label in Japanese in the following roles: %(roles)s."),
1473
+ concept=concept.qname.localName,
1474
+ roles=warningRoles,
1475
+ modelObject=concept
1476
+ )
1477
+
1478
+
1479
+ @validation(
1480
+ hook=ValidationHook.XBRL_FINALLY,
1481
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1482
+ )
1483
+ def rule_gfm_1_5_5(
1484
+ pluginData: PluginValidationDataExtension,
1485
+ val: ValidateXbrl,
1486
+ *args: Any,
1487
+ **kwargs: Any,
1488
+ ) -> Iterable[Validation]:
1489
+ """
1490
+ EDINET.EC5700W: [GFM 1.5.5] A label linkbase must not have a documentation label for an element defined in a
1491
+ standard taxonomy.
1492
+ """
1493
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1494
+ if labelRelationshipSet is None:
1495
+ return
1496
+ for concept in val.modelXbrl.qnameConcepts.values():
1497
+ if concept.namespaceURI is not None and not pluginData.isStandardTaxonomyUrl(concept.namespaceURI, val.modelXbrl):
1498
+ continue
1499
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1500
+ for rel in labelRels:
1501
+ label = rel.toModelObject
1502
+ if (label is not None and
1503
+ not pluginData.isStandardTaxonomyUrl(label.modelDocument.uri, val.modelXbrl) and
1504
+ label.role == XbrlConst.documentationLabel):
1505
+ yield Validation.warning(
1506
+ codes='EDINET.EC5700W.GFM.1.5.5',
1507
+ msg=_("The standard concept of '%(concept)s' must not have a documentation label defined."),
1508
+ concept=concept.qname.localName,
1509
+ modelObject=label
1510
+ )
1511
+
1512
+
1513
+ @validation(
1514
+ hook=ValidationHook.XBRL_FINALLY,
1515
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1516
+ )
1517
+ def rule_gfm_1_5_6(
1518
+ pluginData: PluginValidationDataExtension,
1519
+ val: ValidateXbrl,
1520
+ *args: Any,
1521
+ **kwargs: Any,
1522
+ ) -> Iterable[Validation]:
1523
+ """
1524
+ EDINET.EC5700W: [GFM 1.5.6] The length of a label must be less than 511 characters unless its role is documentation.
1525
+ """
1526
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1527
+ if labelRelationshipSet is None:
1528
+ return
1529
+ for concept in val.modelXbrl.qnameConcepts.values():
1530
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1531
+ for rel in labelRels:
1532
+ label = rel.toModelObject
1533
+ if (label is not None and
1534
+ label.role != XbrlConst.documentationLabel and
1535
+ label.viewText() is not None and
1536
+ len(label.viewText()) >= 511):
1537
+ yield Validation.warning(
1538
+ codes='EDINET.EC5700W.GFM.1.5.6',
1539
+ msg=_("The concept of '%(concept)s' has a label classified as '%(role)s' that is greater than or equal to 511 characters: %(label)s"),
1540
+ concept=concept.qname,
1541
+ role=label.role,
1542
+ label=label.viewText(),
1543
+ modelObject=label
1544
+ )
1545
+
1546
+
1547
+ @validation(
1548
+ hook=ValidationHook.XBRL_FINALLY,
1549
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1550
+ )
1551
+ def rule_gfm_1_5_7(
1552
+ pluginData: PluginValidationDataExtension,
1553
+ val: ValidateXbrl,
1554
+ *args: Any,
1555
+ **kwargs: Any,
1556
+ ) -> Iterable[Validation]:
1557
+ """
1558
+ EDINET.EC5700W: [GFM 1.5.7] A label cannot contain the "<" character or consecutive white space characters including
1559
+ but not limited to: space, carriage return, line feed or tab.
1560
+ """
1561
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1562
+ if labelRelationshipSet is None:
1563
+ return
1564
+ for concept in val.modelXbrl.qnameConcepts.values():
1565
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1566
+ for rel in labelRels:
1567
+ label = rel.toModelObject
1568
+ if label is not None and label.role != XbrlConst.documentationLabel and label.textValue is not None:
1569
+ if '<' in label.textValue:
1570
+ yield Validation.warning(
1571
+ codes='EDINET.EC5700W.GFM.1.5.7',
1572
+ msg=_("The concept of '%(concept)s' has a label classified as '%(role)s that contains the '<' character: %(label)s"),
1573
+ concept=concept.qname,
1574
+ role=label.role,
1575
+ label=label.textValue,
1576
+ modelObject=label
1577
+ )
1578
+ elif DISALLOWED_LABEL_WHITE_SPACE_CHARACTERS.search(label.textValue):
1579
+ yield Validation.warning(
1580
+ codes='EDINET.EC5700W.GFM.1.5.7',
1581
+ msg=_("The concept of '%(concept)s' has a label classified as '%(role)s' that contains consecutive white space characters: %(label)s"),
1582
+ concept=concept.qname,
1583
+ role=label.role,
1584
+ label=label.textValue,
1585
+ modelObject=label
1586
+ )
1587
+
1588
+
1589
+ @validation(
1590
+ hook=ValidationHook.XBRL_FINALLY,
1591
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1592
+ )
1593
+ def rule_gfm_1_5_8(
1594
+ pluginData: PluginValidationDataExtension,
1595
+ val: ValidateXbrl,
1596
+ *args: Any,
1597
+ **kwargs: Any,
1598
+ ) -> Iterable[Validation]:
1599
+ """
1600
+ EDINET.EC5700W: [GFM 1.5.8] A label should not begin or end with a white space character
1601
+ """
1602
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1603
+ if labelRelationshipSet is None:
1604
+ return
1605
+ for concept in val.modelXbrl.qnameConcepts.values():
1606
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1607
+ for rel in labelRels:
1608
+ label = rel.toModelObject
1609
+ if label is not None and label.textValue is not None and label.textValue != label.textValue.strip():
1610
+ yield Validation.warning(
1611
+ codes='EDINET.EC5700W.GFM.1.5.8',
1612
+ msg=_("The concept of '%(concept)s' has a label that contains disallowed white space either at the begining or the end: '%(label)s'"),
1613
+ concept=concept.qname,
1614
+ label=label.textValue,
1615
+ modelObject=label
1616
+ )
1617
+
1618
+
1619
+ @validation(
1620
+ hook=ValidationHook.XBRL_FINALLY,
1621
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1622
+ )
1623
+ def rule_gfm_1_5_10(
1624
+ pluginData: PluginValidationDataExtension,
1625
+ val: ValidateXbrl,
1626
+ *args: Any,
1627
+ **kwargs: Any,
1628
+ ) -> Iterable[Validation]:
1629
+ """
1630
+ EDINET.EC5700W: [GFM 1.5.10] A non-numeric concept should not have a label with a numeric role
1631
+ """
1632
+ labelRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
1633
+ if labelRelationshipSet is None:
1634
+ return
1635
+ for concept in val.modelXbrl.qnameConcepts.values():
1636
+ if concept.isNumeric:
1637
+ continue
1638
+ labelRels = labelRelationshipSet.fromModelObject(concept)
1639
+ for rel in labelRels:
1640
+ label = rel.toModelObject
1641
+ if (label is not None and
1642
+ not pluginData.isStandardTaxonomyUrl(label.modelDocument.uri, val.modelXbrl) and
1643
+ label.role in NUMERIC_LABEL_ROLES):
1644
+ yield Validation.warning(
1645
+ codes='EDINET.EC5700W.GFM.1.5.10',
1646
+ msg=_("The non-numeric concept of '%(concept)s' has a label with a numeric role of '%(labelrole)s'"),
1647
+ concept=concept.qname,
1648
+ labelrole=label.role,
1649
+ modelObject=label
1650
+ )
1651
+
1652
+
1653
+ @validation(
1654
+ hook=ValidationHook.XBRL_FINALLY,
1655
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1656
+ )
1657
+ def rule_gfm_1_6_1(
1658
+ pluginData: PluginValidationDataExtension,
1659
+ val: ValidateXbrl,
1660
+ *args: Any,
1661
+ **kwargs: Any,
1662
+ ) -> Iterable[Validation]:
1663
+ """
1664
+ EDINET.EC5700W: [GFM 1.6.1] All presentation relationships must have an order attribute
1665
+ """
1666
+ presentationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.PRESENTATION.getArcroles()))
1667
+ if presentationRelationshipSet is None:
1668
+ return
1669
+ for rel in presentationRelationshipSet.modelRelationships:
1670
+ if not rel.arcElement.get("order"):
1671
+ yield Validation.warning(
1672
+ codes='EDINET.EC5700W.GFM.1.6.1',
1673
+ msg=_("The presentation relationship is missing the order attribute"),
1674
+ modelObject=rel
1675
+ )
1676
+
1677
+
1678
+ @validation(
1679
+ hook=ValidationHook.XBRL_FINALLY,
1680
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1681
+ )
1682
+ def rule_gfm_1_6_2(
1683
+ pluginData: PluginValidationDataExtension,
1684
+ val: ValidateXbrl,
1685
+ *args: Any,
1686
+ **kwargs: Any,
1687
+ ) -> Iterable[Validation]:
1688
+ """
1689
+ EDINET.EC5700W: [GFM 1.6.2] Presentation relationships must have unique order attributes
1690
+ """
1691
+ presentationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.PRESENTATION.getArcroles()))
1692
+ if presentationRelationshipSet is None:
1693
+ return
1694
+ for modelObject, rels in presentationRelationshipSet.fromModelObjects().items():
1695
+ if len(rels) <= 1:
1696
+ continue
1697
+ relsByOrder = defaultdict(list)
1698
+ for rel in rels:
1699
+ order = rel.arcElement.get("order")
1700
+ if order is not None:
1701
+ relsByOrder[(order, rel.linkrole)].append(rel)
1702
+ for key, orderRels in relsByOrder.items():
1703
+ if len(orderRels) > 1:
1704
+ yield Validation.warning(
1705
+ codes='EDINET.EC5700W.GFM.1.6.2',
1706
+ msg=_("The presentation relationships have the same order attribute: '%(order)s'"),
1707
+ order=key[0],
1708
+ modelObject=orderRels
1709
+ )
1710
+
1711
+
1712
+ @validation(
1713
+ hook=ValidationHook.XBRL_FINALLY,
1714
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1715
+ )
1716
+ def rule_gfm_1_6_5(
1717
+ pluginData: PluginValidationDataExtension,
1718
+ val: ValidateXbrl,
1719
+ *args: Any,
1720
+ **kwargs: Any,
1721
+ ) -> Iterable[Validation]:
1722
+ """
1723
+ EDINET.EC5700W: [GFM 1.6.5] If an element used in an instance is the target in the instance DTS of more than one
1724
+ effective presentation arc in a base set with the same source element, then the
1725
+ presentation arcs must have distinct values of the preferredLabel attribute.
1726
+ """
1727
+ presentationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.PRESENTATION.getArcroles()))
1728
+ if presentationRelationshipSet is None:
1729
+ return
1730
+ for modelObject, rels in presentationRelationshipSet.toModelObjects().items():
1731
+ if len(rels) <= 1:
1732
+ continue
1733
+ relsByFrom = defaultdict(list)
1734
+ for rel in rels:
1735
+ relsByFrom[(rel.fromModelObject, rel.preferredLabel, rel.linkrole)].append(rel)
1736
+ for key, fromRels in relsByFrom.items():
1737
+ if len(fromRels) > 1:
1738
+ yield Validation.warning(
1739
+ codes='EDINET.EC5700W.GFM.1.6.5',
1740
+ msg=_("The presentation relationships must have distinct values of the preferredLabel attribute "
1741
+ "when they have the same source and target elements"),
1742
+ modelObject=fromRels
1743
+ )
1744
+
1745
+
1746
+ @validation(
1747
+ hook=ValidationHook.XBRL_FINALLY,
1748
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1749
+ )
1750
+ def rule_gfm_1_7_1(
1751
+ pluginData: PluginValidationDataExtension,
1752
+ val: ValidateXbrl,
1753
+ *args: Any,
1754
+ **kwargs: Any,
1755
+ ) -> Iterable[Validation]:
1756
+ """
1757
+ EDINET.EC5700W: [GFM 1.7.1] All calculation relationships must have an order attribute
1758
+ """
1759
+ calculationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.CALCULATION.getArcroles()))
1760
+ if calculationRelationshipSet is None:
1761
+ return
1762
+ for rel in calculationRelationshipSet.modelRelationships:
1763
+ if not rel.arcElement.get("order"):
1764
+ yield Validation.warning(
1765
+ codes='EDINET.EC5700W.GFM.1.7.1',
1766
+ msg=_("The calculation relationship is missing the order attribute"),
1767
+ modelObject=rel
1768
+ )
1769
+
1770
+
1771
+ @validation(
1772
+ hook=ValidationHook.XBRL_FINALLY,
1773
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1774
+ )
1775
+ def rule_gfm_1_7_2(
1776
+ pluginData: PluginValidationDataExtension,
1777
+ val: ValidateXbrl,
1778
+ *args: Any,
1779
+ **kwargs: Any,
1780
+ ) -> Iterable[Validation]:
1781
+ """
1782
+ EDINET.EC5700W: [GFM 1.7.2] All calculation relationships must have a weight of either 1 or -1
1783
+ """
1784
+ calculationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.CALCULATION.getArcroles()))
1785
+ if calculationRelationshipSet is None:
1786
+ return
1787
+ for rel in calculationRelationshipSet.modelRelationships:
1788
+ if rel.weight not in [1, -1]:
1789
+ yield Validation.warning(
1790
+ codes='EDINET.EC5700W.GFM.1.7.2',
1791
+ msg=_("The calculation relationship must have a weight of 1 or -1, actual weight: '%(weight)s'"),
1792
+ weight=rel.weight,
1793
+ modelObject=rel
1794
+ )
1795
+
1796
+
1797
+ @validation(
1798
+ hook=ValidationHook.XBRL_FINALLY,
1799
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1800
+ )
1801
+ def rule_gfm_1_7_3(
1802
+ pluginData: PluginValidationDataExtension,
1803
+ val: ValidateXbrl,
1804
+ *args: Any,
1805
+ **kwargs: Any,
1806
+ ) -> Iterable[Validation]:
1807
+ """
1808
+ EDINET.EC5700W: [GFM 1.7.3] The concepts participating in a calculation relationship must have the same period type
1809
+ """
1810
+ calculationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.CALCULATION.getArcroles()))
1811
+ if calculationRelationshipSet is None:
1812
+ return
1813
+ for rel in calculationRelationshipSet.modelRelationships:
1814
+ fromConcept = rel.fromModelObject
1815
+ toConcept = rel.toModelObject
1816
+ if fromConcept is not None and toConcept is not None and fromConcept.periodType != toConcept.periodType:
1817
+ yield Validation.warning(
1818
+ codes='EDINET.EC5700W.GFM.1.7.3',
1819
+ msg=_("The concepts participating in a calculation relationship must have the same period types. "
1820
+ "The concept of '%(concept1)s' has a period type of '%(concept1PeriodType)s' and the concept "
1821
+ "of '%(concept2)s' has a period type of '%(concept2PeriodType)s'"),
1822
+ concept1=fromConcept.qname,
1823
+ concept1PeriodType=fromConcept.periodType,
1824
+ concept2=toConcept.qname,
1825
+ concept2PeriodType=toConcept.periodType,
1826
+ modelObject=rel
1827
+ )
1828
+
1829
+
1830
+ @validation(
1831
+ hook=ValidationHook.XBRL_FINALLY,
1832
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1833
+ )
1834
+ def rule_gfm_1_7_5(
1835
+ pluginData: PluginValidationDataExtension,
1836
+ val: ValidateXbrl,
1837
+ *args: Any,
1838
+ **kwargs: Any,
1839
+ ) -> Iterable[Validation]:
1840
+ """
1841
+ EDINET.EC5700W: [GFM 1.7.5] The source and target of a calculation relationship must appear in either:
1842
+ 1) a presentation relationship within each other
1843
+ 2) two presentation relationships with any other elements that also share the same ELR.
1844
+ """
1845
+ calculationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.CALCULATION.getArcroles()))
1846
+ if calculationRelationshipSet is None:
1847
+ return
1848
+ for rel in calculationRelationshipSet.modelRelationships:
1849
+ conceptsMissingRels = []
1850
+ concepts = []
1851
+ for concept in [rel.fromModelObject, rel.toModelObject]:
1852
+ if concept is not None:
1853
+ conceptFacts = val.modelXbrl.factsByQname.get(concept.qname, set())
1854
+ if len([fact for fact in conceptFacts if fact.xValid >= VALID and not fact.isNil]) > 0:
1855
+ concepts.append(concept)
1856
+ if len(concepts) > 0:
1857
+ presentationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.PRESENTATION.getArcroles()), rel.linkrole)
1858
+ if presentationRelationshipSet is None:
1859
+ conceptsMissingRels.extend(concepts)
1860
+ else:
1861
+ for concept in concepts:
1862
+ if (len(presentationRelationshipSet.fromModelObject(concept)) == 0 and
1863
+ len(presentationRelationshipSet.toModelObject(concept)) == 0):
1864
+ conceptsMissingRels.append(concept)
1865
+ if len(conceptsMissingRels) > 0:
1866
+ yield Validation.warning(
1867
+ codes='EDINET.EC5700W.GFM.1.7.5',
1868
+ msg=_("The concepts participating in a calculation relationship must also participate in a presentation "
1869
+ "relationship within the same extended link role. The concept(s) of '%(concepts)s' "
1870
+ "do not appear in a presentation relationship within the extended link role of '%(elr)s'."),
1871
+ concepts=' and '.join([concept.qname.localName for concept in conceptsMissingRels]),
1872
+ elr=rel.linkrole,
1873
+ modelObject=rel
1874
+ )
1875
+
1876
+
1877
+ @validation(
1878
+ hook=ValidationHook.XBRL_FINALLY,
1879
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1880
+ )
1881
+ def rule_gfm_1_7_6(
1882
+ pluginData: PluginValidationDataExtension,
1883
+ val: ValidateXbrl,
1884
+ *args: Any,
1885
+ **kwargs: Any,
1886
+ ) -> Iterable[Validation]:
1887
+ """
1888
+ EDINET.EC5700W: [GFM 1.7.6] Calculation relationships must have unique order attributes
1889
+ """
1890
+ calculationRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.CALCULATION.getArcroles()))
1891
+ if calculationRelationshipSet is None:
1892
+ return
1893
+ for modelObject, rels in calculationRelationshipSet.fromModelObjects().items():
1894
+ if len(rels) <= 1:
1895
+ continue
1896
+ relsByOrder = defaultdict(list)
1897
+ for rel in rels:
1898
+ order = rel.arcElement.get("order")
1899
+ if order is not None:
1900
+ relsByOrder[(order, rel.linkrole)].append(rel)
1901
+ for key, orderRels in relsByOrder.items():
1902
+ if len(orderRels) > 1:
1903
+ yield Validation.warning(
1904
+ codes='EDINET.EC5700W.GFM.1.7.6',
1905
+ msg=_("The calculation relationships have the same order attribute: '%(order)s'"),
1906
+ order=key[0],
1907
+ modelObject=orderRels
1908
+ )
1909
+
1910
+
1911
+ @validation(
1912
+ hook=ValidationHook.XBRL_FINALLY,
1913
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1914
+ )
1915
+ def rule_gfm_1_8_1(
1916
+ pluginData: PluginValidationDataExtension,
1917
+ val: ValidateXbrl,
1918
+ *args: Any,
1919
+ **kwargs: Any,
1920
+ ) -> Iterable[Validation]:
1921
+ """
1922
+ EDINET.EC5700W: [GFM 1.8.1] All definition relationships must have an order attribute
1923
+ """
1924
+ definitionRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.DEFINITION.getArcroles()))
1925
+ if definitionRelationshipSet is None:
1926
+ return
1927
+ for rel in definitionRelationshipSet.modelRelationships:
1928
+ if not rel.arcElement.get("order"):
1929
+ yield Validation.warning(
1930
+ codes='EDINET.EC5700W.GFM.1.8.1',
1931
+ msg=_("The definition relationship is missing the order attribute"),
1932
+ modelObject=rel
1933
+ )
1934
+
1935
+
1936
+ @validation(
1937
+ hook=ValidationHook.XBRL_FINALLY,
1938
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1939
+ )
1940
+ def rule_gfm_1_8_3(
1941
+ pluginData: PluginValidationDataExtension,
1942
+ val: ValidateXbrl,
1943
+ *args: Any,
1944
+ **kwargs: Any,
1945
+ ) -> Iterable[Validation]:
1946
+ """
1947
+ EDINET.EC5700W: [GFM 1.8.3] The target of an effective arc with an xlink:arcrole attribute equal to
1948
+ "http://xbrl.org/int/dim/arcrole/dimension-domain" or
1949
+ "http://xbrl.org/int/arcrole/dimension-default" must be of type
1950
+ nonnum:domainItemType.
1951
+ """
1952
+ dimensionRelationshipSet = val.modelXbrl.relationshipSet((XbrlConst.dimensionDomain, XbrlConst.dimensionDefault))
1953
+ if dimensionRelationshipSet is None:
1954
+ return
1955
+ for rel in dimensionRelationshipSet.modelRelationships:
1956
+ toConcept = rel.toModelObject
1957
+ if toConcept is not None and toConcept.typeQname != domainItemTypeQname:
1958
+ yield Validation.warning(
1959
+ codes='EDINET.EC5700W.GFM.1.8.3',
1960
+ msg=_("The definition relationship target concept of '%(concept)s' has a type of '%(type)s' instead of 'nonnum:domainItemType'."),
1961
+ concept=toConcept.qname,
1962
+ type=toConcept.typeQname,
1963
+ modelObject=rel
1964
+ )
1965
+
1966
+
1967
+ @validation(
1968
+ hook=ValidationHook.XBRL_FINALLY,
1969
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1970
+ )
1971
+ def rule_gfm_1_8_5(
1972
+ pluginData: PluginValidationDataExtension,
1973
+ val: ValidateXbrl,
1974
+ *args: Any,
1975
+ **kwargs: Any,
1976
+ ) -> Iterable[Validation]:
1977
+ """
1978
+ EDINET.EC5700W: [GFM 1.8.5] Each ELR can have at most one effective arc with the role of http://xbrl.org/int/dim/arcrole/all.
1979
+ """
1980
+ dimensionAllRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.all)
1981
+ if dimensionAllRelationshipSet is None:
1982
+ return
1983
+ relsByLinkrole = defaultdict(list)
1984
+ for rel in dimensionAllRelationshipSet.modelRelationships:
1985
+ relsByLinkrole[rel.linkrole].append(rel)
1986
+ for linkrole, rels in relsByLinkrole.items():
1987
+ if len(rels) > 1:
1988
+ yield Validation.warning(
1989
+ codes='EDINET.EC5700W.GFM.1.8.5',
1990
+ msg=_("The extended link role of '%(elr)s' has more than one effective arc with the role of 'http://xbrl.org/int/dim/arcrole/all'"),
1991
+ elr=linkrole,
1992
+ modelObject=rels
1993
+ )
1994
+
1995
+
1996
+ @validation(
1997
+ hook=ValidationHook.XBRL_FINALLY,
1998
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
1999
+ )
2000
+ def rule_gfm_1_8_9(
2001
+ pluginData: PluginValidationDataExtension,
2002
+ val: ValidateXbrl,
2003
+ *args: Any,
2004
+ **kwargs: Any,
2005
+ ) -> Iterable[Validation]:
2006
+ """
2007
+ EDINET.EC5700W: [GFM 1.8.9] Each ELR can have at most one effective arc with the role of http://xbrl.org/int/dim/arcrole/all.
2008
+
2009
+ GFM 1.8.9: If the value of attribute xbrldt:targetRole on an effective definition relationship is
2010
+ not empty, then that relationship must have at least one effective consecutive
2011
+ relationship (as defined by the XBRL Dimensions 1.0 specification).
2012
+ """
2013
+ drsELRs = set()
2014
+ for baseSetKey, baseSetModelLinks in val.modelXbrl.baseSets.items():
2015
+ arcrole, elr, linkqname, arcqname = baseSetKey
2016
+ if elr and linkqname and arcqname and not arcrole.startswith("XBRL-"):
2017
+ if arcrole == XbrlConst.all or arcrole == XbrlConst.notAll:
2018
+ drsELRs.add(elr)
2019
+ for ELR in drsELRs:
2020
+ domainMemberRelationshipSet = val.modelXbrl.relationshipSet( XbrlConst.domainMember, ELR)
2021
+ primaryItems = set()
2022
+ for hypercubeArcrole in (XbrlConst.all, XbrlConst.notAll):
2023
+ hypercubeRelationships = val.modelXbrl.relationshipSet(
2024
+ hypercubeArcrole, ELR).fromModelObjects()
2025
+ for hypercubeRels in hypercubeRelationships.values():
2026
+ for hypercubeRel in hypercubeRels:
2027
+ hypercube = hypercubeRel.toModelObject
2028
+ fromConcept = hypercubeRel.fromModelObject
2029
+ primaryItems.add(fromConcept)
2030
+ toConcept = hypercubeRel.toModelObject
2031
+ dimELR = hypercubeRel.targetRole
2032
+ dimTargetRequired = (dimELR is not None)
2033
+ if not dimELR:
2034
+ dimELR = elr
2035
+ hypercubeDimRels = val.modelXbrl.relationshipSet(XbrlConst.hypercubeDimension, dimELR).fromModelObject(toConcept)
2036
+ if dimTargetRequired and len(hypercubeDimRels) == 0:
2037
+ yield Validation.warning(
2038
+ codes='EDINET.EC5700W.GFM.1.8.9',
2039
+ msg=_("Add the arc related to the xbrldt:targetRole attribute or remove the attribute. "
2040
+ "Arcrole %(arcroleURI)s from %(fromConcept)s to %(toConcept)s."),
2041
+ modelObject=hypercubeRel,
2042
+ arcroleURI=hypercubeRel.arcrole,
2043
+ fromConcept=fromConcept.qname,
2044
+ toConcept=toConcept.qname,
2045
+ )
2046
+ for hypercubeDimRel in hypercubeDimRels:
2047
+ dim = hypercubeDimRel.toModelObject
2048
+ if not isinstance(dim, ModelConcept):
2049
+ continue
2050
+ domELR = hypercubeDimRel.targetRole
2051
+ domTargetRequired = (domELR is not None)
2052
+ if not domELR and dim.isExplicitDimension:
2053
+ domELR = dimELR
2054
+ dimDomRels = val.modelXbrl.relationshipSet(XbrlConst.dimensionDomain, domELR).fromModelObject(dim)
2055
+ if domTargetRequired and len(dimDomRels) == 0:
2056
+ yield Validation.warning(
2057
+ codes='EDINET.EC5700W.GFM.1.8.9',
2058
+ msg=_("Add the arc related to the xbrldt:targetRole attribute or remove the attribute. "
2059
+ "Arcrole %(arcroleURI)s from %(fromConcept)s to %(toConcept)s."),
2060
+ modelObject=hypercubeDimRel,
2061
+ arcroleURI=hypercubeRel.arcrole,
2062
+ fromConcept=hypercube.qname,
2063
+ toConcept=dim.qname,
2064
+ )
2065
+ fromRelationships = domainMemberRelationshipSet.fromModelObjects()
2066
+ for relFrom, rels in fromRelationships.items():
2067
+ for rel in rels:
2068
+ fromMbr = rel.fromModelObject
2069
+ toMbr = rel.toModelObject
2070
+ toELR = rel.targetRole
2071
+ if isinstance(toMbr, ModelConcept) and toELR and len(
2072
+ val.modelXbrl.relationshipSet(XbrlConst.domainMember, toELR).fromModelObject(toMbr)) == 0:
2073
+ yield Validation.warning(
2074
+ codes='EDINET.EC5700W.GFM.1.8.9',
2075
+ msg=_("Add the arc related to the xbrldt:targetRole attribute or remove the attribute. "
2076
+ "Arcrole %(arcroleURI)s from %(fromConcept)s to %(toConcept)s."),
2077
+ modelObject=rel,
2078
+ arcroleURI=hypercubeRel.arcrole,
2079
+ fromConcept=toMbr.qname,
2080
+ toConcept=fromMbr.qname,
2081
+ )
2082
+
2083
+
2084
+ @validation(
2085
+ hook=ValidationHook.XBRL_FINALLY,
2086
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2087
+ )
2088
+ def rule_gfm_1_8_10(
2089
+ pluginData: PluginValidationDataExtension,
2090
+ val: ValidateXbrl,
2091
+ *args: Any,
2092
+ **kwargs: Any,
2093
+ ) -> Iterable[Validation]:
2094
+ """
2095
+ EDINET.EC5700W: [GFM 1.8.10] Definition relationships must have unique order attributes
2096
+ """
2097
+ definitionRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.DEFINITION.getArcroles()))
2098
+ if definitionRelationshipSet is None:
2099
+ return
2100
+ for modelObject, rels in definitionRelationshipSet.loadModelRelationshipsFrom().items():
2101
+ if len(rels) <= 1:
2102
+ continue
2103
+ relsByOrder = defaultdict(list)
2104
+ for rel in rels:
2105
+ order = rel.arcElement.get("order")
2106
+ if order is not None:
2107
+ relsByOrder[(order, rel.linkrole, rel.arcrole)].append(rel)
2108
+ for key, orderRels in relsByOrder.items():
2109
+ if len(orderRels) > 1:
2110
+ yield Validation.warning(
2111
+ codes='EDINET.EC5700W.GFM.1.8.10',
2112
+ msg=_("The definition relationships have the same order attribute: '%(order)s'"),
2113
+ order=key[0],
2114
+ modelObject=orderRels
2115
+ )
2116
+
2117
+
2118
+ @validation(
2119
+ hook=ValidationHook.XBRL_FINALLY,
2120
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2121
+ )
2122
+ def rule_gfm_1_8_11(
2123
+ pluginData: PluginValidationDataExtension,
2124
+ val: ValidateXbrl,
2125
+ *args: Any,
2126
+ **kwargs: Any,
2127
+ ) -> Iterable[Validation]:
2128
+ """
2129
+ EDINET.EC5700W: [GFM 1.8.11] Definition relationships can not have the xbrldt:usable attribute set to False
2130
+ """
2131
+ definitionRelationshipSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.DEFINITION.getArcroles()))
2132
+ if definitionRelationshipSet is None:
2133
+ return
2134
+ for rel in definitionRelationshipSet.modelRelationships:
2135
+ if rel.arcrole in [XbrlConst.dimensionDomain, XbrlConst.domainMember]:
2136
+ continue
2137
+ if not rel.isUsable:
2138
+ yield Validation.warning(
2139
+ codes='EDINET.EC5700W.GFM.1.8.11',
2140
+ msg=_("The definition relationship can not have the xbrldt:usable attribute set to False"),
2141
+ modelObject=rel
2142
+ )
2143
+
2144
+
2145
+ @validation(
2146
+ hook=ValidationHook.XBRL_FINALLY,
2147
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2148
+ )
2149
+ def rule_gfm_1_9_1(
2150
+ pluginData: PluginValidationDataExtension,
2151
+ val: ValidateXbrl,
2152
+ *args: Any,
2153
+ **kwargs: Any,
2154
+ ) -> Iterable[Validation]:
2155
+ """
2156
+ EDINET.EC5700W: [GFM 1.9.1] References should not be defined for extension concepts.
2157
+ """
2158
+ conceptReferenceSet = val.modelXbrl.relationshipSet(XbrlConst.conceptReference)
2159
+ for modelConcept in conceptReferenceSet.fromModelObjects():
2160
+ if not isinstance(modelConcept, ModelConcept):
2161
+ continue
2162
+ if modelConcept.qname is None or modelConcept.qname.namespaceURI is None:
2163
+ continue
2164
+ if pluginData.isExtensionUri(modelConcept.document.uri, val.modelXbrl):
2165
+ yield Validation.warning(
2166
+ codes='EDINET.EC5700W.GFM.1.9.1',
2167
+ msg=_("References should not be defined for extension concepts: %(conceptName)s"),
2168
+ conceptName=modelConcept.qname,
2169
+ modelObject=modelConcept
2170
+ )
2171
+
2172
+
2173
+ @validation(
2174
+ hook=ValidationHook.XBRL_FINALLY,
2175
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2176
+ )
2177
+ def rule_gfm_1_10_3(
2178
+ pluginData: PluginValidationDataExtension,
2179
+ val: ValidateXbrl,
2180
+ *args: Any,
2181
+ **kwargs: Any,
2182
+ ) -> Iterable[Validation]:
2183
+ """
2184
+ EDINET.EC5700W: [GFM 1.10.3] The Inline XBRL document must contain all necessary namespace declarations including
2185
+ those for QName values of attributes. These namespace declarations must be on the root html element.
2186
+ """
2187
+ for ixdsHtmlRootElt in val.modelXbrl.ixdsHtmlElements:
2188
+ for elt in ixdsHtmlRootElt.iterdescendants():
2189
+ if not isinstance(elt, ModelObject):
2190
+ continue
2191
+ parent = elt.getparent()
2192
+ if parent is None or elt.nsmap == parent.nsmap:
2193
+ continue
2194
+ yield Validation.warning(
2195
+ codes='EDINET.EC5700W.GFM.1.10.3',
2196
+ msg=_('The Inline XBRL document must contain all necessary namespace declarations on the root html '
2197
+ 'element. Found namespace declaration on descendant element %(elementName)s.'),
2198
+ elementName=elt.tag,
2199
+ modelObject=elt
2200
+ )
2201
+
2202
+
2203
+ @validation(
2204
+ hook=ValidationHook.XBRL_FINALLY,
2205
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2206
+ )
2207
+ def rule_charsets(
2208
+ pluginData: PluginValidationDataExtension,
2209
+ val: ValidateXbrl,
2210
+ *args: Any,
2211
+ **kwargs: Any,
2212
+ ) -> Iterable[Validation]:
2213
+ """
2214
+ EDINET.EC1010E: The charset specification in the content attribute of the HTML <meta> tag must be UTF-8.
2215
+ EDINET.EC5000E: The encoding of the file must be UTF-8.
2216
+ EDINET.EC5003E: Prohibited characters must not be used.
2217
+ EDINET.EC5700W: [GFM 1.10.4] The document encoding must be set in both the XML document declaration and the HTML
2218
+ meta element for content type.
2219
+ """
2220
+ for modelDocument in val.modelXbrl.urlDocs.values():
2221
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
2222
+ continue
2223
+
2224
+ if modelDocument.type != ModelDocument.Type.INLINEXBRLDOCUMENTSET:
2225
+ if modelDocument.documentEncoding is None or modelDocument.documentEncoding.lower() not in ('utf-8', 'utf-8-sig'):
2226
+ yield Validation.error(
2227
+ codes='EDINET.EC5000E',
2228
+ msg=_("The encoding is not UTF-8. "
2229
+ "File name: '%(path)s'. "
2230
+ "Please change the encoding of the relevant file to UTF-8."),
2231
+ path=modelDocument.uri,
2232
+ modelObject=modelDocument,
2233
+ )
2234
+
2235
+ # TODO: Consolidate wtih NL.FR-NL-1.02
2236
+ for elt in modelDocument.xmlRootElement.iter():
2237
+ if isinstance(elt, ModelComment):
2238
+ texts = [getattr(elt, 'text')]
2239
+ else:
2240
+ texts = [elt.elementAttributesStr, elt.textValue]
2241
+ illegalChars: set[str] = set()
2242
+ for text in texts:
2243
+ illegalChars.update(HALF_KANA.intersection(set(text)))
2244
+ if len(illegalChars) > 0:
2245
+ yield Validation.error(
2246
+ codes='EDINET.EC5003E',
2247
+ msg=_("Prohibited characters (%(chars)s) are used. "
2248
+ "File name: '%(file)s' (line %(line)s). "
2249
+ "The file in question contains prohibited characters. "
2250
+ "Please correct the prohibited characters. "),
2251
+ chars=', '.join(sorted(illegalChars)),
2252
+ file=modelDocument.basename,
2253
+ line=elt.sourceline,
2254
+ modelObject=elt,
2255
+ )
2256
+
2257
+ if modelDocument.type != ModelDocument.Type.INLINEXBRL:
2258
+ continue
2259
+
2260
+ xmlDeclaredEncoding = None
2261
+ try:
2262
+ with val.modelXbrl.fileSource.file(modelDocument.filepath)[0] as f:
2263
+ fileContent = cast(str, f.read(512))
2264
+ match = XmlUtil.xmlEncodingPattern.match(fileContent)
2265
+ if match:
2266
+ xmlDeclaredEncoding = match.group(1)
2267
+ except Exception:
2268
+ pass
2269
+
2270
+ if xmlDeclaredEncoding is None:
2271
+ yield Validation.warning(
2272
+ codes='EDINET.EC5700W.GFM.1.10.4',
2273
+ msg=_("The document encoding must be declared in an XML document declaration"),
2274
+ modelObject=modelDocument
2275
+ )
2276
+
2277
+ metaCharsetDeclared = False
2278
+ for metaElt in modelDocument.xmlRootElement.iterdescendants(tag=XbrlConst.qnXhtmlMeta.clarkNotation):
2279
+ metaCharset = None
2280
+ httpEquiv = metaElt.get("http-equiv", "").lower()
2281
+ if httpEquiv == "content-type":
2282
+ content = metaElt.get("content")
2283
+ if content:
2284
+ metaCharset = attrValue(content)
2285
+ if metaCharset is not None:
2286
+ metaCharsetDeclared = True
2287
+ if xmlDeclaredEncoding is not None and metaCharset.lower() != xmlDeclaredEncoding.lower():
2288
+ yield Validation.warning(
2289
+ codes='EDINET.EC5700W.GFM.1.10.4',
2290
+ msg=_("The XML declaration encoding '%(xmlEncoding)s' does not match the HTML meta charset '%(metaCharset)s'"),
2291
+ xmlEncoding=xmlDeclaredEncoding,
2292
+ metaCharset=metaCharset,
2293
+ modelObject=metaElt
2294
+ )
2295
+ if metaCharset.lower() != 'utf-8':
2296
+ yield Validation.error(
2297
+ codes='EDINET.EC1010E',
2298
+ msg=_("The charset specification in the content attribute of the HTML <meta> tag is not UTF-8. "
2299
+ "File name: '%(path)s'. "
2300
+ "Please set the character code of the file to UTF-8."),
2301
+ path=modelDocument.uri,
2302
+ modelObject=metaElt,
2303
+ )
2304
+
2305
+ if not metaCharsetDeclared:
2306
+ yield Validation.warning(
2307
+ codes='EDINET.EC5700W.GFM.1.10.4',
2308
+ msg=_("The document encoding must be declared in an HTML meta element charset"),
2309
+ modelObject=modelDocument
2310
+ )
2311
+
2312
+
2313
+ @validation(
2314
+ hook=ValidationHook.XBRL_FINALLY,
2315
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2316
+ )
2317
+ def rule_gfm_1_10_12(
2318
+ pluginData: PluginValidationDataExtension,
2319
+ val: ValidateXbrl,
2320
+ *args: Any,
2321
+ **kwargs: Any,
2322
+ ) -> Iterable[Validation]:
2323
+ """
2324
+ EDINET.EC5700W: [GFM 1.10.12] In all inline XBRL files, multiple target attribute values ​​are not allowed.
2325
+ Correct the target attribute value. (A warning will be issued if the target attribute is not specified and is
2326
+ specified at the same time.)
2327
+ """
2328
+ targets: set[str | None] = set()
2329
+ for ixdsHtmlRootElt in val.modelXbrl.ixdsHtmlElements:
2330
+ targetEltTags = [qname.clarkNotation for qname in XbrlConst.ixbrlAllTargetElements]
2331
+ for elt in ixdsHtmlRootElt.iter(targetEltTags):
2332
+ targets.add(elt.get("target"))
2333
+ if len(targets) > 1:
2334
+ if None in targets:
2335
+ msg = _("Inline document set may not use multiple target documents. Found targets: default, %(targets)s")
2336
+ else:
2337
+ msg = _("Inline document set may not use multiple target documents. Found targets: %(targets)s")
2338
+ yield Validation.warning(
2339
+ codes='EDINET.EC5700W.GFM.1.10.12',
2340
+ msg=msg,
2341
+ targets=",".join(target for target in targets if target is not None),
2342
+ modelObject=val.modelXbrl,
2343
+ )
2344
+
2345
+
2346
+ @validation(
2347
+ hook=ValidationHook.XBRL_FINALLY,
2348
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2349
+ )
2350
+ def rule_gfm_1_10_14(
2351
+ pluginData: PluginValidationDataExtension,
2352
+ val: ValidateXbrl,
2353
+ *args: Any,
2354
+ **kwargs: Any,
2355
+ ) -> Iterable[Validation]:
2356
+ """
2357
+ EDINET.EC5700W: [GFM 1.10.14] All non-empty footnotes must be referenced by an element
2358
+ """
2359
+ footnotes = set()
2360
+ usedFootnoteIDs = set()
2361
+ for ixdsHtmlRootElt in val.modelXbrl.ixdsHtmlElements:
2362
+ for elt in ixdsHtmlRootElt.iterdescendants(XbrlConst.qnIXbrlFootnote.clarkNotation, XbrlConst.qnIXbrl11Footnote.clarkNotation):
2363
+ if isinstance(elt, ModelInlineFootnote) and elt.value != '':
2364
+ footnotes.add(elt)
2365
+ for rel in val.modelXbrl.relationshipSet("XBRL-footnotes").modelRelationships:
2366
+ if rel.fromModelObject is not None and rel.toModelObject is not None:
2367
+ usedFootnoteIDs.add(rel.toModelObject.footnoteID)
2368
+ for footnote in footnotes:
2369
+ if footnote.footnoteID not in usedFootnoteIDs:
2370
+ yield Validation.warning(
2371
+ codes='EDINET.EC5700W.GFM.1.10.14',
2372
+ msg=_("A non-empty footnote is not referenced by an element"),
2373
+ modelObject=footnote
2374
+ )
2375
+
2376
+
2377
+ @validation(
2378
+ hook=ValidationHook.XBRL_FINALLY,
2379
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2380
+ )
2381
+ def rule_gfm_2_3_5(
2382
+ pluginData: PluginValidationDataExtension,
2383
+ val: ValidateXbrl,
2384
+ *args: Any,
2385
+ **kwargs: Any,
2386
+ ) -> Iterable[Validation]:
2387
+ """
2388
+ EDINET.EC5700W: [GFM 2.3.5] The name attribute of an xsd:element should consist of
2389
+ capitalized words corresponding to the standard label, a convention called Label
2390
+ Camel Case Concatenation (LC3).
2391
+ 1. The first character of a name attribute must not be underscore.
2392
+ 2. The first character of a name attribute must be capitalized.
2393
+ 3. The following characters are not allowed in a name attribute:
2394
+ ()*+[]?\\/^{}|@#%^=~`“‘;:,<>&$₤€
2395
+ 4. Do not use digits in the name attribute unless the element is
2396
+ being declared specifically because it must identify a regulation
2397
+ known by a number (“12b-1 Fees”, “FAS 132”). Always begin the name
2398
+ with a letter (e.g., “Rule12b1Fees”) and conform to LC3 (e.g., “Fas132”).
2399
+ 5. Convert acronyms to Proper case (e.g., FAS becomes Fas, FHLC becomes
2400
+ Fhlc). Treat digits in an acronym as word separators (e.g., WIN2K becomes Win2K).
2401
+
2402
+ Note: "corresponding to the standard label" is not enforceable, this implementation
2403
+ only checks the LC3 formatting rules. Similarly, rule 4 and 5 are not enforced here.
2404
+ """
2405
+ for name, concepts in val.modelXbrl.nameConcepts.items():
2406
+ for concept in concepts:
2407
+ if pluginData.isStandardTaxonomyUrl(concept.modelDocument.uri, val.modelXbrl):
2408
+ continue
2409
+ if not LC3_NAME_PATTERN.fullmatch(name):
2410
+ yield Validation.warning(
2411
+ codes='EDINET.EC5700W.GFM.2.3.5',
2412
+ msg=_("Element names should be set using capitalized words "
2413
+ "(LC3 conversion rules) that correspond to standard labels."),
2414
+ modelObject=concept
2415
+ )
2416
+
2417
+
2418
+ @validation(
2419
+ hook=ValidationHook.XBRL_FINALLY,
2420
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2421
+ )
2422
+ def rule_gfm_2_5_1(
2423
+ pluginData: PluginValidationDataExtension,
2424
+ val: ValidateXbrl,
2425
+ *args: Any,
2426
+ **kwargs: Any,
2427
+ ) -> Iterable[Validation]:
2428
+ """
2429
+ EDINET.EC5700W: [GFM 2.5.1] A presentation linkbase of a standard taxonomy should not be included in the DTS of an instance.
2430
+ """
2431
+ for elt in pluginData.getStandardTaxonomyExtensionLinks(LinkbaseType.PRESENTATION, val.modelXbrl):
2432
+ yield Validation.warning(
2433
+ codes='EDINET.EC5700W.GFM.2.5.1',
2434
+ msg=_("A presentation linkbase from the standard taxonomy file of '%(uri)s' is not allowed."),
2435
+ uri=elt.attr(XbrlConst.qnXlinkHref.clarkNotation),
2436
+ modelObject=elt
2437
+ )
2438
+
2439
+
2440
+ @validation(
2441
+ hook=ValidationHook.XBRL_FINALLY,
2442
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2443
+ )
2444
+ def rule_gfm_2_6_1(
2445
+ pluginData: PluginValidationDataExtension,
2446
+ val: ValidateXbrl,
2447
+ *args: Any,
2448
+ **kwargs: Any,
2449
+ ) -> Iterable[Validation]:
2450
+ """
2451
+ EDINET.EC5700W: [GFM 2.6.1] A calculation linkbase of a standard taxonomy should not be included in the DTS of an instance.
2452
+ """
2453
+ for elt in pluginData.getStandardTaxonomyExtensionLinks(LinkbaseType.CALCULATION, val.modelXbrl):
2454
+ yield Validation.warning(
2455
+ codes='EDINET.EC5700W.GFM.2.6.1',
2456
+ msg=_("A calculation linkbase from the standard taxonomy file of '%(uri)s' is not allowed."),
2457
+ uri=elt.attr(XbrlConst.qnXlinkHref.clarkNotation),
2458
+ modelObject=elt
2459
+ )
2460
+
2461
+
2462
+ @validation(
2463
+ hook=ValidationHook.XBRL_FINALLY,
2464
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
2465
+ )
2466
+ def rule_gfm_2_8_1(
2467
+ pluginData: PluginValidationDataExtension,
2468
+ val: ValidateXbrl,
2469
+ *args: Any,
2470
+ **kwargs: Any,
2471
+ ) -> Iterable[Validation]:
2472
+ """
2473
+ EDINET.EC5700W: [GFM 2.8.1] A reference linkbase of a standard taxonomy should not be included in the DTS of an instance.
2474
+ """
2475
+ for elt in pluginData.getStandardTaxonomyExtensionLinks(LinkbaseType.REFERENCE, val.modelXbrl):
2476
+ yield Validation.warning(
2477
+ codes='EDINET.EC5700W.GFM.2.8.1',
2478
+ msg=_("A reference linkbase from the standard taxonomy file of '%(uri)s' is not allowed."),
2479
+ uri=elt.attr(XbrlConst.qnXlinkHref.clarkNotation),
2480
+ modelObject=elt
2481
+ )