Skip to content

Commit

Permalink
Code now targets .NET 6. Documents loaded from SEC URIs are now retri…
Browse files Browse the repository at this point in the history
…eved using special handling compatible with the SEC usage rules.
  • Loading branch information
JeffFerguson committed May 29, 2022
1 parent ee3c659 commit a85bbb2
Show file tree
Hide file tree
Showing 24 changed files with 190 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Examples/CSharp/Contexts/CS-Contexts.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/CSharp/FactWeights/CS-FactWeights.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/CSharp/Facts/CS-Facts.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/CSharp/Fragments/CS-Fragments.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/CSharp/Load/CS-Load.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/CSharp/Units/CS-Units.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/CSharp/ValidityChecks/CS-ValidityChecks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/FSharp/FS-Load/FS-Load.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/FSharp/FS-ValidityChecks/FS-ValidityChecks.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/VBNet/VB-Load/VB-Load.vbproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>VB_Load</RootNamespace>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Examples/VBNet/VB-ValidityChecks/VB-ValidityChecks.vbproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>VB_ValidityChecks</RootNamespace>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
5 changes: 3 additions & 2 deletions JeffFerguson.Gepsio.Test/IssueTests/13/Issue13Test.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace JeffFerguson.Gepsio.Test.IssueTests._13
{
Expand All @@ -14,7 +15,7 @@ public class Issue13Test
public void VerifyFixForIssue13()
{
var xbrlDoc = new XbrlDocument();
xbrlDoc.Load(@"..\..\..\IssueTests\13\Issue13.xml");
xbrlDoc.Load($"..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}IssueTests{Path.DirectorySeparatorChar}13{Path.DirectorySeparatorChar}Issue13.xml");
}
}
}
4 changes: 2 additions & 2 deletions JeffFerguson.Gepsio.Test/IssueTests/3/Issue3Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class Issue3Test
public void VerifyFixForIssue3_EnsureLocalSchemaLoad()
{
var xbrlDoc = new XbrlDocument();
xbrlDoc.Load(@"..\..\..\IssueTests\3\offentliggorelse.xml");
xbrlDoc.Load($"..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}IssueTests{Path.DirectorySeparatorChar}3{Path.DirectorySeparatorChar}offentliggorelse.xml");
Assert.IsTrue(xbrlDoc.XbrlFragments[0].Schemas.Count > 0);
}

Expand All @@ -23,7 +23,7 @@ public void VerifyFixForIssue3_EnsureAlternativeSchemaLoadPath()
{
var xbrlDoc = new XbrlDocument();
var unitTestDir = Directory.GetCurrentDirectory();
xbrlDoc.Load(@"..\..\..\IssueTests\3\offentliggorelse.xml");
xbrlDoc.Load($"..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}IssueTests{Path.DirectorySeparatorChar}3{Path.DirectorySeparatorChar}offentliggorelse.xml");
var loadedSchema = xbrlDoc.XbrlFragments[0].Schemas[0];
Assert.AreNotEqual(loadedSchema.SchemaReferencePath, loadedSchema.LoadPath);
}
Expand Down
2 changes: 1 addition & 1 deletion JeffFerguson.Gepsio.Test/JeffFerguson.Gepsio.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
6 changes: 2 additions & 4 deletions JeffFerguson.Gepsio.Test/XbrlConformanceTest.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
using JeffFerguson.Gepsio;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

