├── .gitignore
├── SpeckleCore
├── Models
│ ├── ModelObjects.cs
│ ├── ModelObjectsExt.cs
│ ├── ModelResponses.cs
│ └── ModelBase.cs
├── Data
│ ├── SpeckleError.cs
│ └── SpeckleException.cs
├── Conversion
│ ├── Converter.cs
│ ├── ConverterUtilities.cs
│ ├── ConverterSerialisation.cs
│ ├── JsonConverters.cs
│ └── ConverterDeserialisation.cs
├── SpeckleCore.nuspec
├── SpeckleCore.sln
├── Generic Utils
│ └── GzipContent.cs
├── SpeckleCore.csproj
├── ApiClient
│ ├── SpeckleApiClientHead.cs
│ └── SpeckleApiClientExtension.cs
├── LocalData
│ ├── Models.cs
│ └── SpeckleLocalContext.cs
├── ModuleInitializer.cs
├── Telemetry.cs
└── AssemblyCatalogue.cs
├── ISSUE_TEMPLATE.md
├── SpeckleTests
├── SpeckleTests.csproj
└── Kits.cs
├── LICENSE
├── README.md
├── appveyor.yml
├── .gitattributes
├── CODE_OF_CONDUCT.md
└── CONTRIBUTING.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | obj/
3 | packages/
4 | bin/
5 | *.nupkg
6 | *.snupkg
7 |
--------------------------------------------------------------------------------
/SpeckleCore/Models/ModelObjects.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace SpeckleCore
10 | {
11 | }
12 |
--------------------------------------------------------------------------------
/SpeckleCore/Data/SpeckleError.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SpeckleCore.Data
8 | {
9 | public class SpeckleError
10 | {
11 | public string Message { get; set; }
12 | public string Details { get; set; }
13 | }
14 | public class SpeckleConversionError : SpeckleError
15 | {
16 | public object SourceObject { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Step 0:
2 | - [ ] I've read the [contribution guidelines](https://github.com/speckleworks/SpeckleOrg/blob/master/CONTRIBUTING.md)!
3 | #### Expected Behaviour
4 | How things should actually work!
5 |
6 |
7 | #### Actual Behaviour
8 | What's actually going on!
9 |
10 |
11 | #### Affected Projects
12 | Does this issue propagate to other dependencies or dependants? If so, list them here!
13 |
14 |
15 | #### Reproduction Steps & System Config (win, osx, web, etc.)
16 |
17 | #### Proposed Solution (if any)
18 |
--------------------------------------------------------------------------------
/SpeckleTests/SpeckleTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/SpeckleTests/Kits.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using SpeckleCore;
3 |
4 | namespace SpeckleTests
5 | {
6 | public class GenericTests
7 | {
8 | [SetUp]
9 | public void Setup()
10 | {
11 | System.IO.Directory.CreateDirectory(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + @"\SpeckleKits\");
12 | SpeckleCore.SpeckleInitializer.Initialize();
13 | }
14 |
15 | [Test]
16 | public void LoadingKits()
17 | {
18 | var kits = SpeckleCore.SpeckleInitializer.GetAssemblies();
19 | var types = SpeckleCore.SpeckleInitializer.GetTypes();
20 |
21 | Assert.GreaterOrEqual(types.Count, 1);
22 | Assert.GreaterOrEqual(kits.Count, 1);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/SpeckleCore/Conversion/Converter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Concurrent;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Drawing;
7 | using System.Linq;
8 | using System.Reflection;
9 | using System.Runtime.CompilerServices;
10 | using System.Runtime.InteropServices;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 |
14 |
15 | namespace SpeckleCore
16 | {
17 | public abstract partial class Converter
18 | {
19 | public static Dictionary toSpeckleMethods = new Dictionary();
20 |
21 | public static Dictionary toNativeMethods = new Dictionary();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/SpeckleCore/Data/SpeckleException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SpeckleCore.Data
8 | {
9 | public class SpeckleException : Exception
10 | {
11 | public SpeckleException()
12 | {
13 | }
14 |
15 | public SpeckleException(string message)
16 | : base(message)
17 | {
18 | }
19 |
20 | public SpeckleException(string message, Exception inner)
21 | : base(message, inner)
22 | {
23 | }
24 | }
25 |
26 | public class RevitFamilyNotFoundException : SpeckleException
27 | {
28 | public RevitFamilyNotFoundException()
29 | {
30 | }
31 |
32 | public RevitFamilyNotFoundException(string message)
33 | : base(message)
34 | {
35 | }
36 |
37 | public RevitFamilyNotFoundException(string message, Exception inner)
38 | : base(message, inner)
39 | {
40 | }
41 | }
42 | }
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SpeckleCore/SpeckleCore.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $title$
7 | $author$
8 | $author$
9 | MIT
10 | https://github.com/speckleworks/SpeckleCore
11 | https://avatars2.githubusercontent.com/u/31284874
12 | false
13 | $description$
14 |
15 | $copyright$
16 | speckle core
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Dimitrie A. Stefanescu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SpeckleCore
2 | [](https://ci.appveyor.com/project/SpeckleWorks/specklecore/branch/master) [](https://zenodo.org/badge/latestdoi/100398062)
3 |
4 |
5 |
6 | ## ⚠️ IMPORTANT ⚠️
7 |
8 | Speckle v1 has reached EOL and is no longer mainatined. Check out our brand new 👉 [Speckle v2](https://github.com/specklesystems)!
9 | Read more about the announcemnt [here](https://speckle.systems/blog/speckle2-vision-and-faq) and check out or new [website](https://speckle.systems).
10 |
11 |
12 | ## Overview
13 |
14 | This is the core .NET client lib of Speckle. It provides:
15 | - async methods for calling the speckle [api](https://speckleworks.github.io/SpeckleOpenApi/)
16 | - methods for interacting with the speckle's websocket api
17 | - the core conversion methods (`Serialise` and `Deserialise`) & other helper methods
18 | - a base SpeckleObject from which you can inherit to create your own speckle kits
19 |
20 | Pretty much all of speckle's connectors are using this library, including:
21 | - Rhino
22 | - Grasshopper
23 | - Revit
24 | - Dynamo
25 | - Unity (with flavours)
26 |
27 | ## Example usage
28 |
29 | Please check [out the docs and sample starter project on the speckle website](https://speckle.systems/docs/developers/dotnet-sdk)!
30 |
31 | ## License
32 | MIT
33 |
--------------------------------------------------------------------------------
/SpeckleCore/SpeckleCore.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29519.87
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpeckleCore", "SpeckleCore.csproj", "{2160CC3B-A7E6-4BC5-8C65-742487B16553}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpeckleTests", "..\SpeckleTests\SpeckleTests.csproj", "{C8A44343-4376-4A57-9199-072F08F19E57}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {2160CC3B-A7E6-4BC5-8C65-742487B16553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {2160CC3B-A7E6-4BC5-8C65-742487B16553}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {2160CC3B-A7E6-4BC5-8C65-742487B16553}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {2160CC3B-A7E6-4BC5-8C65-742487B16553}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {C8A44343-4376-4A57-9199-072F08F19E57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {C8A44343-4376-4A57-9199-072F08F19E57}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {C8A44343-4376-4A57-9199-072F08F19E57}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {C8A44343-4376-4A57-9199-072F08F19E57}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {4FFC29F0-AC63-4B46-87B2-946DDC4F1454}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/SpeckleCore/Generic Utils/GzipContent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.IO.Compression;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Net.Http;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace SpeckleCore
12 | {
13 | ///
14 | /// https://cymbeline.ch/2014/03/16/gzip-encoding-an-http-post-request-body/
15 | ///
16 | internal sealed class GzipContent : HttpContent
17 | {
18 | private readonly HttpContent content;
19 |
20 | public GzipContent( HttpContent content )
21 | {
22 | if(content == null)
23 | {
24 | return;
25 | }
26 |
27 | this.content = content;
28 |
29 | // Keep the original content's headers ...
30 | if ( content != null )
31 | foreach ( KeyValuePair> header in content.Headers )
32 | {
33 | Headers.TryAddWithoutValidation( header.Key, header.Value );
34 | }
35 |
36 | // ... and let the server know we've Gzip-compressed the body of this request.
37 | Headers.ContentEncoding.Add( "gzip" );
38 | }
39 |
40 | protected override async Task SerializeToStreamAsync( Stream stream, TransportContext context )
41 | {
42 | // Open a GZipStream that writes to the specified output stream.
43 | using ( GZipStream gzip = new GZipStream( stream, CompressionMode.Compress, true ) )
44 | {
45 | // Copy all the input content to the GZip stream.
46 | if ( content != null )
47 | await content.CopyToAsync( gzip );
48 | else
49 | await ( new System.Net.Http.StringContent( string.Empty ) ).CopyToAsync( gzip );
50 | }
51 | }
52 |
53 | protected override bool TryComputeLength( out long length )
54 | {
55 | length = -1;
56 | return false;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/SpeckleCore/SpeckleCore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net45;netstandard2.0
4 | https://speckle.works
5 | 8.0
6 | Speckle
7 | Speckle
8 | SpeckleCore
9 | .NET base for the speckle api
10 | .NET base for the speckle api
11 | en-US
12 | Copyright © Speckle
13 | SpeckleCore
14 | SpeckleCore
15 | https://speckle.works
16 | https://github.com/speckleworks/SpeckleCore
17 | true
18 | true
19 | MIT
20 | snupkg
21 | 1.0.0.0
22 | 1.0.0.0
23 | 1.0.0.0
24 | 1.0.0.0
25 | 1.0.0.0
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/SpeckleCore/ApiClient/SpeckleApiClientHead.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Net.Http;
5 | using System.IO.Compression;
6 | using System.IO;
7 | using System.Text;
8 |
9 |
10 | namespace SpeckleCore
11 | {
12 | [System.CodeDom.Compiler.GeneratedCode( "NSwag", "11.3.3.0" )]
13 | public partial class SpeckleApiClient
14 | {
15 | private System.Lazy _settings;
16 |
17 | partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings );
18 |
19 | partial void PrepareRequest( System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url );
20 |
21 | partial void PrepareRequest( System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder );
22 |
23 | partial void ProcessResponse( System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response );
24 |
25 | partial void ProcessResponse( HttpClient client, HttpResponseMessage response )
26 | {
27 |
28 | }
29 |
30 | partial void PrepareRequest( HttpClient client, HttpRequestMessage request, string url )
31 | {
32 | // Try and attach the auth token if present
33 | if ( AuthToken != "" && AuthToken != null )
34 | request.Headers.Add( "Authorization", AuthToken );
35 |
36 | // Let the server know about our aspiration to accept gzipped content.
37 | request.Headers.Add( "Accept-Encoding", "gzip" );
38 |
39 | // If actually sending a payload, deflate it.
40 | if ( UseGzip && request.Method != HttpMethod.Get )
41 | request.Content = new GzipContent( request.Content );
42 | }
43 |
44 | private HttpClient GetHttpClient(double timeoutMillisecondsOverride = 0)
45 | {
46 | var handler = new HttpClientHandler
47 | {
48 | AutomaticDecompression = System.Net.DecompressionMethods.GZip
49 | };
50 | return new HttpClient(handler, true)
51 | {
52 | Timeout = TimeSpan.FromMilliseconds(timeoutMillisecondsOverride == 0 ? defaultTimeoutMilliseconds : timeoutMillisecondsOverride)
53 | };
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '{build}'
2 | image: Visual Studio 2019
3 | init:
4 | - ps: |
5 | If($Env:APPVEYOR_REPO_TAG -eq "true")
6 | {
7 | Write-Host "We now have a tagged release. Proper."
8 | Write-Host "Tag is $Env:APPVEYOR_REPO_TAG_NAME"
9 | $base = $env:APPVEYOR_REPO_TAG_NAME.split('-')[0]
10 | $arr = $base.split(".")
11 | $major = $arr[0]
12 | $minor = $arr[1]
13 | $patch = $arr[2]
14 | Update-AppveyorBuild -Version "$major.$minor.$patch.$Env:APPVEYOR_BUILD_VERSION"
15 | $env:CLEANTAG=$base
16 | }
17 | else
18 | {
19 | $releases = "https://api.github.com/repos/$env:APPVEYOR_REPO_NAME/releases"
20 | $tag = (Invoke-WebRequest $releases | ConvertFrom-Json)[0].tag_name
21 |
22 | $base = $tag.Split("-")[0]
23 | $arr = $base.split(".")
24 | $major = $arr[0]
25 | $minor = $arr[1]
26 | $patch = $arr[2]
27 | Update-AppveyorBuild -Version "$major.$minor.$patch.$Env:APPVEYOR_BUILD_VERSION-wip"
28 | $env:CLEANTAG=$base
29 | }
30 | Write-Host "Hello. Build version is: $Env:APPVEYOR_BUILD_VERSION; Clean Tag: $Env:CLEANTAG"
31 |
32 | before_build:
33 | - cmd: >-
34 | nuget restore SpeckleCore\SpeckleCore.sln
35 |
36 | # version
37 | dotnet_csproj:
38 | patch: true
39 | file: '**\*.csproj'
40 | version: $(CLEANTAG)
41 | assembly_version: $(CLEANTAG)
42 | file_version: $(CLEANTAG)
43 | informational_version: $(CLEANTAG)
44 | package_version: '{version}'
45 |
46 |
47 | build:
48 | publish_nuget: true
49 | publish_nuget_symbols: true
50 | use_snupkg_format: true
51 | project: SpeckleCore\SpeckleCore.sln
52 | verbosity: minimal
53 |
54 | deploy:
55 | provider: NuGet
56 | server: # remove to push to NuGet.org
57 | api_key:
58 | secure: 5avZp2CuKwWIDcMTTQhXtRWX297z/dnZraZoSeGSey8W4stBeZIm5pZU38tTmJWZ
59 | skip_symbols: false
60 | symbol_server: # remove to push symbols to SymbolSource.org
61 | on:
62 | appveyor_repo_tag: true
63 | notifications:
64 | - provider: Slack
65 | incoming_webhook:
66 | secure: 9Kt/ImvGdsQ/dzmRdSaMIG+BO0R29MOJC7eZZnK5m5TyWwE+4nofEcYlb/r4lh9Z1Dx/bR+7oQtgAYO3W5s+qJshkT6Is9irYw3TfMZX7/M=
67 | channel: '#devtalk'
68 | template: Build <{{buildUrl}}|#{{buildVersion}}> (<{{commitUrl}}|{{commitId}}>) of {{repositoryName}}@{{branch}}) by {{commitAuthor}} {{status}} in {{duration}}
69 | on_build_success: false
70 | on_build_failure: true
71 | on_build_status_changed: true
72 | configuration:
73 | - Release
74 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces (github, slack, forum) and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@speckle.works. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/SpeckleCore/LocalData/Models.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using SQLite;
7 |
8 | namespace SpeckleCore
9 | {
10 |
11 | ///
12 | /// Simple class to keep track of telemetry settings.
13 | ///
14 | public class TelemetrySettings
15 | {
16 | [PrimaryKey, AutoIncrement]
17 | public int SettingsId { get; set; }
18 |
19 | public bool Enabled { get; set; } = true;
20 | }
21 |
22 | ///
23 | /// A class for a generic speckle account, composed of all the identification props for a user & server combination.
24 | ///
25 | public class Account
26 | {
27 | [PrimaryKey, AutoIncrement]
28 | public int AccountId { get; set; }
29 |
30 | public string ServerName { get; set; }
31 |
32 | [Indexed]
33 | public string RestApi { get; set; }
34 |
35 | [Indexed]
36 | public string Email { get; set; }
37 |
38 | public string Token { get; set; }
39 |
40 | public bool IsDefault { get; set; } = false;
41 | }
42 |
43 | ///
44 | /// Special class for efficiently storing sent objects. Why? We do not want to store them fully as they are already stored in the users's file. Kind of duplicates the CachedObject.
45 | ///
46 | public class SentObject
47 | {
48 | ///
49 | /// Represents the api this object came from
50 | ///
51 | [Indexed]
52 | public string RestApi { get; set; }
53 |
54 | [Indexed]
55 | public string DatabaseId { get; set; }
56 |
57 | [Indexed]
58 | public string Hash { get; set; }
59 | }
60 |
61 | ///
62 | /// A class for storing cached objects (that have been retrieved from a database).
63 | ///
64 | public class CachedObject
65 | {
66 | ///
67 | /// Represents hash(databaseId + restApi)
68 | ///
69 | [PrimaryKey, Indexed( Unique = true )]
70 | public string CombinedHash { get; set; }
71 |
72 | ///
73 | /// Represents the api this object came from
74 | ///
75 | [Indexed]
76 | public string RestApi { get; set; }
77 |
78 | [Indexed]
79 | public string DatabaseId { get; set; }
80 |
81 | [Indexed]
82 | public string Hash { get; set; }
83 |
84 | public DateTime AddedOn {get;set;}
85 |
86 | public byte[ ] Bytes { get; set; }
87 |
88 | ///
89 | /// Returns the speckle object from cache.
90 | ///
91 | ///
92 | public SpeckleObject ToSpeckle( )
93 | {
94 | return SpeckleCore.Converter.getObjFromBytes( this.Bytes ) as SpeckleObject;
95 | }
96 | }
97 |
98 | public class CachedStream
99 | {
100 | ///
101 | /// Represents hash(streamId + restApi)
102 | ///
103 | [PrimaryKey, Indexed( Unique = true )]
104 | public string CombinedHash { get; set; }
105 |
106 | ///
107 | /// Represents the api this object came from
108 | ///
109 | [Indexed]
110 | public string RestApi { get; set; }
111 |
112 | [Indexed]
113 | public string StreamId { get; set; }
114 |
115 | public DateTime AddedOn { get; set; }
116 |
117 | public DateTime UpdatedOn { get; set; }
118 |
119 | public byte[ ] Bytes { get; set; }
120 |
121 | public SpeckleStream ToSpeckle()
122 | {
123 | return SpeckleStream.FromJson( SpeckleCore.Converter.getObjFromBytes( this.Bytes ) as string ); // ((SpeckleCore.Converter.getObjFromBytes( this.Bytes ) as SpeckleStream;
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/SpeckleCore/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Security.Cryptography;
6 | using System.Threading.Tasks;
7 | using CountlySDK;
8 | using CountlySDK.Entities;
9 | using DeviceId;
10 | using DeviceId.Encoders;
11 | using DeviceId.Formatters;
12 |
13 | namespace SpeckleCore
14 | {
15 | ///
16 | /// Use this interface to make sure static extension methods/object defintions are loaded from SpeckleKits AND/OR that you force a reference to SpeckleCore (thus making sure the assembly is loaded.
17 | ///
18 | public interface ISpeckleInitializer { }
19 |
20 | ///
21 | /// Initialisation class to be called from any application that hosts the speckle plugin
22 | /// at the begginning of the rituals
23 | ///
24 | public static class SpeckleInitializer
25 | {
26 | private static bool IsInit = false;
27 | private static IReadOnlyCollection Assembiles;
28 | private static IReadOnlyCollection Types;
29 |
30 | public static void Initialize( string pathToKits = null)
31 | {
32 | if ( IsInit ) return;
33 |
34 | IsInit = true;
35 |
36 | LocalContext.Init();
37 | Assembiles = new SpeckleKitLoader(pathToKits).GetAssemblies();
38 |
39 | var types = new List();
40 | foreach ( var assembly in Assembiles )
41 | {
42 | types.AddRange( FindDerivedTypes( assembly, typeof( SpeckleObject ) ).ToList() );
43 | }
44 | types.Add( typeof( SpeckleObject ) );
45 | Types = types;
46 |
47 | ////////////////////////////////////////////////////////////////////////////////////////////////////
48 | /// ///
49 | /// ///
50 | /// Hello devs! Uncomment the line below to disable telemetry. ///
51 | /// This will make speckle sad, but it's your call. ///
52 | /// See community discussions here: ///
53 | /// https://speckle-works.slack.com/archives/C4TE17LGH/p1567520201017900 ///
54 | /// https://discourse.speckle.works/t/community-consultation-time-telemetry/410 ///
55 | /// ///
56 | /// ///
57 | ////////////////////////////////////////////////////////////////////////////////////////////////////
58 |
59 | // LocalContext.SetTelemetrySettings( false );
60 |
61 | // Note: if telemetry settings is set to false, then this will do nothing.
62 | SpeckleTelemetry.Initialize();
63 | }
64 |
65 | ///
66 | /// Returns all the assemblies that have been loaded and are referencing SpeckleCore.
67 | ///
68 | ///
69 | public static IReadOnlyCollection GetAssemblies( )
70 | {
71 | return Assembiles;
72 | }
73 |
74 | ///
75 | /// Gets the available speckle types, from core and other speckle kits.
76 | ///
77 | ///
78 | public static IReadOnlyCollection GetTypes( )
79 | {
80 | return Types;
81 | }
82 |
83 | private static IEnumerable FindDerivedTypes( Assembly assembly, Type baseType )
84 | {
85 | var types = assembly.GetTypes();
86 | return assembly.GetTypes().Where( t => t.IsSubclassOf( baseType ) );
87 | }
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/SpeckleCore/Telemetry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using CountlySDK;
8 | using CountlySDK.Entities;
9 | using DeviceId;
10 | using DeviceId.Encoders;
11 | using DeviceId.Formatters;
12 |
13 | namespace SpeckleCore
14 | {
15 | public static class SpeckleTelemetry
16 | {
17 | private static bool isInitialized = false;
18 |
19 | public static string DeviceId { get; set; }
20 |
21 | public static void Initialize( )
22 | {
23 | if ( isInitialized )
24 | return;
25 |
26 | if ( LocalContext.GetTelemetrySettings() == false )
27 | return;
28 | try
29 | {
30 | DeviceId = new DeviceIdBuilder()
31 | .AddMachineName()
32 | .AddProcessorId()
33 | .UseFormatter(new HashDeviceIdFormatter(() => SHA256.Create(), new Base64UrlByteArrayEncoder()))
34 | .ToString();
35 |
36 | var config = new CountlyConfig()
37 | {
38 | serverUrl = "https://telemetry.speckle.works",
39 | appKey = "cd6db5058036aafb6a3a82681d434ad74ee50ad9",
40 | deviceIdMethod = Countly.DeviceIdMethod.developerSupplied,
41 | developerProvidedDeviceId = DeviceId
42 | };
43 |
44 | Countly.IsLoggingEnabled = true;
45 | Countly.Instance.Init(config);
46 | Countly.Instance.RecordView("speckle-init");
47 | Countly.Instance.RecordView("speckle-init/version/" + typeof(SpeckleTelemetry).Assembly.GetName().Version);
48 |
49 | isInitialized = true;
50 | }catch(Exception e)
51 | {
52 | // POKEMON
53 | isInitialized = false;
54 | }
55 | }
56 |
57 | public static void RecordTestEvent( string clientType )
58 | {
59 | Initialize();
60 |
61 | if ( LocalContext.GetTelemetrySettings() == false )
62 | return;
63 |
64 | var segmentation = GetSegmentation( clientType );
65 | var test = Countly.RecordEvent( "test-event", 1, segmentation ).Result;
66 | }
67 |
68 | public static void RecordStreamCreated( string clientType )
69 | {
70 | Initialize();
71 |
72 | if ( LocalContext.GetTelemetrySettings() == false )
73 | return;
74 |
75 | Task.Run( ( ) =>
76 | {
77 | try
78 | {
79 | Countly.RecordEvent( "stream-created", 1, GetSegmentation( clientType ) );
80 | }
81 | catch ( Exception e )
82 | {
83 | }
84 | } );
85 | }
86 |
87 | public static void RecordStreamUpdated( string clientType )
88 | {
89 | Initialize();
90 |
91 | if ( LocalContext.GetTelemetrySettings() == false )
92 | return;
93 |
94 | Task.Run( ( ) =>
95 | {
96 | try
97 | {
98 | Countly.RecordEvent( "stream-updated", 1, GetSegmentation( clientType ) );
99 | }
100 | catch { }
101 | } );
102 | }
103 |
104 | public static void RecordStreamReceived( string clientType )
105 | {
106 | Initialize();
107 |
108 | if ( LocalContext.GetTelemetrySettings() == false )
109 | return;
110 |
111 | Task.Run( ( ) =>
112 | {
113 | try
114 | {
115 | Countly.RecordEvent( "stream-received", 1, GetSegmentation( clientType ) );
116 | }
117 | catch ( Exception e )
118 | {
119 |
120 | }
121 | } );
122 | }
123 |
124 | private static Segmentation GetSegmentation( string clientType = "undefined" )
125 | {
126 | Initialize();
127 | var segmentation = new Segmentation();
128 | segmentation.Add( "machineId", DeviceId );
129 | segmentation.Add( "clientType", clientType );
130 | segmentation.Add( "coreVersion", GetAssemblyVersion() );
131 | return segmentation;
132 | }
133 |
134 | private static string GetAssemblyVersion( )
135 | {
136 | return System.Reflection.Assembly.GetCallingAssembly().GetName().Version.ToString();
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/SpeckleCore/Conversion/ConverterUtilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace SpeckleCore
9 | {
10 | ///
11 | /// Utility functions.
12 | ///
13 | public partial class Converter
14 | {
15 | public static string getBase64( object obj )
16 | {
17 | using ( System.IO.MemoryStream ms = new System.IO.MemoryStream() )
18 | {
19 | new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize( ms, obj );
20 | return Convert.ToBase64String( ms.ToArray() );
21 | }
22 | }
23 |
24 | public static byte[ ] getBytes( object obj )
25 | {
26 | using ( System.IO.MemoryStream ms = new System.IO.MemoryStream() )
27 | {
28 | new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize( ms, obj );
29 | return ms.ToArray();
30 | }
31 | }
32 |
33 | public static object getObjFromString( string base64String )
34 | {
35 | if ( base64String == null ) return null;
36 | byte[ ] bytes = Convert.FromBase64String( base64String );
37 | return getObjFromBytes( bytes );
38 | }
39 |
40 | public static object getObjFromBytes( byte[ ] bytes )
41 | {
42 | using ( System.IO.MemoryStream ms = new System.IO.MemoryStream( bytes, 0, bytes.Length ) )
43 | {
44 | ms.Write( bytes, 0, bytes.Length );
45 | ms.Position = 0;
46 | return new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Deserialize( ms );
47 | }
48 | }
49 |
50 | public static string bytesToBase64( byte[ ] arr )
51 | {
52 | return Convert.ToBase64String( arr );
53 | }
54 |
55 | public static byte[ ] base64ToBytes( string str )
56 | {
57 | return Convert.FromBase64String( str );
58 | }
59 |
60 | ///
61 | /// Returns a stringifed MD5 hash of a string.
62 | ///
63 | /// String from which to generate the hash
64 | /// If 0, the full hasdh will be returned, otherwise it will be trimmed to the specified lenght
65 | ///
66 | public static string getMd5Hash( string str, int length = 0 )
67 | {
68 | using ( System.IO.MemoryStream ms = new System.IO.MemoryStream() )
69 | {
70 | new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize( ms, str );
71 | byte[ ] hash;
72 | using ( System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create() )
73 | {
74 | hash = md5.ComputeHash( ms.ToArray() );
75 | StringBuilder sb = new StringBuilder();
76 | foreach ( byte bbb in hash )
77 | sb.Append( bbb.ToString( "X2" ) );
78 |
79 | if ( length != 0 )
80 | return sb.ToString().ToLower().Substring( 0, length );
81 | else
82 | return sb.ToString().ToLower();
83 | }
84 | }
85 | }
86 |
87 | // https://stackoverflow.com/a/299526/3446736
88 | private static IEnumerable GetExtensionMethods( Assembly assembly, Type extendedType, string methodName )
89 | {
90 | var query = from type in assembly.GetTypes()
91 | where type.IsSealed && !type.IsGenericType && !type.IsNested
92 | from method in type.GetMethods( BindingFlags.Static
93 | | BindingFlags.Public | BindingFlags.NonPublic )
94 | where method.IsDefined( typeof( System.Runtime.CompilerServices.ExtensionAttribute ), false )
95 | where method.GetParameters()[ 0 ].ParameterType == extendedType
96 | where method.Name == methodName
97 | select method;
98 | return query;
99 | }
100 | }
101 |
102 | ///
103 | /// ref: https://stackoverflow.com/a/24087164
104 | ///
105 | public static class ListExtensions
106 | {
107 | public static List> ChunkBy( this List source, int chunkSize )
108 | {
109 | return source
110 | .Select( ( x, i ) => new { Index = i, Value = x } )
111 | .GroupBy( x => x.Index / chunkSize )
112 | .Select( x => x.Select( v => v.Value ).ToList() )
113 | .ToList();
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Speckle Contribution Guidelines
2 | ## Introduction
3 |
4 | Thank you for reading this! Speckle's a rather wide network of parts that depend on each other, either directly, indirectly or even just cosmetically.
5 |
6 | > Here's the gist: **Speckle** is an ecosystem consisting of a server, a contract and various clients. All manifestations of speckle that you see and interact with are, essentially, clients or composed of several clients.
7 |
8 | This means that what might look like a simple quick change in one repo may have a big hidden cost that propagates around other parts of the project. We're all here to help each other, and this guide is meant to help you get started and promote a framework that can untangle all these dependecies through discussion!
9 |
10 | ## Bugs & Issues 🐞
11 |
12 | Found a new bug?
13 | - First step is to check whether this is a new bug! We encourage you to search through the issues of the project in question **and** associated repos!
14 |
15 | - If you come up with nothing, open a new issue with a clear title and description, as much relevant information as possible: system configuration, code samples & steps to reproduce the problem.
16 |
17 | - Also, most importantly, do reference & note all potentially affected projects.
18 |
19 | > **Example**: https://github.com/speckleworks/SpeckleCore/issues/67
20 | Adding a project number to `SpeckleProjects`: this is a minor change in Speckle's .NET SDK. Nevertheless, this also requires an update in the SpeckleServer's models definition and, furthermore, an update of the respective schema in Speckle Specs & a rebuild of the docs. What initially looks like a 1 line addition to a c# class suddenly becomes a proper quest by itself!
21 |
22 | ## Patches For Bugs ⚠️
23 | You fixed something!
24 |
25 | - If the bug was logged previously as an issue, do reference that issue!
26 | - If it's a previously unreported bug, do describe it and the resolution you implmemented.
27 |
28 | > Make sure though that you've covered the lateral thinking needed for a bug report, as described above, also in your implementation!
29 |
30 | ## Patches For New Features 🎉
31 | Discuss first!
32 |
33 | - Before embarking on adding a new feature, suggest it first as an issue with the `enhancement` label and/or title - this will allow relevant people to pitch in
34 | - Start writing code & submit a PR once you're moderately happy.
35 |
36 | > Many clients may potentially have overlapping scopes, some features might already be in dev somewhere else, or might have been postponed to the next major release due to api instability in that area. For example, adding a delete stream button in the accounts panel in rhino: this feature was planned for speckle admin, and the whole functionality of the accounts panel in rhino is to be greatly reduced!
37 |
38 | ## Cosmetic Patches ✨
39 |
40 | Changes that are cosmetic in nature and do not add anything substantial to the stability or functionality of Speckle **will generally not be accepted**.
41 |
42 | Why? However trivial the changes might seem, there might be subtle reasons for the original code to be as it is. Furthermore, there are a lot of potential hidden costs (that even maintainers themselves are not aware of fully!) and they eat up review time unncessarily.
43 |
44 | > **Examples**: modifying the colour of an UI element in one client may have a big hidden cost and need propagation in several other clients that implement a similar ui element. Changing the default port or specifiying `localhost` instead of `0.0.0.0` breaks cross-vm debugging and developing.
45 |
46 |
47 | ## Wrap up
48 | Don't worry if you get things wrong. We all do, including project owners: this document should've been here a long time ago. There's plenty of room for discussion either on the [slack group](https://slacker.speckle.works) or [the forum](https://discourse.speckle.works).
49 |
50 | 🙌❤️💙💚💜🙌
51 |
52 | #### Appendix: Ecosystem quick overview
53 |
54 | **The Server** is at the core of all things Speckle, but is not necessarily the primary source of truth. It also relays client messages (which, at the moment, are loosely regulated and not necessarily bound by a contract).
55 |
56 | **That source of truth is (should be!) the SpeckleSpecs**, the OpenApi 2 specification document that describes the REST api as well as the models (schemas) speckle operates with. This is the document that all speckle clients rely on to be able to talk with the server and each other.
57 |
58 | **The clients** all talk to the server via the REST api and optionally to each other via WS messages (that the server relays, and their only bounding box is the `streamId` room). Example client apps include SpeckleRhino (Rhino and Grasshopper components), SpeckleAdmin and the SpeckleViewer. Speckle Rhino depends on SpeckleCore, the .NET Speckle SDK (which is also dependend upon by SpeckleDynamo and other future .net bound clients) and SpeckleView, the UI frontend.
59 |
--------------------------------------------------------------------------------
/SpeckleCore/AssemblyCatalogue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Reflection;
6 | using System.Threading.Tasks;
7 | using System.IO;
8 | using System.Diagnostics;
9 |
10 | namespace SpeckleCore
11 | {
12 | ///
13 | /// Thanks to @radugidei for the idea: we're attempting to rip off NancyFX's guerilla assembly loading.
14 | /// See original src (MIT):
15 | /// https://raw.githubusercontent.com/NancyFx/Nancy/de458a9b42db6478e0c2bb8adef0f9fa342a2674/src/Nancy/AppDomainAssemblyCatalog.cs
16 | ///
17 | public class SpeckleKitLoader
18 | {
19 | private readonly AssemblyName SpeckleAssemblyName;
20 | private readonly Lazy> assemblies;
21 |
22 | public string SpeckleKitsDirectory;
23 |
24 | public SpeckleKitLoader( string pathToKits = null)
25 | {
26 | SpeckleKitsDirectory = pathToKits != null ? pathToKits : System.Environment.GetFolderPath( System.Environment.SpecialFolder.LocalApplicationData ) + @"\SpeckleKits\";
27 |
28 | SpeckleAssemblyName = typeof( SpeckleObject ).GetTypeInfo().Assembly.GetName();
29 | assemblies = new Lazy>( GetAvailableAssemblies );
30 | }
31 |
32 | public virtual IReadOnlyCollection GetAssemblies( )
33 | {
34 | return this.assemblies.Value;
35 | }
36 |
37 | private IReadOnlyCollection GetAvailableAssemblies( )
38 | {
39 | var assemblies = GetLoadedSpeckleReferencingAssemblies();
40 |
41 | var loaded = LoadSpeckleReferencingAssemblies( assemblies );
42 |
43 | return assemblies.Union( loaded ).ToArray();
44 | }
45 |
46 | private List GetLoadedSpeckleReferencingAssemblies( )
47 | {
48 | var assemblies = new List();
49 |
50 | foreach ( var assembly in AppDomain.CurrentDomain.GetAssemblies() )
51 | {
52 | if ( !assembly.IsDynamic && !assembly.ReflectionOnly && assembly.IsReferencing( SpeckleAssemblyName ) )
53 | {
54 | assemblies.Add( assembly );
55 | }
56 | }
57 |
58 | return assemblies;
59 | }
60 |
61 | private IEnumerable LoadSpeckleReferencingAssemblies( IEnumerable loadedAssemblies )
62 | {
63 | var assemblies = new HashSet();
64 | var loadedSpeckleReferencingAssemblyNames = loadedAssemblies.Select( assembly => assembly.GetName() ).ToArray();
65 | var directories = Directory.GetDirectories( SpeckleKitsDirectory );
66 | var currDomain = AppDomain.CurrentDomain;
67 |
68 |
69 | foreach ( var directory in directories )
70 | {
71 | foreach ( var assemblyPath in System.IO.Directory.EnumerateFiles( directory, "*.dll" ) )
72 | {
73 | var unloadedAssemblyName = SafeGetAssemblyName( assemblyPath );
74 |
75 | if ( unloadedAssemblyName == null )
76 | {
77 | continue;
78 | }
79 |
80 | if ( !loadedSpeckleReferencingAssemblyNames.Any( loadedSpeckleReferencingAssemblyName => AssemblyName.ReferenceMatchesDefinition( loadedSpeckleReferencingAssemblyName, unloadedAssemblyName ) ) )
81 | {
82 | //var relfectionLoadAssembly = Assembly.ReflectionOnlyLoadFrom( assemblyPath );
83 | var relfectionLoadAssembly = Assembly.LoadFrom( assemblyPath );
84 | var isReferencingCore = relfectionLoadAssembly.IsReferencing( SpeckleAssemblyName );
85 |
86 | if ( isReferencingCore )
87 | {
88 | Debug.WriteLine( "Load converter: " + unloadedAssemblyName );
89 | var assembly = SafeLoadAssembly( AppDomain.CurrentDomain, unloadedAssemblyName );
90 | if ( assembly != null )
91 | {
92 | var res = assembly.GetTypes();
93 | var copy = res;
94 |
95 | assemblies.Add( assembly );
96 | }
97 | }
98 | }
99 | }
100 | }
101 | return assemblies.ToArray();
102 | }
103 |
104 | private static AssemblyName SafeGetAssemblyName( string assemblyPath )
105 | {
106 | try
107 | {
108 | return AssemblyName.GetAssemblyName( assemblyPath );
109 | }
110 | catch
111 | {
112 | return null;
113 | }
114 | }
115 |
116 | private static Assembly SafeLoadAssembly( AppDomain domain, AssemblyName assemblyName )
117 | {
118 | try
119 | {
120 | return domain.Load( assemblyName );
121 | }
122 | catch
123 | {
124 | return null;
125 | }
126 | }
127 | }
128 |
129 | public static class AssemblyExtensions
130 | {
131 | ///
132 | /// Indicates if a given assembly references another which is identified by its name.
133 | ///
134 | /// The assembly which will be probed.
135 | /// The reference assembly name.
136 | /// A boolean value indicating if there is a reference.
137 | public static bool IsReferencing( this Assembly assembly, AssemblyName referenceName )
138 | {
139 | if ( AssemblyName.ReferenceMatchesDefinition( assembly.GetName(), referenceName ) )
140 | {
141 | return true;
142 | }
143 |
144 | foreach ( var referencedAssemblyName in assembly.GetReferencedAssemblies() )
145 | {
146 | if ( AssemblyName.ReferenceMatchesDefinition( referencedAssemblyName, referenceName ) )
147 | {
148 | return true;
149 | }
150 | }
151 |
152 | return false;
153 | }
154 |
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/SpeckleCore/Models/ModelObjectsExt.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | ///
10 | /// Extends the functionality of some DTO classes to be more accesible.
11 | /// So wow. Much partial.
12 | ///
13 |
14 | namespace SpeckleCore
15 | {
16 |
17 | public partial class SpeckleObject
18 | {
19 | ///
20 | /// Generates a truncated (to 12) md5 hash of an object. Set length to zero to get the full hash.
21 | ///
22 | ///
23 | public string GetMd5FromObject( object fromWhat, int length = 0 )
24 | {
25 | if ( fromWhat == null )
26 | {
27 | return "null";
28 | }
29 | using ( System.IO.MemoryStream ms = new System.IO.MemoryStream() )
30 | {
31 | new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize( ms, fromWhat );
32 |
33 | byte[ ] hash;
34 | using ( System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create() )
35 | {
36 | hash = md5.ComputeHash( ms.ToArray() );
37 | StringBuilder sb = new StringBuilder();
38 | foreach ( byte bbb in hash )
39 | sb.Append( bbb.ToString( "X2" ) );
40 |
41 | if ( length != 0 )
42 | return sb.ToString().ToLower().Substring( 0, length );
43 | else
44 | return sb.ToString().ToLower();
45 | }
46 | }
47 | }
48 |
49 | ///
50 | /// Recomputes the object's current hash; takes into account all values besides the hash itself, which is set to null before the calculation.
51 | ///
52 | public virtual void GenerateHash( )
53 | {
54 | this.Hash = null;
55 | this.Hash = this.GetMd5FromObject( this );
56 | }
57 |
58 | ///
59 | /// Use only for unit conversions. This will not affect the object hashes, thus potentially causing
60 | /// inconsistencies if used to save objects on a server.
61 | ///
62 | /// Scaling factor
63 | public virtual void Scale( double factor )
64 | {
65 | // Implemented object type by object type, if it makes sense.
66 | }
67 |
68 | ///
69 | /// Scales any speckle objects that can be found in an Dictionary.
70 | ///
71 | ///
72 | ///
73 | ///
74 | public Dictionary ScaleProperties( Dictionary dict, double factor )
75 | {
76 | if ( dict == null ) return null;
77 | foreach ( var kvp in dict )
78 | {
79 | try
80 | {
81 | var scaleMethod = kvp.Value.GetType().GetMethod( "Scale" );
82 | scaleMethod.Invoke( kvp.Value, new object[ ] { factor } );
83 | }
84 | catch ( Exception e )
85 | {
86 | Debug.WriteLine( "Error while scaling object." );
87 | }
88 | }
89 | return dict;
90 | }
91 | }
92 |
93 | public partial class SpeckleInput : SpeckleObject
94 | {
95 | public SpeckleInput( ) { }
96 |
97 | [Newtonsoft.Json.JsonProperty( "name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
98 | public string Name { get; set; }
99 |
100 | [Newtonsoft.Json.JsonProperty( "guid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
101 | public string Guid { get; set; }
102 |
103 | [Newtonsoft.Json.JsonProperty( "value", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
104 | public double Value { get; set; }
105 |
106 | [Newtonsoft.Json.JsonProperty( "inputType", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
107 | public string InputType { get; set; }
108 |
109 | [Newtonsoft.Json.JsonProperty( "max", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
110 | public double Max { get; set; }
111 |
112 | [Newtonsoft.Json.JsonProperty( "min", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
113 | public double Min { get; set; }
114 |
115 | [Newtonsoft.Json.JsonProperty( "step", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore )]
116 | public double Step { get; set; }
117 |
118 | public SpeckleInput( string name, float min, float max, float value, string inputType, string guid )
119 | {
120 | this.Name = name;
121 | this.Guid = guid;
122 | this.Min = min;
123 | this.Max = max;
124 | this.Value = value;
125 | this.InputType = inputType;
126 | }
127 | }
128 |
129 | // Output parameter (price, area)
130 | public partial class SpeckleOutput : SpeckleObject
131 | {
132 | public SpeckleOutput( ) { }
133 | public string Name { get; set; }
134 | public string Guid { get; set; }
135 | public string Value { get; set; }
136 |
137 | public SpeckleOutput( string name, string value, string guid )
138 | {
139 | this.Name = name;
140 | this.Guid = guid;
141 | this.Value = value;
142 | }
143 | }
144 |
145 | public partial class Layer : IEquatable
146 | {
147 | public Layer( ) { }
148 |
149 | public Layer( string name, string guid, string topology, int objectCount, int startIndex, int orderIndex )
150 | {
151 | this.Name = name;
152 | this.Guid = guid;
153 | this.Topology = topology;
154 | this.StartIndex = startIndex;
155 | this.ObjectCount = objectCount;
156 | this.OrderIndex = orderIndex;
157 | }
158 |
159 | public static void DiffLayerLists( IEnumerable oldLayers, IEnumerable newLayers, ref List toRemove, ref List toAdd, ref List toUpdate )
160 | {
161 | toRemove = oldLayers.Except( newLayers, new SpeckleLayerComparer() ).ToList();
162 | toAdd = newLayers.Except( oldLayers, new SpeckleLayerComparer() ).ToList();
163 | toUpdate = newLayers.Intersect( oldLayers, new SpeckleLayerComparer() ).ToList();
164 | }
165 |
166 | public bool Equals( Layer other )
167 | {
168 | return this.Guid == other.Guid;
169 | }
170 | }
171 |
172 | internal class SpeckleLayerComparer : IEqualityComparer
173 | {
174 | public bool Equals( Layer x, Layer y )
175 | {
176 | return x.Guid == y.Guid;
177 | }
178 |
179 | public int GetHashCode( Layer obj )
180 | {
181 | return obj.Guid.GetHashCode();
182 | }
183 | }
184 |
185 | }
186 |
--------------------------------------------------------------------------------
/SpeckleCore/Conversion/ConverterSerialisation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace SpeckleCore
10 | {
11 | public abstract partial class Converter
12 | {
13 | ///
14 | /// This method will convert an object to a SpeckleObject, if possible.
15 | ///
16 | /// The object.
17 | /// Null or a speckle object (SpeckleAbstract if no explicit conversion method is found).
18 | public static List Serialise(IEnumerable