From 578cf3948d0467e4ea93a2ae06716b4c8d88d337 Mon Sep 17 00:00:00 2001 From: BHoMBot Date: Tue, 3 Jan 2023 11:45:51 +0000 Subject: [PATCH 001/116] Upgrade AssemblyFileVersion to 6.1.0.0 --- Adapter_Engine/Adapter_Engine.csproj | 4 ++-- Adapter_oM/Adapter_oM.csproj | 4 ++-- BHoM_Adapter/BHoM_Adapter.csproj | 4 ++-- Structure_AdapterModules/Structure_AdapterModules.csproj | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Adapter_Engine/Adapter_Engine.csproj b/Adapter_Engine/Adapter_Engine.csproj index 13683644..4a3e8747 100644 --- a/Adapter_Engine/Adapter_Engine.csproj +++ b/Adapter_Engine/Adapter_Engine.csproj @@ -3,12 +3,12 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM BH.Engine.Adapter - 6.0.0.0 + 6.1.0.0 diff --git a/Adapter_oM/Adapter_oM.csproj b/Adapter_oM/Adapter_oM.csproj index 0aadd7ed..704a51ff 100644 --- a/Adapter_oM/Adapter_oM.csproj +++ b/Adapter_oM/Adapter_oM.csproj @@ -3,12 +3,12 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM BH.oM.Adapter - 6.0.0.0 + 6.1.0.0 diff --git a/BHoM_Adapter/BHoM_Adapter.csproj b/BHoM_Adapter/BHoM_Adapter.csproj index 4b9d05a0..b7f84929 100644 --- a/BHoM_Adapter/BHoM_Adapter.csproj +++ b/BHoM_Adapter/BHoM_Adapter.csproj @@ -3,12 +3,12 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM BH.Adapter - 6.0.0.0 + 6.1.0.0 diff --git a/Structure_AdapterModules/Structure_AdapterModules.csproj b/Structure_AdapterModules/Structure_AdapterModules.csproj index 844a42cb..8eb2709b 100644 --- a/Structure_AdapterModules/Structure_AdapterModules.csproj +++ b/Structure_AdapterModules/Structure_AdapterModules.csproj @@ -3,12 +3,12 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM BH.Adapter.Modules.Structure - 6.0.0.0 + 6.1.0.0 From 6bf0cb032d2a2a77352a637b220ad0407babd143 Mon Sep 17 00:00:00 2001 From: Fraser Greenroyd Date: Tue, 3 Jan 2023 15:57:24 +0000 Subject: [PATCH 002/116] Apply suggestions from code review --- Adapter_Engine/Adapter_Engine.csproj | 2 +- Adapter_oM/Adapter_oM.csproj | 2 +- BHoM_Adapter/BHoM_Adapter.csproj | 2 +- Structure_AdapterModules/Structure_AdapterModules.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Adapter_Engine/Adapter_Engine.csproj b/Adapter_Engine/Adapter_Engine.csproj index 4a3e8747..306514e1 100644 --- a/Adapter_Engine/Adapter_Engine.csproj +++ b/Adapter_Engine/Adapter_Engine.csproj @@ -3,7 +3,7 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM diff --git a/Adapter_oM/Adapter_oM.csproj b/Adapter_oM/Adapter_oM.csproj index 704a51ff..9c0029e7 100644 --- a/Adapter_oM/Adapter_oM.csproj +++ b/Adapter_oM/Adapter_oM.csproj @@ -3,7 +3,7 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM diff --git a/BHoM_Adapter/BHoM_Adapter.csproj b/BHoM_Adapter/BHoM_Adapter.csproj index b7f84929..e9f82e09 100644 --- a/BHoM_Adapter/BHoM_Adapter.csproj +++ b/BHoM_Adapter/BHoM_Adapter.csproj @@ -3,7 +3,7 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM diff --git a/Structure_AdapterModules/Structure_AdapterModules.csproj b/Structure_AdapterModules/Structure_AdapterModules.csproj index 8eb2709b..b9f16af8 100644 --- a/Structure_AdapterModules/Structure_AdapterModules.csproj +++ b/Structure_AdapterModules/Structure_AdapterModules.csproj @@ -3,7 +3,7 @@ netstandard2.0 6.0.0.0 - https://github.com/BHoM/BHoM_Adapter + https://github.com/BHoM/BHoM_Adapter 5.0.0 BHoM Copyright © https://github.com/BHoM From 00f162d489f03789e77e88cf0db9ea09a954b19f Mon Sep 17 00:00:00 2001 From: BHoMBot Date: Wed, 4 Jan 2023 11:35:14 +0000 Subject: [PATCH 003/116] Update copyright headers to 2023 --- Adapter_Engine/Create/BHoMAdapter.cs | 3 ++- Adapter_Engine/Modify/SetAdapterId.cs | 3 ++- Adapter_Engine/Query/AdapterId.cs | 3 ++- Adapter_Engine/Query/AdapterIds.cs | 3 ++- Adapter_Engine/Query/AdapterMethods.cs | 3 ++- Adapter_Engine/Query/GetComparerForType.cs | 3 ++- Adapter_Engine/Query/GetCopyPropertiesModules.cs | 3 ++- Adapter_Engine/Query/GetDependencyObjects.cs | 3 ++- Adapter_Engine/Query/GetDependencyTypes.cs | 3 ++- Adapter_Engine/Query/GetFullFileName.cs | 3 ++- Adapter_Engine/Query/HasAdapterIdFragment.cs | 3 ++- Adapter_oM/Enums/PullType.cs | 3 ++- Adapter_oM/Enums/PushType.cs | 3 ++- Adapter_oM/ExecuteCommands/Analyse.cs | 3 ++- Adapter_oM/ExecuteCommands/AnalyseLoadCases.cs | 3 ++- Adapter_oM/ExecuteCommands/ClearResults.cs | 3 ++- Adapter_oM/ExecuteCommands/Close.cs | 3 ++- Adapter_oM/ExecuteCommands/CustomCommand.cs | 3 ++- Adapter_oM/ExecuteCommands/Exit.cs | 3 ++- Adapter_oM/ExecuteCommands/NewModel.cs | 3 ++- Adapter_oM/ExecuteCommands/Open.cs | 3 ++- Adapter_oM/ExecuteCommands/Save.cs | 3 ++- Adapter_oM/ExecuteCommands/SaveAs.cs | 3 ++- Adapter_oM/ExecuteCommands/_IExecuteCommand.cs | 3 ++- Adapter_oM/FileSettings.cs | 3 ++- Adapter_oM/IBHoMAdapter.cs | 3 ++- Adapter_oM/Module/IAdapterModule.cs | 3 ++- Adapter_oM/Module/ICopyPropertiesModule.cs | 3 ++- Adapter_oM/Module/IGetDependencyModule.cs | 3 ++- Adapter_oM/Module/ModuleSet.cs | 3 ++- Adapter_oM/ObjectWrapper.cs | 3 ++- Adapter_oM/Settings-Config/ActionConfig.cs | 3 ++- Adapter_oM/Settings-Config/AdapterSettings.cs | 3 ++- BHoM_Adapter/AdapterActions/Execute.cs | 3 ++- BHoM_Adapter/AdapterActions/Move.cs | 3 ++- BHoM_Adapter/AdapterActions/Pull.cs | 3 ++- BHoM_Adapter/AdapterActions/Push.cs | 3 ++- BHoM_Adapter/AdapterActions/Remove.cs | 3 ++- BHoM_Adapter/AdapterActions/_PullMethods/ReadResults.cs | 3 ++- BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/AssignId.cs | 3 ++- .../AdapterActions/_PushMethods/AdapterId/NextFreeId.cs | 3 ++- .../AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs | 3 ++- .../AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs | 3 ++- .../AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs | 3 ++- .../AdapterActions/_PushMethods/ProcessObjectsForPush.cs | 3 ++- BHoM_Adapter/AdapterActions/_PushMethods/Support/UpdateTag.cs | 3 ++- BHoM_Adapter/BHoMAdapter.cs | 3 ++- BHoM_Adapter/CRUD/ICreate.cs | 3 ++- BHoM_Adapter/CRUD/IDelete.cs | 3 ++- BHoM_Adapter/CRUD/IRead.cs | 3 ++- BHoM_Adapter/CRUD/IUpdate.cs | 3 ++- BHoM_Adapter/HelperMethods/AdapterId.cs | 3 ++- BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs | 3 ++- BHoM_Adapter/HelperMethods/WrapNonBHoMObjects.cs | 3 ++- Structure_AdapterModules/CopyNodeProperties.cs | 3 ++- Structure_AdapterModules/ErrorMessages/ErrorMessages.cs | 3 ++- Structure_AdapterModules/GetCasesFromCombinations.cs | 3 ++- Structure_AdapterModules/GetCombinationsFromCombinations.cs | 3 ++- Structure_AdapterModules/ModuleLoader.cs | 3 ++- 59 files changed, 118 insertions(+), 59 deletions(-) diff --git a/Adapter_Engine/Create/BHoMAdapter.cs b/Adapter_Engine/Create/BHoMAdapter.cs index e6f08bf8..3263c596 100644 --- a/Adapter_Engine/Create/BHoMAdapter.cs +++ b/Adapter_Engine/Create/BHoMAdapter.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -162,3 +162,4 @@ public static IBHoMAdapter BHoMAdapter(Type adapterType, List parameters } } + diff --git a/Adapter_Engine/Modify/SetAdapterId.cs b/Adapter_Engine/Modify/SetAdapterId.cs index c252bf2c..829a9564 100644 --- a/Adapter_Engine/Modify/SetAdapterId.cs +++ b/Adapter_Engine/Modify/SetAdapterId.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -82,3 +82,4 @@ public static void SetAdapterId(this IBHoMObject bHoMObject, IAdapterId id) } + diff --git a/Adapter_Engine/Query/AdapterId.cs b/Adapter_Engine/Query/AdapterId.cs index 34421fd8..75a03e35 100644 --- a/Adapter_Engine/Query/AdapterId.cs +++ b/Adapter_Engine/Query/AdapterId.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -78,3 +78,4 @@ public static T AdapterId(this IBHoMObject bHoMObject, Type adapterIdFragment } } + diff --git a/Adapter_Engine/Query/AdapterIds.cs b/Adapter_Engine/Query/AdapterIds.cs index 05ced8eb..cb4e56fc 100644 --- a/Adapter_Engine/Query/AdapterIds.cs +++ b/Adapter_Engine/Query/AdapterIds.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -74,3 +74,4 @@ public static object AdapterIds(this IBHoMObject bHoMObject, Type adapterIdFragm } + diff --git a/Adapter_Engine/Query/AdapterMethods.cs b/Adapter_Engine/Query/AdapterMethods.cs index d1fd5c58..c22bb816 100644 --- a/Adapter_Engine/Query/AdapterMethods.cs +++ b/Adapter_Engine/Query/AdapterMethods.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -177,3 +177,4 @@ private static bool IsOfAllowedTypes(this Type type) + diff --git a/Adapter_Engine/Query/GetComparerForType.cs b/Adapter_Engine/Query/GetComparerForType.cs index 9bc428bf..ef147b42 100644 --- a/Adapter_Engine/Query/GetComparerForType.cs +++ b/Adapter_Engine/Query/GetComparerForType.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -64,3 +64,4 @@ public static IEqualityComparer GetComparerForType(this IBHoMAdapter bHoMA + diff --git a/Adapter_Engine/Query/GetCopyPropertiesModules.cs b/Adapter_Engine/Query/GetCopyPropertiesModules.cs index 99a4d137..d129287a 100644 --- a/Adapter_Engine/Query/GetCopyPropertiesModules.cs +++ b/Adapter_Engine/Query/GetCopyPropertiesModules.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -41,3 +41,4 @@ public static List> GetCopyPropertiesModules(this IB + diff --git a/Adapter_Engine/Query/GetDependencyObjects.cs b/Adapter_Engine/Query/GetDependencyObjects.cs index f1a1f5c8..0d472964 100644 --- a/Adapter_Engine/Query/GetDependencyObjects.cs +++ b/Adapter_Engine/Query/GetDependencyObjects.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -92,3 +92,4 @@ private static List

GetDependencyObjects(this IEnumerable objects, I + diff --git a/Adapter_Engine/Query/GetDependencyTypes.cs b/Adapter_Engine/Query/GetDependencyTypes.cs index a56067cd..0eeeb61b 100644 --- a/Adapter_Engine/Query/GetDependencyTypes.cs +++ b/Adapter_Engine/Query/GetDependencyTypes.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -64,3 +64,4 @@ public static List GetDependencyTypes(this IBHoMAdapter bhomAdapter) } + diff --git a/Adapter_Engine/Query/GetFullFileName.cs b/Adapter_Engine/Query/GetFullFileName.cs index f645ba3b..840484cd 100644 --- a/Adapter_Engine/Query/GetFullFileName.cs +++ b/Adapter_Engine/Query/GetFullFileName.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -50,3 +50,4 @@ public static string GetFullFileName(this FileSettings fileSettings) + diff --git a/Adapter_Engine/Query/HasAdapterIdFragment.cs b/Adapter_Engine/Query/HasAdapterIdFragment.cs index a6858899..e2e3007c 100644 --- a/Adapter_Engine/Query/HasAdapterIdFragment.cs +++ b/Adapter_Engine/Query/HasAdapterIdFragment.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -60,3 +60,4 @@ public static bool HasAdapterIdFragment(this IBHoMObject iBHoMObject, Type fragm + diff --git a/Adapter_oM/Enums/PullType.cs b/Adapter_oM/Enums/PullType.cs index b33b1988..cd2912d7 100644 --- a/Adapter_oM/Enums/PullType.cs +++ b/Adapter_oM/Enums/PullType.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -39,3 +39,4 @@ public enum PullType + diff --git a/Adapter_oM/Enums/PushType.cs b/Adapter_oM/Enums/PushType.cs index 5cbc5f6c..86fdfc2b 100644 --- a/Adapter_oM/Enums/PushType.cs +++ b/Adapter_oM/Enums/PushType.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -51,3 +51,4 @@ namespace BH.oM.Adapter } + diff --git a/Adapter_oM/ExecuteCommands/Analyse.cs b/Adapter_oM/ExecuteCommands/Analyse.cs index 1b531ed0..3fed9d85 100644 --- a/Adapter_oM/ExecuteCommands/Analyse.cs +++ b/Adapter_oM/ExecuteCommands/Analyse.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -37,3 +37,4 @@ public class Analyse : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/AnalyseLoadCases.cs b/Adapter_oM/ExecuteCommands/AnalyseLoadCases.cs index e96df41f..f2c38dfa 100644 --- a/Adapter_oM/ExecuteCommands/AnalyseLoadCases.cs +++ b/Adapter_oM/ExecuteCommands/AnalyseLoadCases.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -40,3 +40,4 @@ public class AnalyseLoadCases : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/ClearResults.cs b/Adapter_oM/ExecuteCommands/ClearResults.cs index 6f62c0bc..5d33dea0 100644 --- a/Adapter_oM/ExecuteCommands/ClearResults.cs +++ b/Adapter_oM/ExecuteCommands/ClearResults.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -37,3 +37,4 @@ public class ClearResults : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/Close.cs b/Adapter_oM/ExecuteCommands/Close.cs index 19a5fff2..1f811489 100644 --- a/Adapter_oM/ExecuteCommands/Close.cs +++ b/Adapter_oM/ExecuteCommands/Close.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -38,3 +38,4 @@ public class Close : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/CustomCommand.cs b/Adapter_oM/ExecuteCommands/CustomCommand.cs index efe21724..274e3080 100644 --- a/Adapter_oM/ExecuteCommands/CustomCommand.cs +++ b/Adapter_oM/ExecuteCommands/CustomCommand.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -41,3 +41,4 @@ public class CustomCommand : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/Exit.cs b/Adapter_oM/ExecuteCommands/Exit.cs index 865e9f96..fd08ea57 100644 --- a/Adapter_oM/ExecuteCommands/Exit.cs +++ b/Adapter_oM/ExecuteCommands/Exit.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -39,3 +39,4 @@ public class Exit : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/NewModel.cs b/Adapter_oM/ExecuteCommands/NewModel.cs index f158621e..b30c2314 100644 --- a/Adapter_oM/ExecuteCommands/NewModel.cs +++ b/Adapter_oM/ExecuteCommands/NewModel.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -37,3 +37,4 @@ public class NewModel : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/Open.cs b/Adapter_oM/ExecuteCommands/Open.cs index a4a1a0ac..5b3e61fe 100644 --- a/Adapter_oM/ExecuteCommands/Open.cs +++ b/Adapter_oM/ExecuteCommands/Open.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -38,3 +38,4 @@ public class Open : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/Save.cs b/Adapter_oM/ExecuteCommands/Save.cs index 93e22b78..40794bb4 100644 --- a/Adapter_oM/ExecuteCommands/Save.cs +++ b/Adapter_oM/ExecuteCommands/Save.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -37,3 +37,4 @@ public class Save : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/SaveAs.cs b/Adapter_oM/ExecuteCommands/SaveAs.cs index 09614d6d..1dadeb74 100644 --- a/Adapter_oM/ExecuteCommands/SaveAs.cs +++ b/Adapter_oM/ExecuteCommands/SaveAs.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -38,3 +38,4 @@ public class SaveAs : IExecuteCommand + diff --git a/Adapter_oM/ExecuteCommands/_IExecuteCommand.cs b/Adapter_oM/ExecuteCommands/_IExecuteCommand.cs index 83e8bcbc..280d02cf 100644 --- a/Adapter_oM/ExecuteCommands/_IExecuteCommand.cs +++ b/Adapter_oM/ExecuteCommands/_IExecuteCommand.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -38,3 +38,4 @@ public interface IExecuteCommand : IObject + diff --git a/Adapter_oM/FileSettings.cs b/Adapter_oM/FileSettings.cs index e98bd5ae..89f2d42f 100644 --- a/Adapter_oM/FileSettings.cs +++ b/Adapter_oM/FileSettings.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -42,3 +42,4 @@ public class FileSettings : BHoMObject } + diff --git a/Adapter_oM/IBHoMAdapter.cs b/Adapter_oM/IBHoMAdapter.cs index 45662c35..24f6be7a 100644 --- a/Adapter_oM/IBHoMAdapter.cs +++ b/Adapter_oM/IBHoMAdapter.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -49,3 +49,4 @@ public interface IBHoMAdapter + diff --git a/Adapter_oM/Module/IAdapterModule.cs b/Adapter_oM/Module/IAdapterModule.cs index 8c097144..05962be3 100644 --- a/Adapter_oM/Module/IAdapterModule.cs +++ b/Adapter_oM/Module/IAdapterModule.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -35,3 +35,4 @@ public interface IAdapterModule + diff --git a/Adapter_oM/Module/ICopyPropertiesModule.cs b/Adapter_oM/Module/ICopyPropertiesModule.cs index 7a2a34a9..9049040c 100644 --- a/Adapter_oM/Module/ICopyPropertiesModule.cs +++ b/Adapter_oM/Module/ICopyPropertiesModule.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -37,3 +37,4 @@ public interface ICopyPropertiesModule : IAdapterModule where T : IBHoMObj + diff --git a/Adapter_oM/Module/IGetDependencyModule.cs b/Adapter_oM/Module/IGetDependencyModule.cs index f734427c..55ec3860 100644 --- a/Adapter_oM/Module/IGetDependencyModule.cs +++ b/Adapter_oM/Module/IGetDependencyModule.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -40,3 +40,4 @@ public interface IGetDependencyModule : IAdapterModule where T : IB + diff --git a/Adapter_oM/Module/ModuleSet.cs b/Adapter_oM/Module/ModuleSet.cs index 2ed0a235..2d3b0439 100644 --- a/Adapter_oM/Module/ModuleSet.cs +++ b/Adapter_oM/Module/ModuleSet.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -42,3 +42,4 @@ public ModuleSet() : + diff --git a/Adapter_oM/ObjectWrapper.cs b/Adapter_oM/ObjectWrapper.cs index 27ec3756..82d39767 100644 --- a/Adapter_oM/ObjectWrapper.cs +++ b/Adapter_oM/ObjectWrapper.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -37,3 +37,4 @@ public class ObjectWrapper : BHoMObject + diff --git a/Adapter_oM/Settings-Config/ActionConfig.cs b/Adapter_oM/Settings-Config/ActionConfig.cs index 6c5b637e..5fa91b70 100644 --- a/Adapter_oM/Settings-Config/ActionConfig.cs +++ b/Adapter_oM/Settings-Config/ActionConfig.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -49,3 +49,4 @@ public class ActionConfig : IObject + diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index d2a06a49..3d419855 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -75,3 +75,4 @@ public class AdapterSettings : IObject + diff --git a/BHoM_Adapter/AdapterActions/Execute.cs b/BHoM_Adapter/AdapterActions/Execute.cs index 2d5320dd..d6a072fc 100644 --- a/BHoM_Adapter/AdapterActions/Execute.cs +++ b/BHoM_Adapter/AdapterActions/Execute.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -65,3 +65,4 @@ public virtual Output, bool> Execute(IExecuteCommand command, Actio + diff --git a/BHoM_Adapter/AdapterActions/Move.cs b/BHoM_Adapter/AdapterActions/Move.cs index ffc1242c..b5dd724b 100644 --- a/BHoM_Adapter/AdapterActions/Move.cs +++ b/BHoM_Adapter/AdapterActions/Move.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -61,3 +61,4 @@ public virtual bool Move(IBHoMAdapter to, IRequest request, + diff --git a/BHoM_Adapter/AdapterActions/Pull.cs b/BHoM_Adapter/AdapterActions/Pull.cs index 8823fe1e..5f94de3f 100644 --- a/BHoM_Adapter/AdapterActions/Pull.cs +++ b/BHoM_Adapter/AdapterActions/Pull.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -86,3 +86,4 @@ public virtual IEnumerable Pull(IRequest request, PullType pullType = Pu } + diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 53013ea8..839ced1e 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -116,3 +116,4 @@ public virtual List Push(IEnumerable objects, string tag = "", P + diff --git a/BHoM_Adapter/AdapterActions/Remove.cs b/BHoM_Adapter/AdapterActions/Remove.cs index 1cad6df9..7ed4a716 100644 --- a/BHoM_Adapter/AdapterActions/Remove.cs +++ b/BHoM_Adapter/AdapterActions/Remove.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -67,3 +67,4 @@ public virtual int Remove(IRequest request, ActionConfig actionConfig = null) + diff --git a/BHoM_Adapter/AdapterActions/_PullMethods/ReadResults.cs b/BHoM_Adapter/AdapterActions/_PullMethods/ReadResults.cs index e2e6f89e..fc56f7ae 100644 --- a/BHoM_Adapter/AdapterActions/_PullMethods/ReadResults.cs +++ b/BHoM_Adapter/AdapterActions/_PullMethods/ReadResults.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -67,3 +67,4 @@ protected virtual IEnumerable ReadResults(IRequest request, ActionConfi + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/AssignId.cs b/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/AssignId.cs index 85060252..a5898ba8 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/AssignId.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/AssignId.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -56,3 +56,4 @@ protected virtual void AssignNextFreeId(IEnumerable objects) where T : IBH } + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/NextFreeId.cs b/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/NextFreeId.cs index 3f2c9506..8ec76172 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/NextFreeId.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/AdapterId/NextFreeId.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -45,3 +45,4 @@ protected virtual object NextFreeId(Type objectType, bool refresh = false) } + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index 3da1b3ae..ceb4e4a4 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -99,3 +99,4 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 4c466b0d..593e4051 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -224,3 +224,4 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index 15171ccf..ede91282 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -67,3 +67,4 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = } + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs index 16b5aedb..8ea0d698 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -84,3 +84,4 @@ protected virtual IEnumerable ProcessObjectsForPush(IEnumerable ids, object newTa + diff --git a/BHoM_Adapter/BHoMAdapter.cs b/BHoM_Adapter/BHoMAdapter.cs index 7854a3d3..7184c3fd 100644 --- a/BHoM_Adapter/BHoMAdapter.cs +++ b/BHoM_Adapter/BHoMAdapter.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -87,3 +87,4 @@ protected virtual void OnDataUpdated() + diff --git a/BHoM_Adapter/CRUD/ICreate.cs b/BHoM_Adapter/CRUD/ICreate.cs index 767937bf..5ead54a9 100644 --- a/BHoM_Adapter/CRUD/ICreate.cs +++ b/BHoM_Adapter/CRUD/ICreate.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -60,3 +60,4 @@ protected virtual bool ICreate(IEnumerable objects, ActionConfig actionCon } + diff --git a/BHoM_Adapter/CRUD/IDelete.cs b/BHoM_Adapter/CRUD/IDelete.cs index a2e3ff52..80ef9daa 100644 --- a/BHoM_Adapter/CRUD/IDelete.cs +++ b/BHoM_Adapter/CRUD/IDelete.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -103,3 +103,4 @@ protected virtual int Delete(Type type, string tag = "", ActionConfig actionConf + diff --git a/BHoM_Adapter/CRUD/IRead.cs b/BHoM_Adapter/CRUD/IRead.cs index ae8f8844..56f07bf3 100644 --- a/BHoM_Adapter/CRUD/IRead.cs +++ b/BHoM_Adapter/CRUD/IRead.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -113,3 +113,4 @@ protected virtual IEnumerable Read(Type type, string tag = "", Acti + diff --git a/BHoM_Adapter/CRUD/IUpdate.cs b/BHoM_Adapter/CRUD/IUpdate.cs index 66694815..ab42a046 100644 --- a/BHoM_Adapter/CRUD/IUpdate.cs +++ b/BHoM_Adapter/CRUD/IUpdate.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -67,3 +67,4 @@ protected virtual int IUpdateTags(Type type, IEnumerable ids, IEnumerabl + diff --git a/BHoM_Adapter/HelperMethods/AdapterId.cs b/BHoM_Adapter/HelperMethods/AdapterId.cs index 47a67cf3..214ffcfc 100644 --- a/BHoM_Adapter/HelperMethods/AdapterId.cs +++ b/BHoM_Adapter/HelperMethods/AdapterId.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -54,3 +54,4 @@ public T GetAdapterId(IBHoMObject bHoMObject) + diff --git a/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs b/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs index f600dcd0..d321b870 100644 --- a/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs +++ b/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -55,3 +55,4 @@ public void CopyBHoMObjectProperties(T target, T source) where T : class, IBH + diff --git a/BHoM_Adapter/HelperMethods/WrapNonBHoMObjects.cs b/BHoM_Adapter/HelperMethods/WrapNonBHoMObjects.cs index c35ad9e0..6d48889a 100644 --- a/BHoM_Adapter/HelperMethods/WrapNonBHoMObjects.cs +++ b/BHoM_Adapter/HelperMethods/WrapNonBHoMObjects.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -49,3 +49,4 @@ public IEnumerable WrapNonBHoMObjects(IEnumerable objects) } + diff --git a/Structure_AdapterModules/CopyNodeProperties.cs b/Structure_AdapterModules/CopyNodeProperties.cs index f8fb36ce..2a35a4c1 100644 --- a/Structure_AdapterModules/CopyNodeProperties.cs +++ b/Structure_AdapterModules/CopyNodeProperties.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -50,3 +50,4 @@ public void CopyProperties(Node target, Node source) + diff --git a/Structure_AdapterModules/ErrorMessages/ErrorMessages.cs b/Structure_AdapterModules/ErrorMessages/ErrorMessages.cs index 83d3da09..0f434214 100644 --- a/Structure_AdapterModules/ErrorMessages/ErrorMessages.cs +++ b/Structure_AdapterModules/ErrorMessages/ErrorMessages.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -103,3 +103,4 @@ public static void LoadsWithoutObejctIdsAssignedError(IElementLoad load) w } + diff --git a/Structure_AdapterModules/GetCasesFromCombinations.cs b/Structure_AdapterModules/GetCasesFromCombinations.cs index 0e8f74eb..f19bd64d 100644 --- a/Structure_AdapterModules/GetCasesFromCombinations.cs +++ b/Structure_AdapterModules/GetCasesFromCombinations.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -42,3 +42,4 @@ public IEnumerable GetDependencies(IEnumerable object } } + diff --git a/Structure_AdapterModules/GetCombinationsFromCombinations.cs b/Structure_AdapterModules/GetCombinationsFromCombinations.cs index 231bfe57..b64885a6 100644 --- a/Structure_AdapterModules/GetCombinationsFromCombinations.cs +++ b/Structure_AdapterModules/GetCombinationsFromCombinations.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -42,3 +42,4 @@ public IEnumerable GetDependencies(IEnumerable } } + diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 943b38cd..5f608ffb 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -46,3 +46,4 @@ public static void LoadModules(this BHoMAdapter adapter) + From e0122981354bb15a40b89401c653d1ba747b34fa Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 10:07:20 +0000 Subject: [PATCH 004/116] Wip - first iteration --- Adapter_Engine/Adapter_Engine.csproj | 6 +- Adapter_Engine/Query/BaseTypes.cs | 68 ++++++++++++ .../Query/GetAllObjectsAndDependencies.cs | 103 ++++++++++++++++++ Adapter_Engine/Query/GetDependencyObjects.cs | 2 +- Adapter_oM/Adapter_oM.csproj | 2 +- BHoM_Adapter.sln | 16 ++- BHoM_Adapter/AdapterActions/Push.cs | 73 ++++++++++++- BHoM_Adapter/BHoM_Adapter.csproj | 5 +- BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj | 58 ++++++++++ BHoM_Adapter_Tests/Create/RandomObject.cs | 44 ++++++++ BHoM_Adapter_Tests/Create/RandomObjects.cs | 93 ++++++++++++++++ BHoM_Adapter_Tests/StructuralAdapter.cs | 39 +++++++ BHoM_Adapter_Tests/UnitTest1.cs | 37 +++++++ BHoM_Adapter_Tests/Usings.cs | 1 + .../Structure_AdapterModules.csproj | 2 +- 15 files changed, 535 insertions(+), 14 deletions(-) create mode 100644 Adapter_Engine/Query/BaseTypes.cs create mode 100644 Adapter_Engine/Query/GetAllObjectsAndDependencies.cs create mode 100644 BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj create mode 100644 BHoM_Adapter_Tests/Create/RandomObject.cs create mode 100644 BHoM_Adapter_Tests/Create/RandomObjects.cs create mode 100644 BHoM_Adapter_Tests/StructuralAdapter.cs create mode 100644 BHoM_Adapter_Tests/UnitTest1.cs create mode 100644 BHoM_Adapter_Tests/Usings.cs diff --git a/Adapter_Engine/Adapter_Engine.csproj b/Adapter_Engine/Adapter_Engine.csproj index 306514e1..b6badae7 100644 --- a/Adapter_Engine/Adapter_Engine.csproj +++ b/Adapter_Engine/Adapter_Engine.csproj @@ -16,9 +16,13 @@ - + + + + + diff --git a/Adapter_Engine/Query/BaseTypes.cs b/Adapter_Engine/Query/BaseTypes.cs new file mode 100644 index 00000000..c055f0a2 --- /dev/null +++ b/Adapter_Engine/Query/BaseTypes.cs @@ -0,0 +1,68 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Adapter; +using BH.oM.Base; +using BH.Engine.Base; +using BH.oM.Base.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Collections; + +namespace BH.Engine.Adapter +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + public static Dictionary> m_cachedBaseTypes = new Dictionary>(); + + [Description("Gets all implemented interfaces and any base type of a given type.")] + public static List BaseTypes(this Type type) + { + List baseTypes = new List(); + + if (type == null) + return baseTypes; + + if (m_cachedBaseTypes.TryGetValue(type, out baseTypes)) + return baseTypes; + else + baseTypes = new List(); + + baseTypes.AddRange(type.GetInterfaces()); + + Type baseType = type.BaseType; + if (baseType != null) + baseTypes.Add(baseType); + + m_cachedBaseTypes[type] = baseTypes; + + return baseTypes; + } + } +} + diff --git a/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs b/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs new file mode 100644 index 00000000..f9ddb53f --- /dev/null +++ b/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs @@ -0,0 +1,103 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.Engine.Reflection; +using BH.oM.Base; +using BH.oM.Data.Collections; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using BH.oM.Adapter; +using BH.oM.Base.Attributes; + +namespace BH.Engine.Adapter +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Fetches all dependancy objects of types provided from the list of the objects. Firsts checks for any DependencyModules, if no present matching the type, tries to scan any property returning the types.")] + public static Dictionary> GetAllObjectsAndDependencies(this IEnumerable objects, Dictionary> allDependencyTypes, IBHoMAdapter adapter = null) where T : IBHoMObject + { + // Group the objects by their specific type. + var typeGroups = objects.GroupBy(x => x.GetType()); + + Dictionary> allObjectsPerType = new Dictionary>(); + + foreach (var typeGroup in typeGroups) + { + if (allObjectsPerType.ContainsKey(typeGroup.Key)) + allObjectsPerType[typeGroup.Key].AddRange(typeGroup.Cast()); + else + allObjectsPerType[typeGroup.Key] = typeGroup.Cast().ToList(); + + + if (!allDependencyTypes.TryGetValue(typeGroup.Key, out List dependencyTypes)) + continue; + + //MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); + //dynamic objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); + + //Dictionary dependencyObjects = GetDependecyObjectWithCasting(typeGroup.First() as dynamic, typeGroup as dynamic, dependencyTypes, adapter); + Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(CastToFirstType(typeGroup.First() as dynamic, typeGroup as dynamic), dependencyTypes, adapter); + + // Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objList_specificType, dependencyTypes, adapter); + foreach (var kv in dependencyObjects) + { + if (allObjectsPerType.ContainsKey(kv.Key)) + allObjectsPerType[kv.Key].AddRange(kv.Value.Cast()); + else + allObjectsPerType[kv.Key] = kv.Value.Cast().ToList(); + + var recursedResult = kv.Value.OfType().GetAllObjectsAndDependencies(allDependencyTypes, adapter); + foreach (var recursedRes in recursedResult) + if (allObjectsPerType.ContainsKey(recursedRes.Key)) + throw new Exception(""); + else + allObjectsPerType[recursedRes.Key] = recursedRes.Value; + } + } + + return allObjectsPerType; + } + + /***************************************************/ + + private static Dictionary GetDependecyObjectWithCasting(T item, IEnumerable ienumerable, List dependencyTypes, IBHoMAdapter adapter) where T : IBHoMObject + { + return Engine.Adapter.Query.GetDependencyObjects(ienumerable.Cast(), dependencyTypes, adapter); + } + + private static IEnumerable CastToFirstType(T type, IEnumerable objects) + { + return objects.Cast(); + } + } +} + + + diff --git a/Adapter_Engine/Query/GetDependencyObjects.cs b/Adapter_Engine/Query/GetDependencyObjects.cs index 0d472964..7ca433a7 100644 --- a/Adapter_Engine/Query/GetDependencyObjects.cs +++ b/Adapter_Engine/Query/GetDependencyObjects.cs @@ -72,7 +72,7 @@ private static List

