Codeunit 3676 BOM Tree Node Dictionary Impl., source in 29
Source29
src/Layers/W1/BaseApp/Inventory/BOM/Tree/BOMTreeNodeDictionaryImpl.Codeunit.al187 lines, Copyright (c) Microsoft Corporation. MIT
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Inventory.BOM.Tree;
codeunit 3676 "BOM Tree Node Dictionary Impl."
{
Access = Internal;
var
FirstBucket: Codeunit "BOM Tree Nodes Bucket";
EmptyValuesIndices: List of [Integer];
LastIndex: Integer;
KeyIndexMap: Dictionary of [Text, Integer];
Initialized: Boolean;
EnumeratorIndex: Integer;
EnumerationInProgress: Boolean;
NotFoundErr: Label 'The element with unique key %1 was not found.', Comment = '%1 is the unique identifying text for an instance.';
KeyAlreadyExistsErr: Label 'Cannot add instance as another with key %1 has already been added.', Comment = '%1 is the unique identifying text for an instance.';
EnumerationInProgressErr: Label 'The collection cannot be modified as an enumeration is in progress. Please call ResetEnumerator() before modifying.';
BucketOutOfRangeErr: Label 'Bucket Id %1 is out of range.', Comment = '%1 is the index of bucket';
local procedure Init()
begin
if Initialized then
exit;
LastIndex := 0;
Initialized := true;
FirstBucket.Init();
end;
procedure Get(InstanceKey: Text; var Found: Codeunit "BOM Tree Node")
var
FoundAtIndex: Integer;
begin
FoundAtIndex := IndexOf(InstanceKey);
if FoundAtIndex = 0 then
Error(NotFoundErr, InstanceKey);
Get(FoundAtIndex, Found);
end;
procedure Contains(InstanceKey: Text): Boolean
begin
exit(IndexOf(InstanceKey) <> 0);
end;
procedure Add(Instance: Codeunit "BOM Tree Node") AtIndex: Integer
var
InstanceKey: Text;
begin
Init();
if EnumerationInProgress then
Error(EnumerationInProgressErr);
// check instance with same key already exists
InstanceKey := Instance.GetKey();
if KeyIndexMap.ContainsKey(InstanceKey) then
Error(KeyAlreadyExistsErr, InstanceKey);
// try to add the instance to an index pointing to a gap
if EmptyValuesIndices.Count() > 0 then begin
AtIndex := EmptyValuesIndices.Get(1); // first element
Set(AtIndex, Instance);
KeyIndexMap.Add(InstanceKey, AtIndex);
EmptyValuesIndices.RemoveAt(1);
exit;
end;
// add to the end
LastIndex += 1;
AtIndex := LastIndex;
Set(LastIndex, Instance);
KeyIndexMap.Add(InstanceKey, AtIndex);
end;
procedure Remove(InstanceKey: Text)
var
FoundAtIndex: Integer;
begin
if EnumerationInProgress then
Error(EnumerationInProgressErr);
FoundAtIndex := IndexOf(InstanceKey);
if FoundAtIndex = 0 then
Error(NotFoundErr, InstanceKey);
KeyIndexMap.Remove(InstanceKey);
EmptyValuesIndices.Add(FoundAtIndex);
end;
procedure ResetEnumerator()
begin
EnumeratorIndex := 0;
EnumerationInProgress := false;
end;
procedure MoveNext(): Boolean
begin
EnumerationInProgress := true;
EnumeratorIndex += 1;
while EnumeratorIndex <= LastIndex do begin
if not EmptyValuesIndices.Contains(EnumeratorIndex) then
exit(true);
EnumeratorIndex += 1;
end;
// cannot move further
exit(false);
end;
procedure GetCurrent(var Instance: Codeunit "BOM Tree Node")
begin
Get(EnumeratorIndex, Instance);
end;
procedure Count(): Integer
begin
exit(LastIndex - EmptyValuesIndices.Count());
end;
local procedure GetBucketId(FromIndex: Integer) RequiredBucketId: Integer
var
Bucket: Codeunit "BOM Tree Nodes Bucket";
BucketSize: Integer;
begin
BucketSize := Bucket.SizeOfBucket();
RequiredBucketId := Round((FromIndex - 1) / BucketSize, 1, '<');
end;
local procedure GetBucket(RequestedBucketId: Integer; var Bucket: Codeunit "BOM Tree Nodes Bucket"; CreateBuckets: Boolean)
var
CurrentBucket: Codeunit "BOM Tree Nodes Bucket";
begin
Bucket := FirstBucket;
CurrentBucket := Bucket;
while CurrentBucket.GetBucketId() < RequestedBucketId do begin
CurrentBucket.GetNextBucket(Bucket);
if not Bucket.IsInitialized() then
if CreateBuckets then begin
Bucket.Init(CurrentBucket);
CurrentBucket.SetNextBucket(Bucket);
end else
Error(BucketOutOfRangeErr, RequestedBucketId);
CurrentBucket := Bucket;
end;
end;
local procedure Get(AtIndex: Integer; var Instance: Codeunit "BOM Tree Node")
var
Bucket: Codeunit "BOM Tree Nodes Bucket";
RequiredBucketId: Integer;
LocalIndex: Integer;
begin
RequiredBucketId := GetBucketId(AtIndex);
GetBucket(RequiredBucketId, Bucket, false);
LocalIndex := AtIndex - (Bucket.SizeOfBucket() * RequiredBucketId);
Bucket.GetValue(LocalIndex, Instance);
end;
local procedure Set(AtIndex: Integer; Instance: Codeunit "BOM Tree Node")
var
Bucket: Codeunit "BOM Tree Nodes Bucket";
RequiredBucketId: Integer;
LocalIndex: Integer;
begin
RequiredBucketId := GetBucketId(AtIndex);
GetBucket(RequiredBucketId, Bucket, true);
LocalIndex := AtIndex - (Bucket.SizeOfBucket() * RequiredBucketId);
Bucket.SetValue(LocalIndex, Instance);
end;
local procedure IndexOf(UniqueKey: Text): Integer
begin
if LastIndex = 0 then
exit(0);
if not KeyIndexMap.ContainsKey(UniqueKey) then
exit(0);
exit(KeyIndexMap.Get(UniqueKey));
end;
}