Expand Down Expand Up @@ -34,7 +31,8 @@ public XbrlConformanceTest()
public void ExecuteXBRLCONF20141210Testcases()
{
thisTestsPassed = 0;
var conformanceXmlSource = @"..\..\..\XBRL-CONF-2014-12-10\xbrl.xml";
Debug.AutoFlush = true;
var conformanceXmlSource = $"..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}XBRL-CONF-2014-12-10{Path.DirectorySeparatorChar}xbrl.xml";
var conformanceXmlSourcePath = Path.GetDirectoryName(conformanceXmlSource);
var conformanceXmlDocument = new XmlDocument();
conformanceXmlDocument.Load(conformanceXmlSource);
Expand Down
2 changes: 1 addition & 1 deletion JeffFerguson.Gepsio/JeffFerguson.Gepsio.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>Gepsio</PackageId>
<Version>2.1.0.16</Version>
Expand Down
30 changes: 11 additions & 19 deletions JeffFerguson.Gepsio/LinkbaseDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal LinkbaseDocument(string ContainingDocumentUri, string DocumentPath, Xbr
// Used for when a linkbaseRef element has no "role" attribute and the type of linkbase
// document must be discovered. The 331-equivalentRelationships-instance-02.xml
// document in the XBRL-CONF-2014-12-10 conformance suite is an example of this need.
// A NULL reference will be returned if the correct type cannot be identified.
//------------------------------------------------------------------------------------
internal static LinkbaseDocument Create(string containingDocumentUri, string href, XbrlFragment containingFragment)
{
Expand Down Expand Up @@ -65,7 +66,7 @@ internal static LinkbaseDocument Create(string containingDocumentUri, string hre
{
return new ReferenceLinkbaseDocument(containingDocumentUri, href, containingFragment);
}
throw new NotSupportedException($"Linkbase node has unsupported child node with local name {firstChildLocalName} in document {href} at URI {containingDocumentUri}.");
return null;
}

//------------------------------------------------------------------------------------
Expand All @@ -77,26 +78,17 @@ private string GetFullLinkbasePath(string ContainingDocumentUri, string Linkbase
{
return LinkbaseDocFilename;
}
int FirstPathSeparator = LinkbaseDocFilename.IndexOf(System.IO.Path.DirectorySeparatorChar);
if (FirstPathSeparator == -1)
{
string DocumentUri = ContainingDocumentUri;
int LastPathSeparator = DocumentUri.LastIndexOf(System.IO.Path.DirectorySeparatorChar);
if (LastPathSeparator == -1)
LastPathSeparator = DocumentUri.LastIndexOf('/');
string DocumentPath = DocumentUri.Substring(0, LastPathSeparator + 1);

// Check for remote linkbases when using local files
var DocumentUri = ContainingDocumentUri;
int LastPathSeparator = DocumentUri.LastIndexOf(System.IO.Path.DirectorySeparatorChar);
if (LastPathSeparator == -1)
LastPathSeparator = DocumentUri.LastIndexOf('/');
string DocumentPath = DocumentUri.Substring(0, LastPathSeparator + 1);

if ((DocumentPath.StartsWith("file:///") == true) && (LinkbaseDocFilename.StartsWith("http://") == true))
return LinkbaseDocFilename;
// Check for remote linkbases when using local files.

FullPath = DocumentPath + LinkbaseDocFilename;
}
else
{
throw new NotImplementedException("XbrlSchema.GetFullSchemaPath() code path not implemented.");
}
if ((DocumentPath.StartsWith("file:///") == true) && (LinkbaseDocFilename.StartsWith("http://") == true))
return LinkbaseDocFilename;
FullPath = DocumentPath + LinkbaseDocFilename;
return FullPath;
}

Expand Down
6 changes: 5 additions & 1 deletion JeffFerguson.Gepsio/LinkbaseDocumentCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,11 @@ private void ReadLinkbaseReference(string ContainingDocumentUri, INode LinkbaseR
// Attempt to use a factory method to look at the linkbase document and attempt to discover
// the correct document type.

this.thisLinkbaseDocuments.Add(LinkbaseDocument.Create(ContainingDocumentUri, xlinkNode.Href, containingFragment));
var createdDocument = LinkbaseDocument.Create(ContainingDocumentUri, xlinkNode.Href, containingFragment);
if (createdDocument != null)
{
this.thisLinkbaseDocuments.Add(createdDocument);
}
}
}
}
Expand Down
129 changes: 119 additions & 10 deletions JeffFerguson.Gepsio/XbrlDocument.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using JeffFerguson.Gepsio.IoC;
using JeffFerguson.Gepsio.Xml.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace JeffFerguson.Gepsio
Expand Down Expand Up @@ -174,13 +177,85 @@ public XbrlDocument()
/// </param>
public void Load(string Filename)
{
var SchemaValidXbrl = Container.Resolve<IDocument>();
SchemaValidXbrl.Load(Filename);
this.Filename = Filename;
this.Path = System.IO.Path.GetDirectoryName(this.Filename);
Parse(SchemaValidXbrl);
if (IsSecUri(Filename) == true)
{
LoadFromSec(Filename);
}
else
{
var SchemaValidXbrl = Container.Resolve<IDocument>();
SchemaValidXbrl.Load(Filename);
this.Filename = Filename;
this.Path = System.IO.Path.GetDirectoryName(this.Filename);
Parse(SchemaValidXbrl);
}
}

/// <summary>
/// Synchronously load a document directly from the SEC Web site.
/// </summary>
/// <remarks>
/// The SEC Web site does not allow code to scrape documents from the site
/// without supplying appropriate HTTP headers. Without the correct HTTP
/// headers, simply calling XDocument.Load() for a document stored at the
/// SEC Web site will fail, most likely with an HTTP 403 error code. Since
/// Gepsio contains unit tests that reference documents stored at the SEC Web
/// site, support for SEC-compatible HTTP headers is necessary. See documentation
/// at https://www.sec.gov/os/accessing-edgar-data for more information.
/// </remarks>
/// <param name="path">
/// The path of the document to load from the SEC Web site.
/// </param>
private void LoadFromSec(string path)
{
using(var request = new HttpRequestMessage(HttpMethod.Get, path))
{
var httpClientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
using (var httpClient = new HttpClient(httpClientHandler))
{
request.Headers.TryAddWithoutValidation("User-Agent", "Gepsio [email protected]");
request.Headers.Add("Accept-Encoding", "gzip, deflate");
request.Headers.Add("Host", "www.sec.gov");
var response = httpClient.Send(request);
response.EnsureSuccessStatusCode();
var responseAsStream = response.Content.ReadAsStream();
Load(responseAsStream);
}
}
}
/// <summary>
/// Asynchronously load a document directly from the SEC Web site.
/// </summary>
/// <remarks>
/// The SEC Web site does not allow code to scrape documents from the site
/// without supplying appropriate HTTP headers. Without the correct HTTP
/// headers, simply calling XDocument.Load() for a document stored at the
/// SEC Web site will fail, most likely with an HTTP 403 error code. Since
/// Gepsio contains unit tests that reference documents stored at the SEC Web
/// site, support for SEC-compatible HTTP headers is necessary. See documentation
/// at https://www.sec.gov/os/accessing-edgar-data for more information.
/// </remarks>
/// <param name="path">
/// The path of the document to load from the SEC Web site.
/// </param>
private async Task LoadFromSecAsync(string path)
{
using(var request = new HttpRequestMessage(HttpMethod.Get, path))
{
var httpClientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
using (var httpClient = new HttpClient(httpClientHandler))
{
request.Headers.TryAddWithoutValidation("User-Agent", "Gepsio [email protected]");
request.Headers.Add("Accept-Encoding", "gzip, deflate");
request.Headers.Add("Host", "www.sec.gov");
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var responseAsStream = await response.Content.ReadAsStreamAsync();
await LoadAsync(responseAsStream);
}
}
}

/// <summary>
/// Asynchronously loads a local filesystem or Internet-accessible XBRL document containing
/// XBRL data.
Expand All @@ -200,11 +275,23 @@ public void Load(string Filename)
/// </param>
public async Task LoadAsync(string Filename)
{
var SchemaValidXbrl = Container.Resolve<IDocument>();
await SchemaValidXbrl.LoadAsync(Filename);
this.Filename = Filename;
this.Path = System.IO.Path.GetDirectoryName(this.Filename);
Parse(SchemaValidXbrl);
//var SchemaValidXbrl = Container.Resolve<IDocument>();
//await SchemaValidXbrl.LoadAsync(Filename);
//this.Filename = Filename;
//this.Path = System.IO.Path.GetDirectoryName(this.Filename);
//Parse(SchemaValidXbrl);
if (IsSecUri(Filename) == true)
{
await LoadFromSecAsync(Filename);
}
else
{
var SchemaValidXbrl = Container.Resolve<IDocument>();
await SchemaValidXbrl.LoadAsync(Filename);
this.Filename = Filename;
this.Path = System.IO.Path.GetDirectoryName(this.Filename);
Parse(SchemaValidXbrl);
}
}

/// <summary>
Expand Down Expand Up @@ -373,6 +460,28 @@ public async Task LoadAsync(Stream dataStream)
Parse(SchemaValidXbrl);
}

/// <summary>
/// Determines whether or not a URI references the SEC Web site.
/// </summary>
/// <param name="uriPath">
/// The URI to check.
/// </param>
/// <returns>
/// True if the supplied URI is an SEC URI; false otherwise.
/// </returns>
private bool IsSecUri(string uriPath)
{
try
{
var uriToInspect = new Uri(uriPath);
return uriToInspect.Host.ToLower().Trim().Equals("www.sec.gov");
}
catch(UriFormatException)
{
return false;
}
}

/// <summary>
/// Parse the document, looking for fragments that can be processed.
/// </summary>
Expand Down
Loading

0 comments on commit a85bbb2

Please sign in to comment.