GetDependencyObjects(this IEnumerable objects, I { //If adapter is provided and not null, check for dependency modules if (adapter != null) - { + { //Look for any GetDependencyModules of the current type List> dependencyModules = adapter.AdapterModules.OfType>().ToList(); if (dependencyModules.Count != 0) diff --git a/Adapter_oM/Adapter_oM.csproj b/Adapter_oM/Adapter_oM.csproj index 9c0029e7..7f518773 100644 --- a/Adapter_oM/Adapter_oM.csproj +++ b/Adapter_oM/Adapter_oM.csproj @@ -16,7 +16,7 @@ - + diff --git a/BHoM_Adapter.sln b/BHoM_Adapter.sln index 3df90704..091d0b78 100644 --- a/BHoM_Adapter.sln +++ b/BHoM_Adapter.sln @@ -1,15 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31205.134 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32922.545 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BHoM_Adapter", "BHoM_Adapter\BHoM_Adapter.csproj", "{41FE6552-45DE-4B79-A11E-B2724077EFFF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adapter_Engine", "Adapter_Engine\Adapter_Engine.csproj", "{06E1FCF3-B637-4902-80B9-7176EBFAD757}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter_Engine", "Adapter_Engine\Adapter_Engine.csproj", "{06E1FCF3-B637-4902-80B9-7176EBFAD757}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adapter_oM", "Adapter_oM\Adapter_oM.csproj", "{59752259-D2F6-46DE-A203-027F6FA1C1EA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter_oM", "Adapter_oM\Adapter_oM.csproj", "{59752259-D2F6-46DE-A203-027F6FA1C1EA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Structure_AdapterModules", "Structure_AdapterModules\Structure_AdapterModules.csproj", "{48BE209E-658F-48FE-B45B-BB4D7E6CDD03}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Structure_AdapterModules", "Structure_AdapterModules\Structure_AdapterModules.csproj", "{48BE209E-658F-48FE-B45B-BB4D7E6CDD03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BHoM_Adapter_Tests", "BHoM_Adapter_Tests\BHoM_Adapter_Tests.csproj", "{E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,6 +35,10 @@ Global {48BE209E-658F-48FE-B45B-BB4D7E6CDD03}.Debug|Any CPU.Build.0 = Debug|Any CPU {48BE209E-658F-48FE-B45B-BB4D7E6CDD03}.Release|Any CPU.ActiveCfg = Release|Any CPU {48BE209E-658F-48FE-B45B-BB4D7E6CDD03}.Release|Any CPU.Build.0 = Release|Any CPU + {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 839ced1e..83510ff5 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -22,6 +22,7 @@ using BH.oM.Base; using BH.oM.Adapter; +using BH.Engine.Reflection; using BH.Engine.Base; using BH.Engine.Adapter; using System; @@ -91,11 +92,75 @@ public virtual List Push(IEnumerable objects, string tag = "", P // Group the objects by their specific type. var typeGroups = objectsToPush.GroupBy(x => x.GetType()); - foreach (var typeGroup in typeGroups) + // Collect all objects and related dependency objects, and group them by type, in this dictionary. + Dictionary> allObjectsPerType = new Dictionary>(); + + allObjectsPerType = Engine.Adapter.Query.GetAllObjectsAndDependencies(objectsToPush, DependencyTypes, this); + + // Sort all objects and related dependencies by dependency order, so they can be pushed in the correct order. + List>> orderedObjects = new List>>(); + + List handledGroups = new List(); + foreach (var typeGroup in allObjectsPerType) + { + if (handledGroups.Contains(typeGroup.Key)) + continue; + + // We can scan the rest of the input objects to see if they include dependencies of this current object type. + List dependenciesToLookFor = new List(); + + // Add direct dependencies of this current object type. + if (DependencyTypes.TryGetValue(typeGroup.Key, out List typeDeps)) + dependenciesToLookFor.AddRange(typeDeps); + + // Check if the current object type has basetypes (interfaces) for which dependencies may have been specified. + // E.g. for a CrossSection object we can get ISectionProperty which it implements, + // which in turn is a type that commonly specifies additional dependencies (generally, IMaterialFragment). + foreach (var baseType in typeGroup.Key.BaseTypes()) + { + if (DependencyTypes.TryGetValue(baseType, out List baseTypeDeps)) + dependenciesToLookFor.AddRange(baseTypeDeps); + } + + // If this current object type does not have dependencies, add it at the start of the list and continue. + if (!dependenciesToLookFor.Any()) + { + orderedObjects.Insert(0, new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); + handledGroups.Add(typeGroup.Key); + continue; + } + + // Scan the rest of the input objects to see they include dependencies, + // and add them to the orderedObjects list in order to prioritize them. + foreach (var otherTypeGroup in allObjectsPerType) + { + if (otherTypeGroup.Key == typeGroup.Key) + continue; + + if (dependenciesToLookFor.Contains(otherTypeGroup.Key) || dependenciesToLookFor.Any(d => d.IsAssignableFromIncludeGenericsAndRefTypes(otherTypeGroup.Key))) + { + orderedObjects.Add(new Tuple>(otherTypeGroup.Key, otherTypeGroup.Value.OfType())); + handledGroups.Add(otherTypeGroup.Key); + } + } + } + + // The non-handled groups can be added at the end in any order, because they don't have any dependency ordering. + foreach (var typeGroup in allObjectsPerType) + { + if (handledGroups.Contains(typeGroup.Key)) + continue; + + orderedObjects.Add(new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); + } + + // We now have objects grouped per type, and the groups are sorted following the dependency order. + foreach (var group in orderedObjects) { - // Cast the objects to their specific types - MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); - var objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); + // Cast the IEnumerable to an IEnumerable where T is the the specific type it contains. + // This is used to dynamically dispatch to the right type-specific CRUD method. + MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { group.Item1 }); + object objList_specificType = enumCastMethod_specificType.Invoke(group.Item2, new object[] { group.Item2.ToList() }); if (pushType == PushType.FullPush || pushType == PushType.CreateNonExisting || pushType == PushType.UpdateOrCreateOnly) success &= FullCRUD(objList_specificType as dynamic, pushType, tag, actionConfig); diff --git a/BHoM_Adapter/BHoM_Adapter.csproj b/BHoM_Adapter/BHoM_Adapter.csproj index e9f82e09..3957aa60 100644 --- a/BHoM_Adapter/BHoM_Adapter.csproj +++ b/BHoM_Adapter/BHoM_Adapter.csproj @@ -16,7 +16,7 @@ - + @@ -69,6 +69,9 @@ false false + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Reflection_Engine.dll + diff --git a/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj new file mode 100644 index 00000000..318d97e4 --- /dev/null +++ b/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -0,0 +1,58 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + + + + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Analytical_oM.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\BHoM.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\BHoM_Engine.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Dimensional_oM.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Geometry_Engine.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Geometry_oM.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Physical_oM.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Spatial_oM.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Structure_Engine.dll + + + ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Structure_oM.dll + + + + diff --git a/BHoM_Adapter_Tests/Create/RandomObject.cs b/BHoM_Adapter_Tests/Create/RandomObject.cs new file mode 100644 index 00000000..9f61b703 --- /dev/null +++ b/BHoM_Adapter_Tests/Create/RandomObject.cs @@ -0,0 +1,44 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.Engine.Base; +using BH.oM.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BH.Adapter.Tests +{ + public static partial class Create + { + public static T RandomObject() where T : IObject + { + if (typeof(T).IsInterface) + return default(T); + + return (T)BH.Engine.Base.Create.RandomObject(typeof(T)); + } + } +} + diff --git a/BHoM_Adapter_Tests/Create/RandomObjects.cs b/BHoM_Adapter_Tests/Create/RandomObjects.cs new file mode 100644 index 00000000..9ac829fe --- /dev/null +++ b/BHoM_Adapter_Tests/Create/RandomObjects.cs @@ -0,0 +1,93 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.Engine.Base; +using BH.oM.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BH.Adapter.Tests +{ + public static partial class Create + { + public static List RandomObjects(int count = 100, bool assignIdFragmentWithProgressiveId = false, bool assignObjectName = false, string objectNamePrefix = "bar_") where T : IObject + { + return RandomBHoMObjects(typeof(T), count, assignIdFragmentWithProgressiveId, assignObjectName, objectNamePrefix).OfType().ToList(); + } + + public static List RandomBHoMObjects(Type t, int count = 100, bool assignIdFragmentWithProgressiveId = false, bool assignObjectName = false, string objectNamePrefix = "bar_") + { + List objs = new List(); + + for (int i = 0; i < count; i++) + { + IObject obj = BH.Engine.Base.Create.RandomObject(t); + + if (obj == null) + throw new ArgumentException($"Could not create a Random Object of type {t.FullName}."); + + if (assignIdFragmentWithProgressiveId) + { + IBHoMObject bhomObj = obj as IBHoMObject; + TestFragment testIdFragment = new TestFragment() { SomeProp = i }; + bhomObj = bhomObj.AddFragment(testIdFragment); + obj = bhomObj; + } + + if (assignObjectName) + { + IBHoMObject bhomObj = obj as IBHoMObject; + bhomObj.Name = objectNamePrefix + i.ToString(); + obj = bhomObj; + } + + objs.Add(obj as dynamic); + } + + return objs; + } + + public static List RandomIObjects(Type t, int count = 100) + { + List objs = new List(); + + for (int i = 0; i < count; i++) + { + IObject obj = BH.Engine.Base.Create.RandomObject(t); + + objs.Add(obj); + } + + return objs; + } + } + + + public class TestFragment : IFragment + { + public object SomeProp { get; set; } + } +} + diff --git a/BHoM_Adapter_Tests/StructuralAdapter.cs b/BHoM_Adapter_Tests/StructuralAdapter.cs new file mode 100644 index 00000000..ea1118ac --- /dev/null +++ b/BHoM_Adapter_Tests/StructuralAdapter.cs @@ -0,0 +1,39 @@ + +using BH.Adapter; +using BH.oM.Structure.Constraints; +using BH.oM.Structure.Elements; +using BH.oM.Structure.Loads; +using BH.oM.Structure.MaterialFragments; +using BH.oM.Structure.Offsets; +using BH.oM.Structure.SectionProperties; +using BH.oM.Structure.SurfaceProperties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace BHoM_Adapter_Tests +{ + public class StructuralAdapter : BHoMAdapter + { + public StructuralAdapter() + { + DependencyTypes = new Dictionary> + { + {typeof(Bar), new List { typeof(ISectionProperty), typeof(Node), typeof(BarRelease), typeof(Offset)}}, + {typeof(ISectionProperty), new List { typeof(IMaterialFragment) } }, + {typeof(Node), new List { typeof(Constraint6DOF) } }, + {typeof(ILoad), new List { typeof(Loadcase) } }, + {typeof(LoadCombination), new List { typeof(Loadcase) } }, + {typeof(Panel), new List { typeof(ISurfaceProperty) , typeof(Opening), typeof(Edge)} }, + {typeof(Opening), new List {typeof(Edge) } }, + {typeof(Edge), new List { typeof(Constraint6DOF), typeof(Constraint4DOF) } }, + {typeof(ISurfaceProperty), new List { typeof(IMaterialFragment) } }, + {typeof(RigidLink), new List { typeof(LinkConstraint), typeof(Node) } }, + {typeof(FEMesh), new List { typeof(Node), typeof(ISurfaceProperty)} } + }; + } + } +} diff --git a/BHoM_Adapter_Tests/UnitTest1.cs b/BHoM_Adapter_Tests/UnitTest1.cs new file mode 100644 index 00000000..6b62a53b --- /dev/null +++ b/BHoM_Adapter_Tests/UnitTest1.cs @@ -0,0 +1,37 @@ +using BH.Adapter.Tests; +using BH.oM.Structure.Constraints; +using BH.oM.Structure.Elements; +using BH.oM.Structure.Loads; +using BH.oM.Structure.MaterialFragments; +using BH.oM.Structure.SectionProperties; + +namespace BHoM_Adapter_Tests +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void TestPush() + { + StructuralAdapter sa = new StructuralAdapter(); + + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + // Constraint6DOF, Node, Material, SteelSection, BarRelease, Offset, Bar, Loadcase, BarUniformlyDistributedLoad + + //inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + } + } +} \ No newline at end of file diff --git a/BHoM_Adapter_Tests/Usings.cs b/BHoM_Adapter_Tests/Usings.cs new file mode 100644 index 00000000..cefced49 --- /dev/null +++ b/BHoM_Adapter_Tests/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/Structure_AdapterModules/Structure_AdapterModules.csproj b/Structure_AdapterModules/Structure_AdapterModules.csproj index b9f16af8..59e05c14 100644 --- a/Structure_AdapterModules/Structure_AdapterModules.csproj +++ b/Structure_AdapterModules/Structure_AdapterModules.csproj @@ -17,7 +17,7 @@ - + From 0c05b53733a7fb15dd7fd5f47d9159a2f5cfc04e Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 10:48:17 +0000 Subject: [PATCH 005/116] Changed recursive function --- .../Query/GetAllObjectsAndDependencies.cs | 50 ++++++------------- BHoM_Adapter/AdapterActions/Push.cs | 2 +- BHoM_Adapter_Tests/UnitTest1.cs | 4 ++ 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs b/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs index f9ddb53f..ebc6df84 100644 --- a/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs +++ b/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs @@ -40,8 +40,7 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - [Description("Fetches all dependancy objects of types provided from the list of the objects. Firsts checks for any DependencyModules, if no present matching the type, tries to scan any property returning the types.")] - public static Dictionary> GetAllObjectsAndDependencies(this IEnumerable objects, Dictionary> allDependencyTypes, IBHoMAdapter adapter = null) where T : IBHoMObject + public static Dictionary> GetAllObjectsAndDependencies(this IEnumerable objects, IBHoMAdapter adapter) { // Group the objects by their specific type. var typeGroups = objects.GroupBy(x => x.GetType()); @@ -55,46 +54,29 @@ public static Dictionary> GetAllObjectsAndDependencies().ToList(); + MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); + dynamic objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); - if (!allDependencyTypes.TryGetValue(typeGroup.Key, out List dependencyTypes)) - continue; - - //MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); - //dynamic objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); - - //Dictionary dependencyObjects = GetDependecyObjectWithCasting(typeGroup.First() as dynamic, typeGroup as dynamic, dependencyTypes, adapter); - Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(CastToFirstType(typeGroup.First() as dynamic, typeGroup as dynamic), dependencyTypes, adapter); - - // Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objList_specificType, dependencyTypes, adapter); - foreach (var kv in dependencyObjects) - { - if (allObjectsPerType.ContainsKey(kv.Key)) - allObjectsPerType[kv.Key].AddRange(kv.Value.Cast()); - else - allObjectsPerType[kv.Key] = kv.Value.Cast().ToList(); - - var recursedResult = kv.Value.OfType().GetAllObjectsAndDependencies(allDependencyTypes, adapter); - foreach (var recursedRes in recursedResult) - if (allObjectsPerType.ContainsKey(recursedRes.Key)) - throw new Exception(""); - else - allObjectsPerType[recursedRes.Key] = recursedRes.Value; - } + GetAllDependenciesForType(objList_specificType, allObjectsPerType, adapter); } return allObjectsPerType; } - /***************************************************/ - - private static Dictionary GetDependecyObjectWithCasting(T item, IEnumerable ienumerable, List dependencyTypes, IBHoMAdapter adapter) where T : IBHoMObject + private static void GetAllDependenciesForType(this IEnumerable objects, Dictionary> gatheredDependecies, IBHoMAdapter adapter) where T : IBHoMObject { - return Engine.Adapter.Query.GetDependencyObjects(ienumerable.Cast(), dependencyTypes, adapter); - } + List dependencies = GetDependencyTypes(adapter); + Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objects, dependencies, adapter); - private static IEnumerable CastToFirstType(T type, IEnumerable objects) - { - return objects.Cast(); + foreach (var depObj in dependencyObjects) + { + if (gatheredDependecies.ContainsKey(depObj.Key)) + gatheredDependecies[depObj.Key].AddRange(depObj.Value.Cast()); + else + gatheredDependecies[depObj.Key] = depObj.Value.Cast().ToList(); + + GetAllDependenciesForType(depObj.Value as dynamic, gatheredDependecies, adapter); + } } } } diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 83510ff5..bf3dd314 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -95,7 +95,7 @@ public virtual List Push(IEnumerable objects, string tag = "", P // Collect all objects and related dependency objects, and group them by type, in this dictionary. Dictionary> allObjectsPerType = new Dictionary>(); - allObjectsPerType = Engine.Adapter.Query.GetAllObjectsAndDependencies(objectsToPush, DependencyTypes, this); + allObjectsPerType = Engine.Adapter.Query.GetAllObjectsAndDependencies(objectsToPush, this); // Sort all objects and related dependencies by dependency order, so they can be pushed in the correct order. List>> orderedObjects = new List>>(); diff --git a/BHoM_Adapter_Tests/UnitTest1.cs b/BHoM_Adapter_Tests/UnitTest1.cs index 6b62a53b..8651c0d5 100644 --- a/BHoM_Adapter_Tests/UnitTest1.cs +++ b/BHoM_Adapter_Tests/UnitTest1.cs @@ -4,6 +4,7 @@ using BH.oM.Structure.Loads; using BH.oM.Structure.MaterialFragments; using BH.oM.Structure.SectionProperties; +using BH.oM.Structure.SurfaceProperties; namespace BHoM_Adapter_Tests { @@ -26,6 +27,9 @@ public void TestPush() inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); // Constraint6DOF, Node, Material, SteelSection, BarRelease, Offset, Bar, Loadcase, BarUniformlyDistributedLoad From 3270547e59dc3f30aafcb786955b8cf74e6350e6 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 16:58:42 +0000 Subject: [PATCH 006/116] Version for PR --- ...endencies.cs => GetDependencyRecursive.cs} | 8 +- .../Query/GetDependencySortedObjects.cs | 146 ++++++++++++++++++ BHoM_Adapter/AdapterActions/Push.cs | 66 +------- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 11 -- .../CRUDDispatchers/UpdateOnly.cs | 12 +- BHoM_Adapter_Tests/StructuralAdapter.cs | 4 +- BHoM_Adapter_Tests/UnitTest1.cs | 18 +++ 7 files changed, 181 insertions(+), 84 deletions(-) rename Adapter_Engine/Query/{GetAllObjectsAndDependencies.cs => GetDependencyRecursive.cs} (86%) create mode 100644 Adapter_Engine/Query/GetDependencySortedObjects.cs diff --git a/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs b/Adapter_Engine/Query/GetDependencyRecursive.cs similarity index 86% rename from Adapter_Engine/Query/GetAllObjectsAndDependencies.cs rename to Adapter_Engine/Query/GetDependencyRecursive.cs index ebc6df84..5a9f5ab3 100644 --- a/Adapter_Engine/Query/GetAllObjectsAndDependencies.cs +++ b/Adapter_Engine/Query/GetDependencyRecursive.cs @@ -40,7 +40,7 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - public static Dictionary> GetAllObjectsAndDependencies(this IEnumerable objects, IBHoMAdapter adapter) + public static Dictionary> GetObjectsAndRecursiveDependencies(this IEnumerable objects, IBHoMAdapter adapter) { // Group the objects by their specific type. var typeGroups = objects.GroupBy(x => x.GetType()); @@ -57,13 +57,13 @@ public static Dictionary> GetAllObjectsAndDependencies(t MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); dynamic objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); - GetAllDependenciesForType(objList_specificType, allObjectsPerType, adapter); + GetDependencyObjectsRecursive(objList_specificType, allObjectsPerType, adapter); } return allObjectsPerType; } - private static void GetAllDependenciesForType(this IEnumerable objects, Dictionary> gatheredDependecies, IBHoMAdapter adapter) where T : IBHoMObject + private static void GetDependencyObjectsRecursive(this IEnumerable objects, Dictionary> gatheredDependecies, IBHoMAdapter adapter ) where T : IBHoMObject { List dependencies = GetDependencyTypes(adapter); Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objects, dependencies, adapter); @@ -75,7 +75,7 @@ private static void GetAllDependenciesForType(this IEnumerable objects, Di else gatheredDependecies[depObj.Key] = depObj.Value.Cast().ToList(); - GetAllDependenciesForType(depObj.Value as dynamic, gatheredDependecies, adapter); + GetDependencyObjectsRecursive(depObj.Value as dynamic, gatheredDependecies, adapter); } } } diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs new file mode 100644 index 00000000..94dc2bb4 --- /dev/null +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -0,0 +1,146 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base; +using BH.Engine.Base; +using BH.oM.Data; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using BH.oM.Adapter; +using BH.oM.Base.Attributes; + +namespace BH.Engine.Adapter +{ + public static partial class Query + { + /***************************************************/ + /**** Push Support methods ****/ + /***************************************************/ + // These are support methods required by other methods in the Push process. + + [Description("Recursively gets all the dependencies of the input objects. Then, the dependency objects and input objects are grouped by type." + + "Finally, the groups are sorted by dependency order. " + + "The resulting collection can be used as an input to invoke CRUD methods in the correct dependency order.")] + [Input("objects", "Objects to group and sort by dependency order. The dependency of these objects will also be gathered recursively and included in the output.")] + [Input("bHoMAdapter", "The DependencyTypes that define the order of the output will be gathered from this Adapter instance.")] + public static List>> GetDependencySortedObjects(IEnumerable objects, IBHoMAdapter bHoMAdapter) + { + if ((objects?.Any() ?? true)|| bHoMAdapter == null) + return new List>>(); + + // Group the objects by their specific type. + var typeGroups = objects.GroupBy(x => x.GetType()); + + // Collect all objects and related dependency objects, recursively, and group them by type. + Dictionary> allObjectsPerType = Engine.Adapter.Query.GetObjectsAndRecursiveDependencies(objects, bHoMAdapter); + + // Sort the groups by dependency order, so they can be pushed in the correct order. + List>> orderedObjects = new List>>(); + + List handledGroups = new List(); + foreach (var typeGroup in allObjectsPerType) + { + if (handledGroups.Contains(typeGroup.Key)) + continue; + + // We can scan the rest of the input objects to see if they include dependencies of this current object type. + List dependenciesToLookFor = new List(); + + // Add direct dependencies of this current object type. + if (bHoMAdapter.DependencyTypes.TryGetValue(typeGroup.Key, out List typeDeps)) + dependenciesToLookFor.AddRange(typeDeps); + + // Check if the current object type has basetypes (interfaces) for which dependencies may have been specified. + // E.g. for a CrossSection object we can get ISectionProperty which it implements, + // which in turn is a type that commonly specifies additional dependencies (generally, IMaterialFragment). + foreach (var baseType in typeGroup.Key.BaseTypes()) + { + if (bHoMAdapter.DependencyTypes.TryGetValue(baseType, out List baseTypeDeps)) + dependenciesToLookFor.AddRange(baseTypeDeps); + } + + // If this current object type does not have dependencies, add it at the start of the list and continue. + if (!dependenciesToLookFor.Any()) + { + orderedObjects.Insert(0, new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); + handledGroups.Add(typeGroup.Key); + continue; + } + + // Scan the rest of the input objects to see they include dependencies, + // and add them to the orderedObjects list in order to prioritize them. + foreach (var otherTypeGroup in allObjectsPerType) + { + if (handledGroups.Contains(otherTypeGroup.Key) || otherTypeGroup.Key == typeGroup.Key) + continue; + + if (dependenciesToLookFor.Contains(otherTypeGroup.Key) || dependenciesToLookFor.Any(d => d.IsAssignableFromIncludeGenericsAndRefTypes(otherTypeGroup.Key))) + { + orderedObjects.Add(new Tuple>(otherTypeGroup.Key, otherTypeGroup.Value.OfType())); + handledGroups.Add(otherTypeGroup.Key); + } + } + } + + // The non-handled groups can be added at the end in any order, because they don't have any dependency ordering. + foreach (var typeGroup in allObjectsPerType) + { + if (handledGroups.Contains(typeGroup.Key)) + continue; + + orderedObjects.Add(new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); + } + + // Group per base type extracted from dependencies. + // This is useful to reduce the number of CRUD calls. + var allTypesInDependencies = bHoMAdapter.DependencyTypes.Values.SelectMany(v => v); + for (int i = 0; i < orderedObjects.Count; i++) + { + var kv = orderedObjects.ElementAt(i); + + foreach (var baseType in kv.Item1.BaseTypes()) + { + foreach (var t in allTypesInDependencies) + { + if (baseType == t) + { + int idx = orderedObjects.IndexOf(orderedObjects.First(o => o.Item1 == baseType)); + + var toAdd = new Tuple>(baseType, orderedObjects[idx].Item2.Concat(kv.Item2)); + orderedObjects.Insert(idx, toAdd); + + orderedObjects.RemoveAt(i + 1); + orderedObjects.RemoveAt(idx + 1); + } + } + } + } + + return orderedObjects; + } + } +} +} + + diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index bf3dd314..4e9e8140 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -31,6 +31,7 @@ using System.Linq; using System.Reflection; using System.ComponentModel; +using System.Collections.ObjectModel; namespace BH.Adapter { @@ -89,70 +90,7 @@ public virtual List Push(IEnumerable objects, string tag = "", P // ACTUAL PUSH // // ----------------------------------------// - // Group the objects by their specific type. - var typeGroups = objectsToPush.GroupBy(x => x.GetType()); - - // Collect all objects and related dependency objects, and group them by type, in this dictionary. - Dictionary> allObjectsPerType = new Dictionary>(); - - allObjectsPerType = Engine.Adapter.Query.GetAllObjectsAndDependencies(objectsToPush, this); - - // Sort all objects and related dependencies by dependency order, so they can be pushed in the correct order. - List>> orderedObjects = new List>>(); - - List handledGroups = new List(); - foreach (var typeGroup in allObjectsPerType) - { - if (handledGroups.Contains(typeGroup.Key)) - continue; - - // We can scan the rest of the input objects to see if they include dependencies of this current object type. - List dependenciesToLookFor = new List(); - - // Add direct dependencies of this current object type. - if (DependencyTypes.TryGetValue(typeGroup.Key, out List typeDeps)) - dependenciesToLookFor.AddRange(typeDeps); - - // Check if the current object type has basetypes (interfaces) for which dependencies may have been specified. - // E.g. for a CrossSection object we can get ISectionProperty which it implements, - // which in turn is a type that commonly specifies additional dependencies (generally, IMaterialFragment). - foreach (var baseType in typeGroup.Key.BaseTypes()) - { - if (DependencyTypes.TryGetValue(baseType, out List baseTypeDeps)) - dependenciesToLookFor.AddRange(baseTypeDeps); - } - - // If this current object type does not have dependencies, add it at the start of the list and continue. - if (!dependenciesToLookFor.Any()) - { - orderedObjects.Insert(0, new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); - handledGroups.Add(typeGroup.Key); - continue; - } - - // Scan the rest of the input objects to see they include dependencies, - // and add them to the orderedObjects list in order to prioritize them. - foreach (var otherTypeGroup in allObjectsPerType) - { - if (otherTypeGroup.Key == typeGroup.Key) - continue; - - if (dependenciesToLookFor.Contains(otherTypeGroup.Key) || dependenciesToLookFor.Any(d => d.IsAssignableFromIncludeGenericsAndRefTypes(otherTypeGroup.Key))) - { - orderedObjects.Add(new Tuple>(otherTypeGroup.Key, otherTypeGroup.Value.OfType())); - handledGroups.Add(otherTypeGroup.Key); - } - } - } - - // The non-handled groups can be added at the end in any order, because they don't have any dependency ordering. - foreach (var typeGroup in allObjectsPerType) - { - if (handledGroups.Contains(typeGroup.Key)) - continue; - - orderedObjects.Add(new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); - } + List>> orderedObjects = Engine.Adapter.Query.GetDependencySortedObjects(objectsToPush, this); // We now have objects grouped per type, and the groups are sorted following the dependency order. foreach (var group in orderedObjects) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 593e4051..b76a9b35 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -60,17 +60,6 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus readObjects = readObjects ?? new List(); // null guard for readObjects - // Merge and push the dependencies - if (m_AdapterSettings.HandleDependencies) - { - var dependencyTypes = Engine.Adapter.Query.GetDependencyTypes(this); - var dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); - - foreach (var depObj in dependencyObjects) - if (!FullCRUD(depObj.Value as dynamic, pushType, tag, actionConfig)) - return false; - } - // Replace objects that overlap and define the objects that still have to be pushed IEnumerable objectsToCreate; diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index ede91282..c1579f9f 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -51,11 +51,15 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = // Merge and push the dependencies if (m_AdapterSettings.HandleDependencies) { - var dependencyTypes = Engine.Adapter.Query.GetDependencyTypes(this); - var dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); //first-level dependencies + // Get the first-level dependencies. + var dependencyTypes = Query.GetDependencyTypes(this); + var dependencyObjects = Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); - foreach (var depObj in dependencyObjects) - if (!FullCRUD(depObj.Value as dynamic, PushType.FullPush, tag, actionConfig)) + // Of those first-level dependencies, recursively gather all sub-dependencies, and group them by type; sort the group by dependency order. + var allDependencyObjectsSorted = Query.GetDependencySortedObjects(dependencyObjects.Values.Cast(), this); + + foreach (var depObj in allDependencyObjectsSorted) + if (!FullCRUD(depObj.Item2 as dynamic, PushType.FullPush, tag, actionConfig)) return false; } diff --git a/BHoM_Adapter_Tests/StructuralAdapter.cs b/BHoM_Adapter_Tests/StructuralAdapter.cs index ea1118ac..55b32b1a 100644 --- a/BHoM_Adapter_Tests/StructuralAdapter.cs +++ b/BHoM_Adapter_Tests/StructuralAdapter.cs @@ -32,7 +32,9 @@ public StructuralAdapter() {typeof(Edge), new List { typeof(Constraint6DOF), typeof(Constraint4DOF) } }, {typeof(ISurfaceProperty), new List { typeof(IMaterialFragment) } }, {typeof(RigidLink), new List { typeof(LinkConstraint), typeof(Node) } }, - {typeof(FEMesh), new List { typeof(Node), typeof(ISurfaceProperty)} } + {typeof(FEMesh), new List { typeof(Node), typeof(ISurfaceProperty)} }, + { typeof(IElementLoad), new List{ typeof(Bar)} }, + { typeof(IElementLoad), new List{ typeof(Node)} } }; } } diff --git a/BHoM_Adapter_Tests/UnitTest1.cs b/BHoM_Adapter_Tests/UnitTest1.cs index 8651c0d5..813bf97d 100644 --- a/BHoM_Adapter_Tests/UnitTest1.cs +++ b/BHoM_Adapter_Tests/UnitTest1.cs @@ -37,5 +37,23 @@ public void TestPush() sa.Push(inputObjects); } + + [Test] + public void TestPush2() + { + StructuralAdapter sa = new StructuralAdapter(); + + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + // Constraint6DOF, Node, Material, SteelSection, BarRelease, Offset, Bar, Loadcase, BarUniformlyDistributedLoad + + //inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + } } } \ No newline at end of file From e516fbf844da64da35d0531fd1b56cfaa87845ed Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 19:29:04 +0000 Subject: [PATCH 007/116] Update UpdateOnly.cs --- .../AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index c1579f9f..b6219729 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -65,8 +65,6 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = return IUpdate(newObjects, actionConfig); } - - } } From 9113876d37756e7a250017f8de678d4734d4d1f7 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 19:29:49 +0000 Subject: [PATCH 008/116] Better error message when Push input objects are of wrong type. I had many students at UCL stuck because they didn't understand this message when they input "Lines" instead of "Bars" --- BHoM_Adapter/AdapterActions/Push.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 4e9e8140..94742504 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -82,7 +82,7 @@ public virtual List Push(IEnumerable objects, string tag = "", P if (objectsToPush.Count() == 0) { - BH.Engine.Base.Compute.RecordError("Input objects were invalid."); + BH.Engine.Base.Compute.RecordError("Input objects were invalid. Check that they are of a type supported by this Adapter's Push."); return new List(); } From a287318941e4c356227b6a653f72432d72928876 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 19:31:14 +0000 Subject: [PATCH 009/116] Update GetDependencySortedObjects.cs Various fixes at the logic. --- .../Query/GetDependencySortedObjects.cs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index 94dc2bb4..b39e6b1b 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -46,7 +46,7 @@ public static partial class Query [Input("bHoMAdapter", "The DependencyTypes that define the order of the output will be gathered from this Adapter instance.")] public static List>> GetDependencySortedObjects(IEnumerable objects, IBHoMAdapter bHoMAdapter) { - if ((objects?.Any() ?? true)|| bHoMAdapter == null) + if ((!objects?.Any() ?? true)|| bHoMAdapter == null) return new List>>(); // Group the objects by their specific type. @@ -114,7 +114,7 @@ public static List>> GetDependencySortedObjects( // Group per base type extracted from dependencies. // This is useful to reduce the number of CRUD calls. - var allTypesInDependencies = bHoMAdapter.DependencyTypes.Values.SelectMany(v => v); + var allTypesInDependencies = bHoMAdapter.DependencyTypes.Values.SelectMany(v => v).Distinct(); for (int i = 0; i < orderedObjects.Count; i++) { var kv = orderedObjects.ElementAt(i); @@ -128,10 +128,21 @@ public static List>> GetDependencySortedObjects( int idx = orderedObjects.IndexOf(orderedObjects.First(o => o.Item1 == baseType)); var toAdd = new Tuple>(baseType, orderedObjects[idx].Item2.Concat(kv.Item2)); - orderedObjects.Insert(idx, toAdd); - orderedObjects.RemoveAt(i + 1); - orderedObjects.RemoveAt(idx + 1); + if (i < idx) + { + orderedObjects.RemoveAt(i); + orderedObjects.RemoveAt(idx - 1); + orderedObjects.Insert(i, toAdd); + + } + else + { + orderedObjects.RemoveAt(idx); + orderedObjects.RemoveAt(i - 1); + orderedObjects.Insert(idx, toAdd); + } + } } } @@ -141,6 +152,5 @@ public static List>> GetDependencySortedObjects( } } } -} From 73380231f635bce69e9d2766800de875dc726354 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 13 Dec 2022 19:31:34 +0000 Subject: [PATCH 010/116] Improved PushTests --- BHoM_Adapter_Tests/PushTests.cs | 84 +++++++++++++++++++++++++ BHoM_Adapter_Tests/StructuralAdapter.cs | 44 +++++++++++++ BHoM_Adapter_Tests/UnitTest1.cs | 59 ----------------- 3 files changed, 128 insertions(+), 59 deletions(-) create mode 100644 BHoM_Adapter_Tests/PushTests.cs delete mode 100644 BHoM_Adapter_Tests/UnitTest1.cs diff --git a/BHoM_Adapter_Tests/PushTests.cs b/BHoM_Adapter_Tests/PushTests.cs new file mode 100644 index 00000000..ef462bfd --- /dev/null +++ b/BHoM_Adapter_Tests/PushTests.cs @@ -0,0 +1,84 @@ +using BH.Adapter.Tests; +using BH.oM.Base; +using BH.oM.Structure.Constraints; +using BH.oM.Structure.Elements; +using BH.oM.Structure.Loads; +using BH.oM.Structure.MaterialFragments; +using BH.oM.Structure.SectionProperties; +using BH.oM.Structure.SurfaceProperties; + +namespace BHoM_Adapter_Tests +{ + public class PushTests + { + StructuralAdapter sa; + [SetUp] + public void Setup() + { + sa = new StructuralAdapter(); + } + + [Test] + public void GroupByParentInterface() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + + IEnumerable? sectionProperties = sa.Created.Where(c => c.Item1 == typeof(ISectionProperty)).FirstOrDefault()?.Item2 ?? new List(); + Assert.IsTrue(sectionProperties.OfType().Any() && sectionProperties.OfType().Any(), + "Section properties should include both the input SteelSections and the AluminiumSection generated via RandomObject()."); + } + + + [Test] + public void DependencyOrder_BarLoads() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + + string correctOrder = "BH.oM.Structure.Constraints.Constraint6DOF, BH.oM.Structure.MaterialFragments.IMaterialFragment, " + + "BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Node, " + + "BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset, " + + "BH.oM.Structure.Elements.Bar, BH.oM.Structure.Loads.Loadcase, " + + "BH.oM.Structure.Loads.BarUniformlyDistributedLoad"; + + string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); + Assert.IsTrue(createdOrder == correctOrder); + } + + + [Test] + public void DependencyOrder_MostStructuralObjects() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + + string correctOrder = "BH.oM.Structure.Constraints.Constraint4DOF, BH.oM.Structure.MaterialFragments.IMaterialFragment, " + + "BH.oM.Structure.Constraints.Constraint6DOF, BH.oM.Structure.SectionProperties.ISectionProperty, " + + "BH.oM.Structure.Elements.Node, BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset, " + + "BH.oM.Structure.Elements.Bar, BH.oM.Structure.Loads.Loadcase, BH.oM.Structure.SurfaceProperties.ISurfaceProperty, " + + "BH.oM.Structure.Elements.Opening, BH.oM.Structure.Elements.Edge, BH.oM.Structure.Loads.BarUniformlyDistributedLoad, " + + "BH.oM.Structure.Elements.FEMesh, BH.oM.Structure.Elements.Panel"; + + string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); + Assert.AreEqual(correctOrder, createdOrder); + } + } +} \ No newline at end of file diff --git a/BHoM_Adapter_Tests/StructuralAdapter.cs b/BHoM_Adapter_Tests/StructuralAdapter.cs index 55b32b1a..ae925433 100644 --- a/BHoM_Adapter_Tests/StructuralAdapter.cs +++ b/BHoM_Adapter_Tests/StructuralAdapter.cs @@ -1,5 +1,8 @@  using BH.Adapter; +using BH.Adapter.Tests; +using BH.oM.Adapter; +using BH.oM.Base; using BH.oM.Structure.Constraints; using BH.oM.Structure.Elements; using BH.oM.Structure.Loads; @@ -8,9 +11,12 @@ using BH.oM.Structure.SectionProperties; using BH.oM.Structure.SurfaceProperties; using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; @@ -18,8 +24,18 @@ namespace BHoM_Adapter_Tests { public class StructuralAdapter : BHoMAdapter { + public List>> Created { get; set; } = new List>>(); + public List> ReadTypes { get; set; } = new List>(); + public List>> Updated { get; set; } = new List>>(); + public List>> Deleted { get; set; } = new List>>(); + public StructuralAdapter() { + m_AdapterSettings = new AdapterSettings() + { + UseAdapterId = false + }; + DependencyTypes = new Dictionary> { {typeof(Bar), new List { typeof(ISectionProperty), typeof(Node), typeof(BarRelease), typeof(Offset)}}, @@ -37,5 +53,33 @@ public StructuralAdapter() { typeof(IElementLoad), new List{ typeof(Node)} } }; } + + protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) + { + Created.Add(new Tuple>(typeof(T), objects.OfType())); + + return true; + } + + protected override IEnumerable IRead(Type type, IList ids, ActionConfig actionConfig = null) + { + ReadTypes.Add(new Tuple(type, ids)); + + return new List(); + } + + protected override bool IUpdate(IEnumerable objects, ActionConfig actionConfig = null) + { + Updated.Add(new Tuple>(typeof(T), objects.OfType())); + + return true; + } + + protected override int IDelete(Type type, IEnumerable ids, ActionConfig actionConfig = null) + { + Deleted.Add(new Tuple>(type, ids)); + + return 0; + } } } diff --git a/BHoM_Adapter_Tests/UnitTest1.cs b/BHoM_Adapter_Tests/UnitTest1.cs deleted file mode 100644 index 813bf97d..00000000 --- a/BHoM_Adapter_Tests/UnitTest1.cs +++ /dev/null @@ -1,59 +0,0 @@ -using BH.Adapter.Tests; -using BH.oM.Structure.Constraints; -using BH.oM.Structure.Elements; -using BH.oM.Structure.Loads; -using BH.oM.Structure.MaterialFragments; -using BH.oM.Structure.SectionProperties; -using BH.oM.Structure.SurfaceProperties; - -namespace BHoM_Adapter_Tests -{ - public class Tests - { - [SetUp] - public void Setup() - { - } - - [Test] - public void TestPush() - { - StructuralAdapter sa = new StructuralAdapter(); - - List inputObjects = new List(); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - - // Constraint6DOF, Node, Material, SteelSection, BarRelease, Offset, Bar, Loadcase, BarUniformlyDistributedLoad - - //inputObjects.AddRange(Create.RandomObjects(10)); - - sa.Push(inputObjects); - } - - [Test] - public void TestPush2() - { - StructuralAdapter sa = new StructuralAdapter(); - - List inputObjects = new List(); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - inputObjects.AddRange(Create.RandomObjects(10)); - - // Constraint6DOF, Node, Material, SteelSection, BarRelease, Offset, Bar, Loadcase, BarUniformlyDistributedLoad - - //inputObjects.AddRange(Create.RandomObjects(10)); - - sa.Push(inputObjects); - } - } -} \ No newline at end of file From ce0feeda9f34993bf152570308c54fa92614d44e Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:08:07 +0000 Subject: [PATCH 011/116] Update Adapter_Engine/Query/GetDependencyRecursive.cs Co-authored-by: Fraser Greenroyd --- Adapter_Engine/Query/GetDependencyRecursive.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencyRecursive.cs b/Adapter_Engine/Query/GetDependencyRecursive.cs index 5a9f5ab3..57493fa2 100644 --- a/Adapter_Engine/Query/GetDependencyRecursive.cs +++ b/Adapter_Engine/Query/GetDependencyRecursive.cs @@ -81,5 +81,3 @@ private static void GetDependencyObjectsRecursive(this IEnumerable objects } } - - From b6fb15100c8b01f56c06c6479e9d940cfbb5e5df Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:08:37 +0000 Subject: [PATCH 012/116] Update Adapter_Engine/Query/GetDependencyRecursive.cs Co-authored-by: Fraser Greenroyd --- Adapter_Engine/Query/GetDependencyRecursive.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter_Engine/Query/GetDependencyRecursive.cs b/Adapter_Engine/Query/GetDependencyRecursive.cs index 57493fa2..553d17ec 100644 --- a/Adapter_Engine/Query/GetDependencyRecursive.cs +++ b/Adapter_Engine/Query/GetDependencyRecursive.cs @@ -63,7 +63,7 @@ public static Dictionary> GetObjectsAndRecursiveDependen return allObjectsPerType; } - private static void GetDependencyObjectsRecursive(this IEnumerable objects, Dictionary> gatheredDependecies, IBHoMAdapter adapter ) where T : IBHoMObject + private static void GetDependencyObjectsRecursive(this IEnumerable objects, Dictionary> gatheredDependecies, IBHoMAdapter adapter) where T : IBHoMObject { List dependencies = GetDependencyTypes(adapter); Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objects, dependencies, adapter); From 28e64d82696a71e6bbdbd91c177d113fe5ff1056 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:10:47 +0000 Subject: [PATCH 013/116] Removed Exit 0 --- Adapter_Engine/Adapter_Engine.csproj | 2 +- Adapter_oM/Adapter_oM.csproj | 2 +- BHoM_Adapter/BHoM_Adapter.csproj | 2 +- Structure_AdapterModules/Structure_AdapterModules.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Adapter_Engine/Adapter_Engine.csproj b/Adapter_Engine/Adapter_Engine.csproj index b6badae7..437bea6f 100644 --- a/Adapter_Engine/Adapter_Engine.csproj +++ b/Adapter_Engine/Adapter_Engine.csproj @@ -16,7 +16,7 @@ - + diff --git a/Adapter_oM/Adapter_oM.csproj b/Adapter_oM/Adapter_oM.csproj index 7f518773..9c0029e7 100644 --- a/Adapter_oM/Adapter_oM.csproj +++ b/Adapter_oM/Adapter_oM.csproj @@ -16,7 +16,7 @@ - + diff --git a/BHoM_Adapter/BHoM_Adapter.csproj b/BHoM_Adapter/BHoM_Adapter.csproj index 3957aa60..7429305c 100644 --- a/BHoM_Adapter/BHoM_Adapter.csproj +++ b/BHoM_Adapter/BHoM_Adapter.csproj @@ -16,7 +16,7 @@ - + diff --git a/Structure_AdapterModules/Structure_AdapterModules.csproj b/Structure_AdapterModules/Structure_AdapterModules.csproj index 59e05c14..b9f16af8 100644 --- a/Structure_AdapterModules/Structure_AdapterModules.csproj +++ b/Structure_AdapterModules/Structure_AdapterModules.csproj @@ -17,7 +17,7 @@ - + From 1b775b3de69ef080e451162cecd7b055ed0d590d Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:19:14 +0000 Subject: [PATCH 014/116] Update BaseTypes.cs --- Adapter_Engine/Query/BaseTypes.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Adapter_Engine/Query/BaseTypes.cs b/Adapter_Engine/Query/BaseTypes.cs index c055f0a2..fc05c03b 100644 --- a/Adapter_Engine/Query/BaseTypes.cs +++ b/Adapter_Engine/Query/BaseTypes.cs @@ -38,15 +38,16 @@ public static partial class Query /***************************************************/ /**** Public Methods ****/ /***************************************************/ + public static Dictionary> m_cachedBaseTypes = new Dictionary>(); [Description("Gets all implemented interfaces and any base type of a given type.")] public static List BaseTypes(this Type type) { - List baseTypes = new List(); - if (type == null) - return baseTypes; + return new List(); + + List baseTypes; if (m_cachedBaseTypes.TryGetValue(type, out baseTypes)) return baseTypes; From e14d7081393dfdf801ada7209ccf672650734c82 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:22:38 +0000 Subject: [PATCH 015/116] Added copyright headers --- BHoM_Adapter_Tests/PushTests.cs | 23 +++++++++++++++++++++++ BHoM_Adapter_Tests/StructuralAdapter.cs | 24 +++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/BHoM_Adapter_Tests/PushTests.cs b/BHoM_Adapter_Tests/PushTests.cs index ef462bfd..be80a635 100644 --- a/BHoM_Adapter_Tests/PushTests.cs +++ b/BHoM_Adapter_Tests/PushTests.cs @@ -1,3 +1,26 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + + using BH.Adapter.Tests; using BH.oM.Base; using BH.oM.Structure.Constraints; diff --git a/BHoM_Adapter_Tests/StructuralAdapter.cs b/BHoM_Adapter_Tests/StructuralAdapter.cs index ae925433..b007cc00 100644 --- a/BHoM_Adapter_Tests/StructuralAdapter.cs +++ b/BHoM_Adapter_Tests/StructuralAdapter.cs @@ -1,4 +1,26 @@ - +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + + using BH.Adapter; using BH.Adapter.Tests; using BH.oM.Adapter; From 736f6905f7fa64c7224bd4c8779dc73a864f6838 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:20:40 +0000 Subject: [PATCH 016/116] Update Adapter_Engine/Query/GetDependencySortedObjects.cs Co-authored-by: Fraser Greenroyd --- Adapter_Engine/Query/GetDependencySortedObjects.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index b39e6b1b..951562df 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -39,7 +39,7 @@ public static partial class Query /***************************************************/ // These are support methods required by other methods in the Push process. - [Description("Recursively gets all the dependencies of the input objects. Then, the dependency objects and input objects are grouped by type." + + [Description("Recursively gets all the dependencies of the input objects. Then, the dependency objects and input objects are grouped by type. " + "Finally, the groups are sorted by dependency order. " + "The resulting collection can be used as an input to invoke CRUD methods in the correct dependency order.")] [Input("objects", "Objects to group and sort by dependency order. The dependency of these objects will also be gathered recursively and included in the output.")] From c1afc5e2c123ace38a648fa9845c2a0ff7126e5c Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:24:47 +0000 Subject: [PATCH 017/116] Moved TestFragment --- BHoM_Adapter_Tests/Create/RandomObjects.cs | 6 ---- BHoM_Adapter_Tests/Objects/TestFragment.cs | 33 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 BHoM_Adapter_Tests/Objects/TestFragment.cs diff --git a/BHoM_Adapter_Tests/Create/RandomObjects.cs b/BHoM_Adapter_Tests/Create/RandomObjects.cs index 9ac829fe..239d5b56 100644 --- a/BHoM_Adapter_Tests/Create/RandomObjects.cs +++ b/BHoM_Adapter_Tests/Create/RandomObjects.cs @@ -83,11 +83,5 @@ public static List RandomIObjects(Type t, int count = 100) return objs; } } - - - public class TestFragment : IFragment - { - public object SomeProp { get; set; } - } } diff --git a/BHoM_Adapter_Tests/Objects/TestFragment.cs b/BHoM_Adapter_Tests/Objects/TestFragment.cs new file mode 100644 index 00000000..c09a946f --- /dev/null +++ b/BHoM_Adapter_Tests/Objects/TestFragment.cs @@ -0,0 +1,33 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + + +using BH.oM.Base; + +namespace BH.Adapter.Tests +{ + public class TestFragment : IFragment + { + public object SomeProp { get; set; } + } +} + From a27db64d9e602a9f6f59a055694ce44d5cf34708 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 13:36:25 +0100 Subject: [PATCH 018/116] Make dependency types look for all interfaces and base types as well Makes it possible to for example specify something for ILoad, and others for say IElementLoad and still have both cases covered --- Adapter_Engine/Query/GetDependencyTypes.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencyTypes.cs b/Adapter_Engine/Query/GetDependencyTypes.cs index 0eeeb61b..5d5bd331 100644 --- a/Adapter_Engine/Query/GetDependencyTypes.cs +++ b/Adapter_Engine/Query/GetDependencyTypes.cs @@ -42,23 +42,21 @@ public static partial class Query public static List GetDependencyTypes(this IBHoMAdapter bhomAdapter) { Type type = typeof(T); + List dependencyTypes = new List(); if (bhomAdapter.DependencyTypes.ContainsKey(type)) - return bhomAdapter.DependencyTypes[type]; + dependencyTypes.AddRange(bhomAdapter.DependencyTypes[type]); - else if (type.BaseType != null && bhomAdapter.DependencyTypes.ContainsKey(type.BaseType)) - return bhomAdapter.DependencyTypes[type.BaseType]; + if (type.BaseType != null && bhomAdapter.DependencyTypes.ContainsKey(type.BaseType)) + dependencyTypes.AddRange(bhomAdapter.DependencyTypes[type.BaseType]); - else + foreach (Type interType in type.GetInterfaces()) { - foreach (Type interType in type.GetInterfaces()) - { - if (bhomAdapter.DependencyTypes.ContainsKey(interType)) - return bhomAdapter.DependencyTypes[interType]; - } + if (bhomAdapter.DependencyTypes.ContainsKey(interType)) + dependencyTypes.AddRange(bhomAdapter.DependencyTypes[interType]); } - return new List(); + return dependencyTypes.Distinct().ToList(); } } } From ec339bfb55c491c5ed13c059dc958094a7cf4b37 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 13:37:19 +0100 Subject: [PATCH 019/116] Fix management of push type together with getting out the dependencies and fix the grouping, making sure it functions with the push type --- .../Query/GetDependencyRecursive.cs | 26 ++++--- .../Query/GetDependencySortedObjects.cs | 72 ++++++++++++------- BHoM_Adapter/AdapterActions/Push.cs | 37 +++++++--- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencyRecursive.cs b/Adapter_Engine/Query/GetDependencyRecursive.cs index 553d17ec..ea2f0118 100644 --- a/Adapter_Engine/Query/GetDependencyRecursive.cs +++ b/Adapter_Engine/Query/GetDependencyRecursive.cs @@ -40,42 +40,46 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - public static Dictionary> GetObjectsAndRecursiveDependencies(this IEnumerable objects, IBHoMAdapter adapter) + public static Dictionary, List> GetObjectsAndRecursiveDependencies(this IEnumerable objects, PushType pushType, IBHoMAdapter adapter) { // Group the objects by their specific type. var typeGroups = objects.GroupBy(x => x.GetType()); - Dictionary> allObjectsPerType = new Dictionary>(); + Dictionary, List> allObjectsPerType = new Dictionary, List>(); foreach (var typeGroup in typeGroups) { - if (allObjectsPerType.ContainsKey(typeGroup.Key)) - allObjectsPerType[typeGroup.Key].AddRange(typeGroup.Cast()); + var key = new Tuple(typeGroup.Key, pushType); + if (allObjectsPerType.ContainsKey(key)) + allObjectsPerType[key].AddRange(typeGroup.Cast()); else - allObjectsPerType[typeGroup.Key] = typeGroup.Cast().ToList(); + allObjectsPerType[key] = typeGroup.Cast().ToList(); MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); dynamic objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); - GetDependencyObjectsRecursive(objList_specificType, allObjectsPerType, adapter); + PushType dependecyPushType = pushType == PushType.UpdateOnly ? PushType.FullPush : pushType; + + GetDependencyObjectsRecursive(objList_specificType, allObjectsPerType, dependecyPushType, adapter); } return allObjectsPerType; } - private static void GetDependencyObjectsRecursive(this IEnumerable objects, Dictionary> gatheredDependecies, IBHoMAdapter adapter) where T : IBHoMObject + private static void GetDependencyObjectsRecursive(this IEnumerable objects, Dictionary, List> gatheredDependecies, PushType pushType, IBHoMAdapter adapter) where T : IBHoMObject { List dependencies = GetDependencyTypes(adapter); Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objects, dependencies, adapter); foreach (var depObj in dependencyObjects) { - if (gatheredDependecies.ContainsKey(depObj.Key)) - gatheredDependecies[depObj.Key].AddRange(depObj.Value.Cast()); + var key = new Tuple(depObj.Key, pushType); + if (gatheredDependecies.ContainsKey(key)) + gatheredDependecies[key].AddRange(depObj.Value.Cast()); else - gatheredDependecies[depObj.Key] = depObj.Value.Cast().ToList(); + gatheredDependecies[key] = depObj.Value.Cast().ToList(); - GetDependencyObjectsRecursive(depObj.Value as dynamic, gatheredDependecies, adapter); + GetDependencyObjectsRecursive(depObj.Value as dynamic, gatheredDependecies, pushType, adapter); } } } diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index 951562df..c82d2c71 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -44,21 +44,21 @@ public static partial class Query "The resulting collection can be used as an input to invoke CRUD methods in the correct dependency order.")] [Input("objects", "Objects to group and sort by dependency order. The dependency of these objects will also be gathered recursively and included in the output.")] [Input("bHoMAdapter", "The DependencyTypes that define the order of the output will be gathered from this Adapter instance.")] - public static List>> GetDependencySortedObjects(IEnumerable objects, IBHoMAdapter bHoMAdapter) + public static List>> GetDependencySortedObjects(IEnumerable objects, PushType pushType, IBHoMAdapter bHoMAdapter) { if ((!objects?.Any() ?? true)|| bHoMAdapter == null) - return new List>>(); + return new List>>(); // Group the objects by their specific type. var typeGroups = objects.GroupBy(x => x.GetType()); // Collect all objects and related dependency objects, recursively, and group them by type. - Dictionary> allObjectsPerType = Engine.Adapter.Query.GetObjectsAndRecursiveDependencies(objects, bHoMAdapter); + Dictionary, List> allObjectsPerType = Engine.Adapter.Query.GetObjectsAndRecursiveDependencies(objects, pushType, bHoMAdapter); // Sort the groups by dependency order, so they can be pushed in the correct order. - List>> orderedObjects = new List>>(); + List>> orderedObjects = new List>>(); - List handledGroups = new List(); + List> handledGroups = new List>(); foreach (var typeGroup in allObjectsPerType) { if (handledGroups.Contains(typeGroup.Key)) @@ -68,13 +68,13 @@ public static List>> GetDependencySortedObjects( List dependenciesToLookFor = new List(); // Add direct dependencies of this current object type. - if (bHoMAdapter.DependencyTypes.TryGetValue(typeGroup.Key, out List typeDeps)) + if (bHoMAdapter.DependencyTypes.TryGetValue(typeGroup.Key.Item1, out List typeDeps)) dependenciesToLookFor.AddRange(typeDeps); // Check if the current object type has basetypes (interfaces) for which dependencies may have been specified. // E.g. for a CrossSection object we can get ISectionProperty which it implements, // which in turn is a type that commonly specifies additional dependencies (generally, IMaterialFragment). - foreach (var baseType in typeGroup.Key.BaseTypes()) + foreach (var baseType in typeGroup.Key.Item1.BaseTypes()) { if (bHoMAdapter.DependencyTypes.TryGetValue(baseType, out List baseTypeDeps)) dependenciesToLookFor.AddRange(baseTypeDeps); @@ -83,7 +83,7 @@ public static List>> GetDependencySortedObjects( // If this current object type does not have dependencies, add it at the start of the list and continue. if (!dependenciesToLookFor.Any()) { - orderedObjects.Insert(0, new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); + orderedObjects.Insert(0, new Tuple>(typeGroup.Key.Item1, typeGroup.Key.Item2, typeGroup.Value.OfType())); handledGroups.Add(typeGroup.Key); continue; } @@ -95,9 +95,9 @@ public static List>> GetDependencySortedObjects( if (handledGroups.Contains(otherTypeGroup.Key) || otherTypeGroup.Key == typeGroup.Key) continue; - if (dependenciesToLookFor.Contains(otherTypeGroup.Key) || dependenciesToLookFor.Any(d => d.IsAssignableFromIncludeGenericsAndRefTypes(otherTypeGroup.Key))) + if (dependenciesToLookFor.Contains(otherTypeGroup.Key.Item1) || dependenciesToLookFor.Any(d => d.IsAssignableFromIncludeGenericsAndRefTypes(otherTypeGroup.Key.Item1))) { - orderedObjects.Add(new Tuple>(otherTypeGroup.Key, otherTypeGroup.Value.OfType())); + orderedObjects.Add(new Tuple>(otherTypeGroup.Key.Item1, otherTypeGroup.Key.Item2, otherTypeGroup.Value.OfType())); handledGroups.Add(otherTypeGroup.Key); } } @@ -109,7 +109,7 @@ public static List>> GetDependencySortedObjects( if (handledGroups.Contains(typeGroup.Key)) continue; - orderedObjects.Add(new Tuple>(typeGroup.Key, typeGroup.Value.OfType())); + orderedObjects.Add(new Tuple>(typeGroup.Key.Item1, typeGroup.Key.Item2, typeGroup.Value.OfType())); } // Group per base type extracted from dependencies. @@ -121,30 +121,48 @@ public static List>> GetDependencySortedObjects( foreach (var baseType in kv.Item1.BaseTypes()) { + bool found = false; foreach (var t in allTypesInDependencies) { - if (baseType == t) - { - int idx = orderedObjects.IndexOf(orderedObjects.First(o => o.Item1 == baseType)); + if (baseType != t) + continue; - var toAdd = new Tuple>(baseType, orderedObjects[idx].Item2.Concat(kv.Item2)); + //Find matching item in the ordered obejct, matching the base type and push type. + var matchingItem = orderedObjects.FirstOrDefault(o => o.Item1 == baseType && o.Item2 == kv.Item2); - if (i < idx) - { - orderedObjects.RemoveAt(i); - orderedObjects.RemoveAt(idx - 1); - orderedObjects.Insert(i, toAdd); + int matchingIndex; + //Get index of matching object if match is not null. + if (matchingItem != null) + matchingIndex = orderedObjects.IndexOf(matchingItem); + else + matchingIndex = -1; - } - else - { - orderedObjects.RemoveAt(idx); - orderedObjects.RemoveAt(i - 1); - orderedObjects.Insert(idx, toAdd); - } + if (matchingIndex == -1) + { + //Nothing found. Replace the current item with base type instead of concrete type. + orderedObjects[i] = new Tuple>(baseType, kv.Item2, kv.Item3); + } + else + { + //If matching base type is found, concatenate the to sets together, to be CRUD together. + //For example, if the pushtype for both is the same, SteelSections and AluminiumSections will be grouped under ISectionProperty if ISectionProperty is in DependencyTypes. + var toAdd = new Tuple>(baseType, orderedObjects[matchingIndex].Item2, orderedObjects[matchingIndex].Item3.Concat(kv.Item3)); + int minIndex = Math.Min(i, matchingIndex); + int maxIndex = Math.Max(i, matchingIndex); + + //Replace on minimum of the two indecies found and remove the other. + orderedObjects[minIndex] = toAdd; + orderedObjects.RemoveAt(maxIndex); + i--; //Decrement i as item has been removed from the list. } + found = true; + break; + } + + if (found) + break; } } diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 94742504..6c83571b 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -90,7 +90,12 @@ public virtual List Push(IEnumerable objects, string tag = "", P // ACTUAL PUSH // // ----------------------------------------// - List>> orderedObjects = Engine.Adapter.Query.GetDependencySortedObjects(objectsToPush, this); + List>> orderedObjects; + + if(m_AdapterSettings.HandleDependencies) + orderedObjects = Engine.Adapter.Query.GetDependencySortedObjects(objectsToPush, pushType, this); + else + orderedObjects = objectsToPush.GroupBy(x => x.GetType()).Select(x => new Tuple>(x.Key, pushType, x.Cast())).ToList(); // We now have objects grouped per type, and the groups are sorted following the dependency order. foreach (var group in orderedObjects) @@ -98,18 +103,30 @@ public virtual List Push(IEnumerable objects, string tag = "", P // Cast the IEnumerable to an IEnumerable where T is the the specific type it contains. // This is used to dynamically dispatch to the right type-specific CRUD method. MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { group.Item1 }); - object objList_specificType = enumCastMethod_specificType.Invoke(group.Item2, new object[] { group.Item2.ToList() }); + object objList_specificType = enumCastMethod_specificType.Invoke(group.Item2, new object[] { group.Item3.ToList() }); - if (pushType == PushType.FullPush || pushType == PushType.CreateNonExisting || pushType == PushType.UpdateOrCreateOnly) - success &= FullCRUD(objList_specificType as dynamic, pushType, tag, actionConfig); - else if (pushType == PushType.CreateOnly) - { - success &= CreateOnly(objList_specificType as dynamic, tag, actionConfig); - } - else if (pushType == PushType.UpdateOnly) + switch (group.Item2) { - success &= UpdateOnly(objList_specificType as dynamic, tag, actionConfig); + case PushType.FullPush: + case PushType.UpdateOrCreateOnly: + case PushType.CreateNonExisting: + success &= FullCRUD(objList_specificType as dynamic, pushType, tag, actionConfig); + break; + case PushType.CreateOnly: + success &= CreateOnly(objList_specificType as dynamic, tag, actionConfig); + break; + + case PushType.UpdateOnly: + success &= UpdateOnly(objList_specificType as dynamic, tag, actionConfig); + break; + + case PushType.DeleteThenCreate: + case PushType.AdapterDefault: + default: + Engine.Base.Compute.RecordError($"Push type {group.Item2} not implemented in {this.GetType().Name}."); + break; } + } return success ? objectsToPush.Cast().ToList() : new List(); From 584bc2552a2c1db5008c0dc3cef788a60274e82f Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 13:37:44 +0100 Subject: [PATCH 020/116] Remove handle dependencies from CreateOnly and UpdateOnly --- .../CRUDDispatchers/CreateOnly.cs | 13 ---------- .../CRUDDispatchers/UpdateOnly.cs | 24 +++++++++---------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index ceb4e4a4..1e2d6b0d 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -53,19 +53,6 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = if (tag != "") newObjects.ForEach(x => x.Tags.Add(tag)); - // We may treat dependencies differently: like calling distinct only for them. - if (m_AdapterSettings.HandleDependencies) - { - var dependencyTypes = Engine.Adapter.Query.GetDependencyTypes(this); - var dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); //first-level dependencies - - foreach (var kv in dependencyObjects) - { - if (!CreateOnly(kv.Value as dynamic, tag, actionConfig, objectLevel++)) - return false; - } - } - // Assign Id if required if (m_AdapterSettings.UseAdapterId) AssignNextFreeId(newObjects); diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index b6219729..371cd37e 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -48,20 +48,20 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = if (tag != "") newObjects.ForEach(x => x.Tags.Add(tag)); - // Merge and push the dependencies - if (m_AdapterSettings.HandleDependencies) - { - // Get the first-level dependencies. - var dependencyTypes = Query.GetDependencyTypes(this); - var dependencyObjects = Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); + //// Merge and push the dependencies + //if (m_AdapterSettings.HandleDependencies) + //{ + // // Get the first-level dependencies. + // var dependencyTypes = Query.GetDependencyTypes(this); + // var dependencyObjects = Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); - // Of those first-level dependencies, recursively gather all sub-dependencies, and group them by type; sort the group by dependency order. - var allDependencyObjectsSorted = Query.GetDependencySortedObjects(dependencyObjects.Values.Cast(), this); + // // Of those first-level dependencies, recursively gather all sub-dependencies, and group them by type; sort the group by dependency order. + // var allDependencyObjectsSorted = Query.GetDependencySortedObjects(dependencyObjects.Values.Cast(), this); - foreach (var depObj in allDependencyObjectsSorted) - if (!FullCRUD(depObj.Item2 as dynamic, PushType.FullPush, tag, actionConfig)) - return false; - } + // foreach (var depObj in allDependencyObjectsSorted) + // if (!FullCRUD(depObj.Item2 as dynamic, PushType.FullPush, tag, actionConfig)) + // return false; + //} return IUpdate(newObjects, actionConfig); } From 70ae20d90e88e23d84db3051d2fc9d33057d9510 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 13:38:46 +0100 Subject: [PATCH 021/116] Fix reference --- BHoM_Adapter/BHoM_Adapter.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BHoM_Adapter/BHoM_Adapter.csproj b/BHoM_Adapter/BHoM_Adapter.csproj index 7429305c..5b978561 100644 --- a/BHoM_Adapter/BHoM_Adapter.csproj +++ b/BHoM_Adapter/BHoM_Adapter.csproj @@ -70,7 +70,9 @@ false - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Reflection_Engine.dll + C:\ProgramData\BHoM\Assemblies\Reflection_Engine.dll + false + false From 40fa11c5e612dd07b841b4c3fbd1849ce978d3d9 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 13:45:05 +0100 Subject: [PATCH 022/116] Adding more tests for UpdateOnly and update references --- BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj | 20 ++++---- BHoM_Adapter_Tests/PushTests.cs | 48 ++++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj index 318d97e4..106ae162 100644 --- a/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj +++ b/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -24,34 +24,34 @@ - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Analytical_oM.dll + C:\ProgramData\BHoM\Assemblies\Analytical_oM.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\BHoM.dll + C:\ProgramData\BHoM\Assemblies\BHoM.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\BHoM_Engine.dll + C:\ProgramData\BHoM\Assemblies\BHoM_Engine.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Dimensional_oM.dll + C:\ProgramData\BHoM\Assemblies\Dimensional_oM.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Geometry_Engine.dll + C:\ProgramData\BHoM\Assemblies\Geometry_Engine.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Geometry_oM.dll + C:\ProgramData\BHoM\Assemblies\Geometry_oM.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Physical_oM.dll + C:\ProgramData\BHoM\Assemblies\Physical_oM.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Spatial_oM.dll + C:\ProgramData\BHoM\Assemblies\Spatial_oM.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Structure_Engine.dll + C:\ProgramData\BHoM\Assemblies\Structure_Engine.dll - ..\..\..\..\..\..\ProgramData\BHoM\Assemblies\Structure_oM.dll + C:\ProgramData\BHoM\Assemblies\Structure_oM.dll diff --git a/BHoM_Adapter_Tests/PushTests.cs b/BHoM_Adapter_Tests/PushTests.cs index be80a635..77affe02 100644 --- a/BHoM_Adapter_Tests/PushTests.cs +++ b/BHoM_Adapter_Tests/PushTests.cs @@ -103,5 +103,53 @@ public void DependencyOrder_MostStructuralObjects() string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); Assert.AreEqual(correctOrder, createdOrder); } + + [Test] + public void Dependecies_UpdateOnly() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects, "", BH.oM.Adapter.PushType.UpdateOnly); + + string correctOrderCreated = "BH.oM.Structure.Constraints.Constraint6DOF, BH.oM.Structure.MaterialFragments.IMaterialFragment, BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Node, BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset"; + string correctOrderUpdated = "BH.oM.Structure.Elements.Node, BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Bar"; + + string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); + string updateOrder = string.Join(", ", sa.Updated.Select(c => c.Item1.FullName)); + Assert.AreEqual(correctOrderCreated, createdOrder); + Assert.AreEqual(correctOrderUpdated, updateOrder); + } + + [Test] + public void DependencyOrder_MultipleSectionTypes() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + + string correctOrder = "BH.oM.Structure.MaterialFragments.IMaterialFragment, BH.oM.Structure.SectionProperties.ISectionProperty"; + + string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); + + Assert.AreEqual(correctOrder, createdOrder); + + List correctCreatedSectionTypes = inputObjects.Select(x => x.GetType()).Distinct().ToList(); + + Assert.IsTrue(sa.Created.Count == 2, "Wrong number of created object types."); + Assert.IsTrue(sa.Created[1].Item1 == typeof(ISectionProperty), "Sections not created as second item."); + + List createdSectionTypes = sa.Created[1].Item2.Select(x => x.GetType()).Distinct().ToList(); + + Assert.AreEqual(correctCreatedSectionTypes, createdSectionTypes); + + + } } } \ No newline at end of file From 8727afb15b3f71e8e7eb04c35da4291be1e1e0c4 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 14:03:07 +0100 Subject: [PATCH 023/116] removing commented out block --- .../CRUDDispatchers/UpdateOnly.cs | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index 371cd37e..061f7146 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -44,29 +44,11 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = { List newObjects = objectsToPush.ToList(); - // Make sure objects are tagged + // Make sure objects are tagged if (tag != "") newObjects.ForEach(x => x.Tags.Add(tag)); - //// Merge and push the dependencies - //if (m_AdapterSettings.HandleDependencies) - //{ - // // Get the first-level dependencies. - // var dependencyTypes = Query.GetDependencyTypes(this); - // var dependencyObjects = Query.GetDependencyObjects(objectsToPush, dependencyTypes, this); - - // // Of those first-level dependencies, recursively gather all sub-dependencies, and group them by type; sort the group by dependency order. - // var allDependencyObjectsSorted = Query.GetDependencySortedObjects(dependencyObjects.Values.Cast(), this); - - // foreach (var depObj in allDependencyObjectsSorted) - // if (!FullCRUD(depObj.Item2 as dynamic, PushType.FullPush, tag, actionConfig)) - // return false; - //} - return IUpdate(newObjects, actionConfig); } } -} - - - +} \ No newline at end of file From 8d7fc91ff28a383c063519ecac4987b42df100f3 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 14:19:28 +0100 Subject: [PATCH 024/116] SOme additional comments and descriptions --- .../Query/GetDependencyRecursive.cs | 23 ++++++++++++++----- .../Query/GetDependencySortedObjects.cs | 7 +++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencyRecursive.cs b/Adapter_Engine/Query/GetDependencyRecursive.cs index ea2f0118..b7244110 100644 --- a/Adapter_Engine/Query/GetDependencyRecursive.cs +++ b/Adapter_Engine/Query/GetDependencyRecursive.cs @@ -40,6 +40,10 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ + [Description("Groups all objects and their dependencies by Type and PushType.")] + [Input("objects", "Objects to group. The dependency of these objects will also be gathered recursively and included in the output.")] + [Input("pushType", "PushType provided in the Push.")] + [Input("bHoMAdapter", "The DependencyTypes will be gathered from this Adapter instance.")] public static Dictionary, List> GetObjectsAndRecursiveDependencies(this IEnumerable objects, PushType pushType, IBHoMAdapter adapter) { // Group the objects by their specific type. @@ -55,21 +59,27 @@ public static Dictionary, List> GetObjectsAnd else allObjectsPerType[key] = typeGroup.Cast().ToList(); - MethodInfo enumCastMethod_specificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); - dynamic objList_specificType = enumCastMethod_specificType.Invoke(typeGroup, new object[] { typeGroup }); + MethodInfo enumCastMethodSpecificType = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] { typeGroup.Key }); + dynamic objListSpecificType = enumCastMethodSpecificType.Invoke(typeGroup, new object[] { typeGroup }); + //For update only the pushtypes for the dependencies should be full crud. + //For all other push types, the same as the top level should be used for the dependencies. PushType dependecyPushType = pushType == PushType.UpdateOnly ? PushType.FullPush : pushType; - GetDependencyObjectsRecursive(objList_specificType, allObjectsPerType, dependecyPushType, adapter); + GetDependencyObjectsRecursive(objListSpecificType, allObjectsPerType, dependecyPushType, adapter); } return allObjectsPerType; } + /***************************************************/ + /**** Private Methods ****/ + /***************************************************/ + private static void GetDependencyObjectsRecursive(this IEnumerable objects, Dictionary, List> gatheredDependecies, PushType pushType, IBHoMAdapter adapter) where T : IBHoMObject { List dependencies = GetDependencyTypes(adapter); - Dictionary dependencyObjects = Engine.Adapter.Query.GetDependencyObjects(objects, dependencies, adapter); + Dictionary dependencyObjects = GetDependencyObjects(objects, dependencies, adapter); foreach (var depObj in dependencyObjects) { @@ -82,6 +92,7 @@ private static void GetDependencyObjectsRecursive(this IEnumerable objects GetDependencyObjectsRecursive(depObj.Value as dynamic, gatheredDependecies, pushType, adapter); } } - } -} + /***************************************************/ + } +} \ No newline at end of file diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index c82d2c71..871a083a 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -39,10 +39,9 @@ public static partial class Query /***************************************************/ // These are support methods required by other methods in the Push process. - [Description("Recursively gets all the dependencies of the input objects. Then, the dependency objects and input objects are grouped by type. " + - "Finally, the groups are sorted by dependency order. " + - "The resulting collection can be used as an input to invoke CRUD methods in the correct dependency order.")] + [Description("Collects and groups all of the obejcts and dependencies of all the objects by type and pushtype. Groups are sorted by dependency order.")] [Input("objects", "Objects to group and sort by dependency order. The dependency of these objects will also be gathered recursively and included in the output.")] + [Input("pushType", "PushType provided in the Push.")] [Input("bHoMAdapter", "The DependencyTypes that define the order of the output will be gathered from this Adapter instance.")] public static List>> GetDependencySortedObjects(IEnumerable objects, PushType pushType, IBHoMAdapter bHoMAdapter) { @@ -53,7 +52,7 @@ public static List>> GetDependencySort var typeGroups = objects.GroupBy(x => x.GetType()); // Collect all objects and related dependency objects, recursively, and group them by type. - Dictionary, List> allObjectsPerType = Engine.Adapter.Query.GetObjectsAndRecursiveDependencies(objects, pushType, bHoMAdapter); + Dictionary, List> allObjectsPerType = GetObjectsAndRecursiveDependencies(objects, pushType, bHoMAdapter); // Sort the groups by dependency order, so they can be pushed in the correct order. List>> orderedObjects = new List>>(); From 37e866d8a94e12e332a8b833547a9a53fa3a81b3 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Thu, 15 Dec 2022 10:15:01 +0000 Subject: [PATCH 025/116] Move tests out of main sln --- .../BHoM_Adapter_Tests.csproj | 6 +-- .../Create/RandomObject.cs | 3 +- .../Create/RandomObjects.cs | 4 +- .../Objects}/StructuralAdapter.cs | 5 +-- .../Objects/TestFragment.cs | 2 +- .../code/BHoM_Adapter_Tests}/PushTests.cs | 6 +-- .ci/code/Verification.sln | 43 +++++++++++++++++++ BHoM_Adapter_Tests/Usings.cs | 1 - 8 files changed, 54 insertions(+), 16 deletions(-) rename {BHoM_Adapter_Tests => .ci/code/BHoM_Adapter_Tests}/BHoM_Adapter_Tests.csproj (89%) rename {BHoM_Adapter_Tests => .ci/code/BHoM_Adapter_Tests}/Create/RandomObject.cs (99%) rename {BHoM_Adapter_Tests => .ci/code/BHoM_Adapter_Tests}/Create/RandomObjects.cs (99%) rename {BHoM_Adapter_Tests => .ci/code/BHoM_Adapter_Tests/Objects}/StructuralAdapter.cs (99%) rename {BHoM_Adapter_Tests => .ci/code/BHoM_Adapter_Tests}/Objects/TestFragment.cs (98%) rename {BHoM_Adapter_Tests => .ci/code/BHoM_Adapter_Tests}/PushTests.cs (99%) create mode 100644 .ci/code/Verification.sln delete mode 100644 BHoM_Adapter_Tests/Usings.cs diff --git a/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj similarity index 89% rename from BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj rename to .ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj index 106ae162..10da25e8 100644 --- a/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj +++ b/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -17,9 +17,9 @@ - - - + + + diff --git a/BHoM_Adapter_Tests/Create/RandomObject.cs b/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs similarity index 99% rename from BHoM_Adapter_Tests/Create/RandomObject.cs rename to .ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs index 9f61b703..984fe40e 100644 --- a/BHoM_Adapter_Tests/Create/RandomObject.cs +++ b/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs @@ -40,5 +40,4 @@ public static T RandomObject() where T : IObject return (T)BH.Engine.Base.Create.RandomObject(typeof(T)); } } -} - +} \ No newline at end of file diff --git a/BHoM_Adapter_Tests/Create/RandomObjects.cs b/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs similarity index 99% rename from BHoM_Adapter_Tests/Create/RandomObjects.cs rename to .ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs index 239d5b56..71163b67 100644 --- a/BHoM_Adapter_Tests/Create/RandomObjects.cs +++ b/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs @@ -22,6 +22,7 @@ using BH.Engine.Base; using BH.oM.Base; +using BH.Tests.Adapter; using System; using System.Collections.Generic; using System.Linq; @@ -83,5 +84,4 @@ public static List RandomIObjects(Type t, int count = 100) return objs; } } -} - +} \ No newline at end of file diff --git a/BHoM_Adapter_Tests/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs similarity index 99% rename from BHoM_Adapter_Tests/StructuralAdapter.cs rename to .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index b007cc00..af28c775 100644 --- a/BHoM_Adapter_Tests/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -20,7 +20,6 @@ * along with this code. If not, see . */ - using BH.Adapter; using BH.Adapter.Tests; using BH.oM.Adapter; @@ -42,7 +41,7 @@ using System.Text; using System.Threading.Tasks; -namespace BHoM_Adapter_Tests +namespace BH.Tests.Adapter { public class StructuralAdapter : BHoMAdapter { @@ -104,4 +103,4 @@ protected override int IDelete(Type type, IEnumerable ids, ActionConfig return 0; } } -} +} \ No newline at end of file diff --git a/BHoM_Adapter_Tests/Objects/TestFragment.cs b/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs similarity index 98% rename from BHoM_Adapter_Tests/Objects/TestFragment.cs rename to .ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs index c09a946f..e5f3bd48 100644 --- a/BHoM_Adapter_Tests/Objects/TestFragment.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs @@ -23,7 +23,7 @@ using BH.oM.Base; -namespace BH.Adapter.Tests +namespace BH.Tests.Adapter { public class TestFragment : IFragment { diff --git a/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs similarity index 99% rename from BHoM_Adapter_Tests/PushTests.cs rename to .ci/code/BHoM_Adapter_Tests/PushTests.cs index 77affe02..bda547d1 100644 --- a/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -20,7 +20,7 @@ * along with this code. If not, see . */ - +using NUnit.Framework; using BH.Adapter.Tests; using BH.oM.Base; using BH.oM.Structure.Constraints; @@ -30,7 +30,7 @@ using BH.oM.Structure.SectionProperties; using BH.oM.Structure.SurfaceProperties; -namespace BHoM_Adapter_Tests +namespace BH.Tests.Adapter.Structure { public class PushTests { @@ -148,8 +148,6 @@ public void DependencyOrder_MultipleSectionTypes() List createdSectionTypes = sa.Created[1].Item2.Select(x => x.GetType()).Distinct().ToList(); Assert.AreEqual(correctCreatedSectionTypes, createdSectionTypes); - - } } } \ No newline at end of file diff --git a/.ci/code/Verification.sln b/.ci/code/Verification.sln new file mode 100644 index 00000000..37ee2426 --- /dev/null +++ b/.ci/code/Verification.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32922.545 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BHoM_Adapter_Tests", "BHoM_Adapter_Tests\BHoM_Adapter_Tests.csproj", "{2693899C-1398-4486-BED2-02809FB43BE9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter_oM", "..\..\Adapter_oM\Adapter_oM.csproj", "{C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter_Engine", "..\..\Adapter_Engine\Adapter_Engine.csproj", "{CE56A0D0-EB5B-4A49-B20F-0432E1832937}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BHoM_Adapter", "..\..\BHoM_Adapter\BHoM_Adapter.csproj", "{C389BC62-717D-4639-BACD-864CF97336BB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2693899C-1398-4486-BED2-02809FB43BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2693899C-1398-4486-BED2-02809FB43BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2693899C-1398-4486-BED2-02809FB43BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2693899C-1398-4486-BED2-02809FB43BE9}.Release|Any CPU.Build.0 = Release|Any CPU + {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Release|Any CPU.Build.0 = Release|Any CPU + {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Release|Any CPU.Build.0 = Release|Any CPU + {C389BC62-717D-4639-BACD-864CF97336BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C389BC62-717D-4639-BACD-864CF97336BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C389BC62-717D-4639-BACD-864CF97336BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C389BC62-717D-4639-BACD-864CF97336BB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {763D45C4-AF11-4244-B502-01ADEC9953BC} + EndGlobalSection +EndGlobal diff --git a/BHoM_Adapter_Tests/Usings.cs b/BHoM_Adapter_Tests/Usings.cs deleted file mode 100644 index cefced49..00000000 --- a/BHoM_Adapter_Tests/Usings.cs +++ /dev/null @@ -1 +0,0 @@ -global using NUnit.Framework; \ No newline at end of file From d59e6531cb4e99c0439e8fc398e8813d6b2f437f Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Thu, 15 Dec 2022 10:15:16 +0000 Subject: [PATCH 026/116] Update BHoM_Adapter.sln --- BHoM_Adapter.sln | 6 ------ 1 file changed, 6 deletions(-) diff --git a/BHoM_Adapter.sln b/BHoM_Adapter.sln index 091d0b78..fabffeef 100644 --- a/BHoM_Adapter.sln +++ b/BHoM_Adapter.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter_oM", "Adapter_oM\Ad EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Structure_AdapterModules", "Structure_AdapterModules\Structure_AdapterModules.csproj", "{48BE209E-658F-48FE-B45B-BB4D7E6CDD03}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BHoM_Adapter_Tests", "BHoM_Adapter_Tests\BHoM_Adapter_Tests.csproj", "{E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,10 +33,6 @@ Global {48BE209E-658F-48FE-B45B-BB4D7E6CDD03}.Debug|Any CPU.Build.0 = Debug|Any CPU {48BE209E-658F-48FE-B45B-BB4D7E6CDD03}.Release|Any CPU.ActiveCfg = Release|Any CPU {48BE209E-658F-48FE-B45B-BB4D7E6CDD03}.Release|Any CPU.Build.0 = Release|Any CPU - {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E654C15C-BA92-43FB-A2D5-90FFE19EF8FC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 29d3cb38ecbf905dffa14e336a4964a9c3d5606b Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 3 Jan 2023 14:03:31 +0000 Subject: [PATCH 027/116] Logic to prioritize UpdateOnly over FullPush for same types --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 25 ++++++++++++++ .../Query/GetDependencySortedObjects.cs | 34 +++++++++++++++---- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index bda547d1..59e95557 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -29,6 +29,7 @@ using BH.oM.Structure.MaterialFragments; using BH.oM.Structure.SectionProperties; using BH.oM.Structure.SurfaceProperties; +using BH.oM.Adapter; namespace BH.Tests.Adapter.Structure { @@ -149,5 +150,29 @@ public void DependencyOrder_MultipleSectionTypes() Assert.AreEqual(correctCreatedSectionTypes, createdSectionTypes); } + + [Test] + public void DependencyOrder_UpdateAndFullPush() + { + List inputObjects = new List(); + Node n = Create.RandomObject(); + Bar bar = Create.RandomObject(); + bar.StartNode = n; + inputObjects.Add(bar); + inputObjects.Add(n); + inputObjects.Add(Create.RandomObject()); // this should be moved up before the Bar's AluminiumSection's FullPush. + inputObjects.Add(new Aluminium()); + inputObjects.Add(new Constraint6DOF()); // this should not "jump ahead" + + var orderedObjects = Engine.Adapter.Query.GetDependencySortedObjects(inputObjects.OfType().ToList(), BH.oM.Adapter.PushType.UpdateOnly, sa); + + var onlyNodes = orderedObjects.Where(t => t.Item1 == typeof(Node)); + + Assert.IsTrue(onlyNodes.Any(t => t.Item2 == PushType.UpdateOnly), "Missing UpdateOnly in the list of pushed nodes."); + Assert.IsTrue(onlyNodes.Any(t => t.Item2 == PushType.FullPush), "Missing FullPush in the list of pushed nodes."); + + Assert.IsTrue(orderedObjects.Where(t => t.Item1 == typeof(Node)).First().Item2 == PushType.UpdateOnly, + "For Node objects, UpdateOnly should have come before FullPush."); + } } } \ No newline at end of file diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index 871a083a..ea0e97a8 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -45,7 +45,7 @@ public static partial class Query [Input("bHoMAdapter", "The DependencyTypes that define the order of the output will be gathered from this Adapter instance.")] public static List>> GetDependencySortedObjects(IEnumerable objects, PushType pushType, IBHoMAdapter bHoMAdapter) { - if ((!objects?.Any() ?? true)|| bHoMAdapter == null) + if ((!objects?.Any() ?? true) || bHoMAdapter == null) return new List>>(); // Group the objects by their specific type. @@ -118,12 +118,12 @@ public static List>> GetDependencySort { var kv = orderedObjects.ElementAt(i); - foreach (var baseType in kv.Item1.BaseTypes()) + foreach (Type baseType in kv.Item1.BaseTypes()) { bool found = false; - foreach (var t in allTypesInDependencies) + foreach (Type dependencyType in allTypesInDependencies) { - if (baseType != t) + if (baseType != dependencyType) continue; //Find matching item in the ordered obejct, matching the base type and push type. @@ -131,12 +131,12 @@ public static List>> GetDependencySort int matchingIndex; //Get index of matching object if match is not null. - if (matchingItem != null) - matchingIndex = orderedObjects.IndexOf(matchingItem); + if (matchingItem != null) + matchingIndex = orderedObjects.IndexOf(matchingItem); else matchingIndex = -1; - if (matchingIndex == -1) + if (matchingIndex == -1) { //Nothing found. Replace the current item with base type instead of concrete type. orderedObjects[i] = new Tuple>(baseType, kv.Item2, kv.Item3); @@ -165,6 +165,26 @@ public static List>> GetDependencySort } } + // If two types are subject to two different CRUD operations (e.g. UpdateOnly and FullCRUD), + // make sure the order of CRUD operations is appropriate (e.g. UpdateOnly must happen before FullCRUD to avoid duplicates). + // For example, this happens when both Nodes and Bars are sent via UpdateOnly during a same Push operation, + // and the Nodes being updated are the same assigned to the endpoints of the Bars being updated). + for (int i = 0; i < orderedObjects.Count; i++) + { + var kv1 = orderedObjects.ElementAt(i); + + for (int j = i + 1; j < orderedObjects.Count; j++) + { + var kv2 = orderedObjects.ElementAt(j); + + if (kv1.Item1 == kv2.Item1 && kv1.Item2 == PushType.FullPush && kv2.Item2 == PushType.UpdateOnly) + { + orderedObjects.RemoveAt(j); + orderedObjects.Insert(i, kv2); + } + } + } + return orderedObjects; } } From 819903f06b5ed80bf008e909ac656cb227cbe607 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 3 Jan 2023 14:23:00 +0000 Subject: [PATCH 028/116] Using Reflection_Engine method --- Adapter_Engine/Query/BaseTypes.cs | 69 ------------------- .../Query/GetDependencySortedObjects.cs | 1 + 2 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 Adapter_Engine/Query/BaseTypes.cs diff --git a/Adapter_Engine/Query/BaseTypes.cs b/Adapter_Engine/Query/BaseTypes.cs deleted file mode 100644 index fc05c03b..00000000 --- a/Adapter_Engine/Query/BaseTypes.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. - * - * Each contributor holds copyright over their respective contributions. - * The project versioning (Git) records all such contribution source information. - * - * - * The BHoM is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3.0 of the License, or - * (at your option) any later version. - * - * The BHoM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - */ - -using BH.oM.Adapter; -using BH.oM.Base; -using BH.Engine.Base; -using BH.oM.Base.Attributes; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using System.Collections; - -namespace BH.Engine.Adapter -{ - public static partial class Query - { - /***************************************************/ - /**** Public Methods ****/ - /***************************************************/ - - public static Dictionary> m_cachedBaseTypes = new Dictionary>(); - - [Description("Gets all implemented interfaces and any base type of a given type.")] - public static List BaseTypes(this Type type) - { - if (type == null) - return new List(); - - List baseTypes; - - if (m_cachedBaseTypes.TryGetValue(type, out baseTypes)) - return baseTypes; - else - baseTypes = new List(); - - baseTypes.AddRange(type.GetInterfaces()); - - Type baseType = type.BaseType; - if (baseType != null) - baseTypes.Add(baseType); - - m_cachedBaseTypes[type] = baseTypes; - - return baseTypes; - } - } -} - diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index ea0e97a8..168507ac 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -29,6 +29,7 @@ using System.Linq; using BH.oM.Adapter; using BH.oM.Base.Attributes; +using BH.Engine.Reflection; namespace BH.Engine.Adapter { From 0cdb24b79c01b5803b47a9d87bbed39be38cea10 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 3 Jan 2023 14:23:06 +0000 Subject: [PATCH 029/116] Update PushTests.cs --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index 59e95557..9abcd17b 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -109,14 +109,16 @@ public void DependencyOrder_MostStructuralObjects() public void Dependecies_UpdateOnly() { List inputObjects = new List(); - inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); sa.Push(inputObjects, "", BH.oM.Adapter.PushType.UpdateOnly); - string correctOrderCreated = "BH.oM.Structure.Constraints.Constraint6DOF, BH.oM.Structure.MaterialFragments.IMaterialFragment, BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Node, BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset"; + string correctOrderCreated = "BH.oM.Structure.MaterialFragments.IMaterialFragment, BH.oM.Structure.Constraints.Constraint6DOF, " + + "BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Node, " + + "BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset"; string correctOrderUpdated = "BH.oM.Structure.Elements.Node, BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Bar"; string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); From a68490487f7a74d287ae51fb70007c5f0a1a0fd5 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 3 Jan 2023 15:25:46 +0000 Subject: [PATCH 030/116] Update GetDependencySortedObjects.cs --- Adapter_Engine/Query/GetDependencySortedObjects.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index 168507ac..33f774db 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -172,11 +172,11 @@ public static List>> GetDependencySort // and the Nodes being updated are the same assigned to the endpoints of the Bars being updated). for (int i = 0; i < orderedObjects.Count; i++) { - var kv1 = orderedObjects.ElementAt(i); + var kv1 = orderedObjects[i]; for (int j = i + 1; j < orderedObjects.Count; j++) { - var kv2 = orderedObjects.ElementAt(j); + var kv2 = orderedObjects[j]; if (kv1.Item1 == kv2.Item1 && kv1.Item2 == PushType.FullPush && kv2.Item2 == PushType.UpdateOnly) { From be92d305abdec12c071c0c90768e68d51fd0a341 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 10:04:18 +0000 Subject: [PATCH 031/116] compliance --- Adapter_Engine/Query/GetDependencySortedObjects.cs | 4 ++-- ...encyRecursive.cs => GetObjectsAndRecursiveDependencies.cs} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename Adapter_Engine/Query/{GetDependencyRecursive.cs => GetObjectsAndRecursiveDependencies.cs} (98%) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index 33f774db..e04d42be 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -44,7 +44,7 @@ public static partial class Query [Input("objects", "Objects to group and sort by dependency order. The dependency of these objects will also be gathered recursively and included in the output.")] [Input("pushType", "PushType provided in the Push.")] [Input("bHoMAdapter", "The DependencyTypes that define the order of the output will be gathered from this Adapter instance.")] - public static List>> GetDependencySortedObjects(IEnumerable objects, PushType pushType, IBHoMAdapter bHoMAdapter) + public static List>> GetDependencySortedObjects(this IEnumerable objects, PushType pushType, IBHoMAdapter bHoMAdapter) { if ((!objects?.Any() ?? true) || bHoMAdapter == null) return new List>>(); diff --git a/Adapter_Engine/Query/GetDependencyRecursive.cs b/Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs similarity index 98% rename from Adapter_Engine/Query/GetDependencyRecursive.cs rename to Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs index b7244110..8e13ed5f 100644 --- a/Adapter_Engine/Query/GetDependencyRecursive.cs +++ b/Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. From 979e5772eefe0df22cfa1cb0a6707b5a369acdf0 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 10:06:34 +0000 Subject: [PATCH 032/116] compliance --- .ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs | 2 +- .ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs | 2 +- .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 2 +- .ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs b/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs index 984fe40e..2e51b424 100644 --- a/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs +++ b/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. diff --git a/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs b/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs index 71163b67..a130b113 100644 --- a/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs +++ b/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index af28c775..6ccfe64f 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs b/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs index e5f3bd48..0c4f63fb 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. From 82c6dbd3dca06fbf941d52d352a370e93b9d701a Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 11:28:35 +0000 Subject: [PATCH 033/116] Adding ref to StructureAdapterModules --- .ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj | 1 + .ci/code/Verification.sln | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj index 10da25e8..13b70f07 100644 --- a/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj +++ b/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -20,6 +20,7 @@ + diff --git a/.ci/code/Verification.sln b/.ci/code/Verification.sln index 37ee2426..99f1e580 100644 --- a/.ci/code/Verification.sln +++ b/.ci/code/Verification.sln @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Adapter_Engine", "..\..\Ada EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BHoM_Adapter", "..\..\BHoM_Adapter\BHoM_Adapter.csproj", "{C389BC62-717D-4639-BACD-864CF97336BB}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Structure_AdapterModules", "..\..\Structure_AdapterModules\Structure_AdapterModules.csproj", "{3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {C389BC62-717D-4639-BACD-864CF97336BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {C389BC62-717D-4639-BACD-864CF97336BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {C389BC62-717D-4639-BACD-864CF97336BB}.Release|Any CPU.Build.0 = Release|Any CPU + {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 52e06886cdcb5ccf9442b97f7bce19aeaeee70a3 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 11:34:39 +0000 Subject: [PATCH 034/116] Update GetDependencyObjects.cs --- Adapter_Engine/Query/GetDependencyObjects.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Adapter_Engine/Query/GetDependencyObjects.cs b/Adapter_Engine/Query/GetDependencyObjects.cs index 7ca433a7..518af31d 100644 --- a/Adapter_Engine/Query/GetDependencyObjects.cs +++ b/Adapter_Engine/Query/GetDependencyObjects.cs @@ -41,6 +41,9 @@ public static partial class Query /***************************************************/ [Description("Fetches all dependancy objects of types provided from the list of the objects. Firsts checks for any DependencyModules, if no present matching the type, tries to scan any property returning the types.")] + [Input("objects", "Objects to get the dependency objects for.")] + [Input("dependencyTypes", "List of types that have dependencies.")] + [Input("adapter", "Adapter for which dependencies must be gathered.")] public static Dictionary GetDependencyObjects(this IEnumerable objects, List dependencyTypes, IBHoMAdapter adapter = null) where T : IBHoMObject { if (objects == null || !objects.Any() || dependencyTypes == null || !dependencyTypes.Any()) From c9fc163cd4ed17dfd0b8e484ee626ab534ef1301 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 11:36:22 +0000 Subject: [PATCH 035/116] Copyright fixes --- .../AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index b76a9b35..fe9a0fea 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -206,8 +206,6 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer // Return the objectsToPush that do not have any overlap with the existing ones; those will need to be created return objsToPush_exclusive; } - - } } From 9313bc3da6e07cc5afb5fff4afc470c752bf123b Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 11:37:47 +0000 Subject: [PATCH 036/116] Update GetObjectsAndRecursiveDependencies.cs --- Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs b/Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs index 8e13ed5f..f44a6d46 100644 --- a/Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs +++ b/Adapter_Engine/Query/GetObjectsAndRecursiveDependencies.cs @@ -43,7 +43,7 @@ public static partial class Query [Description("Groups all objects and their dependencies by Type and PushType.")] [Input("objects", "Objects to group. The dependency of these objects will also be gathered recursively and included in the output.")] [Input("pushType", "PushType provided in the Push.")] - [Input("bHoMAdapter", "The DependencyTypes will be gathered from this Adapter instance.")] + [Input("adapter", "The DependencyTypes will be gathered from this Adapter instance.")] public static Dictionary, List> GetObjectsAndRecursiveDependencies(this IEnumerable objects, PushType pushType, IBHoMAdapter adapter) { // Group the objects by their specific type. From 7b1fb9e8ac5ae3e11717b67de0e26ea0add96740 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 14 Dec 2022 09:24:47 +0000 Subject: [PATCH 037/116] Moved TestFragment --- BHoM_Adapter_Tests/Objects/TestFragment.cs | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 BHoM_Adapter_Tests/Objects/TestFragment.cs diff --git a/BHoM_Adapter_Tests/Objects/TestFragment.cs b/BHoM_Adapter_Tests/Objects/TestFragment.cs new file mode 100644 index 00000000..c09a946f --- /dev/null +++ b/BHoM_Adapter_Tests/Objects/TestFragment.cs @@ -0,0 +1,33 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + + +using BH.oM.Base; + +namespace BH.Adapter.Tests +{ + public class TestFragment : IFragment + { + public object SomeProp { get; set; } + } +} + From 517ae0fffe5a28a74213a620c23a7c0265e429ec Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 13:37:19 +0100 Subject: [PATCH 038/116] Fix management of push type together with getting out the dependencies and fix the grouping, making sure it functions with the push type --- Adapter_Engine/Query/GetDependencySortedObjects.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index e04d42be..aa33f92d 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -183,6 +183,9 @@ public static List>> GetDependencySort orderedObjects.RemoveAt(j); orderedObjects.Insert(i, kv2); } + + if (found) + break; } } From d51c1892e032489379f731d0f37e84f7deb54ff8 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 14 Dec 2022 14:03:07 +0100 Subject: [PATCH 039/116] removing commented out block --- .../AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index 061f7146..48a21b02 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -51,4 +51,4 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = return IUpdate(newObjects, actionConfig); } } -} \ No newline at end of file +} From c2499781a9d77114ff5a4d4d8f903233069650b6 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Thu, 15 Dec 2022 10:15:01 +0000 Subject: [PATCH 040/116] Move tests out of main sln --- BHoM_Adapter_Tests/Objects/TestFragment.cs | 33 ---------------------- 1 file changed, 33 deletions(-) delete mode 100644 BHoM_Adapter_Tests/Objects/TestFragment.cs diff --git a/BHoM_Adapter_Tests/Objects/TestFragment.cs b/BHoM_Adapter_Tests/Objects/TestFragment.cs deleted file mode 100644 index c09a946f..00000000 --- a/BHoM_Adapter_Tests/Objects/TestFragment.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. - * - * Each contributor holds copyright over their respective contributions. - * The project versioning (Git) records all such contribution source information. - * - * - * The BHoM is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3.0 of the License, or - * (at your option) any later version. - * - * The BHoM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - */ - - -using BH.oM.Base; - -namespace BH.Adapter.Tests -{ - public class TestFragment : IFragment - { - public object SomeProp { get; set; } - } -} - From 84e713a02cf5867d0f2dc86557bef513387d7164 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 4 Jan 2023 17:37:38 +0000 Subject: [PATCH 041/116] Update GetDependencySortedObjects.cs --- Adapter_Engine/Query/GetDependencySortedObjects.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index aa33f92d..e04d42be 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -183,9 +183,6 @@ public static List>> GetDependencySort orderedObjects.RemoveAt(j); orderedObjects.Insert(i, kv2); } - - if (found) - break; } } From 1b798924085368d1ce251544d4c937f23faaeaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Fri, 6 Jan 2023 08:15:34 +0100 Subject: [PATCH 042/116] Update .ci/code/BHoM_Adapter_Tests/PushTests.cs --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index 9abcd17b..531ca507 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. From 341aee2981e8c5e5e7a9872f97e67bf5d1b8b301 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 9 Dec 2022 12:27:25 +0100 Subject: [PATCH 043/116] Add module getting objects with no set ID from loads --- .../GetLoadElementsWithoutId.cs | 74 +++++++++++++++++++ Structure_AdapterModules/ModuleLoader.cs | 5 ++ 2 files changed, 79 insertions(+) create mode 100644 Structure_AdapterModules/GetLoadElementsWithoutId.cs diff --git a/Structure_AdapterModules/GetLoadElementsWithoutId.cs b/Structure_AdapterModules/GetLoadElementsWithoutId.cs new file mode 100644 index 00000000..e872f10a --- /dev/null +++ b/Structure_AdapterModules/GetLoadElementsWithoutId.cs @@ -0,0 +1,74 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base; +using BH.oM.Adapter; +using System; +using System.Linq; +using System.Collections.Generic; +using System.Reflection; +using System.ComponentModel; +using BH.oM.Structure.Elements; +using System.Collections; +using BH.oM.Geometry; +using BH.oM.Structure.Constraints; +using BH.oM.Structure.Loads; + + +namespace BH.Adapter.Modules +{ + [Description("Get all elements that does not contain an adapter ID of the expected type. Avoids the need to again read and check against elements already in the model.")] + public class GetLoadElementsWithoutId : IGetDependencyModule, T> where T : IBHoMObject + { + /***************************************************/ + /**** Interface method ****/ + /***************************************************/ + + public IEnumerable GetDependencies(IEnumerable> objects) + { + List noIdLoadObjects = new List(); + foreach (IElementLoad load in objects) + { + if(load?.Objects?.Elements != null) + noIdLoadObjects.AddRange(load.Objects.Elements.Where(x => x != null && !x.Fragments.Contains(m_adapterIdType))); + } + return noIdLoadObjects; + } + + /***************************************************/ + /**** Constructors ****/ + /***************************************************/ + + public GetLoadElementsWithoutId(IBHoMAdapter adapter) + { + m_adapterIdType = adapter.AdapterIdFragmentType; + } + + /***************************************************/ + + private Type m_adapterIdType; + + /***************************************************/ + } +} + + diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 5f608ffb..90d41c94 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -29,6 +29,7 @@ using BH.Adapter; using BH.oM.Adapter; using BH.oM.Base; +using BH.oM.Structure.Elements; namespace BH.Adapter.Modules.Structure { @@ -40,6 +41,10 @@ public static void LoadModules(this BHoMAdapter adapter) adapter.AdapterModules.Add(new CopyNodeProperties()); adapter.AdapterModules.Add(new GetCasesFromCombinations()); adapter.AdapterModules.Add(new GetCombinationsFromCombinations()); + adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); + adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); + adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); + adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); //Gravity loads } } } From b12c6d0bfc82b19a30b0a235320a802248f389f7 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 9 Dec 2022 15:14:58 +0100 Subject: [PATCH 044/116] Fix capital D --- Structure_AdapterModules/GetLoadElementsWithoutId.cs | 4 ++-- Structure_AdapterModules/ModuleLoader.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Structure_AdapterModules/GetLoadElementsWithoutId.cs b/Structure_AdapterModules/GetLoadElementsWithoutId.cs index e872f10a..51812d9f 100644 --- a/Structure_AdapterModules/GetLoadElementsWithoutId.cs +++ b/Structure_AdapterModules/GetLoadElementsWithoutId.cs @@ -37,7 +37,7 @@ namespace BH.Adapter.Modules { [Description("Get all elements that does not contain an adapter ID of the expected type. Avoids the need to again read and check against elements already in the model.")] - public class GetLoadElementsWithoutId : IGetDependencyModule, T> where T : IBHoMObject + public class GetLoadElementsWithoutID : IGetDependencyModule, T> where T : IBHoMObject { /***************************************************/ /**** Interface method ****/ @@ -58,7 +58,7 @@ public IEnumerable GetDependencies(IEnumerable> objects) /**** Constructors ****/ /***************************************************/ - public GetLoadElementsWithoutId(IBHoMAdapter adapter) + public GetLoadElementsWithoutID(IBHoMAdapter adapter) { m_adapterIdType = adapter.AdapterIdFragmentType; } diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 90d41c94..4aaf9786 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -41,10 +41,10 @@ public static void LoadModules(this BHoMAdapter adapter) adapter.AdapterModules.Add(new CopyNodeProperties()); adapter.AdapterModules.Add(new GetCasesFromCombinations()); adapter.AdapterModules.Add(new GetCombinationsFromCombinations()); - adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); - adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); - adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); - adapter.AdapterModules.Add(new GetLoadElementsWithoutId(adapter)); //Gravity loads + adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); //Gravity loads } } } From 508efb69665a1ff5ebb3cc47136c081645fd7238 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 9 Dec 2022 15:15:27 +0100 Subject: [PATCH 045/116] Dummy commit to force filename change --- .../{GetLoadElementsWithoutId.cs => GetLoadElementsWithoutID1.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Structure_AdapterModules/{GetLoadElementsWithoutId.cs => GetLoadElementsWithoutID1.cs} (100%) diff --git a/Structure_AdapterModules/GetLoadElementsWithoutId.cs b/Structure_AdapterModules/GetLoadElementsWithoutID1.cs similarity index 100% rename from Structure_AdapterModules/GetLoadElementsWithoutId.cs rename to Structure_AdapterModules/GetLoadElementsWithoutID1.cs From c066793b165d677f3d77dfe9772f4d37e05eb7e0 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 9 Dec 2022 15:15:42 +0100 Subject: [PATCH 046/116] Correct filename --- .../{GetLoadElementsWithoutID1.cs => GetLoadElementsWithoutID.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Structure_AdapterModules/{GetLoadElementsWithoutID1.cs => GetLoadElementsWithoutID.cs} (100%) diff --git a/Structure_AdapterModules/GetLoadElementsWithoutID1.cs b/Structure_AdapterModules/GetLoadElementsWithoutID.cs similarity index 100% rename from Structure_AdapterModules/GetLoadElementsWithoutID1.cs rename to Structure_AdapterModules/GetLoadElementsWithoutID.cs From a042b12199484b5fdde58eb56b776d4ce59891e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Mon, 9 Jan 2023 08:12:22 +0100 Subject: [PATCH 047/116] Update Structure_AdapterModules/GetLoadElementsWithoutID.cs Co-authored-by: Fraser Greenroyd --- Structure_AdapterModules/GetLoadElementsWithoutID.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Structure_AdapterModules/GetLoadElementsWithoutID.cs b/Structure_AdapterModules/GetLoadElementsWithoutID.cs index 51812d9f..5e47e995 100644 --- a/Structure_AdapterModules/GetLoadElementsWithoutID.cs +++ b/Structure_AdapterModules/GetLoadElementsWithoutID.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. From cbab762b011d03d31a7a1a29b03be11a46e2f9c5 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 08:46:16 +0100 Subject: [PATCH 048/116] Only add list of dependency objects if the list contains any items --- Adapter_Engine/Query/GetDependencyObjects.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencyObjects.cs b/Adapter_Engine/Query/GetDependencyObjects.cs index 518af31d..18575d54 100644 --- a/Adapter_Engine/Query/GetDependencyObjects.cs +++ b/Adapter_Engine/Query/GetDependencyObjects.cs @@ -59,9 +59,10 @@ public static Dictionary GetDependencyObjects(this IEnumer foreach (Type t in dependencyTypes) { MethodInfo generic = method.MakeGenericMethod(new Type[] { typeof(T), t }); - var list = generic.Invoke(null, new object[] { objects, adapter }); + IList list = generic.Invoke(null, new object[] { objects, adapter }) as IList; - dict.Add(t, list as IEnumerable); + if (list != null && list.Count != 0) + dict.Add(t, list); } return dict; From a68690bdec6a50a737af3ef9973c1b577e43682d Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 09:14:04 +0100 Subject: [PATCH 049/116] Adding AdapterId to the test adapter and loading adapter modules --- .../Objects/StructuralAdapter.cs | 3 ++ .../Objects/StructuralAdapterId.cs | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 6ccfe64f..dccf3907 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -73,6 +73,9 @@ public StructuralAdapter() { typeof(IElementLoad), new List{ typeof(Bar)} }, { typeof(IElementLoad), new List{ typeof(Node)} } }; + + AdapterIdFragmentType = typeof(StructuralAdapterId); + BH.Adapter.Modules.Structure.ModuleLoader.LoadModules(this); } protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs new file mode 100644 index 00000000..04225f3a --- /dev/null +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs @@ -0,0 +1,46 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base; +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace BH.Tests.Adapter +{ + [Description("")] + public class StructuralAdapterId : IAdapterId + { + /***************************************************/ + /**** Properties ****/ + /***************************************************/ + + [Description("")] + public virtual object Id { get; set; } + + + /***************************************************/ + + } +} + + From ae21a0e77ee5f9c40dc52246d0ad46153cc323dc Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 09:14:28 +0100 Subject: [PATCH 050/116] Adding Push tests testing added functionality of the PR --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index 531ca507..8c16df72 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -176,5 +176,52 @@ public void DependencyOrder_UpdateAndFullPush() Assert.IsTrue(orderedObjects.Where(t => t.Item1 == typeof(Node)).First().Item2 == PushType.UpdateOnly, "For Node objects, UpdateOnly should have come before FullPush."); } + + [Test] + public void DependencyOrder_CreateLoadAllObjectsWithIds() + { + List bars = Create.RandomObjects(10); + for (int i = 0; i < bars.Count; i++) + { + Engine.Adapter.Modify.SetAdapterId(bars[i], new StructuralAdapterId { Id = i + 1 }); + } + BarUniformlyDistributedLoad load = Create.RandomObject(); + load.Objects.Elements = bars; + + sa.Push(new List { load }); + + string correctOrder = "BH.oM.Structure.Loads.Loadcase, BH.oM.Structure.Loads.BarUniformlyDistributedLoad"; //All bars contain Ids, hence no bars should be created even if there is a dependency on the bars + string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); + + Assert.AreEqual(correctOrder, createdOrder); + } + + [Test] + public void DependencyOrder_CreateLoadHalfObjectsWithIds() + { + int objectCount = 10; + List bars = Create.RandomObjects(objectCount); + int withIdCount = objectCount / 2; + int withoutIdCount = objectCount - withIdCount; + for (int i = 0; i < withIdCount; i++) + { + Engine.Adapter.Modify.SetAdapterId(bars[i], new StructuralAdapterId { Id = i + 1 }); + } + + //Shuffle the order fo the bars. + //Doing this to test that the order of bars with and without Id does not matter + Random random = new Random(2); + bars = bars.OrderBy(x => random.Next()).ToList(); + + BarUniformlyDistributedLoad load = Create.RandomObject(); + load.Objects.Elements = bars; + + sa.Push(new List { load }); + + Assert.IsTrue(sa.Created.Any(x => x.Item1 == typeof(Bar)), "No bars created."); + int barCreationCount = sa.Created.First(x => x.Item1 == typeof(Bar)).Item2.Count(); + + Assert.AreEqual(withoutIdCount, barCreationCount, "Wrong number of bars created."); + } } } \ No newline at end of file From 016c0b32a7ba38d38d7b24d474eacdb23be2dce2 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 14:01:19 +0100 Subject: [PATCH 051/116] Update desc --- Structure_AdapterModules/GetLoadElementsWithoutID.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Structure_AdapterModules/GetLoadElementsWithoutID.cs b/Structure_AdapterModules/GetLoadElementsWithoutID.cs index 5e47e995..fc23eca0 100644 --- a/Structure_AdapterModules/GetLoadElementsWithoutID.cs +++ b/Structure_AdapterModules/GetLoadElementsWithoutID.cs @@ -36,7 +36,7 @@ namespace BH.Adapter.Modules { - [Description("Get all elements that does not contain an adapter ID of the expected type. Avoids the need to again read and check against elements already in the model.")] + [Description("Get all elements that do not contain an adapter ID of the expected type from the provided IElementLoads. Avoids the need to again read and check against elements already in the model.")] public class GetLoadElementsWithoutID : IGetDependencyModule, T> where T : IBHoMObject { /***************************************************/ From 5daa5970668f930d4831dca7b8ea0c5e82c15a60 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 14:03:22 +0100 Subject: [PATCH 052/116] Improve comments --- Structure_AdapterModules/ModuleLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 4aaf9786..52ed5045 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -44,7 +44,7 @@ public static void LoadModules(this BHoMAdapter adapter) adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); - adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); //Gravity loads + adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); //Here to handle GravityLoads that are IElementLoad } } } From 00b997c0de892113864dcd22746966592bd69229 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 14:16:51 +0100 Subject: [PATCH 053/116] Add specific module for gravity loads --- .../GetGravityLoadElementsWithoutID.cs | 74 +++++++++++++++++++ Structure_AdapterModules/ModuleLoader.cs | 3 +- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs diff --git a/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs b/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs new file mode 100644 index 00000000..cee973be --- /dev/null +++ b/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs @@ -0,0 +1,74 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base; +using BH.oM.Adapter; +using System; +using System.Linq; +using System.Collections.Generic; +using System.Reflection; +using System.ComponentModel; +using BH.oM.Structure.Elements; +using System.Collections; +using BH.oM.Geometry; +using BH.oM.Structure.Constraints; +using BH.oM.Structure.Loads; + + +namespace BH.Adapter.Modules +{ + [Description("Get all elements of type T that do not contain an adapter ID of the expected type from the provided GravityLoads. Avoids the need to again read and check against elements already in the model.")] + public class GetGravityLoadElementsWithoutID : IGetDependencyModule where T : IBHoMObject + { + /***************************************************/ + /**** Interface method ****/ + /***************************************************/ + + public IEnumerable GetDependencies(IEnumerable objects) + { + List noIdLoadObjects = new List(); + foreach (GravityLoad load in objects) + { + if(load?.Objects?.Elements != null) + noIdLoadObjects.AddRange(load.Objects.Elements.OfType().Where(x => x != null && !x.Fragments.Contains(m_adapterIdType))); + } + return noIdLoadObjects; + } + + /***************************************************/ + /**** Constructors ****/ + /***************************************************/ + + public GetGravityLoadElementsWithoutID(IBHoMAdapter adapter) + { + m_adapterIdType = adapter.AdapterIdFragmentType; + } + + /***************************************************/ + + private Type m_adapterIdType; + + /***************************************************/ + } +} + + diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 52ed5045..1f812945 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -44,7 +44,8 @@ public static void LoadModules(this BHoMAdapter adapter) adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); - adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); //Here to handle GravityLoads that are IElementLoad + adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); } } } From f61acf749154df3f4aa431aeddd012910b96fb30 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 9 Jan 2023 14:27:31 +0100 Subject: [PATCH 054/116] Fix correct output types for gravity load and add test --- .../Objects/StructuralAdapter.cs | 3 +- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 36 +++++++++++++++++++ Structure_AdapterModules/ModuleLoader.cs | 3 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index dccf3907..24d60c2c 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -71,7 +71,8 @@ public StructuralAdapter() {typeof(RigidLink), new List { typeof(LinkConstraint), typeof(Node) } }, {typeof(FEMesh), new List { typeof(Node), typeof(ISurfaceProperty)} }, { typeof(IElementLoad), new List{ typeof(Bar)} }, - { typeof(IElementLoad), new List{ typeof(Node)} } + { typeof(IElementLoad), new List{ typeof(Node)} }, + { typeof(GravityLoad), new List{ typeof(Bar), typeof(Panel), typeof(FEMesh)} } }; AdapterIdFragmentType = typeof(StructuralAdapterId); diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index 8c16df72..f77a0cb8 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -223,5 +223,41 @@ public void DependencyOrder_CreateLoadHalfObjectsWithIds() Assert.AreEqual(withoutIdCount, barCreationCount, "Wrong number of bars created."); } + + [Test] + public void DependencyOrder_CreateGravityLoadHalfObjectsWithIds() + { + int objectCount = 10; + List bars = Create.RandomObjects(objectCount); + List panels = Create.RandomObjects(objectCount); + int withIdCount = objectCount / 2; + int withoutIdCount = objectCount - withIdCount; + for (int i = 0; i < withIdCount; i++) + { + Engine.Adapter.Modify.SetAdapterId(bars[i], new StructuralAdapterId { Id = i + 1 }); + Engine.Adapter.Modify.SetAdapterId(panels[i], new StructuralAdapterId { Id = i + 1 }); + } + + //Shuffle the order fo the bars. + //Doing this to test that the order of bars with and without Id does not matter + Random random = new Random(2); + bars = bars.OrderBy(x => random.Next()).ToList(); + panels = panels.OrderBy(x => random.Next()).ToList(); + + GravityLoad load = Create.RandomObject(); + load.Objects.Elements = bars.Cast().Concat(panels).ToList(); + + sa.Push(new List { load }); + + Assert.IsTrue(sa.Created.Any(x => x.Item1 == typeof(Bar)), "No bars created."); + int barCreationCount = sa.Created.First(x => x.Item1 == typeof(Bar)).Item2.Count(); + + Assert.AreEqual(withoutIdCount, barCreationCount, "Wrong number of bars created."); + + Assert.IsTrue(sa.Created.Any(x => x.Item1 == typeof(Panel)), "No Panels created."); + int panelsCreationCount = sa.Created.First(x => x.Item1 == typeof(Panel)).Item2.Count(); + + Assert.AreEqual(withoutIdCount, panelsCreationCount, "Wrong number of Panels created."); + } } } \ No newline at end of file diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 1f812945..3adb37b3 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -45,7 +45,8 @@ public static void LoadModules(this BHoMAdapter adapter) adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); - adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); } } } From 4a3ef32666fba1ae8d8534e2a8ea849027f203b7 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 21 Oct 2022 11:57:20 +0200 Subject: [PATCH 055/116] Enableing additional step of checking identity before calling Update in the FullCrud method --- .../Query/GetIdentityComparerForType.cs | 63 +++++++++++++++++++ Adapter_oM/IBHoMAdapter.cs | 1 + Adapter_oM/Settings-Config/AdapterSettings.cs | 3 + .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 22 ++++++- BHoM_Adapter/BHoMAdapter.cs | 8 +++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 Adapter_Engine/Query/GetIdentityComparerForType.cs diff --git a/Adapter_Engine/Query/GetIdentityComparerForType.cs b/Adapter_Engine/Query/GetIdentityComparerForType.cs new file mode 100644 index 00000000..f33cc0f3 --- /dev/null +++ b/Adapter_Engine/Query/GetIdentityComparerForType.cs @@ -0,0 +1,63 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.Engine; +using BH.oM.Base; +using BH.Engine.Base; +using BH.oM.Data; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using BH.oM.Adapter; +using BH.Engine.Diffing; +using BH.Engine.Base.Objects; + +namespace BH.Engine.Adapter +{ + public static partial class Query + { + /***************************************************/ + /**** Push Support methods ****/ + /***************************************************/ + // These are support methods required by other methods in the Push process. + + [Description("Returns the identity comparer to be used with a certain object type, i.e. the comparer to check if the object is identical on every level as seen from the software. Defaults to the HashComparer.")] + public static IEqualityComparer GetIdentityComparerForType(this IBHoMAdapter bHoMAdapter, ActionConfig actionConfig = null) where T : IBHoMObject + { + Type type = typeof(T); + + if (bHoMAdapter.IdentityComparers.ContainsKey(type)) + return bHoMAdapter.IdentityComparers[type] as IEqualityComparer; + + var interfaceComparer = bHoMAdapter.IdentityComparers.Where(x => x.Key.IsAssignableFrom(type)); + + if (interfaceComparer.Any()) + return interfaceComparer.First().Value as IEqualityComparer; + + return new HashComparer(actionConfig?.DiffingConfig?.ComparisonConfig ?? new BH.oM.Base.ComparisonConfig()); //Default to using the HashComparer + } + } +} + + + diff --git a/Adapter_oM/IBHoMAdapter.cs b/Adapter_oM/IBHoMAdapter.cs index 24f6be7a..74841e0f 100644 --- a/Adapter_oM/IBHoMAdapter.cs +++ b/Adapter_oM/IBHoMAdapter.cs @@ -36,6 +36,7 @@ public interface IBHoMAdapter Type AdapterIdFragmentType { get; } ModuleSet AdapterModules { get; } Dictionary AdapterComparers { get; } + Dictionary IdentityComparers { get; } Dictionary> DependencyTypes { get; } Guid AdapterGuid { get; } diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index 3d419855..1abac41a 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -61,6 +61,9 @@ public class AdapterSettings : IObject public virtual bool UseAdapterId { get; set; } = true; public virtual bool UseHashComparerAsDefault { get; set; } = false; public virtual bool ProcessInMemory { get; set; } = false; + [Description("If true, Objects found to be the same acording to the AdapterComparer for the provided type is checked for full equality using the IdentityComparer of the type, and is not updated if equal acording to the latter.\n" + + "If false, Objects found identical acording to the AdapterComparer for the provided type is always sent to be updated.")] + public virtual bool OnlyUpdateChangedObjects { get; set; } = false; /****************************************/ /**** CreateOnly settings *****/ diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index fe9a0fea..609f6167 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -44,6 +44,9 @@ public abstract partial class BHoMAdapter [Description("Performs the full CRUD, calling the single CRUD methods as appropriate.")] protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = PushType.AdapterDefault, string tag = "", ActionConfig actionConfig = null) where T : class, IBHoMObject { + if (objectsToPush == null || !objectsToPush.Any()) + return true; + // Make sure objects are distinct List newObjects = objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this)).ToList(); @@ -143,7 +146,7 @@ protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerab protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumerable readObjs, string tag, ActionConfig actionConfig, PushType pushType) where T : class, IBHoMObject { - IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this); + IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this, actionConfig); VennDiagram diagram = Engine.Data.Create.VennDiagram(objsToPush, readObjs, comparer); // Objects to push that do not have any overlap with the read ones @@ -190,7 +193,22 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer { // Update the overlapping objects (between read and toPush), with the now ported properties. if (diagram.Intersection != null && diagram.Intersection.Any()) - IUpdate(diagram.Intersection.Select(x => x.Item1), actionConfig); + { + List objectsToUpdate; + if (this.m_AdapterSettings.OnlyUpdateChangedObjects) //If true, make use of the IdentityComparers to scan for objects not fully identical, and filter out objects that are + { + IEqualityComparer identityComparer = Engine.Adapter.Query.GetIdentityComparerForType(this, actionConfig); + if (identityComparer.GetType() == comparer.GetType()) //Same comparer used, hence all objects will be seen as fully identical + objectsToUpdate = new List(); + else + objectsToUpdate = diagram.Intersection.Where(x => !identityComparer.Equals(x.Item1, x.Item2)).Select(x => x.Item1).ToList(); //Filter out objects not identical acording to identitycomparer + } + else + objectsToUpdate = diagram.Intersection.Select(x => x.Item1).ToList(); + + if(objectsToUpdate.Any()) + IUpdate(objectsToUpdate, actionConfig); + } } else if(pushType == PushType.CreateNonExisting) { diff --git a/BHoM_Adapter/BHoMAdapter.cs b/BHoM_Adapter/BHoMAdapter.cs index 7184c3fd..7d94ffb3 100644 --- a/BHoM_Adapter/BHoMAdapter.cs +++ b/BHoM_Adapter/BHoMAdapter.cs @@ -50,6 +50,14 @@ public abstract partial class BHoMAdapter : IBHoMAdapter // {typeof(Node), new BH.Engine.Structure.NodeDistanceComparer(3) } }; + [Description("Object Identity comparers to be used within a specific Adapter.\n" + + "Used to determine if the objects are identical and no update is required.\n" + + "Differs from the AdapterComparers in that the AdapterComparers checks if two objects will be seen as the same in the software packege, while this comparers check if the objects are identical.\n" + + "By default the HashComparer using the DiffingConfig on the ActionConfig is used.")] + public Dictionary IdentityComparers { get; protected set; } = new Dictionary + { + }; + [Description("Dependecies between different IBHoMObjects to be considered within a specific Adapter." + "E.g. A Line has dependency type of Points. " + "Needed because different software have different dependency relationships.")] From 64d3f1d8e3a060109997b7228e14959bc7636a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Mon, 24 Oct 2022 08:16:10 +0200 Subject: [PATCH 056/116] Update Adapter_oM/Settings-Config/AdapterSettings.cs Co-authored-by: Alessio Lombardi --- Adapter_oM/Settings-Config/AdapterSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index 1abac41a..cfb525aa 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -62,7 +62,7 @@ public class AdapterSettings : IObject public virtual bool UseHashComparerAsDefault { get; set; } = false; public virtual bool ProcessInMemory { get; set; } = false; [Description("If true, Objects found to be the same acording to the AdapterComparer for the provided type is checked for full equality using the IdentityComparer of the type, and is not updated if equal acording to the latter.\n" + - "If false, Objects found identical acording to the AdapterComparer for the provided type is always sent to be updated.")] + "If false, Objects found identical according to the AdapterComparer for the provided type is always sent to be updated.")] public virtual bool OnlyUpdateChangedObjects { get; set; } = false; /****************************************/ From e6747ca8b19b599de0b3a1948fd8ec762ad0d206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Tue, 10 Jan 2023 08:19:38 +0100 Subject: [PATCH 057/116] Apply suggestions from code review Co-authored-by: Fraser Greenroyd --- Adapter_Engine/Query/GetIdentityComparerForType.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Adapter_Engine/Query/GetIdentityComparerForType.cs b/Adapter_Engine/Query/GetIdentityComparerForType.cs index f33cc0f3..566dbc67 100644 --- a/Adapter_Engine/Query/GetIdentityComparerForType.cs +++ b/Adapter_Engine/Query/GetIdentityComparerForType.cs @@ -1,6 +1,6 @@ /* * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. * * Each contributor holds copyright over their respective contributions. * The project versioning (Git) records all such contribution source information. @@ -59,5 +59,3 @@ public static IEqualityComparer GetIdentityComparerForType(this IBHoMAdapt } } - - From a5c0497391ce02c9baf780170019bc874ca41d31 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 10 Jan 2023 11:45:30 +0100 Subject: [PATCH 058/116] Remove the additional comparers in favour of only relying on the hash comparer In call with @alelom agreed to simply to this for now. If turns out this is a bottleneck, then can add back functionality removed in this commit --- .../Query/GetIdentityComparerForType.cs | 61 ------------------- Adapter_oM/IBHoMAdapter.cs | 1 - Adapter_oM/Settings-Config/AdapterSettings.cs | 2 +- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 8 +-- BHoM_Adapter/BHoMAdapter.cs | 7 --- 5 files changed, 4 insertions(+), 75 deletions(-) delete mode 100644 Adapter_Engine/Query/GetIdentityComparerForType.cs diff --git a/Adapter_Engine/Query/GetIdentityComparerForType.cs b/Adapter_Engine/Query/GetIdentityComparerForType.cs deleted file mode 100644 index 566dbc67..00000000 --- a/Adapter_Engine/Query/GetIdentityComparerForType.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. - * - * Each contributor holds copyright over their respective contributions. - * The project versioning (Git) records all such contribution source information. - * - * - * The BHoM is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3.0 of the License, or - * (at your option) any later version. - * - * The BHoM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - */ - -using BH.Engine; -using BH.oM.Base; -using BH.Engine.Base; -using BH.oM.Data; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using BH.oM.Adapter; -using BH.Engine.Diffing; -using BH.Engine.Base.Objects; - -namespace BH.Engine.Adapter -{ - public static partial class Query - { - /***************************************************/ - /**** Push Support methods ****/ - /***************************************************/ - // These are support methods required by other methods in the Push process. - - [Description("Returns the identity comparer to be used with a certain object type, i.e. the comparer to check if the object is identical on every level as seen from the software. Defaults to the HashComparer.")] - public static IEqualityComparer GetIdentityComparerForType(this IBHoMAdapter bHoMAdapter, ActionConfig actionConfig = null) where T : IBHoMObject - { - Type type = typeof(T); - - if (bHoMAdapter.IdentityComparers.ContainsKey(type)) - return bHoMAdapter.IdentityComparers[type] as IEqualityComparer; - - var interfaceComparer = bHoMAdapter.IdentityComparers.Where(x => x.Key.IsAssignableFrom(type)); - - if (interfaceComparer.Any()) - return interfaceComparer.First().Value as IEqualityComparer; - - return new HashComparer(actionConfig?.DiffingConfig?.ComparisonConfig ?? new BH.oM.Base.ComparisonConfig()); //Default to using the HashComparer - } - } -} - diff --git a/Adapter_oM/IBHoMAdapter.cs b/Adapter_oM/IBHoMAdapter.cs index 74841e0f..24f6be7a 100644 --- a/Adapter_oM/IBHoMAdapter.cs +++ b/Adapter_oM/IBHoMAdapter.cs @@ -36,7 +36,6 @@ public interface IBHoMAdapter Type AdapterIdFragmentType { get; } ModuleSet AdapterModules { get; } Dictionary AdapterComparers { get; } - Dictionary IdentityComparers { get; } Dictionary> DependencyTypes { get; } Guid AdapterGuid { get; } diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index cfb525aa..bc86fdad 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -61,7 +61,7 @@ public class AdapterSettings : IObject public virtual bool UseAdapterId { get; set; } = true; public virtual bool UseHashComparerAsDefault { get; set; } = false; public virtual bool ProcessInMemory { get; set; } = false; - [Description("If true, Objects found to be the same acording to the AdapterComparer for the provided type is checked for full equality using the IdentityComparer of the type, and is not updated if equal acording to the latter.\n" + + [Description("If true, Objects found to be the same acording to the AdapterComparer for the provided type is checked for full equality using the HashComparer of the type, and is not updated if equal acording to the HashComaprer.\n" + "If false, Objects found identical according to the AdapterComparer for the provided type is always sent to be updated.")] public virtual bool OnlyUpdateChangedObjects { get; set; } = false; diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 609f6167..f6e4e24b 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -31,6 +31,7 @@ using BH.oM.Diffing; using BH.oM.Adapter; using BH.Engine.Base; +using BH.Engine.Base.Objects; namespace BH.Adapter { @@ -197,11 +198,8 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer List objectsToUpdate; if (this.m_AdapterSettings.OnlyUpdateChangedObjects) //If true, make use of the IdentityComparers to scan for objects not fully identical, and filter out objects that are { - IEqualityComparer identityComparer = Engine.Adapter.Query.GetIdentityComparerForType(this, actionConfig); - if (identityComparer.GetType() == comparer.GetType()) //Same comparer used, hence all objects will be seen as fully identical - objectsToUpdate = new List(); - else - objectsToUpdate = diagram.Intersection.Where(x => !identityComparer.Equals(x.Item1, x.Item2)).Select(x => x.Item1).ToList(); //Filter out objects not identical acording to identitycomparer + IEqualityComparer fullyEqualComparer = new HashComparer(actionConfig?.DiffingConfig?.ComparisonConfig ?? new ComparisonConfig()); + objectsToUpdate = diagram.Intersection.Where(x => !fullyEqualComparer.Equals(x.Item1, x.Item2)).Select(x => x.Item1).ToList(); //Filter out objects not identical acording to identitycomparer } else objectsToUpdate = diagram.Intersection.Select(x => x.Item1).ToList(); diff --git a/BHoM_Adapter/BHoMAdapter.cs b/BHoM_Adapter/BHoMAdapter.cs index 7d94ffb3..100d47e0 100644 --- a/BHoM_Adapter/BHoMAdapter.cs +++ b/BHoM_Adapter/BHoMAdapter.cs @@ -50,13 +50,6 @@ public abstract partial class BHoMAdapter : IBHoMAdapter // {typeof(Node), new BH.Engine.Structure.NodeDistanceComparer(3) } }; - [Description("Object Identity comparers to be used within a specific Adapter.\n" + - "Used to determine if the objects are identical and no update is required.\n" + - "Differs from the AdapterComparers in that the AdapterComparers checks if two objects will be seen as the same in the software packege, while this comparers check if the objects are identical.\n" + - "By default the HashComparer using the DiffingConfig on the ActionConfig is used.")] - public Dictionary IdentityComparers { get; protected set; } = new Dictionary - { - }; [Description("Dependecies between different IBHoMObjects to be considered within a specific Adapter." + "E.g. A Line has dependency type of Points. " + From ce9305dfe008adffe0c5978a0446792444455e29 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 10 Jan 2023 12:58:43 +0100 Subject: [PATCH 059/116] Make the test adapter read created objects --- .../Objects/StructuralAdapter.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 24d60c2c..cc070d0d 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -22,6 +22,7 @@ using BH.Adapter; using BH.Adapter.Tests; +using BH.Engine.Structure; using BH.oM.Adapter; using BH.oM.Base; using BH.oM.Structure.Constraints; @@ -75,8 +76,20 @@ public StructuralAdapter() { typeof(GravityLoad), new List{ typeof(Bar), typeof(Panel), typeof(FEMesh)} } }; + AdapterComparers = new Dictionary + { + {typeof(Bar), new BarEndNodesDistanceComparer(3) }, + {typeof(Node), new NodeDistanceComparer(3) }, + {typeof(ISectionProperty), new NameOrDescriptionComparer() }, + {typeof(ISurfaceProperty), new NameOrDescriptionComparer() }, + {typeof(IMaterialFragment), new NameOrDescriptionComparer() }, + {typeof(LinkConstraint), new NameOrDescriptionComparer() }, + {typeof(Constraint6DOF), new NameOrDescriptionComparer() }, + }; + AdapterIdFragmentType = typeof(StructuralAdapterId); BH.Adapter.Modules.Structure.ModuleLoader.LoadModules(this); + this.m_AdapterSettings.OnlyUpdateChangedObjects = true; } protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) @@ -90,7 +103,9 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo { ReadTypes.Add(new Tuple(type, ids)); - return new List(); + List modelObejcts = Created.Where(x => x.Item1.IsAssignableFrom(type)).SelectMany(x => x.Item2).ToList(); + + return modelObejcts; } protected override bool IUpdate(IEnumerable objects, ActionConfig actionConfig = null) From 1e6903483c17817fbc88d6c4a9d4678e2d30796e Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 10 Jan 2023 13:36:51 +0100 Subject: [PATCH 060/116] Add unittest for updating --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 79 ++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index f77a0cb8..772c115d 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -30,6 +30,7 @@ using BH.oM.Structure.SectionProperties; using BH.oM.Structure.SurfaceProperties; using BH.oM.Adapter; +using System.Diagnostics.Contracts; namespace BH.Tests.Adapter.Structure { @@ -259,5 +260,83 @@ public void DependencyOrder_CreateGravityLoadHalfObjectsWithIds() Assert.AreEqual(withoutIdCount, panelsCreationCount, "Wrong number of Panels created."); } + + [Test] + public void UpdateOnlyChanged() + { + //Create some random objects + int objectCount = 10; + + List bars = new List(); + List nodes = new List(); + List sectionProperties = new List(); + List steels = new List(); + + //Using methodology below to ensure the same random obejcts are created each set of the run. + //For some edge cases not using the methodology, some strings turned out the same/empty leading to the test failing + for (int i = 0; i < objectCount; i++) + { + bars.Add(BH.Engine.Base.Create.RandomObject(typeof(Bar), (i + 1) * 3) as Bar); + nodes.Add(BH.Engine.Base.Create.RandomObject(typeof(Node), (i + 1) * 7) as Node); + sectionProperties.Add(BH.Engine.Base.Create.RandomObject(typeof(SteelSection), (i + 1) * 37) as SteelSection); + steels.Add(BH.Engine.Base.Create.RandomObject(typeof(Steel), (i + 1) * 13) as Steel); + } + + + List allObjects = bars.Cast().Concat(nodes).Concat(sectionProperties).Concat(steels).ToList(); + + sa.Push(allObjects); + + int changeCount = objectCount / 2; + + HashSet randomIds = new HashSet(); + Random random = new Random(2); + //Generate random ids to change + while (randomIds.Count < changeCount) + { + randomIds.Add((int)Math.Floor(random.NextDouble() * objectCount)); + } + + //Update the random obejcts with the random ids + //The update is ensured to not change the part of the object used by the comparer to identify the objects as the same + //Using methodology below to ensure the same random obejcts are created each set of the run. + //For some edge cases not using the methodology, some strings turned out the same/empty leading to the test failing + foreach (int i in randomIds) + { + bars[i].SectionProperty = BH.Engine.Base.Create.RandomObject(typeof(SteelSection), (i + 1) * 17) as SteelSection; + nodes[i].Support = BH.Engine.Base.Create.RandomObject(typeof(Constraint6DOF), (i + 1) * 19) as Constraint6DOF; + SteelSection newSection = BH.Engine.Base.Create.RandomObject(typeof(SteelSection), (i + 1) * 23) as SteelSection; + newSection.Name = sectionProperties[i].Name; + sectionProperties[i] = newSection; + Steel newMaterial = BH.Engine.Base.Create.RandomObject(typeof(Steel), (i + 1) * 31) as Steel; + newMaterial.Name = steels[i].Name; + steels[i] = newMaterial; + } + + allObjects = bars.Cast().Concat(nodes).Concat(sectionProperties).Concat(steels).ToList(); + + //Push the updated objects again + sa.Push(allObjects); + + Assert.IsTrue(sa.Updated.Any(x => x.Item1 == typeof(Bar)), "No Bars Updated."); + int barUpdateCount = sa.Updated.First(x => x.Item1 == typeof(Bar)).Item2.Count(); + + Assert.AreEqual(changeCount, barUpdateCount, "Wrong number of Bars Updated."); + + Assert.IsTrue(sa.Updated.Any(x => x.Item1 == typeof(Node)), "No Nodes Updated."); + int nodeUpdateCount = sa.Updated.First(x => x.Item1 == typeof(Node)).Item2.Count(); + + Assert.AreEqual(changeCount, nodeUpdateCount, "Wrong number of Nodes Updated."); + + Assert.IsTrue(sa.Updated.Any(x => x.Item1 == typeof(ISectionProperty)), "No SectionProperty Updated."); + int sectionUpdateCount = sa.Updated.First(x => x.Item1 == typeof(ISectionProperty)).Item2.Count(); + + Assert.AreEqual(changeCount, sectionUpdateCount, "Wrong number of ISectionProperties Updated."); + + Assert.IsTrue(sa.Updated.Any(x => x.Item1 == typeof(IMaterialFragment)), "No Materials Updated."); + int materialUpdateCount = sa.Updated.First(x => x.Item1 == typeof(IMaterialFragment)).Item2.Count(); + + Assert.AreEqual(changeCount, materialUpdateCount, "Wrong number of Materials Updated."); + } } } \ No newline at end of file From ba0d193bf528120829c6bad00cd5109d67f1627f Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 10 Jan 2023 13:44:06 +0100 Subject: [PATCH 061/116] remove emtpy line added --- BHoM_Adapter/BHoMAdapter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/BHoM_Adapter/BHoMAdapter.cs b/BHoM_Adapter/BHoMAdapter.cs index 100d47e0..7184c3fd 100644 --- a/BHoM_Adapter/BHoMAdapter.cs +++ b/BHoM_Adapter/BHoMAdapter.cs @@ -50,7 +50,6 @@ public abstract partial class BHoMAdapter : IBHoMAdapter // {typeof(Node), new BH.Engine.Structure.NodeDistanceComparer(3) } }; - [Description("Dependecies between different IBHoMObjects to be considered within a specific Adapter." + "E.g. A Line has dependency type of Points. " + "Needed because different software have different dependency relationships.")] From 465caf97fa99f4173c0ddd53dbfa9c2cb8068e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Tue, 10 Jan 2023 15:33:10 +0100 Subject: [PATCH 062/116] Update Adapter_oM/Settings-Config/AdapterSettings.cs Co-authored-by: Alessio Lombardi --- Adapter_oM/Settings-Config/AdapterSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index bc86fdad..41c233d7 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -61,8 +61,8 @@ public class AdapterSettings : IObject public virtual bool UseAdapterId { get; set; } = true; public virtual bool UseHashComparerAsDefault { get; set; } = false; public virtual bool ProcessInMemory { get; set; } = false; - [Description("If true, Objects found to be the same acording to the AdapterComparer for the provided type is checked for full equality using the HashComparer of the type, and is not updated if equal acording to the HashComaprer.\n" + - "If false, Objects found identical according to the AdapterComparer for the provided type is always sent to be updated.")] + [Description("If true, Objects found to be the same according to the AdapterComparer for the provided type are checked for full equality using the HashComparer of the type (which by default checks every property except BHoM_Guid). If equal according to the HashComparer, they are not updated.\n" + + "Otherwise, Objects found identical according to the AdapterComparer for the provided type are sent to the Update method.")] public virtual bool OnlyUpdateChangedObjects { get; set; } = false; /****************************************/ From e1396f98672dd39e2092fa6735fef6385a2a854b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Tue, 10 Jan 2023 15:33:22 +0100 Subject: [PATCH 063/116] Update BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs Co-authored-by: Alessio Lombardi --- .../AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index f6e4e24b..6a5a0470 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -199,7 +199,7 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer if (this.m_AdapterSettings.OnlyUpdateChangedObjects) //If true, make use of the IdentityComparers to scan for objects not fully identical, and filter out objects that are { IEqualityComparer fullyEqualComparer = new HashComparer(actionConfig?.DiffingConfig?.ComparisonConfig ?? new ComparisonConfig()); - objectsToUpdate = diagram.Intersection.Where(x => !fullyEqualComparer.Equals(x.Item1, x.Item2)).Select(x => x.Item1).ToList(); //Filter out objects not identical acording to identitycomparer + objectsToUpdate = diagram.Intersection.Where(x => !fullyEqualComparer.Equals(x.Item1, x.Item2)).Select(x => x.Item1).ToList(); //Filter out objects not identical according to the HashComparer } else objectsToUpdate = diagram.Intersection.Select(x => x.Item1).ToList(); From 0e9bd9543b910535dff40edcf0527f85e6fd2da4 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 10 Jan 2023 15:36:32 +0100 Subject: [PATCH 064/116] MOve OnlyUpdateChangedObjects to the settings initialisation --- .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index cc070d0d..0cb68198 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -55,7 +55,8 @@ public StructuralAdapter() { m_AdapterSettings = new AdapterSettings() { - UseAdapterId = false + UseAdapterId = false, + OnlyUpdateChangedObjects = true, }; DependencyTypes = new Dictionary> @@ -89,7 +90,6 @@ public StructuralAdapter() AdapterIdFragmentType = typeof(StructuralAdapterId); BH.Adapter.Modules.Structure.ModuleLoader.LoadModules(this); - this.m_AdapterSettings.OnlyUpdateChangedObjects = true; } protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) From 583860a32c114e00e5b1f717058bbd634ed7b1ab Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 10 Jan 2023 16:01:37 +0100 Subject: [PATCH 065/116] always pass ActionConfig to GetComparerForType --- .../_PushMethods/CRUDDispatchers/CreateOnly.cs | 4 ++-- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index 1e2d6b0d..d120c871 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -47,7 +47,7 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = { bool callDistinct = objectLevel == 0 ? m_AdapterSettings.CreateOnly_DistinctObjects : m_AdapterSettings.CreateOnly_DistinctDependencies; - List newObjects = !callDistinct ? objectsToPush.ToList() : objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this)).ToList(); + List newObjects = !callDistinct ? objectsToPush.ToList() : objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this, actionConfig)).ToList(); // Tag the objects, if tag is given. if (tag != "") @@ -66,7 +66,7 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = // Map Ids to the original set of objects (before we extracted the distincts elements from it). // If some objects of the original set were not Created (because e.g. they were already existing in the external model and had already an id, // therefore no new id was assigned to them) they will not get mapped, so the original set will be left with them intact. - IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this); + IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this, actionConfig); foreach (T item in objectsToPush) { // Fetch any existing IAdapterId fragment and assign it to the item. diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 6a5a0470..1602ab46 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -49,7 +49,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus return true; // Make sure objects are distinct - List newObjects = objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this)).ToList(); + List newObjects = objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this, actionConfig)).ToList(); // Add the tag if provided if (!string.IsNullOrWhiteSpace(tag)) @@ -57,7 +57,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus //Read all the objects of that type from the external model IEnumerable readObjects; - if (tag != "" || Engine.Adapter.Query.GetComparerForType(this) != EqualityComparer.Default) + if (tag != "" || Engine.Adapter.Query.GetComparerForType(this, actionConfig) != EqualityComparer.Default) readObjects = Read(typeof(T), "", actionConfig)?.Where(x => x != null && x is T).Cast(); else readObjects = new List(); @@ -77,7 +77,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus objectsToCreate = newObjects; } else if (m_AdapterSettings.ProcessInMemory) - objectsToCreate = ReplaceInMemory(newObjects, readObjects, tag); + objectsToCreate = ReplaceInMemory(newObjects, readObjects, tag, actionConfig); else objectsToCreate = ReplaceThroughAPI(newObjects, readObjects, tag, actionConfig, pushType); @@ -94,7 +94,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus // Map Ids to the original set of objects (before we extracted the distincts elements from it). // If some objects of the original set were not Created (because e.g. they were already existing in the external model and had already an id, // therefore no new id was assigned to them) they will not get mapped, so the original set will be left with them intact. - IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this); + IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this, actionConfig); foreach (T item in objectsToPush) { // Fetch any existing IAdapterId fragment and assign it to the item. @@ -111,7 +111,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus /***************************************************/ - protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerable existingOjects, string tag, bool mergeWithComparer = false) where T : class, IBHoMObject + protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerable existingOjects, string tag, ActionConfig actionConfig, bool mergeWithComparer = false) where T : class, IBHoMObject { // Separate objects based on tags List multiTaggedObjects = existingOjects.Where(x => x.Tags.Contains(tag) && x.Tags.Count > 1).ToList(); @@ -125,7 +125,7 @@ protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerab { VennDiagram diagram = Engine.Data.Create.VennDiagram( newObjects, multiTaggedObjects.Concat(nonTaggedObjects), - Engine.Adapter.Query.GetComparerForType(this)); + Engine.Adapter.Query.GetComparerForType(this, actionConfig)); List> copyPropertiesModules = this.GetCopyPropertiesModules(); From dff7610daf299d0d2466807b9dca6db948e1b3d8 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 17 Jan 2023 12:48:29 +0100 Subject: [PATCH 066/116] Add caching system --- BHoM_Adapter/CRUD/Cache.cs | 343 +++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 BHoM_Adapter/CRUD/Cache.cs diff --git a/BHoM_Adapter/CRUD/Cache.cs b/BHoM_Adapter/CRUD/Cache.cs new file mode 100644 index 00000000..6b40f7b7 --- /dev/null +++ b/BHoM_Adapter/CRUD/Cache.cs @@ -0,0 +1,343 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base; +using System; +using System.Collections.Generic; +using System.Collections; +using System.Linq; +using BH.oM.Data.Requests; +using BH.oM.Adapter; +using BH.Engine.Adapter; +using System.Xml.Linq; +using System.Runtime.InteropServices; + +namespace BH.Adapter +{ + public abstract partial class BHoMAdapter + { + /***************************************************/ + /**** Basic methods ****/ + /***************************************************/ + + protected bool CreateAndCache(IEnumerable objects, ActionConfig actionConfig = null) where T : IBHoMObject + { + if (!ICreate(objects, actionConfig)) + return false; + + Type t = typeof(T); + Dictionary typeCache; + if (!m_cache.TryGetValue(t, out typeCache)) + typeCache = new Dictionary(); + + if (m_AdapterSettings.UseAdapterId) + { + foreach (IBHoMObject bhObj in objects) + { + typeCache[this.GetAdapterId(bhObj)] = bhObj; + } + } + else + { + // For adapters not using Ids, simply cache with integers counting up from 0. + + int n = typeCache.Count; + foreach (IBHoMObject bhObj in objects) + { + typeCache[n] = bhObj; + n++; + } + } + + m_cache[t] = typeCache; + + return true; + } + + /***************************************************/ + + protected virtual IEnumerable ReadCashed(string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject + { + // Call the Basic Method Read() to get the objects based on the ids + IEnumerable objects = ReadCashed(new List(), actionConfig); + + // Null guard + objects = objects ?? new List(); + + // Filter by tag if any + if (tag == "") + return objects; + else + return objects.Where(x => x.Tags.Contains(tag)); + } + + /***************************************************/ + + protected List ReadCashed(IList ids, ActionConfig actionConfig = null) + { + return ReadCashedDictionary(ids, actionConfig).Values.ToList(); + } + + /***************************************************/ + + protected Dictionary ReadCashedDictionary(IList ids, ActionConfig actionConfig = null) + { + + Type t = typeof(T); + if (ids == null || ids.Count == 0) + { + if (m_FullyCachedTypes.Contains(typeof(T))) + { + Dictionary typeCache; + if (m_cache.TryGetValue(t, out typeCache)) + return typeCache.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + else + return new Dictionary(); + } + else + { + // Because we are in the case of no Ids specified, we want to be reading the entire model. + // There may be objects that may have been read, although objects of their type may not be all read yet. + // This means that, because there is no way of knowing which ids (objects) are missing to be read, + // we need to re-read the entire model and cache it fully, although some reads may be redundant. + IEnumerable readObjects = IRead(t, ids, actionConfig); + m_FullyCachedTypes.Add(t); + Dictionary typeCache; + if (m_AdapterSettings.UseAdapterId) + { + typeCache = readObjects.ToDictionary(x => this.GetAdapterId(x), x => x); + m_cache[t] = typeCache; + } + else + { + // For adapters not using Ids, simply cache with integers counting up from 0. + typeCache = new Dictionary(); + + int n = 0; + foreach (IBHoMObject bhObj in readObjects) + { + typeCache[n] = bhObj; + n++; + } + + m_cache[t] = typeCache; + } + + return typeCache.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + } + } + else + { + Dictionary filteredObjects = new Dictionary(); + Dictionary typeCache; + if (m_cache.TryGetValue(t, out typeCache)) + { + List idsNotInCache = new List(); + List cachedObjects = new List(); + + //Loop through the ids and try to fetch from cache. + foreach (object id in ids) + { + if (typeCache.TryGetValue(id, out IBHoMObject obj)) + { + cachedObjects.Add(obj); + filteredObjects[id] = obj; + } + else + idsNotInCache.Add(id); + } + + if (idsNotInCache.Count > 0) + { + //If some of the objects not found in the cache, they need to be read. + //if (m_FullyCachedTypes.Contains(t)) + //{ + // //Already read all objects, but still missing id. Return what was found and raise a warning + // Engine.Base.Compute.RecordWarning($"Unable to extract some objects of type {t.Name} with ids {string.Join(",", idsNotInCache)}."); + // return cachedObjects.OfType().ToList(); + //} + + IEnumerable additionalObjects = IRead(t, idsNotInCache, actionConfig); + + if (m_AdapterSettings.UseAdapterId) + { + foreach (IBHoMObject bhObj in additionalObjects) + { + object id = this.GetAdapterId(bhObj); + typeCache[id] = bhObj; + filteredObjects[id] = bhObj; + } + } + else + { + int n = typeCache.Count; + foreach (IBHoMObject bhObj in additionalObjects) + { + typeCache[n] = bhObj; + filteredObjects[n] = bhObj; + n++; + } + } + m_cache[t] = typeCache; + } + + return filteredObjects.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + } + else + { + typeCache = new Dictionary(); + IEnumerable readObjects = IRead(t, ids, actionConfig); + + if (m_AdapterSettings.UseAdapterId) + { + foreach (IBHoMObject bhObj in readObjects) + { + typeCache[this.GetAdapterId(bhObj)] = bhObj; + } + } + else + { + int n = typeCache.Count; + foreach (IBHoMObject bhObj in readObjects) + { + typeCache[n] = bhObj; + n++; + } + } + m_cache[t] = typeCache; + + return typeCache.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + } + } + } + + /***************************************************/ + + protected virtual bool UpdateCached(IEnumerable objects, ActionConfig actionConfig = null) where T : IBHoMObject + { + if (!IUpdate(objects, actionConfig)) + return false; + + if (!m_AdapterSettings.UseAdapterId) + { + Engine.Base.Compute.RecordWarning("Unable to update cache for adapters not using AdapterIds."); + return true; + } + + Type t = typeof(T); + Dictionary typeCache; + if (!m_cache.TryGetValue(t, out typeCache)) + typeCache = new Dictionary(); + + foreach (IBHoMObject bhObj in objects) + { + typeCache[this.GetAdapterId(bhObj)] = bhObj; + } + + m_cache[t] = typeCache; + + return true; + } + + /***************************************************/ + + protected virtual int UpdateTagsCached(IEnumerable ids, IEnumerable> newTags, ActionConfig actionConfig = null) + { + Type t = typeof(T); + int updateCount = IUpdateTags(t, ids, newTags, actionConfig); + + if (updateCount == 0) + return 0; + + if (!m_AdapterSettings.UseAdapterId) + { + Engine.Base.Compute.RecordWarning("Unable to update cache for adapters not using AdapterIds."); + return updateCount; + } + + Dictionary typeCache; + if (!m_cache.TryGetValue(t, out typeCache)) + typeCache = new Dictionary(); + + List idsList = ids.ToList(); + List> tagsList = newTags.ToList(); + + if (idsList.Count != tagsList.Count) + return updateCount; //Not raising a warning here due to the assumption that the concrete adapter will already have done that + + for (int i = 0; i < idsList.Count; i++) + { + object id = idsList[i]; + IBHoMObject bhObj; + if (typeCache.TryGetValue(id, out bhObj)) + bhObj.Tags = tagsList[i]; + } + + m_cache[t] = typeCache; + + return updateCount; + } + + /***************************************************/ + + protected int DeleteFromModelAndCache(IEnumerable ids, ActionConfig actionConfig = null) where T : IBHoMObject + { + Type t = typeof(T); + int deleteCount = IDelete(t, ids, actionConfig); + if (deleteCount == 0) + return deleteCount; + + if (ids == null || !ids.Any()) + { + m_FullyCachedTypes.Remove(t); + m_cache.Remove(t); + } + else + { + Dictionary typeCache; + if (m_cache.TryGetValue(t, out typeCache)) + { + foreach (object id in ids) + { + typeCache.Remove(id); + } + } + m_cache[t] = typeCache; + } + + return deleteCount; + } + + /***************************************************/ + + protected void ClearCache() + { + m_cache = new Dictionary>(); + m_FullyCachedTypes = new HashSet(); + } + + /***************************************************/ + + private Dictionary> m_cache = new Dictionary>(); + private HashSet m_FullyCachedTypes = new HashSet(); + } +} \ No newline at end of file From cbc16d1875f92ccf4a1e87bbad55e9f24b9ed2cb Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 17 Jan 2023 12:48:48 +0100 Subject: [PATCH 067/116] Ensure cache is cleared for all actions --- BHoM_Adapter/AdapterActions/Pull.cs | 5 ++++- BHoM_Adapter/AdapterActions/Push.cs | 2 ++ BHoM_Adapter/AdapterActions/Remove.cs | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/BHoM_Adapter/AdapterActions/Pull.cs b/BHoM_Adapter/AdapterActions/Pull.cs index 5f94de3f..29e43ccc 100644 --- a/BHoM_Adapter/AdapterActions/Pull.cs +++ b/BHoM_Adapter/AdapterActions/Pull.cs @@ -72,6 +72,7 @@ public virtual bool SetupPullConfig(ActionConfig actionConfig, out ActionConfig [Description("Pulls objects from an external software using the basic CRUD/Read method as appropriate.")] public virtual IEnumerable Pull(IRequest request, PullType pullType = PullType.AdapterDefault, ActionConfig actionConfig = null) { + this.ClearCache(); // `(this as dynamic)` casts the abstract BHoMAdapter to its instance type (e.g. Speckle_Adapter), so all public ReadResults methods are captured if (request is IResultRequest) return (this as dynamic).ReadResults(request as dynamic, actionConfig); @@ -80,7 +81,9 @@ public virtual IEnumerable Pull(IRequest request, PullType pullType = Pu if (request is IRequest) return (this as dynamic).Read(request as dynamic, actionConfig); - return IRead(null, null, actionConfig); + IEnumerable read = IRead(null, null, actionConfig); + this.ClearCache(); + return read; } } } diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 6c83571b..7cad6a45 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -67,6 +67,7 @@ public virtual bool SetupPushType(PushType inputPushType, out PushType pushType) [Description("Pushes input objects using either the 'Full CRUD', 'CreateOnly' or 'UpdateOnly', depending on the PushType.")] public virtual List Push(IEnumerable objects, string tag = "", PushType pushType = PushType.AdapterDefault, ActionConfig actionConfig = null) { + this.ClearCache(); bool success = true; // ----------------------------------------// @@ -129,6 +130,7 @@ public virtual List Push(IEnumerable objects, string tag = "", P } + this.ClearCache(); return success ? objectsToPush.Cast().ToList() : new List(); } } diff --git a/BHoM_Adapter/AdapterActions/Remove.cs b/BHoM_Adapter/AdapterActions/Remove.cs index 7ed4a716..b5eec1e9 100644 --- a/BHoM_Adapter/AdapterActions/Remove.cs +++ b/BHoM_Adapter/AdapterActions/Remove.cs @@ -60,6 +60,7 @@ public virtual bool SetupRemoveConfig(ActionConfig actionConfig, out ActionConfi "The base implementation just calls Delete. It can be overridden in Toolkits.")] public virtual int Remove(IRequest request, ActionConfig actionConfig = null) { + this.ClearCache(); return Delete(request as dynamic, actionConfig); } } From b8ef52f0b6d1e01d7a5d7e68170a00ed913fda18 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 17 Jan 2023 12:49:16 +0100 Subject: [PATCH 068/116] Make crud dispatchers call the cache methods --- .../_PushMethods/CRUDDispatchers/CreateOnly.cs | 2 +- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 17 +++++++---------- .../_PushMethods/CRUDDispatchers/UpdateOnly.cs | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index d120c871..ad106279 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -58,7 +58,7 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = AssignNextFreeId(newObjects); // Create objects - if (!ICreate(newObjects, actionConfig)) + if (!CreateAndCache(newObjects, actionConfig)) return false; if (callDistinct && m_AdapterSettings.UseAdapterId) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 1602ab46..1fb008b9 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -58,7 +58,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus //Read all the objects of that type from the external model IEnumerable readObjects; if (tag != "" || Engine.Adapter.Query.GetComparerForType(this, actionConfig) != EqualityComparer.Default) - readObjects = Read(typeof(T), "", actionConfig)?.Where(x => x != null && x is T).Cast(); + readObjects = ReadCashed("", actionConfig)?.Where(x => x != null); else readObjects = new List(); @@ -72,7 +72,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus // All objects read from the model are to be deleted. // Note that this means that only objects of the same type of the objects being pushed will be deleted. if (readObjects.Any()) - IDelete(typeof(T), readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + DeleteFromModelAndCache(readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); objectsToCreate = newObjects; } @@ -86,7 +86,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus AssignNextFreeId(objectsToCreate); // Create objects - if (!ICreate(objectsToCreate, actionConfig)) + if (!CreateAndCache(objectsToCreate, actionConfig)) return false; if (m_AdapterSettings.UseAdapterId) @@ -168,11 +168,10 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer // Extract the adapterIds from the toBeDeleted and call Delete() for all of them. if (pushType != PushType.UpdateOrCreateOnly && toBeDeleted != null && toBeDeleted.Any()) - IDelete(typeof(T), toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + DeleteFromModelAndCache(toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); // Update the tags for the rest of the existing objects in the model - IUpdateTags(typeof(T), - readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.AdapterIds(AdapterIdFragmentType)), + UpdateTagsCached(readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.AdapterIds(AdapterIdFragmentType)), readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.Tags), actionConfig); @@ -205,20 +204,18 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer objectsToUpdate = diagram.Intersection.Select(x => x.Item1).ToList(); if(objectsToUpdate.Any()) - IUpdate(objectsToUpdate, actionConfig); + UpdateCached(objectsToUpdate, actionConfig); } } else if(pushType == PushType.CreateNonExisting) { //For CreateNonExisting, the overlap objects are just kept, and not updated. To make sure tag functionality works though, //The obejcts need to get their tags (if any) updated. - IUpdateTags(typeof(T), - diagram.Intersection.Where(x => x.Item1.Tags.Count > 0).Select(x => x.Item1.AdapterIds(AdapterIdFragmentType)), + UpdateTagsCached(diagram.Intersection.Where(x => x.Item1.Tags.Count > 0).Select(x => x.Item1.AdapterIds(AdapterIdFragmentType)), diagram.Intersection.Where(x => x.Item1.Tags.Count > 0).Select(x => x.Item1.Tags), actionConfig); } - // Return the objectsToPush that do not have any overlap with the existing ones; those will need to be created return objsToPush_exclusive; } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index 48a21b02..b0250d28 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -48,7 +48,7 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = if (tag != "") newObjects.ForEach(x => x.Tags.Add(tag)); - return IUpdate(newObjects, actionConfig); + return UpdateCached(newObjects, actionConfig); } } } From c332178064c3c7b8b630c8b624902352112255c4 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 17 Jan 2023 13:21:33 +0100 Subject: [PATCH 069/116] Default ids to null --- BHoM_Adapter/CRUD/Cache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BHoM_Adapter/CRUD/Cache.cs b/BHoM_Adapter/CRUD/Cache.cs index 6b40f7b7..a98c66d5 100644 --- a/BHoM_Adapter/CRUD/Cache.cs +++ b/BHoM_Adapter/CRUD/Cache.cs @@ -99,7 +99,7 @@ protected List ReadCashed(IList ids, ActionConfig actionConfig = null) /***************************************************/ - protected Dictionary ReadCashedDictionary(IList ids, ActionConfig actionConfig = null) + protected Dictionary ReadCashedDictionary(IList ids = null, ActionConfig actionConfig = null) { Type t = typeof(T); From c646f2278bc9925cc915c08988a4c9d22534d6c8 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 17 Jan 2023 12:41:06 +0000 Subject: [PATCH 070/116] Adding AdapterSetting to toggle caching mechanism Useful mainly for testing. --- .../CRUDDispatchers/CreateOnly.cs | 3 +- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 51 +++++++++++++++---- .../CRUDDispatchers/UpdateOnly.cs | 5 +- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index ad106279..2d2e3fc5 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -58,7 +58,8 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = AssignNextFreeId(newObjects); // Create objects - if (!CreateAndCache(newObjects, actionConfig)) + if ((m_AdapterSettings.CacheCRUDobjects && !CreateAndCache(newObjects, actionConfig)) + || !ICreate(newObjects, actionConfig)) return false; if (callDistinct && m_AdapterSettings.UseAdapterId) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 1fb008b9..85a747ca 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -58,7 +58,12 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus //Read all the objects of that type from the external model IEnumerable readObjects; if (tag != "" || Engine.Adapter.Query.GetComparerForType(this, actionConfig) != EqualityComparer.Default) - readObjects = ReadCashed("", actionConfig)?.Where(x => x != null); + { + if (m_AdapterSettings.CacheCRUDobjects) + readObjects = ReadCashed("", actionConfig)?.Where(x => x != null); + else + readObjects = Read(typeof(T), "", actionConfig)?.Where(x => x != null && x is T).Cast(); + } else readObjects = new List(); @@ -72,7 +77,12 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus // All objects read from the model are to be deleted. // Note that this means that only objects of the same type of the objects being pushed will be deleted. if (readObjects.Any()) - DeleteFromModelAndCache(readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + { + if (m_AdapterSettings.CacheCRUDobjects) + DeleteFromModelAndCache(readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + else + IDelete(typeof(T), readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + } objectsToCreate = newObjects; } @@ -86,7 +96,8 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus AssignNextFreeId(objectsToCreate); // Create objects - if (!CreateAndCache(objectsToCreate, actionConfig)) + if ((m_AdapterSettings.CacheCRUDobjects && !CreateAndCache(objectsToCreate, actionConfig)) + || !ICreate(objectsToCreate, actionConfig)) return false; if (m_AdapterSettings.UseAdapterId) @@ -168,12 +179,29 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer // Extract the adapterIds from the toBeDeleted and call Delete() for all of them. if (pushType != PushType.UpdateOrCreateOnly && toBeDeleted != null && toBeDeleted.Any()) - DeleteFromModelAndCache(toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + { + if (m_AdapterSettings.CacheCRUDobjects) + DeleteFromModelAndCache(toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + else + IDelete(typeof(T), toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + } // Update the tags for the rest of the existing objects in the model - UpdateTagsCached(readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.AdapterIds(AdapterIdFragmentType)), - readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.Tags), - actionConfig); + if (m_AdapterSettings.CacheCRUDobjects) + { + UpdateTagsCached( + readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.AdapterIds(AdapterIdFragmentType)), + readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.Tags), + actionConfig); + } + else + { + IUpdateTags( + typeof(T), + readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.AdapterIds(AdapterIdFragmentType)), + readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.Tags), + actionConfig); + } // For the objects that have an overlap between existing and pushed // (e.g. an end Node of a Bar being pushed is overlapping with the End Node of a Bar already in the model) @@ -203,8 +231,13 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer else objectsToUpdate = diagram.Intersection.Select(x => x.Item1).ToList(); - if(objectsToUpdate.Any()) - UpdateCached(objectsToUpdate, actionConfig); + if (objectsToUpdate.Any()) + { + if (this.m_AdapterSettings.CacheCRUDobjects) + UpdateCached(objectsToUpdate, actionConfig); + else + IUpdate(objectsToUpdate, actionConfig); + } } } else if(pushType == PushType.CreateNonExisting) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index b0250d28..d3013dfc 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -47,8 +47,11 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = // Make sure objects are tagged if (tag != "") newObjects.ForEach(x => x.Tags.Add(tag)); + + if (m_AdapterSettings.CacheCRUDobjects) + return UpdateCached(newObjects, actionConfig); - return UpdateCached(newObjects, actionConfig); + return IUpdate(newObjects, actionConfig); } } } From 1c3b0254430121923cfa5a8dbefd69c0dadaf8e4 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 17 Jan 2023 12:41:32 +0000 Subject: [PATCH 071/116] Update AdapterSettings.cs --- Adapter_oM/Settings-Config/AdapterSettings.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index 41c233d7..2dbebf4b 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -65,6 +65,9 @@ public class AdapterSettings : IObject "Otherwise, Objects found identical according to the AdapterComparer for the provided type are sent to the Update method.")] public virtual bool OnlyUpdateChangedObjects { get; set; } = false; + [Description("If true, CRUD operations will attempt read/write cache objects to speed things during a same Action.")] + public virtual bool CacheCRUDobjects { get; set; } = true; + /****************************************/ /**** CreateOnly settings *****/ /****************************************/ From 3ca52b5fa6c27b01e980d1ba37fbe50da88a8d23 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 17 Jan 2023 14:20:16 +0100 Subject: [PATCH 072/116] Renaming of cache methods to be more explicit it what they are doing --- .../CRUDDispatchers/CreateOnly.cs | 8 +++- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 20 ++++++---- .../CRUDDispatchers/UpdateOnly.cs | 2 +- BHoM_Adapter/CRUD/Cache.cs | 39 ++++++++----------- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index 2d2e3fc5..3feee507 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -58,8 +58,12 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = AssignNextFreeId(newObjects); // Create objects - if ((m_AdapterSettings.CacheCRUDobjects && !CreateAndCache(newObjects, actionConfig)) - || !ICreate(newObjects, actionConfig)) + if (m_AdapterSettings.CacheCRUDobjects) + { + if (!CreateAndCache(newObjects, actionConfig)) + return false; + } + else if(!ICreate(newObjects, actionConfig)) return false; if (callDistinct && m_AdapterSettings.UseAdapterId) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 85a747ca..242fbf5b 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -60,7 +60,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus if (tag != "" || Engine.Adapter.Query.GetComparerForType(this, actionConfig) != EqualityComparer.Default) { if (m_AdapterSettings.CacheCRUDobjects) - readObjects = ReadCashed("", actionConfig)?.Where(x => x != null); + readObjects = GetCachedOrRead("", actionConfig)?.Where(x => x != null); else readObjects = Read(typeof(T), "", actionConfig)?.Where(x => x != null && x is T).Cast(); } @@ -79,7 +79,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus if (readObjects.Any()) { if (m_AdapterSettings.CacheCRUDobjects) - DeleteFromModelAndCache(readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + DeleteIncludingCache(readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); else IDelete(typeof(T), readObjects.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); } @@ -96,8 +96,12 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus AssignNextFreeId(objectsToCreate); // Create objects - if ((m_AdapterSettings.CacheCRUDobjects && !CreateAndCache(objectsToCreate, actionConfig)) - || !ICreate(objectsToCreate, actionConfig)) + if (m_AdapterSettings.CacheCRUDobjects) + { + if (!CreateAndCache(newObjects, actionConfig)) + return false; + } + else if (!ICreate(newObjects, actionConfig)) return false; if (m_AdapterSettings.UseAdapterId) @@ -181,7 +185,7 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer if (pushType != PushType.UpdateOrCreateOnly && toBeDeleted != null && toBeDeleted.Any()) { if (m_AdapterSettings.CacheCRUDobjects) - DeleteFromModelAndCache(toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); + DeleteIncludingCache(toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); else IDelete(typeof(T), toBeDeleted.Select(obj => obj.AdapterIds(AdapterIdFragmentType)), actionConfig); } @@ -189,7 +193,7 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer // Update the tags for the rest of the existing objects in the model if (m_AdapterSettings.CacheCRUDobjects) { - UpdateTagsCached( + UpdateTagsIncludingCache( readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.AdapterIds(AdapterIdFragmentType)), readObjs_exclusive.Where(x => x.Tags.Count > 0).Select(x => x.Tags), actionConfig); @@ -234,7 +238,7 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer if (objectsToUpdate.Any()) { if (this.m_AdapterSettings.CacheCRUDobjects) - UpdateCached(objectsToUpdate, actionConfig); + UpdateIncludingCache(objectsToUpdate, actionConfig); else IUpdate(objectsToUpdate, actionConfig); } @@ -244,7 +248,7 @@ protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumer { //For CreateNonExisting, the overlap objects are just kept, and not updated. To make sure tag functionality works though, //The obejcts need to get their tags (if any) updated. - UpdateTagsCached(diagram.Intersection.Where(x => x.Item1.Tags.Count > 0).Select(x => x.Item1.AdapterIds(AdapterIdFragmentType)), + UpdateTagsIncludingCache(diagram.Intersection.Where(x => x.Item1.Tags.Count > 0).Select(x => x.Item1.AdapterIds(AdapterIdFragmentType)), diagram.Intersection.Where(x => x.Item1.Tags.Count > 0).Select(x => x.Item1.Tags), actionConfig); } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs index d3013dfc..5215bbc3 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/UpdateOnly.cs @@ -49,7 +49,7 @@ protected virtual bool UpdateOnly(IEnumerable objectsToPush, string tag = newObjects.ForEach(x => x.Tags.Add(tag)); if (m_AdapterSettings.CacheCRUDobjects) - return UpdateCached(newObjects, actionConfig); + return UpdateIncludingCache(newObjects, actionConfig); return IUpdate(newObjects, actionConfig); } diff --git a/BHoM_Adapter/CRUD/Cache.cs b/BHoM_Adapter/CRUD/Cache.cs index a98c66d5..22788d9f 100644 --- a/BHoM_Adapter/CRUD/Cache.cs +++ b/BHoM_Adapter/CRUD/Cache.cs @@ -30,6 +30,7 @@ using BH.Engine.Adapter; using System.Xml.Linq; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace BH.Adapter { @@ -75,10 +76,10 @@ protected bool CreateAndCache(IEnumerable objects, ActionConfig actionConf /***************************************************/ - protected virtual IEnumerable ReadCashed(string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject + protected virtual IEnumerable GetCachedOrRead(string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject { // Call the Basic Method Read() to get the objects based on the ids - IEnumerable objects = ReadCashed(new List(), actionConfig); + IEnumerable objects = GetCachedOrRead(new List(), actionConfig); // Null guard objects = objects ?? new List(); @@ -92,26 +93,26 @@ protected virtual IEnumerable ReadCashed(string tag = "", ActionConfig act /***************************************************/ - protected List ReadCashed(IList ids, ActionConfig actionConfig = null) + protected List GetCachedOrRead(IList ids, ActionConfig actionConfig = null) { - return ReadCashedDictionary(ids, actionConfig).Values.ToList(); + return GetCachedOrReadAsDictionary(ids, actionConfig).Values.ToList(); } /***************************************************/ - protected Dictionary ReadCashedDictionary(IList ids = null, ActionConfig actionConfig = null) + protected Dictionary GetCachedOrReadAsDictionary(IList ids = null, ActionConfig actionConfig = null) { - Type t = typeof(T); + Type t = typeof(TObj); if (ids == null || ids.Count == 0) { - if (m_FullyCachedTypes.Contains(typeof(T))) + if (m_FullyCachedTypes.Contains(typeof(TObj))) { Dictionary typeCache; if (m_cache.TryGetValue(t, out typeCache)) - return typeCache.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + return typeCache.ToDictionary(x => (TId)x.Key, x => (TObj)x.Value); else - return new Dictionary(); + return new Dictionary(); } else { @@ -142,7 +143,7 @@ protected Dictionary ReadCashedDictionary(IList ids = null, Acti m_cache[t] = typeCache; } - return typeCache.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + return typeCache.ToDictionary(x => (TId)x.Key, x => (TObj)x.Value); } } else @@ -168,14 +169,6 @@ protected Dictionary ReadCashedDictionary(IList ids = null, Acti if (idsNotInCache.Count > 0) { - //If some of the objects not found in the cache, they need to be read. - //if (m_FullyCachedTypes.Contains(t)) - //{ - // //Already read all objects, but still missing id. Return what was found and raise a warning - // Engine.Base.Compute.RecordWarning($"Unable to extract some objects of type {t.Name} with ids {string.Join(",", idsNotInCache)}."); - // return cachedObjects.OfType().ToList(); - //} - IEnumerable additionalObjects = IRead(t, idsNotInCache, actionConfig); if (m_AdapterSettings.UseAdapterId) @@ -200,7 +193,7 @@ protected Dictionary ReadCashedDictionary(IList ids = null, Acti m_cache[t] = typeCache; } - return filteredObjects.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + return filteredObjects.ToDictionary(x => (TId)x.Key, x => (TObj)x.Value); } else { @@ -225,14 +218,14 @@ protected Dictionary ReadCashedDictionary(IList ids = null, Acti } m_cache[t] = typeCache; - return typeCache.ToDictionary(x => (TId)x.Key, x => (T)x.Value); + return typeCache.ToDictionary(x => (TId)x.Key, x => (TObj)x.Value); } } } /***************************************************/ - protected virtual bool UpdateCached(IEnumerable objects, ActionConfig actionConfig = null) where T : IBHoMObject + protected virtual bool UpdateIncludingCache(IEnumerable objects, ActionConfig actionConfig = null) where T : IBHoMObject { if (!IUpdate(objects, actionConfig)) return false; @@ -260,7 +253,7 @@ protected virtual bool UpdateCached(IEnumerable objects, ActionConfig acti /***************************************************/ - protected virtual int UpdateTagsCached(IEnumerable ids, IEnumerable> newTags, ActionConfig actionConfig = null) + protected virtual int UpdateTagsIncludingCache(IEnumerable ids, IEnumerable> newTags, ActionConfig actionConfig = null) { Type t = typeof(T); int updateCount = IUpdateTags(t, ids, newTags, actionConfig); @@ -299,7 +292,7 @@ protected virtual int UpdateTagsCached(IEnumerable ids, IEnumerable(IEnumerable ids, ActionConfig actionConfig = null) where T : IBHoMObject + protected int DeleteIncludingCache(IEnumerable ids, ActionConfig actionConfig = null) where T : IBHoMObject { Type t = typeof(T); int deleteCount = IDelete(t, ids, actionConfig); From aae230e1d2c64133b2eea5f8dc2d577cb925905a Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 18 Jan 2023 10:57:51 +0000 Subject: [PATCH 073/116] Bug fix: provide correct pushtype in FullCrud Bug was added in DependencyTypes refactor --- BHoM_Adapter/AdapterActions/Push.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BHoM_Adapter/AdapterActions/Push.cs b/BHoM_Adapter/AdapterActions/Push.cs index 7cad6a45..0d7f68bd 100644 --- a/BHoM_Adapter/AdapterActions/Push.cs +++ b/BHoM_Adapter/AdapterActions/Push.cs @@ -111,7 +111,7 @@ public virtual List Push(IEnumerable objects, string tag = "", P case PushType.FullPush: case PushType.UpdateOrCreateOnly: case PushType.CreateNonExisting: - success &= FullCRUD(objList_specificType as dynamic, pushType, tag, actionConfig); + success &= FullCRUD(objList_specificType as dynamic, group.Item2, tag, actionConfig); break; case PushType.CreateOnly: success &= CreateOnly(objList_specificType as dynamic, tag, actionConfig); From d500d5690a8c33c280a027026d6daf4dfa89e79b Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 18 Jan 2023 10:58:22 +0000 Subject: [PATCH 074/116] FullCRUD: Only call Create if there are Objects to be created --- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 242fbf5b..25b2f6a3 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -95,15 +95,19 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus if (m_AdapterSettings.UseAdapterId) AssignNextFreeId(objectsToCreate); - // Create objects - if (m_AdapterSettings.CacheCRUDobjects) + // Create objects if there are any to be created. + if (objectsToCreate.Any()) { - if (!CreateAndCache(newObjects, actionConfig)) + if (m_AdapterSettings.CacheCRUDobjects) + { + if (!CreateAndCache(objectsToCreate, actionConfig)) + return false; + } + else if (!ICreate(objectsToCreate, actionConfig)) return false; } - else if (!ICreate(newObjects, actionConfig)) - return false; + // Needs to be done even if there are no objectsToCreate as this could include updated objects if (m_AdapterSettings.UseAdapterId) { // Map Ids to the original set of objects (before we extracted the distincts elements from it). From 72240d7ee562ea228756e0e7bbb6aa419417cde6 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Wed, 18 Jan 2023 10:58:41 +0000 Subject: [PATCH 075/116] Adding tests and test logic to count CRUD calls per type --- .../Objects/StructuralAdapter.cs | 53 +++++++++++++++++-- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 31 ++++++++++- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 0cb68198..31ae6489 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -36,11 +36,13 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; +using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; +using System.Reflection; namespace BH.Tests.Adapter { @@ -51,12 +53,22 @@ public class StructuralAdapter : BHoMAdapter public List>> Updated { get; set; } = new List>>(); public List>> Deleted { get; set; } = new List>>(); - public StructuralAdapter() + [Description("Useful e.g. to compare how many calls to Create are done with/without the caching mechanism.")] + public Dictionary CallsToCreatePerType { get; set; } = new Dictionary(); + [Description("Useful e.g. to compare how many calls to Create are done with/without the caching mechanism.")] + public Dictionary CallsToReadPerType { get; set; } = new Dictionary(); + [Description("Useful e.g. to compare how many calls to Create are done with/without the caching mechanism.")] + public Dictionary CallsToUpdatePerType { get; set; } = new Dictionary(); + [Description("Useful e.g. to compare how many calls to Create are done with/without the caching mechanism.")] + public Dictionary CallsToDeletePerType { get; set; } = new Dictionary(); + + public StructuralAdapter(bool cacheCRUDobjects = true) { m_AdapterSettings = new AdapterSettings() { UseAdapterId = false, OnlyUpdateChangedObjects = true, + CacheCRUDobjects = cacheCRUDobjects }; DependencyTypes = new Dictionary> @@ -86,6 +98,8 @@ public StructuralAdapter() {typeof(IMaterialFragment), new NameOrDescriptionComparer() }, {typeof(LinkConstraint), new NameOrDescriptionComparer() }, {typeof(Constraint6DOF), new NameOrDescriptionComparer() }, + {typeof(Offset), new NameOrDescriptionComparer() }, + {typeof(BarRelease), new NameOrDescriptionComparer() } }; AdapterIdFragmentType = typeof(StructuralAdapterId); @@ -96,6 +110,11 @@ protected override bool ICreate(IEnumerable objects, ActionConfig actionCo { Created.Add(new Tuple>(typeof(T), objects.OfType())); + if (!CallsToCreatePerType.TryGetValue(typeof(T), out int n)) + CallsToCreatePerType[typeof(T)] = 1; + else + CallsToCreatePerType[typeof(T)] = n + 1; + return true; } @@ -103,15 +122,38 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo { ReadTypes.Add(new Tuple(type, ids)); - List modelObejcts = Created.Where(x => x.Item1.IsAssignableFrom(type)).SelectMany(x => x.Item2).ToList(); + List modelObjects = Created.Where(x => x.Item1.IsAssignableFrom(type)).SelectMany(x => x.Item2).ToList(); + + MethodInfo method = typeof(Engine.Adapter.Query).GetMethod("GetDependencyTypes"); + method = method.MakeGenericMethod(type); + + List dependencyTypes = method.Invoke(null, new object[] { this }) as List; + + MethodInfo readCached = typeof(BHoMAdapter).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == "GetCachedOrRead"); - return modelObejcts; + foreach (Type t in dependencyTypes) + { + MethodInfo generic = readCached.MakeGenericMethod(t); + generic.Invoke(this, new object[] { null, null }); + } + + if (!CallsToReadPerType.TryGetValue(type, out int n)) + CallsToReadPerType[type] = 1; + else + CallsToReadPerType[type] = n + 1; + + return modelObjects; } protected override bool IUpdate(IEnumerable objects, ActionConfig actionConfig = null) { Updated.Add(new Tuple>(typeof(T), objects.OfType())); + if (!CallsToUpdatePerType.TryGetValue(typeof(T), out int n)) + CallsToUpdatePerType[typeof(T)] = 1; + else + CallsToUpdatePerType[typeof(T)] = n + 1; + return true; } @@ -119,6 +161,11 @@ protected override int IDelete(Type type, IEnumerable ids, ActionConfig { Deleted.Add(new Tuple>(type, ids)); + if (!CallsToDeletePerType.TryGetValue(type, out int n)) + CallsToDeletePerType[type] = 1; + else + CallsToDeletePerType[type] = n + 1; + return 0; } } diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index 772c115d..a294e284 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -174,7 +174,7 @@ public void DependencyOrder_UpdateAndFullPush() Assert.IsTrue(onlyNodes.Any(t => t.Item2 == PushType.UpdateOnly), "Missing UpdateOnly in the list of pushed nodes."); Assert.IsTrue(onlyNodes.Any(t => t.Item2 == PushType.FullPush), "Missing FullPush in the list of pushed nodes."); - Assert.IsTrue(orderedObjects.Where(t => t.Item1 == typeof(Node)).First().Item2 == PushType.UpdateOnly, + Assert.IsTrue(orderedObjects.Where(t => t.Item1 == typeof(Node)).First().Item2 == PushType.UpdateOnly, "For Node objects, UpdateOnly should have come before FullPush."); } @@ -338,5 +338,34 @@ public void UpdateOnlyChanged() Assert.AreEqual(changeCount, materialUpdateCount, "Wrong number of Materials Updated."); } + + [Test] + public void CountCRUDCallsPerType() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + + Assert.IsTrue(sa.CallsToCreatePerType.All(kv => kv.Value == 1), "Calls to Create should be done once per each type."); + Assert.IsTrue(sa.CallsToReadPerType.All(kv => kv.Value == 1), "Calls to Read should be done once per each type."); + } + + [Test] + public void CountCRUDCallsPerType_UpdateOnly() + { + List inputObjects = new List(); + inputObjects.AddRange(Create.RandomObjects(10)); + inputObjects.AddRange(Create.RandomObjects(10)); + + sa.Push(inputObjects); + sa.Push(inputObjects, "", PushType.UpdateOnly); + + Assert.IsTrue(sa.CallsToCreatePerType.All(kv => kv.Value == 1), "Calls to Create should be done once per each type."); + Assert.IsTrue(sa.CallsToReadPerType.Where(kv => kv.Key == typeof(Bar)).First().Value == 1, "The Bar should be read only once."); + Assert.IsTrue(sa.CallsToReadPerType.Where(kv => kv.Key != typeof(Bar)).All(kv => kv.Value == 2)); + Assert.IsTrue(sa.CallsToUpdatePerType.All(kv => kv.Value == 1), "Calls to Update should be done once per each type."); + } } } \ No newline at end of file From d71608fce65dae289d0fb7fe7f24419418be2554 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 18 Jan 2023 15:43:20 +0100 Subject: [PATCH 076/116] Consolidate GetCachedOrRead to single method --- .../Objects/StructuralAdapter.cs | 2 +- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 2 +- BHoM_Adapter/CRUD/Cache.cs | 22 +++++++++---------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 31ae6489..8ce91614 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -134,7 +134,7 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo foreach (Type t in dependencyTypes) { MethodInfo generic = readCached.MakeGenericMethod(t); - generic.Invoke(this, new object[] { null, null }); + generic.Invoke(this, new object[] { null, null, actionConfig }); } if (!CallsToReadPerType.TryGetValue(type, out int n)) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 25b2f6a3..ab7d0769 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -60,7 +60,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus if (tag != "" || Engine.Adapter.Query.GetComparerForType(this, actionConfig) != EqualityComparer.Default) { if (m_AdapterSettings.CacheCRUDobjects) - readObjects = GetCachedOrRead("", actionConfig)?.Where(x => x != null); + readObjects = GetCachedOrRead(null, "", actionConfig)?.Where(x => x != null); else readObjects = Read(typeof(T), "", actionConfig)?.Where(x => x != null && x is T).Cast(); } diff --git a/BHoM_Adapter/CRUD/Cache.cs b/BHoM_Adapter/CRUD/Cache.cs index 22788d9f..881e403e 100644 --- a/BHoM_Adapter/CRUD/Cache.cs +++ b/BHoM_Adapter/CRUD/Cache.cs @@ -31,6 +31,7 @@ using System.Xml.Linq; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.ComponentModel; namespace BH.Adapter { @@ -76,30 +77,26 @@ protected bool CreateAndCache(IEnumerable objects, ActionConfig actionConf /***************************************************/ - protected virtual IEnumerable GetCachedOrRead(string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject + [Description("Method for getting out a list of objects from the cache or the read from the model.")] + protected List GetCachedOrRead(IList ids = null, string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject { - // Call the Basic Method Read() to get the objects based on the ids - IEnumerable objects = GetCachedOrRead(new List(), actionConfig); + // Call the method extracting from cache or reading from model as dictionary. + //Setting key type to object to allow for any type of key + List objects = GetCachedOrReadAsDictionary(ids, actionConfig).Values.ToList(); // Null guard objects = objects ?? new List(); // Filter by tag if any - if (tag == "") + if (string.IsNullOrWhiteSpace(tag)) return objects; else - return objects.Where(x => x.Tags.Contains(tag)); - } - - /***************************************************/ - - protected List GetCachedOrRead(IList ids, ActionConfig actionConfig = null) - { - return GetCachedOrReadAsDictionary(ids, actionConfig).Values.ToList(); + return objects.Where(x => x.Tags.Contains(tag)).ToList(); } /***************************************************/ + [Description("Method for getting out a Dictionary of id and object from the cache or the read from the model.")] protected Dictionary GetCachedOrReadAsDictionary(IList ids = null, ActionConfig actionConfig = null) { @@ -148,6 +145,7 @@ protected Dictionary GetCachedOrReadAsDictionary(IList ids } else { + //Filtered obejct collection to store the objects to be returned either from the model or from the cache Dictionary filteredObjects = new Dictionary(); Dictionary typeCache; if (m_cache.TryGetValue(t, out typeCache)) From f9f65824e22314966510eefcb2aeb761770173b0 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 18 Jan 2023 15:43:42 +0100 Subject: [PATCH 077/116] Add method for getting single item out from Cache or model --- BHoM_Adapter/CRUD/Cache.cs | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/BHoM_Adapter/CRUD/Cache.cs b/BHoM_Adapter/CRUD/Cache.cs index 881e403e..526105e2 100644 --- a/BHoM_Adapter/CRUD/Cache.cs +++ b/BHoM_Adapter/CRUD/Cache.cs @@ -77,6 +77,46 @@ protected bool CreateAndCache(IEnumerable objects, ActionConfig actionConf /***************************************************/ + [Description("Method for getting out a single object from the cache or the read from the model.")] + protected TObj GetCachedOrRead(TId id, ActionConfig actionConfig = null) where TObj : IBHoMObject + { + if (!m_AdapterSettings.UseAdapterId) + { + Engine.Base.Compute.RecordWarning("Unable to get single item from cache for adapters not using AdapterIds."); + return default(TObj); + } + + if (id == null) + return default(TObj); + + Type t = typeof(TObj); + Dictionary typeCache; + if (!m_cache.TryGetValue(t, out typeCache)) + typeCache = new Dictionary(); + + IBHoMObject cacheObj = null; + if (!typeCache.TryGetValue(id, out cacheObj)) + { + IEnumerable read = IRead(t, new List() { id }, actionConfig); + + foreach (IBHoMObject item in read) + { + object itemId = GetAdapterId(item); + if (itemId.Equals(id)) + cacheObj = item; + typeCache[itemId] = item; + } + m_cache[t] = typeCache; + } + + if (cacheObj is TObj) + return (TObj)cacheObj; + else + return default(TObj); + } + + /***************************************************/ + [Description("Method for getting out a list of objects from the cache or the read from the model.")] protected List GetCachedOrRead(IList ids = null, string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject { From 4b8d1849c7a9539ecebbc1c3ee6335bf013a3bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Fri, 20 Jan 2023 09:03:02 +0100 Subject: [PATCH 078/116] Apply suggestions from code review Co-authored-by: Alessio Lombardi --- .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 4 ++-- BHoM_Adapter/CRUD/Cache.cs | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 8ce91614..126a64ca 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -124,12 +124,12 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo List modelObjects = Created.Where(x => x.Item1.IsAssignableFrom(type)).SelectMany(x => x.Item2).ToList(); - MethodInfo method = typeof(Engine.Adapter.Query).GetMethod("GetDependencyTypes"); + MethodInfo method = typeof(Engine.Adapter.Query).GetMethod(nameof(Engine.Adapter.Query.GetDependencyTypes)); method = method.MakeGenericMethod(type); List dependencyTypes = method.Invoke(null, new object[] { this }) as List; - MethodInfo readCached = typeof(BHoMAdapter).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == "GetCachedOrRead"); + MethodInfo readCached = typeof(BHoMAdapter).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == nameof(GetCachedOrRead)); foreach (Type t in dependencyTypes) { diff --git a/BHoM_Adapter/CRUD/Cache.cs b/BHoM_Adapter/CRUD/Cache.cs index 526105e2..e5e87977 100644 --- a/BHoM_Adapter/CRUD/Cache.cs +++ b/BHoM_Adapter/CRUD/Cache.cs @@ -191,14 +191,12 @@ protected Dictionary GetCachedOrReadAsDictionary(IList ids if (m_cache.TryGetValue(t, out typeCache)) { List idsNotInCache = new List(); - List cachedObjects = new List(); //Loop through the ids and try to fetch from cache. foreach (object id in ids) { if (typeCache.TryGetValue(id, out IBHoMObject obj)) { - cachedObjects.Add(obj); filteredObjects[id] = obj; } else From 7a389261f857150de7403b474da638c3bdc19ea7 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 20 Jan 2023 11:44:38 +0100 Subject: [PATCH 079/116] Fix for test calling the correct cache method --- .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 126a64ca..0528c6b7 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -129,7 +129,7 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo List dependencyTypes = method.Invoke(null, new object[] { this }) as List; - MethodInfo readCached = typeof(BHoMAdapter).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(x => x.Name == nameof(GetCachedOrRead)); + MethodInfo readCached = typeof(BHoMAdapter).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.GetGenericArguments().Length == 1).FirstOrDefault(x => x.Name == nameof(GetCachedOrRead)); foreach (Type t in dependencyTypes) { From 558475d7c578d080f0e8667499bf1ff256ce3a9c Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 20 Jan 2023 11:45:54 +0100 Subject: [PATCH 080/116] Change default value for UpdateOnlyChangedObjects to true Discussing with @alelom that this should be the default for most if not all cases, with opt out being the exception case where Toolkits have to set this parameter --- Adapter_oM/Settings-Config/AdapterSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter_oM/Settings-Config/AdapterSettings.cs b/Adapter_oM/Settings-Config/AdapterSettings.cs index 2dbebf4b..36c98e3e 100644 --- a/Adapter_oM/Settings-Config/AdapterSettings.cs +++ b/Adapter_oM/Settings-Config/AdapterSettings.cs @@ -63,7 +63,7 @@ public class AdapterSettings : IObject public virtual bool ProcessInMemory { get; set; } = false; [Description("If true, Objects found to be the same according to the AdapterComparer for the provided type are checked for full equality using the HashComparer of the type (which by default checks every property except BHoM_Guid). If equal according to the HashComparer, they are not updated.\n" + "Otherwise, Objects found identical according to the AdapterComparer for the provided type are sent to the Update method.")] - public virtual bool OnlyUpdateChangedObjects { get; set; } = false; + public virtual bool OnlyUpdateChangedObjects { get; set; } = true; [Description("If true, CRUD operations will attempt read/write cache objects to speed things during a same Action.")] public virtual bool CacheCRUDobjects { get; set; } = true; From 07accb9fd4ec6f3d57070542656041ff141f458d Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Feb 2023 10:49:27 +0100 Subject: [PATCH 081/116] Adding non-generic method for GetDependencyTypes --- Adapter_Engine/Query/GetDependencyTypes.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Adapter_Engine/Query/GetDependencyTypes.cs b/Adapter_Engine/Query/GetDependencyTypes.cs index 5d5bd331..2f53a741 100644 --- a/Adapter_Engine/Query/GetDependencyTypes.cs +++ b/Adapter_Engine/Query/GetDependencyTypes.cs @@ -41,7 +41,12 @@ public static partial class Query [Description("Returns the dependency types for a certain object type.")] public static List GetDependencyTypes(this IBHoMAdapter bhomAdapter) { - Type type = typeof(T); + return GetDependencyTypes(bhomAdapter, typeof(T)); + } + + [Description("Returns the dependency types for a certain object type.")] + public static List GetDependencyTypes(this IBHoMAdapter bhomAdapter, Type type) + { List dependencyTypes = new List(); if (bhomAdapter.DependencyTypes.ContainsKey(type)) From 773a34e82cb690b3d8b3484651ff5be3f409a8ff Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Feb 2023 10:50:03 +0100 Subject: [PATCH 082/116] Update structural adapter tin test to call the non-generic method for GetDependencyTypes --- .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 0528c6b7..57aa329e 100644 --- a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -43,6 +43,7 @@ using System.Text; using System.Threading.Tasks; using System.Reflection; +using BH.Engine.Adapter; namespace BH.Tests.Adapter { @@ -124,10 +125,7 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo List modelObjects = Created.Where(x => x.Item1.IsAssignableFrom(type)).SelectMany(x => x.Item2).ToList(); - MethodInfo method = typeof(Engine.Adapter.Query).GetMethod(nameof(Engine.Adapter.Query.GetDependencyTypes)); - method = method.MakeGenericMethod(type); - - List dependencyTypes = method.Invoke(null, new object[] { this }) as List; + List dependencyTypes = this.GetDependencyTypes(type); MethodInfo readCached = typeof(BHoMAdapter).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.GetGenericArguments().Length == 1).FirstOrDefault(x => x.Name == nameof(GetCachedOrRead)); From 0d95dae542712297a24e991c9bf7216a719bbbec Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Feb 2023 10:52:45 +0100 Subject: [PATCH 083/116] Update sorting based on dependency types Changing method to compute a dependency depth and use that for sorting the order of the objects --- .../Query/GetDependencySortedObjects.cs | 103 +++++++----------- 1 file changed, 40 insertions(+), 63 deletions(-) diff --git a/Adapter_Engine/Query/GetDependencySortedObjects.cs b/Adapter_Engine/Query/GetDependencySortedObjects.cs index e04d42be..188a11fc 100644 --- a/Adapter_Engine/Query/GetDependencySortedObjects.cs +++ b/Adapter_Engine/Query/GetDependencySortedObjects.cs @@ -30,6 +30,7 @@ using BH.oM.Adapter; using BH.oM.Base.Attributes; using BH.Engine.Reflection; +using System.Reflection; namespace BH.Engine.Adapter { @@ -56,68 +57,14 @@ public static List>> GetDependencySort Dictionary, List> allObjectsPerType = GetObjectsAndRecursiveDependencies(objects, pushType, bHoMAdapter); // Sort the groups by dependency order, so they can be pushed in the correct order. - List>> orderedObjects = new List>>(); - - List> handledGroups = new List>(); - foreach (var typeGroup in allObjectsPerType) - { - if (handledGroups.Contains(typeGroup.Key)) - continue; - - // We can scan the rest of the input objects to see if they include dependencies of this current object type. - List dependenciesToLookFor = new List(); - - // Add direct dependencies of this current object type. - if (bHoMAdapter.DependencyTypes.TryGetValue(typeGroup.Key.Item1, out List typeDeps)) - dependenciesToLookFor.AddRange(typeDeps); - - // Check if the current object type has basetypes (interfaces) for which dependencies may have been specified. - // E.g. for a CrossSection object we can get ISectionProperty which it implements, - // which in turn is a type that commonly specifies additional dependencies (generally, IMaterialFragment). - foreach (var baseType in typeGroup.Key.Item1.BaseTypes()) - { - if (bHoMAdapter.DependencyTypes.TryGetValue(baseType, out List baseTypeDeps)) - dependenciesToLookFor.AddRange(baseTypeDeps); - } - - // If this current object type does not have dependencies, add it at the start of the list and continue. - if (!dependenciesToLookFor.Any()) - { - orderedObjects.Insert(0, new Tuple>(typeGroup.Key.Item1, typeGroup.Key.Item2, typeGroup.Value.OfType())); - handledGroups.Add(typeGroup.Key); - continue; - } - - // Scan the rest of the input objects to see they include dependencies, - // and add them to the orderedObjects list in order to prioritize them. - foreach (var otherTypeGroup in allObjectsPerType) - { - if (handledGroups.Contains(otherTypeGroup.Key) || otherTypeGroup.Key == typeGroup.Key) - continue; - - if (dependenciesToLookFor.Contains(otherTypeGroup.Key.Item1) || dependenciesToLookFor.Any(d => d.IsAssignableFromIncludeGenericsAndRefTypes(otherTypeGroup.Key.Item1))) - { - orderedObjects.Add(new Tuple>(otherTypeGroup.Key.Item1, otherTypeGroup.Key.Item2, otherTypeGroup.Value.OfType())); - handledGroups.Add(otherTypeGroup.Key); - } - } - } - - // The non-handled groups can be added at the end in any order, because they don't have any dependency ordering. - foreach (var typeGroup in allObjectsPerType) - { - if (handledGroups.Contains(typeGroup.Key)) - continue; - - orderedObjects.Add(new Tuple>(typeGroup.Key.Item1, typeGroup.Key.Item2, typeGroup.Value.OfType())); - } + List>> baseTypeGroupObjects = allObjectsPerType.Select(x => new Tuple> (x.Key.Item1, x.Key.Item2, x.Value )).ToList(); // Group per base type extracted from dependencies. // This is useful to reduce the number of CRUD calls. var allTypesInDependencies = bHoMAdapter.DependencyTypes.Values.SelectMany(v => v).Distinct(); - for (int i = 0; i < orderedObjects.Count; i++) + for (int i = 0; i < baseTypeGroupObjects.Count; i++) { - var kv = orderedObjects.ElementAt(i); + var kv = baseTypeGroupObjects.ElementAt(i); foreach (Type baseType in kv.Item1.BaseTypes()) { @@ -128,32 +75,32 @@ public static List>> GetDependencySort continue; //Find matching item in the ordered obejct, matching the base type and push type. - var matchingItem = orderedObjects.FirstOrDefault(o => o.Item1 == baseType && o.Item2 == kv.Item2); + var matchingItem = baseTypeGroupObjects.FirstOrDefault(o => o.Item1 == baseType && o.Item2 == kv.Item2); int matchingIndex; //Get index of matching object if match is not null. if (matchingItem != null) - matchingIndex = orderedObjects.IndexOf(matchingItem); + matchingIndex = baseTypeGroupObjects.IndexOf(matchingItem); else matchingIndex = -1; if (matchingIndex == -1) { //Nothing found. Replace the current item with base type instead of concrete type. - orderedObjects[i] = new Tuple>(baseType, kv.Item2, kv.Item3); + baseTypeGroupObjects[i] = new Tuple>(baseType, kv.Item2, kv.Item3); } else { //If matching base type is found, concatenate the to sets together, to be CRUD together. //For example, if the pushtype for both is the same, SteelSections and AluminiumSections will be grouped under ISectionProperty if ISectionProperty is in DependencyTypes. - var toAdd = new Tuple>(baseType, orderedObjects[matchingIndex].Item2, orderedObjects[matchingIndex].Item3.Concat(kv.Item3)); + var toAdd = new Tuple>(baseType, baseTypeGroupObjects[matchingIndex].Item2, baseTypeGroupObjects[matchingIndex].Item3.Concat(kv.Item3)); int minIndex = Math.Min(i, matchingIndex); int maxIndex = Math.Max(i, matchingIndex); //Replace on minimum of the two indecies found and remove the other. - orderedObjects[minIndex] = toAdd; - orderedObjects.RemoveAt(maxIndex); + baseTypeGroupObjects[minIndex] = toAdd; + baseTypeGroupObjects.RemoveAt(maxIndex); i--; //Decrement i as item has been removed from the list. } found = true; @@ -166,6 +113,17 @@ public static List>> GetDependencySort } } + //Dictionary to store the dependency depth of each type + //The dependency depth indicates how many objects being pushed that depend on them + //This means that the types with the highest depth count should be pushed first + Dictionary dependecyDepth = new Dictionary(); + + //Method runs through all types, and recursively calls the dependecy types, and increments the depth of each type for every time it is found + EvaluateDependencyDepths(bHoMAdapter, baseTypeGroupObjects.Select(x => x.Item1).Distinct(), dependecyDepth); + + //Sorts the types by highest to lowest depth count + List>> orderedObjects = baseTypeGroupObjects.OrderByDescending(x => dependecyDepth[x.Item1]).ToList(); + // If two types are subject to two different CRUD operations (e.g. UpdateOnly and FullCRUD), // make sure the order of CRUD operations is appropriate (e.g. UpdateOnly must happen before FullCRUD to avoid duplicates). // For example, this happens when both Nodes and Bars are sent via UpdateOnly during a same Push operation, @@ -188,6 +146,25 @@ public static List>> GetDependencySort return orderedObjects; } + + /***************************************************/ + + [Description("Looping through all types and their dependencies and incrementally increases the depth counter for every time a type is found.")] + private static void EvaluateDependencyDepths(this IBHoMAdapter bHoMAdapter, IEnumerable types, Dictionary depths) + { + foreach (Type type in types) + { + if (!depths.ContainsKey(type)) + depths[type] = 0; //First appearance of the type, either as a standalone object or as a dependecy + else + depths[type]++; //Increment depth counter for every time the dependecy is found, either as the standalone type, or as a dependency object + + //Recursive call to make sure all dependecies are incremented + EvaluateDependencyDepths(bHoMAdapter, bHoMAdapter.GetDependencyTypes(type), depths); + } + } + + /***************************************************/ } } From 0032e6764a25b494ae80fac300620204c92bb02c Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Feb 2023 10:55:41 +0100 Subject: [PATCH 084/116] Update Create order for failing tests Validated with @alelom that the changes to the create order is only between types that the order is fine to be switched. For example, IMaterialProperty vs Constraint6DOF, and that all dependencies are still pushed before any potential host object. Essentially, there are a couple of orders that all are fine. The previous order was fine, but so is this new one. Hence updating the correct order to new order. --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 46 ++++++++++++++++-------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index a294e284..a38d49fb 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -68,14 +68,18 @@ public void DependencyOrder_BarLoads() sa.Push(inputObjects); - string correctOrder = "BH.oM.Structure.Constraints.Constraint6DOF, BH.oM.Structure.MaterialFragments.IMaterialFragment, " + - "BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Node, " + - "BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset, " + - "BH.oM.Structure.Elements.Bar, BH.oM.Structure.Loads.Loadcase, " + - "BH.oM.Structure.Loads.BarUniformlyDistributedLoad"; + string correctOrder = "BH.oM.Structure.MaterialFragments.IMaterialFragment, " + + "BH.oM.Structure.Constraints.Constraint6DOF, " + + "BH.oM.Structure.SectionProperties.ISectionProperty, " + + "BH.oM.Structure.Elements.Node, " + + "BH.oM.Structure.Constraints.BarRelease, " + + "BH.oM.Structure.Offsets.Offset, " + + "BH.oM.Structure.Elements.Bar, " + + "BH.oM.Structure.Loads.Loadcase, " + + "BH.oM.Structure.Loads.BarUniformlyDistributedLoad"; string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); - Assert.IsTrue(createdOrder == correctOrder); + Assert.AreEqual(correctOrder, createdOrder); } @@ -95,12 +99,21 @@ public void DependencyOrder_MostStructuralObjects() sa.Push(inputObjects); - string correctOrder = "BH.oM.Structure.Constraints.Constraint4DOF, BH.oM.Structure.MaterialFragments.IMaterialFragment, " + - "BH.oM.Structure.Constraints.Constraint6DOF, BH.oM.Structure.SectionProperties.ISectionProperty, " + - "BH.oM.Structure.Elements.Node, BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset, " + - "BH.oM.Structure.Elements.Bar, BH.oM.Structure.Loads.Loadcase, BH.oM.Structure.SurfaceProperties.ISurfaceProperty, " + - "BH.oM.Structure.Elements.Opening, BH.oM.Structure.Elements.Edge, BH.oM.Structure.Loads.BarUniformlyDistributedLoad, " + - "BH.oM.Structure.Elements.FEMesh, BH.oM.Structure.Elements.Panel"; + string correctOrder = "BH.oM.Structure.Constraints.Constraint6DOF, " + + "BH.oM.Structure.MaterialFragments.IMaterialFragment, " + + "BH.oM.Structure.Constraints.Constraint4DOF, " + + "BH.oM.Structure.Elements.Node, " + + "BH.oM.Structure.Elements.Edge, " + + "BH.oM.Structure.SectionProperties.ISectionProperty, " + + "BH.oM.Structure.Constraints.BarRelease, " + + "BH.oM.Structure.Offsets.Offset, " + + "BH.oM.Structure.SurfaceProperties.ISurfaceProperty, " + + "BH.oM.Structure.Elements.Bar, " + + "BH.oM.Structure.Loads.Loadcase, " + + "BH.oM.Structure.Elements.Opening, " + + "BH.oM.Structure.Loads.BarUniformlyDistributedLoad, " + + "BH.oM.Structure.Elements.FEMesh, " + + "BH.oM.Structure.Elements.Panel"; string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); Assert.AreEqual(correctOrder, createdOrder); @@ -117,9 +130,12 @@ public void Dependecies_UpdateOnly() sa.Push(inputObjects, "", BH.oM.Adapter.PushType.UpdateOnly); - string correctOrderCreated = "BH.oM.Structure.MaterialFragments.IMaterialFragment, BH.oM.Structure.Constraints.Constraint6DOF, " + - "BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Node, " + - "BH.oM.Structure.Constraints.BarRelease, BH.oM.Structure.Offsets.Offset"; + string correctOrderCreated = "BH.oM.Structure.Constraints.Constraint6DOF, " + + "BH.oM.Structure.MaterialFragments.IMaterialFragment, " + + "BH.oM.Structure.SectionProperties.ISectionProperty, " + + "BH.oM.Structure.Elements.Node, " + + "BH.oM.Structure.Constraints.BarRelease, " + + "BH.oM.Structure.Offsets.Offset"; string correctOrderUpdated = "BH.oM.Structure.Elements.Node, BH.oM.Structure.SectionProperties.ISectionProperty, BH.oM.Structure.Elements.Bar"; string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); From bce49f9d46dbbf927d542296103d7dc2e1d396f5 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Feb 2023 10:56:41 +0100 Subject: [PATCH 085/116] Adding new test pushing only loads Adding test for the case highlighted in the issue that was the one used to find the problem being fixed in the PR --- .ci/code/BHoM_Adapter_Tests/PushTests.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/code/BHoM_Adapter_Tests/PushTests.cs index a38d49fb..e0479f2b 100644 --- a/.ci/code/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/code/BHoM_Adapter_Tests/PushTests.cs @@ -194,6 +194,27 @@ public void DependencyOrder_UpdateAndFullPush() "For Node objects, UpdateOnly should have come before FullPush."); } + [Test] + public void DependencyOrder_CreateLoadNoObjectsWithIds() + { + List loads = Create.RandomObjects(3); + + sa.Push(loads); + + string correctOrder = "BH.oM.Structure.MaterialFragments.IMaterialFragment, " + + "BH.oM.Structure.Constraints.Constraint6DOF, " + + "BH.oM.Structure.SectionProperties.ISectionProperty, " + + "BH.oM.Structure.Elements.Node, " + + "BH.oM.Structure.Constraints.BarRelease, " + + "BH.oM.Structure.Offsets.Offset, " + + "BH.oM.Structure.Elements.Bar, " + + "BH.oM.Structure.Loads.Loadcase, " + + "BH.oM.Structure.Loads.BarUniformlyDistributedLoad"; + string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); + + Assert.AreEqual(correctOrder, createdOrder); + } + [Test] public void DependencyOrder_CreateLoadAllObjectsWithIds() { From 99d570828abf54a74a353c6c1f96f0140a1842b9 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Thu, 9 Feb 2023 16:18:46 +0000 Subject: [PATCH 086/116] Adding recorderror message --- BHoM_Adapter/AdapterActions/Execute.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/Execute.cs b/BHoM_Adapter/AdapterActions/Execute.cs index d6a072fc..6197cf2b 100644 --- a/BHoM_Adapter/AdapterActions/Execute.cs +++ b/BHoM_Adapter/AdapterActions/Execute.cs @@ -58,11 +58,9 @@ public virtual bool SetupExecuteConfig(ActionConfig actionConfig, out ActionConf "Item2 = A boolean indicating if the Execute was successful.")] public virtual Output, bool> Execute(IExecuteCommand command, ActionConfig actionConfig = null) { + BH.Engine.Base.Compute.RecordError($"Execute is not implemented in {this.GetType().Name}."); + return new Output, bool> { Item1 = null, Item2 = false}; } } -} - - - - +} \ No newline at end of file From f32bf1f6f04a44ef43ea9820d4be6cbc7228058e Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 14 Feb 2023 12:50:52 +0000 Subject: [PATCH 087/116] Moved and renamed Test solution --- .ci/{code/Verification.sln => unit-tests/BHoM_Adapter_Tests.sln} | 0 .../BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj | 0 .../BHoM_Adapter_Tests/Create/RandomObject.cs | 0 .../BHoM_Adapter_Tests/Create/RandomObjects.cs | 0 .../BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 0 .../BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs | 0 .../BHoM_Adapter_Tests/Objects/TestFragment.cs | 0 .ci/{code => unit-tests}/BHoM_Adapter_Tests/PushTests.cs | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename .ci/{code/Verification.sln => unit-tests/BHoM_Adapter_Tests.sln} (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/Create/RandomObject.cs (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/Create/RandomObjects.cs (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/Objects/TestFragment.cs (100%) rename .ci/{code => unit-tests}/BHoM_Adapter_Tests/PushTests.cs (100%) diff --git a/.ci/code/Verification.sln b/.ci/unit-tests/BHoM_Adapter_Tests.sln similarity index 100% rename from .ci/code/Verification.sln rename to .ci/unit-tests/BHoM_Adapter_Tests.sln diff --git a/.ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj rename to .ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj diff --git a/.ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Create/RandomObject.cs similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/Create/RandomObject.cs rename to .ci/unit-tests/BHoM_Adapter_Tests/Create/RandomObject.cs diff --git a/.ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Create/RandomObjects.cs similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/Create/RandomObjects.cs rename to .ci/unit-tests/BHoM_Adapter_Tests/Create/RandomObjects.cs diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs rename to .ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs rename to .ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapterId.cs diff --git a/.ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/TestFragment.cs similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/Objects/TestFragment.cs rename to .ci/unit-tests/BHoM_Adapter_Tests/Objects/TestFragment.cs diff --git a/.ci/code/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs similarity index 100% rename from .ci/code/BHoM_Adapter_Tests/PushTests.cs rename to .ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs From c2d1d7e9188a90298560257a2d40491a3c838199 Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 14 Feb 2023 13:30:10 +0000 Subject: [PATCH 088/116] New Test build configuration, adjusted build events --- .ci/unit-tests/BHoM_Adapter_Tests.sln | 11 +++++++++++ .../BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj | 6 ++++++ Adapter_Engine/Adapter_Engine.csproj | 7 ++++++- Adapter_oM/Adapter_oM.csproj | 7 ++++++- BHoM_Adapter/BHoM_Adapter.csproj | 7 ++++++- .../Structure_AdapterModules.csproj | 8 +++++++- 6 files changed, 42 insertions(+), 4 deletions(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests.sln b/.ci/unit-tests/BHoM_Adapter_Tests.sln index 99f1e580..23c80008 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests.sln +++ b/.ci/unit-tests/BHoM_Adapter_Tests.sln @@ -17,28 +17,39 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU + Test|Any CPU = Test|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2693899C-1398-4486-BED2-02809FB43BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2693899C-1398-4486-BED2-02809FB43BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU {2693899C-1398-4486-BED2-02809FB43BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU {2693899C-1398-4486-BED2-02809FB43BE9}.Release|Any CPU.Build.0 = Release|Any CPU + {2693899C-1398-4486-BED2-02809FB43BE9}.Test|Any CPU.ActiveCfg = Test|Any CPU + {2693899C-1398-4486-BED2-02809FB43BE9}.Test|Any CPU.Build.0 = Test|Any CPU {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Debug|Any CPU.Build.0 = Debug|Any CPU {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Release|Any CPU.ActiveCfg = Release|Any CPU {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Release|Any CPU.Build.0 = Release|Any CPU + {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Test|Any CPU.ActiveCfg = Test|Any CPU + {C62FB82E-FDAB-4FF4-98B6-5EBD695B579F}.Test|Any CPU.Build.0 = Test|Any CPU {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Release|Any CPU.Build.0 = Release|Any CPU + {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Test|Any CPU.ActiveCfg = Test|Any CPU + {CE56A0D0-EB5B-4A49-B20F-0432E1832937}.Test|Any CPU.Build.0 = Test|Any CPU {C389BC62-717D-4639-BACD-864CF97336BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C389BC62-717D-4639-BACD-864CF97336BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {C389BC62-717D-4639-BACD-864CF97336BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {C389BC62-717D-4639-BACD-864CF97336BB}.Release|Any CPU.Build.0 = Release|Any CPU + {C389BC62-717D-4639-BACD-864CF97336BB}.Test|Any CPU.ActiveCfg = Test|Any CPU + {C389BC62-717D-4639-BACD-864CF97336BB}.Test|Any CPU.Build.0 = Test|Any CPU {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Release|Any CPU.ActiveCfg = Release|Any CPU {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Release|Any CPU.Build.0 = Release|Any CPU + {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Test|Any CPU.ActiveCfg = Test|Any CPU + {3E8F16BF-4EB2-47C8-B5D6-9A370A55B902}.Test|Any CPU.Build.0 = Test|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj index 13b70f07..936333eb 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj +++ b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -6,6 +6,8 @@ enable false + + Debug;Release;Test @@ -56,4 +58,8 @@ + + + + diff --git a/Adapter_Engine/Adapter_Engine.csproj b/Adapter_Engine/Adapter_Engine.csproj index 437bea6f..fa6265ee 100644 --- a/Adapter_Engine/Adapter_Engine.csproj +++ b/Adapter_Engine/Adapter_Engine.csproj @@ -9,14 +9,19 @@ Copyright © https://github.com/BHoM BH.Engine.Adapter 6.1.0.0 + Debug;Release;Test ..\Build\ + + ..\Build\ + + - + diff --git a/Adapter_oM/Adapter_oM.csproj b/Adapter_oM/Adapter_oM.csproj index 9c0029e7..6727b517 100644 --- a/Adapter_oM/Adapter_oM.csproj +++ b/Adapter_oM/Adapter_oM.csproj @@ -9,14 +9,19 @@ Copyright © https://github.com/BHoM BH.oM.Adapter 6.1.0.0 + Debug;Release;Test ..\Build\ + + ..\Build\ + + - + diff --git a/BHoM_Adapter/BHoM_Adapter.csproj b/BHoM_Adapter/BHoM_Adapter.csproj index 5b978561..2d607c67 100644 --- a/BHoM_Adapter/BHoM_Adapter.csproj +++ b/BHoM_Adapter/BHoM_Adapter.csproj @@ -9,14 +9,19 @@ Copyright © https://github.com/BHoM BH.Adapter 6.1.0.0 + Debug;Release;Test ..\Build\ + + ..\Build\ + + - + diff --git a/Structure_AdapterModules/Structure_AdapterModules.csproj b/Structure_AdapterModules/Structure_AdapterModules.csproj index b9f16af8..bd1d7473 100644 --- a/Structure_AdapterModules/Structure_AdapterModules.csproj +++ b/Structure_AdapterModules/Structure_AdapterModules.csproj @@ -9,6 +9,7 @@ Copyright © https://github.com/BHoM BH.Adapter.Modules.Structure 6.1.0.0 + Debug;Release;Test @@ -16,8 +17,13 @@ ..\Build\ + + Off + ..\Build\ + + - + From 57a9ba469816d0b962264b0d0e05c46bd0e4239a Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Fri, 10 Feb 2023 14:47:39 +0000 Subject: [PATCH 089/116] Adding method to unpack objects provided in Push --- .../BHoM_Adapter_Tests.csproj | 2 ++ .../Objects/TestContainer.cs | 36 +++++++++++++++++++ .../BHoM_Adapter_Tests/PushTests.cs | 22 ++++++++++++ .../_PushMethods/ProcessObjectsForPush.cs | 19 ++++++++-- 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 .ci/unit-tests/BHoM_Adapter_Tests/Objects/TestContainer.cs diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj index 936333eb..b85de4a8 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj +++ b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -11,11 +11,13 @@ + + diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/TestContainer.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/TestContainer.cs new file mode 100644 index 00000000..572114ea --- /dev/null +++ b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/TestContainer.cs @@ -0,0 +1,36 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + + +using BH.oM.Base; + +namespace BH.Tests.Adapter +{ + // Must be unpackable + public class TestContainer : BHoMObject, IContainer + { + public T? SomeObject { get; set; } + public IEnumerable ListOfObjects { get; set; } = new List(); + public IEnumerable> ListOfLists { get; set; } = new List>(); + } +} + diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index e0479f2b..cb2ef36b 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -31,6 +31,8 @@ using BH.oM.Structure.SurfaceProperties; using BH.oM.Adapter; using System.Diagnostics.Contracts; +using AutoBogus; +using Shouldly; namespace BH.Tests.Adapter.Structure { @@ -43,6 +45,26 @@ public void Setup() sa = new StructuralAdapter(); } + private static IEnumerable GetTestContainers() + { + // BH.Engine.Base.Create.RandomObject() can't deal with generics. Using AutoFaker instead. Example: + // AutoFaker creates 1 objects of the requested type per each IEnumerable property. + // E.g. Container will have 1 + 1 + 1 = 3 Bars. + yield return new TestCaseData(new AutoFaker>().Generate(), 5, 50); + } + + + [Test] + [TestCaseSource(nameof(GetTestContainers))] + public void UnpackObjsDuringPush(TestContainer container, int numberOfTypes, int minTotalObjects) + { + sa.Push(new List() { container }); + + IEnumerable? sectionProperties = sa.Created.Where(c => c.Item1 == typeof(ISectionProperty)).FirstOrDefault()?.Item2 ?? new List(); + sa.Created.Count.ShouldBe(numberOfTypes); + sa.Created.SelectMany(kv => kv.Item2).Count().ShouldBeGreaterThan(minTotalObjects); + } + [Test] public void GroupByParentInterface() { diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs index 8ea0d698..0e21d37a 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs @@ -28,6 +28,7 @@ using System.ComponentModel; using System.Linq; using BH.oM.Adapter; +using IContainer = BH.oM.Base.IContainer; namespace BH.Adapter { @@ -66,13 +67,27 @@ protected virtual IEnumerable ProcessObjectsForPush(IEnumerable unpackedObjs = new List(); + + foreach (var obj in objects) + { + if (obj is IContainer container) + { + unpackedObjs.AddRange(container.Unpack()); + } + else + unpackedObjs.Add(obj); + } + IEnumerable objectsToPush = new List(); // Wrap non-BHoM objects into a Custom BHoMObject to make them compatible with the CRUD. if (wrapNonBHoMObjects) - objectsToPush = WrapNonBHoMObjects(objects); + objectsToPush = WrapNonBHoMObjects(unpackedObjs); else - objectsToPush = objects.OfType(); + objectsToPush = unpackedObjs.OfType(); + // Clone the objects for immutability in the UI. CloneBeforePush should always be true, except for very specific cases. if (m_AdapterSettings.CloneBeforePush) From 868afb3efdb28b5383c032750dda88af2c978a0c Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Tue, 21 Feb 2023 09:24:14 +0000 Subject: [PATCH 090/116] Added build events in test project --- .ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj index b85de4a8..d7ed3d90 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj +++ b/.ci/unit-tests/BHoM_Adapter_Tests/BHoM_Adapter_Tests.csproj @@ -61,7 +61,7 @@ - + From 3c1960982c5967c872f0e974d08aae9fb6bea7d5 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 13:23:28 +0100 Subject: [PATCH 091/116] #347 Add push preproccing module for additional preproccing to be done to objects --- Adapter_oM/Module/IPushPreProcessModule.cs | 36 +++++++++++++++++++ .../_PushMethods/ProcessObjectsForPush.cs | 7 ++++ 2 files changed, 43 insertions(+) create mode 100644 Adapter_oM/Module/IPushPreProcessModule.cs diff --git a/Adapter_oM/Module/IPushPreProcessModule.cs b/Adapter_oM/Module/IPushPreProcessModule.cs new file mode 100644 index 00000000..60f579df --- /dev/null +++ b/Adapter_oM/Module/IPushPreProcessModule.cs @@ -0,0 +1,36 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace BH.oM.Adapter.Module +{ + [Description("Module for any additional pre-processing to be done to the objects beofre being pushed. This is called after all other preprocessing, such as cloning is done.")] + public interface IPushPreProcessModule : IAdapterModule + { + [Description("Method called during ProcessObjectsForPush")] + void PreprocessObjects(IEnumerable objects); + } +} diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs index 0e21d37a..f1774887 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs @@ -29,6 +29,7 @@ using System.Linq; using BH.oM.Adapter; using IContainer = BH.oM.Base.IContainer; +using BH.oM.Adapter.Module; namespace BH.Adapter { @@ -93,6 +94,12 @@ protected virtual IEnumerable ProcessObjectsForPush(IEnumerable x.DeepClone()).ToList(); + //Run through any Preprocessing modules on the Adapter + foreach (IPushPreProcessModule preprocessModule in AdapterModules.OfType()) + { + preprocessModule.PreprocessObjects(objectsToPush); + } + return objectsToPush; } } From f077d87faffa6d4dce1f604674273a33cf5671ab Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 13:23:49 +0100 Subject: [PATCH 092/116] #348 add module for pre-processing loads --- Structure_AdapterModules/ModuleLoader.cs | 1 + Structure_AdapterModules/PreProcessLoads.cs | 69 +++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 Structure_AdapterModules/PreProcessLoads.cs diff --git a/Structure_AdapterModules/ModuleLoader.cs b/Structure_AdapterModules/ModuleLoader.cs index 3adb37b3..f0a625f5 100644 --- a/Structure_AdapterModules/ModuleLoader.cs +++ b/Structure_AdapterModules/ModuleLoader.cs @@ -47,6 +47,7 @@ public static void LoadModules(this BHoMAdapter adapter) adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); adapter.AdapterModules.Add(new GetGravityLoadElementsWithoutID(adapter)); + adapter.AdapterModules.Add(new ReplaceObjectsInLoadsModule()); } } } diff --git a/Structure_AdapterModules/PreProcessLoads.cs b/Structure_AdapterModules/PreProcessLoads.cs new file mode 100644 index 00000000..69e9ae96 --- /dev/null +++ b/Structure_AdapterModules/PreProcessLoads.cs @@ -0,0 +1,69 @@ +using BH.oM.Adapter.Module; +using System; +using System.Collections.Generic; +using System.Text; +using BH.oM.Structure.Loads; +using BH.oM.Base; +using System.Linq; +using System.Runtime.CompilerServices; +using System.ComponentModel; + +namespace BH.Adapter.Modules.Structure +{ + [Description("Module for replacing the objects in the loads with objects with the same BHoM_Guid being pushed at the same time.\n" + + "No action is taken if loads are pushed in isolation, without the elements pushed at the same time as individual instances.")] + public class ReplaceObjectsInLoadsModule : IPushPreProcessModule + { + public void PreprocessObjects(IEnumerable objects) + { + return; + IEnumerable bhObjs = objects.OfType(); + + List loads = new List(); + Dictionary nonLoads = new Dictionary(); + + //Split load obejcts from non-load objects + foreach (IBHoMObject obj in bhObjs) + { + if (obj is ILoad load) + loads.Add(load); + else if(!(obj is ICase)) + nonLoads[obj.BHoM_Guid] = obj; + } + + //If no non-load obejcts are being pushed, can simply return, as nothing can be replaced + if (nonLoads.Count == 0) + return; + + foreach (ILoad load in loads) + { + //Load through all loads, and try to update the objects + ReplaceObjects(load as dynamic, nonLoads); + } + } + + + private void ReplaceObjects(IElementLoad load, Dictionary objects) where T : IBHoMObject + { + //Run through all elements stored on the load + for (int i = 0; i < load.Objects.Elements.Count; i++) + { + //Try to find an item with the same guid in the non-load objects + if (objects.TryGetValue(load.Objects.Elements[i].BHoM_Guid, out IBHoMObject replacement)) + { + //Ensure the found object is of the correct type + if (replacement is T tObject) + { + //replace with the other object + load.Objects.Elements[i] = tObject; + } + } + } + } + + private void ReplaceObjects(ILoad load, Dictionary objects) + { + //Do nothing for non-element loads + } + } +} From 1769112885a47cb9ec38002a206fa4bf90088494 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 13:24:09 +0100 Subject: [PATCH 093/116] Initial test added - not passing on this commit --- .../Objects/StructuralAdapter.cs | 23 +++++++++++++++++++ .../BHoM_Adapter_Tests/PushTests.cs | 15 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 57aa329e..18425070 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -44,6 +44,7 @@ using System.Threading.Tasks; using System.Reflection; using BH.Engine.Adapter; +using BH.Engine.Base; namespace BH.Tests.Adapter { @@ -109,8 +110,12 @@ public StructuralAdapter(bool cacheCRUDobjects = true) protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) { + ValidateCreateObjects(objects as dynamic); + Created.Add(new Tuple>(typeof(T), objects.OfType())); + + if (!CallsToCreatePerType.TryGetValue(typeof(T), out int n)) CallsToCreatePerType[typeof(T)] = 1; else @@ -119,6 +124,24 @@ protected override bool ICreate(IEnumerable objects, ActionConfig actionCo return true; } + private void ValidateCreateObjects(IEnumerable objects) + { + + } + + private void ValidateCreateObjects(IEnumerable> objects) where T : IBHoMObject + { + foreach (IElementLoad load in objects) + { + foreach (IBHoMObject bhObj in load.Objects.Elements) + { + StructuralAdapterId id = bhObj.FindFragment(); + if (id == null) + throw new Exception("Elements on loads do not contain required Ids."); + } + } + } + protected override IEnumerable IRead(Type type, IList ids, ActionConfig actionConfig = null) { ReadTypes.Add(new Tuple(type, ids)); diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index cb2ef36b..d32c2582 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -426,5 +426,20 @@ public void CountCRUDCallsPerType_UpdateOnly() Assert.IsTrue(sa.CallsToReadPerType.Where(kv => kv.Key != typeof(Bar)).All(kv => kv.Value == 2)); Assert.IsTrue(sa.CallsToUpdatePerType.All(kv => kv.Value == 1), "Calls to Update should be done once per each type."); } + + [Test] + public void Preprocess_PanelLoads() + { + List inputObjects = new List(); + List panels = Create.RandomObjects(); + AreaUniformlyDistributedLoad load = Create.RandomObject(); + load.Objects.Elements = panels.Cast().ToList(); + inputObjects.AddRange(panels); + inputObjects.Add(load); + + sa.Push(inputObjects); + + + } } } \ No newline at end of file From b5d04e0a91b49afa0c668291e3f2fab7fcd46b0e Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 13:46:26 +0100 Subject: [PATCH 094/116] Remove temporary return in method used to test --- Structure_AdapterModules/PreProcessLoads.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Structure_AdapterModules/PreProcessLoads.cs b/Structure_AdapterModules/PreProcessLoads.cs index 69e9ae96..f1886704 100644 --- a/Structure_AdapterModules/PreProcessLoads.cs +++ b/Structure_AdapterModules/PreProcessLoads.cs @@ -16,7 +16,6 @@ public class ReplaceObjectsInLoadsModule : IPushPreProcessModule { public void PreprocessObjects(IEnumerable objects) { - return; IEnumerable bhObjs = objects.OfType(); List loads = new List(); From 5efbc76c610dfe13dd4b9a2de4a678c76f250ef9 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 13:47:13 +0100 Subject: [PATCH 095/116] Add NextFreeId method for StructuralAdapter to enable ID based functions --- .../Objects/StructuralAdapter.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 18425070..6d662767 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -68,7 +68,7 @@ public StructuralAdapter(bool cacheCRUDobjects = true) { m_AdapterSettings = new AdapterSettings() { - UseAdapterId = false, + UseAdapterId = true, OnlyUpdateChangedObjects = true, CacheCRUDobjects = cacheCRUDobjects }; @@ -110,12 +110,11 @@ public StructuralAdapter(bool cacheCRUDobjects = true) protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) { + ValidateCreateObjects(objects as dynamic); Created.Add(new Tuple>(typeof(T), objects.OfType())); - - if (!CallsToCreatePerType.TryGetValue(typeof(T), out int n)) CallsToCreatePerType[typeof(T)] = 1; else @@ -189,5 +188,24 @@ protected override int IDelete(Type type, IEnumerable ids, ActionConfig return 0; } + + protected override object NextFreeId(Type objectType, bool refresh = false) + { + if (refresh || !m_nextId.ContainsKey(objectType)) + { + int nextId = Created.Where(x => x.Item1 == objectType).SelectMany(x => x.Item2).Count(); + m_nextId[objectType] = nextId; + return nextId; + } + else + { + int prev = m_nextId[objectType]; + int next = prev + 1; + m_nextId[objectType] = next; + return next; + } + } + + Dictionary m_nextId = new Dictionary(); } } \ No newline at end of file From 599cf549c299b5bfd908b78fd6370af45a323b14 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 13:48:23 +0100 Subject: [PATCH 096/116] Update tests failing When switching on UseAdapterId to tru, the caching system crashes if the obejcts being sent to the UpdateAndCache does nto contain an id. Simple increment Ids added to objects being pushed with UpdateOnly CRUD type --- .ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index d32c2582..79dfe6b7 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -144,12 +144,17 @@ public void DependencyOrder_MostStructuralObjects() [Test] public void Dependecies_UpdateOnly() { - List inputObjects = new List(); + List inputObjects = new List(); inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); + for (int i = 0; i < inputObjects.Count; i++) + { + BH.Engine.Adapter.Modify.SetAdapterId(inputObjects[i], typeof(StructuralAdapterId), i); + } + sa.Push(inputObjects, "", BH.oM.Adapter.PushType.UpdateOnly); string correctOrderCreated = "BH.oM.Structure.Constraints.Constraint6DOF, " + @@ -414,10 +419,15 @@ public void CountCRUDCallsPerType() [Test] public void CountCRUDCallsPerType_UpdateOnly() { - List inputObjects = new List(); + List inputObjects = new List(); inputObjects.AddRange(Create.RandomObjects(10)); inputObjects.AddRange(Create.RandomObjects(10)); + for (int i = 0; i < inputObjects.Count; i++) + { + BH.Engine.Adapter.Modify.SetAdapterId(inputObjects[i], typeof(StructuralAdapterId), i); + } + sa.Push(inputObjects); sa.Push(inputObjects, "", PushType.UpdateOnly); @@ -438,8 +448,6 @@ public void Preprocess_PanelLoads() inputObjects.Add(load); sa.Push(inputObjects); - - } } } \ No newline at end of file From 0273f4fc3e818a4ef17f34c3a27ad4e57dcc8508 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 15:21:13 +0100 Subject: [PATCH 097/116] Update IPushPreProcessModule to return list of objects Make sure the ReplaceObejctsInLoads puts the order so that the loads are last in the list of objects being pushed --- .ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs | 7 ++++--- Adapter_oM/Module/IPushPreProcessModule.cs | 3 ++- .../_PushMethods/ProcessObjectsForPush.cs | 2 +- ...essLoads.cs => ReplaceObjectsInLoadsModule.cs} | 15 +++++++++------ 4 files changed, 16 insertions(+), 11 deletions(-) rename Structure_AdapterModules/{PreProcessLoads.cs => ReplaceObjectsInLoadsModule.cs} (80%) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index 79dfe6b7..e8e74259 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -133,9 +133,9 @@ public void DependencyOrder_MostStructuralObjects() "BH.oM.Structure.Elements.Bar, " + "BH.oM.Structure.Loads.Loadcase, " + "BH.oM.Structure.Elements.Opening, " + - "BH.oM.Structure.Loads.BarUniformlyDistributedLoad, " + "BH.oM.Structure.Elements.FEMesh, " + - "BH.oM.Structure.Elements.Panel"; + "BH.oM.Structure.Elements.Panel, " + + "BH.oM.Structure.Loads.BarUniformlyDistributedLoad"; string createdOrder = string.Join(", ", sa.Created.Select(c => c.Item1.FullName)); Assert.AreEqual(correctOrder, createdOrder); @@ -444,8 +444,9 @@ public void Preprocess_PanelLoads() List panels = Create.RandomObjects(); AreaUniformlyDistributedLoad load = Create.RandomObject(); load.Objects.Elements = panels.Cast().ToList(); - inputObjects.AddRange(panels); + inputObjects.Add(load); + inputObjects.AddRange(panels); sa.Push(inputObjects); } diff --git a/Adapter_oM/Module/IPushPreProcessModule.cs b/Adapter_oM/Module/IPushPreProcessModule.cs index 60f579df..8bb620e7 100644 --- a/Adapter_oM/Module/IPushPreProcessModule.cs +++ b/Adapter_oM/Module/IPushPreProcessModule.cs @@ -20,6 +20,7 @@ * along with this code. If not, see . */ +using BH.oM.Base; using System; using System.Collections.Generic; using System.ComponentModel; @@ -31,6 +32,6 @@ namespace BH.oM.Adapter.Module public interface IPushPreProcessModule : IAdapterModule { [Description("Method called during ProcessObjectsForPush")] - void PreprocessObjects(IEnumerable objects); + IEnumerable PreprocessObjects(IEnumerable objects); } } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs index f1774887..a8ea1334 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs @@ -97,7 +97,7 @@ protected virtual IEnumerable ProcessObjectsForPush(IEnumerable()) { - preprocessModule.PreprocessObjects(objectsToPush); + objectsToPush = preprocessModule.PreprocessObjects(objectsToPush); } return objectsToPush; diff --git a/Structure_AdapterModules/PreProcessLoads.cs b/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs similarity index 80% rename from Structure_AdapterModules/PreProcessLoads.cs rename to Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs index f1886704..dc10f726 100644 --- a/Structure_AdapterModules/PreProcessLoads.cs +++ b/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs @@ -14,31 +14,34 @@ namespace BH.Adapter.Modules.Structure "No action is taken if loads are pushed in isolation, without the elements pushed at the same time as individual instances.")] public class ReplaceObjectsInLoadsModule : IPushPreProcessModule { - public void PreprocessObjects(IEnumerable objects) + public IEnumerable PreprocessObjects(IEnumerable objects) { - IEnumerable bhObjs = objects.OfType(); - List loads = new List(); Dictionary nonLoads = new Dictionary(); //Split load obejcts from non-load objects - foreach (IBHoMObject obj in bhObjs) + foreach (IBHoMObject obj in objects) { if (obj is ILoad load) loads.Add(load); - else if(!(obj is ICase)) + else nonLoads[obj.BHoM_Guid] = obj; } //If no non-load obejcts are being pushed, can simply return, as nothing can be replaced if (nonLoads.Count == 0) - return; + return objects; foreach (ILoad load in loads) { //Load through all loads, and try to update the objects ReplaceObjects(load as dynamic, nonLoads); } + + //Returns the objects in order of first non-loads followed by loads + //This ensures that the objects are pushed before loads + //For many cases this will be handled by dependency types, but for cases where this is yet to be implemented, this solution helps fix the order + return nonLoads.Values.Concat(loads); } From 2b0ed1d9b03b0423eecd93df90b662869577f198 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 16:22:26 +0100 Subject: [PATCH 098/116] Add missing copyright header --- .../ReplaceObjectsInLoadsModule.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs b/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs index dc10f726..c52b2ea4 100644 --- a/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs +++ b/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs @@ -1,4 +1,26 @@ -using BH.oM.Adapter.Module; +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Adapter.Module; using System; using System.Collections.Generic; using System.Text; From 9bd5ca8aa26652841a6166738ee06d53079befdd Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 1 Mar 2023 16:23:13 +0100 Subject: [PATCH 099/116] . --- Adapter_oM/Module/IPushPreProcessModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adapter_oM/Module/IPushPreProcessModule.cs b/Adapter_oM/Module/IPushPreProcessModule.cs index 8bb620e7..9c602cc1 100644 --- a/Adapter_oM/Module/IPushPreProcessModule.cs +++ b/Adapter_oM/Module/IPushPreProcessModule.cs @@ -31,7 +31,7 @@ namespace BH.oM.Adapter.Module [Description("Module for any additional pre-processing to be done to the objects beofre being pushed. This is called after all other preprocessing, such as cloning is done.")] public interface IPushPreProcessModule : IAdapterModule { - [Description("Method called during ProcessObjectsForPush")] + [Description("Method called during ProcessObjectsForPush.")] IEnumerable PreprocessObjects(IEnumerable objects); } } From 22ec7ae8300bb37bd7f4c4892732eb42d55b963f Mon Sep 17 00:00:00 2001 From: Alessio Lombardi Date: Thu, 2 Mar 2023 18:15:58 +0000 Subject: [PATCH 100/116] Update ProcessObjectsForPush.cs --- .../_PushMethods/ProcessObjectsForPush.cs | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs index a8ea1334..146d9855 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/ProcessObjectsForPush.cs @@ -53,42 +53,46 @@ protected virtual IEnumerable ProcessObjectsForPush(IEnumerable().Count() != objects.Count() & !wrapNonBHoMObjects) - { - BH.Engine.Base.Compute.RecordWarning("Only non-null BHoMObjects are supported by the default Push. " + // = you can override if needed; - "\nConsider specifying actionConfig['WrapNonBHoMObjects'] to true."); - } - - // -------------------------------- // - // OBJECT PREPARATION // - // -------------------------------- // + // ---------------------------------------- // + // OBJECT PREPARATION - Unpack // + // ---------------------------------------- // // Unpack any container present in the input objects - List unpackedObjs = new List(); + List objectsIncludingUnpacked = new List(); foreach (var obj in objects) { if (obj is IContainer container) { - unpackedObjs.AddRange(container.Unpack()); + objectsIncludingUnpacked.AddRange(container.Unpack()); } else - unpackedObjs.Add(obj); + objectsIncludingUnpacked.Add(obj); + } + + // -------------------------------- // + // CHECKS // + // -------------------------------- // + + // Verify that the input objects are IBHoMObjects. + if (objectsIncludingUnpacked.OfType().Count() != objectsIncludingUnpacked.Count() & !wrapNonBHoMObjects) + { + BH.Engine.Base.Compute.RecordWarning("Only non-null BHoMObjects are supported by the default Push. " + // = you can override if needed; + "\nConsider specifying actionConfig['WrapNonBHoMObjects'] to true."); } IEnumerable objectsToPush = new List(); // Wrap non-BHoM objects into a Custom BHoMObject to make them compatible with the CRUD. if (wrapNonBHoMObjects) - objectsToPush = WrapNonBHoMObjects(unpackedObjs); + objectsToPush = WrapNonBHoMObjects(objectsIncludingUnpacked); else - objectsToPush = unpackedObjs.OfType(); + objectsToPush = objectsIncludingUnpacked.OfType(); + + // ----------------------------------------- // + // OBJECT PREPARATION - Cloning // + // ----------------------------------------- // // Clone the objects for immutability in the UI. CloneBeforePush should always be true, except for very specific cases. if (m_AdapterSettings.CloneBeforePush) From 4821bd78a2053bdd87b2e504131605eebfef33c8 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 3 Mar 2023 11:15:57 +0100 Subject: [PATCH 101/116] Adding tests to handle edge cases --- .../BHoM_Adapter_Tests/PushTests.cs | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index e8e74259..3bc74c45 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -34,6 +34,7 @@ using AutoBogus; using Shouldly; + namespace BH.Tests.Adapter.Structure { public class PushTests @@ -441,7 +442,7 @@ public void CountCRUDCallsPerType_UpdateOnly() public void Preprocess_PanelLoads() { List inputObjects = new List(); - List panels = Create.RandomObjects(); + List panels = Create.RandomObjects(10); AreaUniformlyDistributedLoad load = Create.RandomObject(); load.Objects.Elements = panels.Cast().ToList(); @@ -450,5 +451,65 @@ public void Preprocess_PanelLoads() sa.Push(inputObjects); } + + + [Test] + public void Preprocess_PushTranslatedBars() + { + List inputObjects = new List(); + + Bar bar = Create.RandomObject(); + int barCount = 10; + + for (int i = 0; i < barCount; i++) + { + //Tranforming bars does not replace the Guids + Bar translated = BH.Engine.Structure.Modify.Transform(bar, Engine.Geometry.Create.TranslationMatrix(new oM.Geometry.Vector { Z = i })); + inputObjects.Add(translated); + } + + //Culling only happens when there are loads + PointLoad load = Create.RandomObject(); + inputObjects.Add(load); + + + sa.Push(inputObjects); + + + sa.Created.Where(x => x.Item1 == typeof(Bar)).SelectMany(x => x.Item2).Count().ShouldBe(barCount); + } + + [Test] + public void Preprocess_PanelLoadsDuplicateIds() + { + //All panels are set to have the same Guid, hence should not be able to rely on the replace mechanism + List inputObjects = new List(); + List panels = Create.RandomObjects(10); + Guid guid = Guid.NewGuid(); + panels.ForEach(x => x.BHoM_Guid = guid); + + AreaUniformlyDistributedLoad load = Create.RandomObject(); + load.Objects.Elements = panels.Cast().ToList(); + + inputObjects.Add(load); + inputObjects.AddRange(panels); + + //Expecting this to crash on ValidateCreateObjects, and warning to be raised to inform that replacement could not happen + try + { + sa.Push(inputObjects); + } + catch (Exception e) + { + if (e.Message == "Elements on loads do not contain required Ids.") + { + BH.Engine.Base.Query.CurrentEvents().ShouldContain(x => x.Message.StartsWith("Some objects pushed have duplicate BHoM_Guids")); + } + else + throw; + } + + + } } } \ No newline at end of file From 1b2ff890a727686669fc522794cc424741ee80b9 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 3 Mar 2023 11:16:15 +0100 Subject: [PATCH 102/116] Fix test cases added --- .../ReplaceObjectsInLoadsModule.cs | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs b/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs index c52b2ea4..f297d9fa 100644 --- a/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs +++ b/Structure_AdapterModules/ReplaceObjectsInLoadsModule.cs @@ -39,50 +39,63 @@ public class ReplaceObjectsInLoadsModule : IPushPreProcessModule public IEnumerable PreprocessObjects(IEnumerable objects) { List loads = new List(); - Dictionary nonLoads = new Dictionary(); + Dictionary> nonLoads = new Dictionary>(); //Split load obejcts from non-load objects foreach (IBHoMObject obj in objects) { if (obj is ILoad load) loads.Add(load); + else if (!nonLoads.ContainsKey(obj.BHoM_Guid)) + nonLoads[obj.BHoM_Guid] = new List { obj }; else - nonLoads[obj.BHoM_Guid] = obj; + nonLoads[obj.BHoM_Guid].Add(obj); } - //If no non-load obejcts are being pushed, can simply return, as nothing can be replaced - if (nonLoads.Count == 0) + //If no non-load obejcts are being pushed or the list does not contain any load, can simply return, as nothing can be replaced + if (nonLoads.Count == 0 || loads.Count == 0) return objects; + bool duplicatesFound = false; foreach (ILoad load in loads) { - //Load through all loads, and try to update the objects - ReplaceObjects(load as dynamic, nonLoads); + //Loop through all loads, and try to update the objects + duplicatesFound |= ReplaceObjects(load as dynamic, nonLoads); } + if (duplicatesFound) + BH.Engine.Base.Compute.RecordWarning("Some objects pushed have duplicate BHoM_Guids. This means objects on loads not able to be updated."); + //Returns the objects in order of first non-loads followed by loads //This ensures that the objects are pushed before loads //For many cases this will be handled by dependency types, but for cases where this is yet to be implemented, this solution helps fix the order - return nonLoads.Values.Concat(loads); + return nonLoads.Values.SelectMany(x => x).Concat(loads); } - private void ReplaceObjects(IElementLoad load, Dictionary objects) where T : IBHoMObject + private bool ReplaceObjects(IElementLoad load, Dictionary> objects) where T : IBHoMObject { + bool duplicatesFound = false; //Run through all elements stored on the load for (int i = 0; i < load.Objects.Elements.Count; i++) { //Try to find an item with the same guid in the non-load objects - if (objects.TryGetValue(load.Objects.Elements[i].BHoM_Guid, out IBHoMObject replacement)) + if (objects.TryGetValue(load.Objects.Elements[i].BHoM_Guid, out List replacement)) { + if (replacement.Count != 1) + { + duplicatesFound = true; + continue; + } //Ensure the found object is of the correct type - if (replacement is T tObject) + if (replacement[0] is T tObject) { //replace with the other object load.Objects.Elements[i] = tObject; } } } + return duplicatesFound; } private void ReplaceObjects(ILoad load, Dictionary objects) From 47e36c257576ed5e0e6ca447c75e2a2da8709efd Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 3 Mar 2023 11:23:23 +0100 Subject: [PATCH 103/116] Checking warning not raised for cases when it should not be Also adding in ClearCurrentEvent to startup --- .ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index 3bc74c45..12a11aa3 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -44,6 +44,7 @@ public class PushTests public void Setup() { sa = new StructuralAdapter(); + BH.Engine.Base.Compute.ClearCurrentEvents(); } private static IEnumerable GetTestContainers() @@ -450,6 +451,8 @@ public void Preprocess_PanelLoads() inputObjects.AddRange(panels); sa.Push(inputObjects); + //No duplicate ids, hence no warning should be raised + Engine.Base.Query.CurrentEvents().ShouldNotContain(x => x.Message.StartsWith("Some objects pushed have duplicate BHoM_Guids")); } @@ -477,6 +480,8 @@ public void Preprocess_PushTranslatedBars() sa.Created.Where(x => x.Item1 == typeof(Bar)).SelectMany(x => x.Item2).Count().ShouldBe(barCount); + //Duplicate Ids irrelevant hence no warning should be raised + Engine.Base.Query.CurrentEvents().ShouldNotContain(x => x.Message.StartsWith("Some objects pushed have duplicate BHoM_Guids")); } [Test] From 91012611d5ef70c26f9709181af84625371ceff7 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 12:24:54 +0100 Subject: [PATCH 104/116] Adding new test showcasing failing case, and second test to check id management First test is failing, second test is not, but added to ensure changes does not negatively impact ID management --- .../BHoM_Adapter_Tests/PushTests.cs | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index 12a11aa3..0fafdf04 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -33,7 +33,7 @@ using System.Diagnostics.Contracts; using AutoBogus; using Shouldly; - +using BH.oM.Geometry; namespace BH.Tests.Adapter.Structure { @@ -516,5 +516,62 @@ public void Preprocess_PanelLoadsDuplicateIds() } + + [Test] + public void CopyProperties_NodesReplaced() + { + //Create bar from line. Nodes will have null-constraints on the Bar + Line line = new Line { Start = new Point { X = 0 }, End = new Point { X = 10 } }; + Bar bar = BH.Engine.Structure.Create.Bar(line, null, 0); + + //Create nodes in the same position + Node node1 = new Node { Position = line.Start, Support = Create.RandomObject() }; + Node node2 = new Node { Position = line.End, Support = Create.RandomObject() }; + + //Push with bar before the nodes + List inputObjs = new List { bar, node1, node2 }; + sa.Push(inputObjs); + + //Make sure the nodes in the model contain the supports + var supports = sa.Created.Where(x => x.Item1 == typeof(Node)).SelectMany(x => x.Item2).Cast().Select(x => x.Support).Where(x => x != null); + supports.ShouldContain(x => x.Name == node1.Support.Name); + supports.ShouldContain(x => x.Name == node2.Support.Name); + } + + [Test] + public void DuplicateObjects_EnsureAllOutputHaveIds() + { + //Create duplicate elements + Steel steel1 = Create.RandomObject(); + Steel steel2 = Create.RandomObject(); + + steel1.Name = "MatName"; + steel2.Name = steel1.Name; + + SteelSection section1 = Create.RandomObject(); + SteelSection section2 = Create.RandomObject(); + section1.Material = steel1; + section2.Material = steel2; + section1.Name = "SecName"; + section2.Name = section1.Name; + + Line line = new Line { Start = new Point { X = 0 }, End = new Point { X = 10 } }; + Bar bar1 = BH.Engine.Structure.Create.Bar(line, section1, 0); + Bar bar2 = BH.Engine.Structure.Create.Bar(line, section1, 0); + + Node node1 = new Node { Position = line.Start }; + Node node2 = new Node { Position = line.End }; + + //Push duplicates + List inputObjs = new List { bar1, bar2, node1, node2, section1, section2 }; + List pushed = sa.Push(inputObjs).OfType().ToList(); + + //Make sure correct number of items has been created to ensure comparers work. + //If this does not work, the check of all objects having assigned Ids is pointless + sa.Created.Where(x => x.Item1 != typeof(Node)).ShouldAllBe(x => x.Item2.Count() == 1); + sa.Created.Where(x => x.Item1 == typeof(Node)).ShouldAllBe(x => x.Item2.Count() == 2); + + pushed.ShouldAllBe(x => BH.Engine.Base.Query.FindFragment(x, typeof(StructuralAdapterId)) != null, "At least one of the pushed objects did not contain an AdapterId Fragment."); + } } } \ No newline at end of file From a0b14fdae58d71218871f194d1aef58579c42c29 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 12:25:54 +0100 Subject: [PATCH 105/116] Adding methods for grouping by comparer type, and calling copy Properties modules, ensuring all properties are properly copied across --- .../Support/DistinctWithCopiedProperties.cs | 48 ++++++++++++++ .../Support/GroupAndCopyProperties.cs | 63 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs create mode 100644 BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs b/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs new file mode 100644 index 00000000..683dab7f --- /dev/null +++ b/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs @@ -0,0 +1,48 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.Engine.Adapter; +using BH.Engine.Base; +using BH.oM.Adapter; +using BH.oM.Base; +using BH.oM.Data; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace BH.Adapter +{ + + public abstract partial class BHoMAdapter + { + [Description("Gets distinct objects based on implemented AdapterComparer of the particular type, with CopyPropertyModules available for the type run.")] + private List DistinctWithCopiedProperties(IEnumerable objectsToPush, ActionConfig actionConfig = null) where T : class, IBHoMObject + { + return GroupAndCopyProperties(objectsToPush, actionConfig).Select(x => x.Key).ToList(); + } + } +} + + + + diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs b/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs new file mode 100644 index 00000000..582b8b25 --- /dev/null +++ b/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs @@ -0,0 +1,63 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.Engine.Adapter; +using BH.Engine.Base; +using BH.oM.Adapter; +using BH.oM.Base; +using BH.oM.Data; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace BH.Adapter +{ + public abstract partial class BHoMAdapter + { + [Description("Groups the objects by the coparer for the particular type, and then runs any CopyPropertiesModules available for the type.")] + private IEnumerable> GroupAndCopyProperties(IEnumerable objectsToPush, ActionConfig actionConfig = null) where T : class, IBHoMObject + { + IEnumerable> grouped = objectsToPush.GroupBy(x => x, Engine.Adapter.Query.GetComparerForType(this, actionConfig)); + + List> copyPropertiesModules = this.GetCopyPropertiesModules(); + + foreach (var copyModule in copyPropertiesModules) + { + foreach (var group in grouped) + { + T keep = group.Key; + foreach (T item in group.Skip(1)) + { + copyModule.CopyProperties(keep, item); + } + } + } + + return grouped; + } + } +} + + + + From a3d81afbfbf2c50b66effe946c775d1ef79a51d5 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 13:21:08 +0100 Subject: [PATCH 106/116] Remove `class` restriction on copy properties --- Adapter_Engine/Query/GetCopyPropertiesModules.cs | 2 +- .../Support/DistinctWithCopiedProperties.cs | 2 +- .../_PushMethods/Support/GroupAndCopyProperties.cs | 10 +++++----- BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Adapter_Engine/Query/GetCopyPropertiesModules.cs b/Adapter_Engine/Query/GetCopyPropertiesModules.cs index d129287a..06f6f77b 100644 --- a/Adapter_Engine/Query/GetCopyPropertiesModules.cs +++ b/Adapter_Engine/Query/GetCopyPropertiesModules.cs @@ -32,7 +32,7 @@ namespace BH.Engine.Adapter { public static partial class Query { - public static List> GetCopyPropertiesModules(this IBHoMAdapter adapter) where T : class, IBHoMObject + public static List> GetCopyPropertiesModules(this IBHoMAdapter adapter) where T : IBHoMObject { return adapter.AdapterModules.OfType>().ToList(); } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs b/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs index 683dab7f..9e230b3b 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs @@ -36,7 +36,7 @@ namespace BH.Adapter public abstract partial class BHoMAdapter { [Description("Gets distinct objects based on implemented AdapterComparer of the particular type, with CopyPropertyModules available for the type run.")] - private List DistinctWithCopiedProperties(IEnumerable objectsToPush, ActionConfig actionConfig = null) where T : class, IBHoMObject + private List DistinctWithCopiedProperties(IEnumerable objectsToPush, ActionConfig actionConfig = null) where T : IBHoMObject { return GroupAndCopyProperties(objectsToPush, actionConfig).Select(x => x.Key).ToList(); } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs b/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs index 582b8b25..d66c93ab 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs @@ -35,18 +35,18 @@ namespace BH.Adapter public abstract partial class BHoMAdapter { [Description("Groups the objects by the coparer for the particular type, and then runs any CopyPropertiesModules available for the type.")] - private IEnumerable> GroupAndCopyProperties(IEnumerable objectsToPush, ActionConfig actionConfig = null) where T : class, IBHoMObject + private IEnumerable> GroupAndCopyProperties(IEnumerable objectsToPush, ActionConfig actionConfig = null) where T : IBHoMObject { IEnumerable> grouped = objectsToPush.GroupBy(x => x, Engine.Adapter.Query.GetComparerForType(this, actionConfig)); List> copyPropertiesModules = this.GetCopyPropertiesModules(); - foreach (var copyModule in copyPropertiesModules) + foreach (var group in grouped) { - foreach (var group in grouped) + T keep = group.Key; + foreach (T item in group.Skip(1)) { - T keep = group.Key; - foreach (T item in group.Skip(1)) + foreach (var copyModule in copyPropertiesModules) { copyModule.CopyProperties(keep, item); } diff --git a/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs b/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs index d321b870..a2f50132 100644 --- a/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs +++ b/BHoM_Adapter/HelperMethods/CopyBHoMObjectProperties.cs @@ -36,7 +36,7 @@ namespace BH.Adapter public abstract partial class BHoMAdapter { [Description("Gets called during the Push. Takes properties specified from the source IBHoMObject and assigns them to the target IBHoMObject.")] - public void CopyBHoMObjectProperties(T target, T source) where T : class, IBHoMObject + public void CopyBHoMObjectProperties(T target, T source) where T : IBHoMObject { // Port tags from source to target foreach (string tag in source.Tags) From 744b1da02a8b4e2f005a70a9007212a5ab657824 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 13:21:54 +0100 Subject: [PATCH 107/116] Call base CopyBHoMObjectPRoeprties method from grouping method --- .../_PushMethods/Support/GroupAndCopyProperties.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs b/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs index d66c93ab..4ae9ddce 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs @@ -46,6 +46,7 @@ private IEnumerable> GroupAndCopyProperties(IEnumerable ob T keep = group.Key; foreach (T item in group.Skip(1)) { + CopyBHoMObjectProperties(keep, item); foreach (var copyModule in copyPropertiesModules) { copyModule.CopyProperties(keep, item); From 606141f148dcdf0d691f98a48efcdba86a122fa9 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 13:22:34 +0100 Subject: [PATCH 108/116] Move to HelperMethods from Support folder --- .../Support => HelperMethods}/DistinctWithCopiedProperties.cs | 0 .../Support => HelperMethods}/GroupAndCopyProperties.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename BHoM_Adapter/{AdapterActions/_PushMethods/Support => HelperMethods}/DistinctWithCopiedProperties.cs (100%) rename BHoM_Adapter/{AdapterActions/_PushMethods/Support => HelperMethods}/GroupAndCopyProperties.cs (100%) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs b/BHoM_Adapter/HelperMethods/DistinctWithCopiedProperties.cs similarity index 100% rename from BHoM_Adapter/AdapterActions/_PushMethods/Support/DistinctWithCopiedProperties.cs rename to BHoM_Adapter/HelperMethods/DistinctWithCopiedProperties.cs diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs b/BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs similarity index 100% rename from BHoM_Adapter/AdapterActions/_PushMethods/Support/GroupAndCopyProperties.cs rename to BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs From 6668ade72792b842522c4fc5b6cfbcbc00d9592c Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 13:23:43 +0100 Subject: [PATCH 109/116] Update FullCrud and CreateOnly to make use of new functionality --- .../_PushMethods/CRUDDispatchers/CreateOnly.cs | 9 ++++++++- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 11 ++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index 3feee507..f60ab8f3 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -47,7 +47,14 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = { bool callDistinct = objectLevel == 0 ? m_AdapterSettings.CreateOnly_DistinctObjects : m_AdapterSettings.CreateOnly_DistinctDependencies; - List newObjects = !callDistinct ? objectsToPush.ToList() : objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this, actionConfig)).ToList(); + List newObjects; + if (!callDistinct) + newObjects = objectsToPush.ToList(); + else + { + IEnumerable> distinctGroups = GroupAndCopyProperties(objectsToPush, actionConfig); + newObjects = distinctGroups.Select(x => x.Key).ToList(); + } // Tag the objects, if tag is given. if (tag != "") diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index ab7d0769..af360619 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -43,13 +43,14 @@ public abstract partial class BHoMAdapter // These methods dispatch calls to different CRUD methods as required by the Push. [Description("Performs the full CRUD, calling the single CRUD methods as appropriate.")] - protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = PushType.AdapterDefault, string tag = "", ActionConfig actionConfig = null) where T : class, IBHoMObject + protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = PushType.AdapterDefault, string tag = "", ActionConfig actionConfig = null) where T : IBHoMObject { if (objectsToPush == null || !objectsToPush.Any()) return true; - // Make sure objects are distinct - List newObjects = objectsToPush.Distinct(Engine.Adapter.Query.GetComparerForType(this, actionConfig)).ToList(); + // Make sure objects are distinct and that any copy-proeprty module for the type is run + IEnumerable> distinctGroups = GroupAndCopyProperties(objectsToPush, actionConfig); + List newObjects = distinctGroups.Select(x => x.Key).ToList(); // Add the tag if provided if (!string.IsNullOrWhiteSpace(tag)) @@ -130,7 +131,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus /***************************************************/ - protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerable existingOjects, string tag, ActionConfig actionConfig, bool mergeWithComparer = false) where T : class, IBHoMObject + protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerable existingOjects, string tag, ActionConfig actionConfig, bool mergeWithComparer = false) where T : IBHoMObject { // Separate objects based on tags List multiTaggedObjects = existingOjects.Where(x => x.Tags.Contains(tag) && x.Tags.Count > 1).ToList(); @@ -164,7 +165,7 @@ protected IEnumerable ReplaceInMemory(IEnumerable newObjects, IEnumerab /***************************************************/ - protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumerable readObjs, string tag, ActionConfig actionConfig, PushType pushType) where T : class, IBHoMObject + protected IEnumerable ReplaceThroughAPI(IEnumerable objsToPush, IEnumerable readObjs, string tag, ActionConfig actionConfig, PushType pushType) where T : IBHoMObject { IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this, actionConfig); VennDiagram diagram = Engine.Data.Create.VennDiagram(objsToPush, readObjs, comparer); From bd4b5ded63c339e7d85d517106526c88aa65076b Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 13:27:20 +0100 Subject: [PATCH 110/116] Make use of groups for updating adapter Ids --- .../CRUDDispatchers/CreateOnly.cs | 22 ++++++++++--------- .../_PushMethods/CRUDDispatchers/FullCRUD.cs | 17 +++++++------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index f60ab8f3..1438f4f8 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -48,11 +48,12 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = bool callDistinct = objectLevel == 0 ? m_AdapterSettings.CreateOnly_DistinctObjects : m_AdapterSettings.CreateOnly_DistinctDependencies; List newObjects; + IEnumerable> distinctGroups = null; if (!callDistinct) newObjects = objectsToPush.ToList(); else { - IEnumerable> distinctGroups = GroupAndCopyProperties(objectsToPush, actionConfig); + distinctGroups = GroupAndCopyProperties(objectsToPush, actionConfig); newObjects = distinctGroups.Select(x => x.Key).ToList(); } @@ -73,20 +74,21 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = else if(!ICreate(newObjects, actionConfig)) return false; - if (callDistinct && m_AdapterSettings.UseAdapterId) + if (callDistinct && m_AdapterSettings.UseAdapterId && distinctGroups != null) { // Map Ids to the original set of objects (before we extracted the distincts elements from it). // If some objects of the original set were not Created (because e.g. they were already existing in the external model and had already an id, // therefore no new id was assigned to them) they will not get mapped, so the original set will be left with them intact. - IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this, actionConfig); - foreach (T item in objectsToPush) + foreach (var group in distinctGroups) { - // Fetch any existing IAdapterId fragment and assign it to the item. - // This preserves any additional property other than `Id` that may be in the fragment. - IFragment fragment; - newObjects.First(x => comparer.Equals(x, item)).Fragments.TryGetValue(AdapterIdFragmentType, out fragment); - - item.SetAdapterId(fragment as IAdapterId); + IFragment idFragment; + if (group.Key.Fragments.TryGetValue(AdapterIdFragmentType, out idFragment)) + { + foreach (T item in group.Skip(1)) + { + item.SetAdapterId(idFragment as IAdapterId); + } + } } } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index af360619..2709395c 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -114,15 +114,16 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus // Map Ids to the original set of objects (before we extracted the distincts elements from it). // If some objects of the original set were not Created (because e.g. they were already existing in the external model and had already an id, // therefore no new id was assigned to them) they will not get mapped, so the original set will be left with them intact. - IEqualityComparer comparer = Engine.Adapter.Query.GetComparerForType(this, actionConfig); - foreach (T item in objectsToPush) + foreach (var group in distinctGroups) { - // Fetch any existing IAdapterId fragment and assign it to the item. - // This preserves any additional property other than `Id` that may be in the fragment. - IFragment fragment; - newObjects.First(x => comparer.Equals(x, item)).Fragments.TryGetValue(AdapterIdFragmentType, out fragment); - - item.SetAdapterId(fragment as IAdapterId); + IFragment idFragment; + if (group.Key.Fragments.TryGetValue(AdapterIdFragmentType, out idFragment)) + { + foreach (T item in group.Skip(1)) + { + item.SetAdapterId(idFragment as IAdapterId); + } + } } } From 148396e14fccb3653ac55009f2cf93b7c5a58cb0 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 14:20:51 +0100 Subject: [PATCH 111/116] Update COpyNodes properties module to raise Notes for conflicts found --- .../CopyNodeProperties.cs | 25 ++++++++++++++++--- .../Structure_AdapterModules.csproj | 10 ++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Structure_AdapterModules/CopyNodeProperties.cs b/Structure_AdapterModules/CopyNodeProperties.cs index 2a35a4c1..28f6eb56 100644 --- a/Structure_AdapterModules/CopyNodeProperties.cs +++ b/Structure_AdapterModules/CopyNodeProperties.cs @@ -28,6 +28,8 @@ using System.ComponentModel; using BH.oM.Structure.Elements; using BH.oM.Structure.SectionProperties; +using BH.Engine.Structure; +using BH.Engine.Geometry; namespace BH.Adapter.Modules { @@ -38,12 +40,27 @@ public class CopyNodeProperties : ICopyPropertiesModule public void CopyProperties(Node target, Node source) { // If source is constrained and target is not, add source constraint to target - if (source.Support != null && target.Support == null) - target.Support = source.Support; + if (source.Support != null) + { + if (target.Support == null) + target.Support = source.Support; + else + { + string desc1 = target.Support.Description(); + string desc2 = source.Support.Description(); + if(desc1 != desc2) + Engine.Base.Compute.RecordNote($"Node in position ({target.Position.X},{target.Position.Y},{target.Position.Z}) contains conflicting supports. Support {desc1} will be used on the node."); + } + } // If source has a defined orientation and target does not, add local orientation from the source - if (source.Orientation != null && target.Orientation == null) - target.Orientation = source.Orientation; + if (source.Orientation != null) + { + if (target.Orientation == null) + target.Orientation = source.Orientation; + else if(!source.Orientation.IsEqual(target.Orientation)) + BH.Engine.Base.Compute.RecordNote($"Node in position ({target.Position.X}, {target.Position.Y}, {target.Position.Z}) contains conflicting orientaions. Orientation with Normal vector ({target.Orientation.Z.X}, {target.Orientation.Z.Y}, {target.Orientation.Z.Z}) will be used on the node."); + } } } } diff --git a/Structure_AdapterModules/Structure_AdapterModules.csproj b/Structure_AdapterModules/Structure_AdapterModules.csproj index bd1d7473..18b427f6 100644 --- a/Structure_AdapterModules/Structure_AdapterModules.csproj +++ b/Structure_AdapterModules/Structure_AdapterModules.csproj @@ -78,11 +78,21 @@ false false + + C:\ProgramData\BHoM\Assemblies\Spatial_oM.dll + false + false + C:\ProgramData\BHoM\Assemblies\Structure_oM.dll false false + + C:\ProgramData\BHoM\Assemblies\Structure_Engine.dll + false + false + From 6334717e8c9b3287538ccecc63610411d8b12f17 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 14:36:09 +0100 Subject: [PATCH 112/116] Clarifying comment --- .../AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs | 2 +- .../AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs | 2 +- BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs index 1438f4f8..fdfc7d89 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/CreateOnly.cs @@ -84,7 +84,7 @@ protected virtual bool CreateOnly(IEnumerable objectsToPush, string tag = IFragment idFragment; if (group.Key.Fragments.TryGetValue(AdapterIdFragmentType, out idFragment)) { - foreach (T item in group.Skip(1)) + foreach (T item in group.Skip(1)) //Skip 1 as first instance is the key { item.SetAdapterId(idFragment as IAdapterId); } diff --git a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs index 2709395c..c9e18fb2 100644 --- a/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs +++ b/BHoM_Adapter/AdapterActions/_PushMethods/CRUDDispatchers/FullCRUD.cs @@ -119,7 +119,7 @@ protected bool FullCRUD(IEnumerable objectsToPush, PushType pushType = Pus IFragment idFragment; if (group.Key.Fragments.TryGetValue(AdapterIdFragmentType, out idFragment)) { - foreach (T item in group.Skip(1)) + foreach (T item in group.Skip(1)) //Skip 1 as first instance is the key { item.SetAdapterId(idFragment as IAdapterId); } diff --git a/BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs b/BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs index 4ae9ddce..2f07a91a 100644 --- a/BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs +++ b/BHoM_Adapter/HelperMethods/GroupAndCopyProperties.cs @@ -44,7 +44,7 @@ private IEnumerable> GroupAndCopyProperties(IEnumerable ob foreach (var group in grouped) { T keep = group.Key; - foreach (T item in group.Skip(1)) + foreach (T item in group.Skip(1)) //Skip 1 as first instance is the key { CopyBHoMObjectProperties(keep, item); foreach (var copyModule in copyPropertiesModules) From 6a02360bff53e08873cc309164c3a3f5c31351b3 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 6 Mar 2023 14:39:37 +0100 Subject: [PATCH 113/116] Add description --- Adapter_Engine/Query/GetCopyPropertiesModules.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Adapter_Engine/Query/GetCopyPropertiesModules.cs b/Adapter_Engine/Query/GetCopyPropertiesModules.cs index 06f6f77b..ae1254e0 100644 --- a/Adapter_Engine/Query/GetCopyPropertiesModules.cs +++ b/Adapter_Engine/Query/GetCopyPropertiesModules.cs @@ -32,6 +32,7 @@ namespace BH.Engine.Adapter { public static partial class Query { + [Description("Gets any adapter module on the adapter for copying properties of an object of type T to another object of type T.")] public static List> GetCopyPropertiesModules(this IBHoMAdapter adapter) where T : IBHoMObject { return adapter.AdapterModules.OfType>().ToList(); From 7124839d9a62c0cefd140af4a89b98d92584d7ae Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 7 Mar 2023 11:14:31 +0100 Subject: [PATCH 114/116] Add descriptions to new tests Also adding the steel materials to the input objects for obejcts to be pushed in the DuplicateObjects_EnsureAllOutputHaveIds test. They should have been there in the first palce, but got missed when writing the test. --- .ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs index 0fafdf04..e0be67d4 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/PushTests.cs @@ -518,6 +518,8 @@ public void Preprocess_PanelLoadsDuplicateIds() } [Test] + [Description("Tests that objects being pushed are correctly 'merged' by calls to CopyProperties modules. \n" + + "Two nodes pushed in the same location, one with a support and one without, the adapter should make sure the final node being sent for creation should contain the support.")] public void CopyProperties_NodesReplaced() { //Create bar from line. Nodes will have null-constraints on the Bar @@ -539,6 +541,7 @@ public void CopyProperties_NodesReplaced() } [Test] + [Description("Tests that all objects sent to the push have AdapterIds assigned, even though some have been identified as duplicates and hence culled out.")] public void DuplicateObjects_EnsureAllOutputHaveIds() { //Create duplicate elements @@ -563,7 +566,7 @@ public void DuplicateObjects_EnsureAllOutputHaveIds() Node node2 = new Node { Position = line.End }; //Push duplicates - List inputObjs = new List { bar1, bar2, node1, node2, section1, section2 }; + List inputObjs = new List { bar1, bar2, node1, node2, section1, section2, steel1, steel2 }; List pushed = sa.Push(inputObjs).OfType().ToList(); //Make sure correct number of items has been created to ensure comparers work. From 1fe400784d84d82d044bdabca0fe699b5a8a8e9d Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 8 Mar 2023 16:28:33 +0100 Subject: [PATCH 115/116] Update StructuralAdapter putting the setting of the AdapterIdFragmentType after calling dependency modules This makes half of the UnitTest fail, which is the intention, and what needs to be fixed. --- .ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs index 6d662767..bcde4e66 100644 --- a/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs +++ b/.ci/unit-tests/BHoM_Adapter_Tests/Objects/StructuralAdapter.cs @@ -104,8 +104,9 @@ public StructuralAdapter(bool cacheCRUDobjects = true) {typeof(BarRelease), new NameOrDescriptionComparer() } }; - AdapterIdFragmentType = typeof(StructuralAdapterId); + BH.Adapter.Modules.Structure.ModuleLoader.LoadModules(this); + AdapterIdFragmentType = typeof(StructuralAdapterId); } protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig = null) From b848f32424cd827f3977180614c8b053c5cd19d2 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 8 Mar 2023 16:30:54 +0100 Subject: [PATCH 116/116] Fix GetElementsFromLoad modules Store the adapter rather than the AdapterIdFragmentType Use the AdapterIdFragmentType on the stored IBHoMAdapter rather than the previously stored type Add better null handling on the adapter and ID --- .../GetGravityLoadElementsWithoutID.cs | 25 +++++++++++++------ .../GetLoadElementsWithoutID.cs | 24 ++++++++++++------ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs b/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs index cee973be..82790027 100644 --- a/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs +++ b/Structure_AdapterModules/GetGravityLoadElementsWithoutID.cs @@ -45,27 +45,36 @@ public class GetGravityLoadElementsWithoutID : IGetDependencyModule GetDependencies(IEnumerable objects) { - List noIdLoadObjects = new List(); - foreach (GravityLoad load in objects) + + if (m_adapter?.AdapterIdFragmentType == null) + { + string adapterType = m_adapter == null ? "Adapter" : m_adapter.GetType().Name; + BH.Engine.Base.Compute.RecordWarning($"{adapterType} does not have a set {nameof(m_adapter.AdapterIdFragmentType)}. Unable to filter load objects by set ID. All objects on the load will be treated as a dependency."); + return objects.Select(x => x?.Objects?.Elements).Where(x => x != null).SelectMany(x => x).Where(x => x != null).OfType().ToList(); + } + else { - if(load?.Objects?.Elements != null) - noIdLoadObjects.AddRange(load.Objects.Elements.OfType().Where(x => x != null && !x.Fragments.Contains(m_adapterIdType))); + List noIdLoadObjects = new List(); + foreach (GravityLoad load in objects) + { + if (load?.Objects?.Elements != null) + noIdLoadObjects.AddRange(load.Objects.Elements.OfType().Where(x => x != null && !x.Fragments.Contains(m_adapter.AdapterIdFragmentType))); + } + return noIdLoadObjects; } - return noIdLoadObjects; } - /***************************************************/ /**** Constructors ****/ /***************************************************/ public GetGravityLoadElementsWithoutID(IBHoMAdapter adapter) { - m_adapterIdType = adapter.AdapterIdFragmentType; + m_adapter = adapter; } /***************************************************/ - private Type m_adapterIdType; + private IBHoMAdapter m_adapter; /***************************************************/ } diff --git a/Structure_AdapterModules/GetLoadElementsWithoutID.cs b/Structure_AdapterModules/GetLoadElementsWithoutID.cs index fc23eca0..5903c5cf 100644 --- a/Structure_AdapterModules/GetLoadElementsWithoutID.cs +++ b/Structure_AdapterModules/GetLoadElementsWithoutID.cs @@ -45,13 +45,23 @@ public class GetLoadElementsWithoutID : IGetDependencyModule, public IEnumerable GetDependencies(IEnumerable> objects) { - List noIdLoadObjects = new List(); - foreach (IElementLoad load in objects) + if (m_adapter?.AdapterIdFragmentType == null) { - if(load?.Objects?.Elements != null) - noIdLoadObjects.AddRange(load.Objects.Elements.Where(x => x != null && !x.Fragments.Contains(m_adapterIdType))); + string adapterType = m_adapter == null ? "Adapter" : m_adapter.GetType().Name; + BH.Engine.Base.Compute.RecordWarning($"{adapterType} does not have a set {nameof(m_adapter.AdapterIdFragmentType)}. Unable to filter load objects by set ID. All objects on the load will be treated as a dependency."); + return objects.Select(x => x?.Objects?.Elements).Where(x => x != null).SelectMany(x => x).Where(x => x != null).ToList(); } - return noIdLoadObjects; + else + { + List noIdLoadObjects = new List(); + foreach (IElementLoad load in objects) + { + if (load?.Objects?.Elements != null) + noIdLoadObjects.AddRange(load.Objects.Elements.Where(x => x != null && !x.Fragments.Contains(m_adapter.AdapterIdFragmentType))); + } + return noIdLoadObjects; + } + } /***************************************************/ @@ -60,12 +70,12 @@ public IEnumerable GetDependencies(IEnumerable> objects) public GetLoadElementsWithoutID(IBHoMAdapter adapter) { - m_adapterIdType = adapter.AdapterIdFragmentType; + m_adapter = adapter; } /***************************************************/ - private Type m_adapterIdType; + private IBHoMAdapter m_adapter; /***************************************************/ }