/// <summary>
        /// Update all the relevant <see cref="CDP4Common.DTO.ParameterBase"/>
        /// </summary>
        /// <param name="actualFiniteStateList">The updated <see cref="CDP4Common.DTO.ActualFiniteStateList"/></param>
        /// <param name="iteration">The <see cref="CDP4Common.DTO.Iteration"/></param>
        /// <param name="transaction">The current transaction</param>
        /// <param name="partition">The current partition</param>
        /// <param name="securityContext">The security context</param>
        /// <param name="newOldActualStateMap">The map that links the new to old <see cref="CDP4Common.DTO.ActualFiniteState"/></param>
        public void UpdateAllStateDependentParameters(ActualFiniteStateList actualFiniteStateList, Iteration iteration, NpgsqlTransaction transaction, string partition, ISecurityContext securityContext, IReadOnlyDictionary <ActualFiniteState, ActualFiniteState> newOldActualStateMap)
        {
            if (iteration == null)
            {
                throw new ArgumentNullException("iteration");
            }

            var parameters = this.ParameterService.GetShallow(transaction, partition, null, securityContext).Where(i => i is Parameter).Cast <Parameter>()
                             .Where(x => x.StateDependence == actualFiniteStateList.Iid).ToList();
            var parameterOverrides = this.ParameterOverrideService.GetShallow(transaction, partition, null, securityContext).Where(i => i is ParameterOverride).Cast <ParameterOverride>()
                                     .Where(x => parameters.Select(p => p.Iid).Contains(x.Parameter)).ToList();

            // update the parameters with the new actual states
            var newOldParameterValueSetMap = new Dictionary <Parameter, IDictionary <ParameterValueSet, ParameterValueSet> >();

            foreach (var parameter in parameters)
            {
                var tmpMap = new Dictionary <ParameterValueSet, ParameterValueSet>();
                this.UpdateParameter(parameter, iteration, transaction, partition, securityContext, newOldActualStateMap, ref tmpMap);
                newOldParameterValueSetMap.Add(parameter, tmpMap);
            }

            // update the parameter override from the updated parameters
            var parameterOrOVerrideValueSetMap = new Dictionary <ParameterOrOverrideBase, IReadOnlyDictionary <ParameterValueSetBase, ParameterValueSetBase> >();

            foreach (var pair in newOldParameterValueSetMap)
            {
                parameterOrOVerrideValueSetMap.Add(pair.Key, pair.Value.ToDictionary(newSet => (ParameterValueSetBase)newSet.Key, oldSet => (ParameterValueSetBase)oldSet.Value));
            }

            foreach (var parameterOverride in parameterOverrides)
            {
                var tmpMap             = new Dictionary <ParameterValueSetBase, ParameterValueSetBase>();
                var overridenParameter = parameters.Single(x => x.Iid == parameterOverride.Parameter);
                this.UpdateParameterOverride(parameterOverride, transaction, partition, securityContext, newOldParameterValueSetMap[overridenParameter], ref tmpMap);
                parameterOrOVerrideValueSetMap.Add(parameterOverride, tmpMap);
            }

            // update the parameter subscription from the updated parameter/overide value sets
            var parameterOrOverrides   = parameters.Cast <ParameterOrOverrideBase>().Union(parameterOverrides).ToList();
            var parameterSubscriptions = this.ParameterSubscriptionService.GetShallow(transaction, partition, null, securityContext).Where(i => i is ParameterSubscription).Cast <ParameterSubscription>()
                                         .Where(x => parameterOrOverrides.SelectMany(p => p.ParameterSubscription).Contains(x.Iid));

            foreach (var parameterSubscription in parameterSubscriptions)
            {
                var subscribedParameterOrOverride = parameterOrOverrides.Single(x => x.ParameterSubscription.Contains(parameterSubscription.Iid));
                this.UpdateParameterSubscription(parameterSubscription, transaction, partition, securityContext, parameterOrOVerrideValueSetMap[subscribedParameterOrOverride]);
            }
        }
        /// <summary>
        /// Instantiate and deserialize the properties of a <paramref name="ActualFiniteStateList"/>
        /// </summary>
        /// <param name="jObject">The <see cref="JObject"/> containing the data</param>
        /// <returns>The <see cref="ActualFiniteStateList"/> to instantiate</returns>
        public static CDP4Common.DTO.ActualFiniteStateList FromJsonObject(JObject jObject)
        {
            var iid                   = jObject["iid"].ToObject <Guid>();
            var revisionNumber        = jObject["revisionNumber"].IsNullOrEmpty() ? 0 : jObject["revisionNumber"].ToObject <int>();
            var actualFiniteStateList = new CDP4Common.DTO.ActualFiniteStateList(iid, revisionNumber);

            if (!jObject["actualState"].IsNullOrEmpty())
            {
                actualFiniteStateList.ActualState.AddRange(jObject["actualState"].ToObject <IEnumerable <Guid> >());
            }

            if (!jObject["excludedDomain"].IsNullOrEmpty())
            {
                actualFiniteStateList.ExcludedDomain.AddRange(jObject["excludedDomain"].ToObject <IEnumerable <Guid> >());
            }

            if (!jObject["excludedPerson"].IsNullOrEmpty())
            {
                actualFiniteStateList.ExcludedPerson.AddRange(jObject["excludedPerson"].ToObject <IEnumerable <Guid> >());
            }

            if (!jObject["excludeOption"].IsNullOrEmpty())
            {
                actualFiniteStateList.ExcludeOption.AddRange(jObject["excludeOption"].ToObject <IEnumerable <Guid> >());
            }

            if (!jObject["modifiedOn"].IsNullOrEmpty())
            {
                actualFiniteStateList.ModifiedOn = jObject["modifiedOn"].ToObject <DateTime>();
            }

            if (!jObject["owner"].IsNullOrEmpty())
            {
                actualFiniteStateList.Owner = jObject["owner"].ToObject <Guid>();
            }

            if (!jObject["possibleFiniteStateList"].IsNullOrEmpty())
            {
                actualFiniteStateList.PossibleFiniteStateList.AddRange(jObject["possibleFiniteStateList"].ToOrderedItemCollection());
            }

            if (!jObject["thingPreference"].IsNullOrEmpty())
            {
                actualFiniteStateList.ThingPreference = jObject["thingPreference"].ToObject <string>();
            }

            return(actualFiniteStateList);
        }
        /// <summary>
        /// Update a <see cref="ActualFiniteStateList"/> by allocating new <see cref="ActualFiniteState"/>
        /// </summary>
        /// <param name="actualFiniteStateList">The <see cref="ActualFiniteStateList"/></param>
        /// <param name="iteration">The <see cref="Iteration"/></param>
        /// <param name="transaction">The current <see cref="NpgsqlTransaction"/></param>
        /// <param name="partition">The partition</param>
        /// <param name="securityContext">The <see cref="ISecurityContext"/></param>
        public void UpdateActualFinisteStateList(ActualFiniteStateList actualFiniteStateList, Iteration iteration, NpgsqlTransaction transaction, string partition, ISecurityContext securityContext)
        {
            // delete the old ActualFiniteState
            var oldActualStates = this.ActualFiniteStateService.GetShallow(transaction, partition, actualFiniteStateList.ActualState, securityContext)
                                  .OfType <ActualFiniteState>().ToList();

            // Gets the possible finite state list of the current processed ActualFiniteStateList
            var pslCollection =
                this.PossibleFiniteStateListService
                .GetShallow(transaction, partition, actualFiniteStateList.PossibleFiniteStateList.Select(item => Guid.Parse(item.V.ToString())), securityContext)
                .OfType <PossibleFiniteStateList>()
                .ToList();

            if (pslCollection.Count != actualFiniteStateList.PossibleFiniteStateList.Count)
            {
                throw new InvalidOperationException("All the Possible finite state lists could not be retrieved.");
            }

            // Build the ordered collection of PossibleFiniteStateList for the current ActualFiniteStateList
            var orderedPslCollection = new List <PossibleFiniteStateList>(pslCollection.Count);

            foreach (var item in actualFiniteStateList.PossibleFiniteStateList.OrderBy(x => x.K))
            {
                var psl = pslCollection.Single(x => x.Iid.ToString() == item.V.ToString());
                orderedPslCollection.Add(psl);
            }

            var newOldActualStateMap = new Dictionary <ActualFiniteState, ActualFiniteState>();

            this.CreateActualStates(orderedPslCollection, 0, null, actualFiniteStateList, transaction, partition, oldActualStates, ref newOldActualStateMap);

            this.StateDependentParameterUpdateService.UpdateAllStateDependentParameters(actualFiniteStateList, iteration, transaction, partition, securityContext, newOldActualStateMap);

            // This is where value-set are cleaned up
            // delete old actual states which will clean up all value sets that depend on it
            foreach (var actualState in oldActualStates)
            {
                if (!this.ActualFiniteStateService.DeleteConcept(transaction, partition, actualState, actualFiniteStateList))
                {
                    throw new InvalidOperationException(string.Format("The actual finite state {0} could not be deleted", actualState.Iid));
                }
            }
        }
        /// <summary>
        /// Create the <see cref="ActualFiniteState"/>s for a <see cref="ActualFiniteStateList"/>
        /// </summary>
        /// <param name="pslCollection">The ordered collection of <see cref="PossibleFiniteStateList"/></param>
        /// <param name="pslIndex">The index of the <see cref="PossibleFiniteStateList"/> in the collection to process</param>
        /// <param name="possibleStateIds">The current collection of <see cref="Guid"/> to use for the <see cref="ActualFiniteState"/> to create</param>
        /// <param name="container">The <see cref="ActualFiniteStateList"/></param>
        /// <param name="transaction">The current <see cref="NpgsqlTransaction"/></param>
        /// <param name="partition">The partition in the database</param>
        /// <param name="oldActualStates">The old <see cref="ActualFiniteState"/></param>
        /// <param name="newOldStateMap">The resulting map that links the new to old <see cref="ActualFiniteState"/></param>
        private void CreateActualStates(IReadOnlyList <PossibleFiniteStateList> pslCollection, int pslIndex, IEnumerable <Guid> possibleStateIds, ActualFiniteStateList container, NpgsqlTransaction transaction, string partition, IReadOnlyList <ActualFiniteState> oldActualStates, ref Dictionary <ActualFiniteState, ActualFiniteState> newOldStateMap)
        {
            var currentPossibleStateIds = possibleStateIds == null ? new List <Guid>() : possibleStateIds.ToList();

            // build the different PossibleStates combination taken from the PossibleFiniteStateLists and create an ActualState for each of these combinations
            foreach (var orderedItem in pslCollection[pslIndex].PossibleState.OrderBy(x => x.K))
            {
                var newPossibleStateIds = currentPossibleStateIds.ToList();
                newPossibleStateIds.Add(Guid.Parse(orderedItem.V.ToString()));

                // Last PossibleFiniteStateList in the ordered collection
                if (pslIndex == pslCollection.Count - 1)
                {
                    // create actual state
                    var newActualstate = new ActualFiniteState(Guid.NewGuid(), 1);
                    newActualstate.PossibleState.AddRange(newPossibleStateIds);

                    this.ActualFiniteStateService.CreateConcept(transaction, partition, newActualstate, container);

                    var oldActualState =
                        oldActualStates.FirstOrDefault(x => x.PossibleState.All(ps => newPossibleStateIds.Contains(ps)));

                    newActualstate.Kind = oldActualState?.Kind ?? ActualFiniteStateKind.MANDATORY;

                    newOldStateMap.Add(newActualstate, oldActualState);
                    continue;
                }

                this.CreateActualStates(pslCollection, pslIndex + 1, newPossibleStateIds, container, transaction, partition, oldActualStates, ref newOldStateMap);
            }
        }