private void TransformToTopologyElement(ResourceDescription modelEntity)
        {
            DMSType dmsType;

            dmsType = GetDMSTypeOfTopologyElement(modelEntity.Id);

            if (dmsType == DMSType.DISCRETE)
            {
                Measurement newDiscrete = GetPopulatedDiscreteMeasurement(modelEntity);
                Measurements.Add(newDiscrete.Id, newDiscrete);
                Provider.Instance.MeasurementProvider.AddDiscreteMeasurement(newDiscrete as DiscreteMeasurement);
            }
            else if (dmsType == DMSType.ANALOG)
            {
                Measurement newAnalog = GetPopulatedAnalogMeasurement(modelEntity);
                Measurements.Add(newAnalog.Id, newAnalog);
                Provider.Instance.MeasurementProvider.AddAnalogMeasurement(newAnalog as AnalogMeasurement);
            }
            else if (dmsType != DMSType.MASK_TYPE && dmsType != DMSType.BASEVOLTAGE)
            {
                ITopologyElement newElement = GetPopulatedElement(modelEntity);
                TopologyElements.Add(newElement.Id, newElement);
                if (dmsType == DMSType.ENERGYSOURCE)
                {
                    EnergySources.Add(newElement.Id);
                }
                ElementConnections.Add(modelEntity.Id, (GetAllReferencedElements(modelEntity)));
            }
        }
        private void PutMeasurementsInElements(IMeasurement measurement)
        {
            string message = $"[NMSManager]Putting measurement with GID 0x{measurement.Id.ToString("X16")} in element.";

            if (MeasurementToConnectedTerminalMap.TryGetValue(measurement.Id, out long terminalId))
            {
                if (TerminalToConnectedElementsMap.TryGetValue(terminalId, out List <long> connectedElements))
                {
                    try
                    {
                        var elementId = connectedElements.Find(
                            e => GetDMSTypeOfTopologyElement(e) != DMSType.CONNECTIVITYNODE &&
                            GetDMSTypeOfTopologyElement(e) != DMSType.ANALOG);

                        if (TopologyElements.TryGetValue(elementId, out ITopologyElement element))
                        {
                            element.Measurements.Add(measurement.Id, measurement.GetMeasurementType());
                            measurement.ElementId = elementId;

                            if (measurement.GetMeasurementType().Equals(AnalogMeasurementType.FEEDER_CURRENT.ToString()))
                            {
                                //element = new Feeder(element);
                                TopologyElements[elementId] = new Feeder(element);
                            }
                        }
                        else
                        {
                            logger.LogWarn($"{message} Element with GID {elementId.ToString("X")} does not exist in elements dictionary.");
                        }
                    }
                    catch (Exception)
                    {
                        logger.LogWarn($"{message} Failed to find appropriate element for mesuremnt with GID {measurement.Id.ToString("X")}. There is no conducting equipment connected to common terminal.");
                    }
                }
                else
                {
                    logger.LogWarn($"{message} Terminal with GID 0x{terminalId.ToString("X16")} does not exist in terminal to element map.");
                }
            }
            else
            {
                logger.LogWarn($"{message} Measurement with GID 0x{measurement.Id.ToString("X16")} does not exist in mesurement to terminal map.");
            }
        }
        public bool TryGetAllModelEntities(
            out Dictionary <long, ITopologyElement> topologyElements,
            out Dictionary <long, List <long> > elementConnections,
            out HashSet <long> reclosers,
            out List <long> energySources)
        {
            TopologyElements.Clear();
            Measurements.Clear();
            EnergySources.Clear();
            ElementConnections.Clear();
            MeasurementToConnectedTerminalMap.Clear();
            TerminalToConnectedElementsMap.Clear();
            BaseVoltages.Clear();
            Reclosers.Clear();

            bool success = true;

            try
            {
                logger.LogInfo("Getting all network model elements and converting them...");
                GetBaseVoltages().Wait();
                Parallel.For(0, ConcreteModels.Count, (i) =>
                {
                    var model = ConcreteModels.ElementAt(i);
                    if (model != ModelCode.BASEVOLTAGE)
                    {
                        List <ModelCode> properties = modelResourcesDesc.GetAllPropertyIds(model);
                        var elements = networkModelGDA.GetExtentValues(model, properties).Result;
                        foreach (var element in elements)
                        {
                            TransformToTopologyElement(element);
                        }
                    }
                });

                foreach (var measurement in Measurements.Values)
                {
                    PutMeasurementsInElements(measurement);
                    Provider.Instance.MeasurementProvider.AddMeasurementElementPair(measurement.Id, measurement.ElementId);
                }

                foreach (var element in TopologyElements.Values)
                {
                    if (element.Measurements.Count == 0)
                    {
                        CreateNoScadaMeasurement(element);
                    }
                }

                topologyElements   = TopologyElements;
                elementConnections = ElementConnections;
                reclosers          = Reclosers;
                energySources      = EnergySources;
            }
            catch (Exception ex)
            {
                logger.LogError($"[NMSManager] Failed in get all network model elements. Exception message: {ex.Message}");
                topologyElements   = null;
                elementConnections = null;
                reclosers          = null;
                energySources      = null;
                success            = false;
            }
            return(success);
        }
        private async Task TransformToTopologyElementAsync(ResourceDescription modelEntity)
        {
            string verboseMessage = $"{baseLogString} entering TransformToTopologyElement method.";

            Logger.LogVerbose(verboseMessage);

            DMSType dmsType;

            dmsType = GetDMSTypeOfTopologyElement(modelEntity.Id);

            if (dmsType == DMSType.DISCRETE)
            {
                Measurement newDiscrete = await GetPopulatedDiscreteMeasurement(modelEntity);

                if (!await Measurements.ContainsKeyAsync(newDiscrete.Id))
                {
                    await Measurements.SetAsync(newDiscrete.Id, newDiscrete);                     //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...)
                }
                var measurementProviderClient = MeasurementProviderClient.CreateClient();
                await measurementProviderClient.AddDiscreteMeasurement(newDiscrete as DiscreteMeasurement);
            }
            else if (dmsType == DMSType.ANALOG)
            {
                Measurement newAnalog = await GetPopulatedAnalogMeasurement(modelEntity);

                if (!await Measurements.ContainsKeyAsync(newAnalog.Id))
                {
                    await Measurements.SetAsync(newAnalog.Id, newAnalog);                     //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...)
                }
                var measurementProviderClient = MeasurementProviderClient.CreateClient();
                await measurementProviderClient.AddAnalogMeasurement(newAnalog as AnalogMeasurement);
            }
            else if (dmsType != DMSType.MASK_TYPE && dmsType != DMSType.BASEVOLTAGE)
            {
                ITopologyElement newElement = await GetPopulatedElement(modelEntity);

                //lock (syncObj)
                //{
                if (!await TopologyElements.ContainsKeyAsync(newElement.Id))
                {
                    await TopologyElements.SetAsync(newElement.Id, newElement);                     //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...)
                }
                else
                {
                    Logger.LogDebug($"{baseLogString} TransformToTopologyElementAsync => TopologyElements contain key {newElement.Id:X16}");
                }
                //}

                if (dmsType == DMSType.ENERGYSOURCE)
                {
                    var energySourcesResult = await EnergySources.TryGetValueAsync(ReliableDictionaryNames.EnergySources);

                    if (energySourcesResult.HasValue)
                    {
                        var energySources = energySourcesResult.Value;
                        energySources.Add(newElement.Id);

                        await EnergySources.SetAsync(ReliableDictionaryNames.EnergySources, energySources);
                    }
                    else
                    {
                        Logger.LogWarning($"{baseLogString} Reliable collection '{ReliableDictionaryNames.EnergySources}' was not defined yet. Handling...");
                        await EnergySources.SetAsync(ReliableDictionaryNames.EnergySources, new List <long>() { newElement.Id });
                    }
                }

                //lock (syncObj)
                //{
                if (!await ElementConnections.ContainsKeyAsync(modelEntity.Id))
                {
                    await ElementConnections.SetAsync(modelEntity.Id, await GetAllReferencedElements(modelEntity));                     //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...)
                }
                else
                {
                    Logger.LogDebug($"{baseLogString} TransformToTopologyElementAsync => ElementConnections contain key {modelEntity.Id:X16}");
                }
                //}
            }
        }
        private async Task <long> PutMeasurementsInElements(IMeasurement measurement)
        {
            string verboseMessage = $"{baseLogString} entering PutMeasurementsInElements method. Measurement GID {measurement?.Id:X16}.";

            Logger.LogVerbose(verboseMessage);

            var enumerableMeasurementToConnectedTerminalMap = await MeasurementToConnectedTerminalMap.GetEnumerableDictionaryAsync();

            if (enumerableMeasurementToConnectedTerminalMap.TryGetValue(measurement.Id, out long terminalId))
            {
                var enumerableTerminalToConnectedElementsMap = await TerminalToConnectedElementsMap.GetEnumerableDictionaryAsync();

                if (enumerableTerminalToConnectedElementsMap.TryGetValue(terminalId, out List <long> connectedElements))
                {
                    try
                    {
                        var elementId = connectedElements.Find(
                            e => GetDMSTypeOfTopologyElement(e) != DMSType.CONNECTIVITYNODE &&
                            GetDMSTypeOfTopologyElement(e) != DMSType.ANALOG);

                        var enumerableTopologyElements = await TopologyElements.GetEnumerableDictionaryAsync();

                        if (enumerableTopologyElements.TryGetValue(elementId, out ITopologyElement element))
                        {
                            if (!element.Measurements.ContainsKey(measurement.Id))
                            {
                                element.Measurements.Add(measurement.Id, measurement.GetMeasurementType());
                            }
                            else
                            {
                                Logger.LogWarning($"{baseLogString} PutMeasurementsInElements => element.Measurements contains key: 0x{measurement.Id:X16}");
                            }

                            measurement.ElementId = elementId;

                            if (measurement is DiscreteMeasurement)
                            {
                                var measurementProviderClient = MeasurementProviderClient.CreateClient();
                                await measurementProviderClient.AddDiscreteMeasurement((DiscreteMeasurement)measurement);
                            }

                            if (measurement.GetMeasurementType().Equals(AnalogMeasurementType.FEEDER_CURRENT.ToString()))
                            {
                                await TopologyElements.SetAsync(elementId, new Feeder(element));
                            }
                            else
                            {
                                await TopologyElements.SetAsync(elementId, element);
                            }
                        }
                        else
                        {
                            Logger.LogError($"{baseLogString} PutMeasurementsInElement => Element with GID 0x{elementId:16X} does not exist in elements dictionary.");
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.LogError($"{baseLogString} PutMeasurementsInElement =>  {e.Message} {Environment.NewLine} {e.StackTrace}");
                        //Logger.LogError($"{baseLogString} PutMeasurementsInElement =>  Failed to find appropriate element for mesuremnt with GID {measurement.Id:16X}. There is no conducting equipment connected to common terminal.");
                    }
                }
                else
                {
                    Logger.LogError($"{baseLogString} PutMeasurementsInElement => Terminal with GID 0x{terminalId:X16} does not exist in terminal to element map.");
                }
            }
            else
            {
                Logger.LogError($"{baseLogString} PutMeasurementsInElement => Measurement with GID {measurement.Id:X16} does not exist in mesurement to terminal map.");
            }
            return(measurement.ElementId);
        }
        public async Task <IModelDelta> TryGetAllModelEntitiesAsync()
        {
            string verboseMessage = $"{baseLogString} entering TryGetAllModelEntities method.";

            Logger.LogVerbose(verboseMessage);

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            ModelDelta modelDelta = new ModelDelta();

            try
            {
                //var clearTasks = new List<Task>
                //{
                await TopologyElements.ClearAsync();

                await Measurements.ClearAsync();

                await EnergySources.ClearAsync();

                await ElementConnections.ClearAsync();

                await MeasurementToConnectedTerminalMap.ClearAsync();

                await TerminalToConnectedElementsMap.ClearAsync();

                await BaseVoltages.ClearAsync();

                await Reclosers.ClearAsync();

                //};

                //Task.WaitAll(clearTasks.ToArray());

                await energySources.SetAsync(ReliableDictionaryNames.EnergySources, new List <long>());

                await reclosers.SetAsync(ReliableDictionaryNames.Reclosers, new HashSet <long>());

                Logger.LogDebug($"{baseLogString} TryGetAllModelEntities => Getting all network model elements and converting them.");

                await GetBaseVoltagesAsync();

                foreach (var model in ConcreteModels)
                {
                    if (model != ModelCode.BASEVOLTAGE)
                    {
                        List <ModelCode> properties = modelResourcesDesc.GetAllPropertyIds(model);
                        var elements = await networkModelGda.GetExtentValuesAsync(model, properties);

                        foreach (var element in elements)
                        {
                            try
                            {
                                await TransformToTopologyElementAsync(element);
                            }
                            catch (Exception e)
                            {
                                Logger.LogError($"{baseLogString} TryGetAllModelEntitiesAsync failed." +
                                                $" {Environment.NewLine} {e.Message} " +
                                                $"{Environment.NewLine} {e.StackTrace}");
                            }
                        }
                    }
                }


                //Parallel.For(0, ConcreteModels.Count, async (i) =>
                //{
                //	var model = ConcreteModels.ElementAt(i);
                //	if (model != ModelCode.BASEVOLTAGE)
                //	{
                //		List<ModelCode> properties = modelResourcesDesc.GetAllPropertyIds(model);
                //		var elements = await networkModelGda.GetExtentValuesAsync(model, properties);
                //		foreach (var element in elements)
                //		{
                //			try
                //			{
                //				await TransformToTopologyElementAsync(element);
                //			}
                //			catch (Exception e)
                //			{
                //				Logger.LogError($"{baseLogString} TryGetAllModelEntitiesAsync failed." +
                //					$" {Environment.NewLine} {e.Message} " +
                //					$"{Environment.NewLine} {e.StackTrace}");
                //			}
                //		}
                //	}
                //});

                var enumerableMeasurements = await Measurements.GetEnumerableDictionaryAsync();

                List <IMeasurement> updatedMeasurements = new List <IMeasurement>(enumerableMeasurements.Count);
                foreach (var measurement in enumerableMeasurements.Values)
                {
                    var elementId = await PutMeasurementsInElements(measurement);

                    var measurementProviderClient = MeasurementProviderClient.CreateClient();
                    await measurementProviderClient.AddMeasurementElementPair(measurement.Id, elementId);

                    updatedMeasurements.Add(measurement);
                }

                foreach (var updatedMeas in updatedMeasurements)
                {
                    await Measurements.SetAsync(updatedMeas.Id, updatedMeas);
                }

                var enumerableTopologyElements = await TopologyElements.GetEnumerableDictionaryAsync();

                List <ITopologyElement> updatedElements = new List <ITopologyElement>(enumerableTopologyElements.Count);
                foreach (var element in enumerableTopologyElements.Values)
                {
                    if (element.Measurements.Count == 0)
                    {
                        await CreateNoScadaMeasurementAsync(element);

                        updatedElements.Add(element);
                    }
                }

                foreach (var updatedEl in updatedElements)
                {
                    await TopologyElements.SetAsync(updatedEl.Id, updatedEl);
                }

                modelDelta.TopologyElements   = enumerableTopologyElements;
                modelDelta.ElementConnections = await ElementConnections.GetEnumerableDictionaryAsync();

                var reclosersResult = await Reclosers.TryGetValueAsync(ReliableDictionaryNames.Reclosers);

                if (reclosersResult.HasValue)
                {
                    modelDelta.Reclosers = reclosersResult.Value;
                }
                else
                {
                    Logger.LogWarning($"{baseLogString} Reliable collection '{ReliableDictionaryNames.Reclosers}' was not defined yet. Handling...");
                    await Reclosers.SetAsync(ReliableDictionaryNames.Reclosers, new HashSet <long>());

                    modelDelta.Reclosers = new HashSet <long>();
                }

                var enegySourcesResult = await EnergySources.TryGetValueAsync(ReliableDictionaryNames.EnergySources);

                if (reclosersResult.HasValue)
                {
                    modelDelta.EnergySources = enegySourcesResult.Value;
                }
                else
                {
                    Logger.LogWarning($"{baseLogString} Reliable collection '{ReliableDictionaryNames.EnergySources}' was not defined yet. Handling...");
                    await EnergySources.SetAsync(ReliableDictionaryNames.EnergySources, new List <long>());

                    modelDelta.EnergySources = new List <long>();
                }
            }
            catch (Exception e)
            {
                string message = $"{baseLogString} TryGetAllModelEntities => Failed in get all network model elements." +
                                 $"{Environment.NewLine} Exception message: {e.Message}" +
                                 $"{Environment.NewLine} Stack trace: {e.StackTrace}";
                Logger.LogError(message);
                throw new Exception(message);
            }

            return(modelDelta);
        }