/// <summary>
        /// Create new <see cref="ParameterValueSet"/> for a <see cref="Parameter"/>
        /// </summary>
        /// <param name="parameter">The <see cref="Parameter"/></param>
        /// <param name="actualOption">The actual <see cref="CDP4Common.DTO.Option"/></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 <see cref="ActualFiniteState"/> to the old ones</param>
        /// <param name="oldValueSets">The old <see cref="ParameterValueSet"/></param>
        /// <param name="newOldValueSetMap">The map that links the new to old <see cref="ParameterValueSet"/></param>
        private void CreateParameterValueSets(Parameter parameter, Guid?actualOption, NpgsqlTransaction transaction, string partition, ISecurityContext securityContext, IReadOnlyDictionary <ActualFiniteState, ActualFiniteState> newOldActualStateMap, IReadOnlyList <ParameterValueSet> oldValueSets, ref Dictionary <ParameterValueSet, ParameterValueSet> newOldValueSetMap)
        {
            if (newOldActualStateMap == null || !newOldActualStateMap.Any())
            {
                // the parameter lost the state dependency
                var oldValueSet = oldValueSets.FirstOrDefault(x => x.ActualOption == actualOption);
                var newValueset = this.CreateParameterValueSet(oldValueSet, parameter, actualOption, null, transaction, partition, securityContext);
                newOldValueSetMap.Add(newValueset, oldValueSet);
                return;
            }

            foreach (var newOldStatePair in newOldActualStateMap)
            {
                ParameterValueSet oldValueSet;
                if (newOldStatePair.Value == null)
                {
                    oldValueSet = null;
                }
                else
                {
                    oldValueSet =
                        oldValueSets.SingleOrDefault(
                            x =>
                            x.ActualOption == actualOption &&
                            x.ActualState == newOldStatePair.Value.Iid);
                }

                var newValueSet = this.CreateParameterValueSet(oldValueSet, parameter, actualOption, newOldStatePair.Key.Iid, transaction, partition, securityContext);
                newOldValueSetMap.Add(newValueSet, oldValueSet);
            }
        }
        /// <summary>
        /// Update a <see cref="Parameter"/> with new <see cref="ParameterValueSet"/>
        /// </summary>
        /// <param name="parameter">The <see cref="Parameter"/></param>
        /// <param name="iteration">The <see cref="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="ActualFiniteState"/></param>
        /// <param name="newOldValueSetMap">The resulting map that links the new to old <see cref="ParameterValueSet"/></param>
        private void UpdateParameter(Parameter parameter, Iteration iteration, NpgsqlTransaction transaction, string partition, ISecurityContext securityContext, IReadOnlyDictionary <ActualFiniteState, ActualFiniteState> newOldActualStateMap, ref Dictionary <ParameterValueSet, ParameterValueSet> newOldValueSetMap)
        {
            var oldValueSets = this.ParameterValueSetService.GetShallow(transaction, partition, parameter.ValueSet, securityContext)
                               .Where(i => i is ParameterValueSet).Cast <ParameterValueSet>().ToList();

            if (parameter.IsOptionDependent)
            {
                foreach (var orderedItem in iteration.Option.OrderBy(x => x.K))
                {
                    var actualOption = Guid.Parse(orderedItem.V.ToString());
                    this.CreateParameterValueSets(parameter, actualOption, transaction, partition, securityContext, newOldActualStateMap, oldValueSets, ref newOldValueSetMap);
                }
            }
            else
            {
                this.CreateParameterValueSets(parameter, null, transaction, partition, securityContext, newOldActualStateMap, oldValueSets, ref newOldValueSetMap);
            }
        }
        /// <summary>
        /// Create a <see cref="ParameterValueSet"/> with a specific option and state. The old value set is used if it exists, otherwise default values are used
        /// </summary>
        /// <param name="oldValue">The old <see cref="ParameterValueSet"/></param>
        /// <param name="parameter">The current <see cref="Parameter"/></param>
        /// <param name="actualOption">The actual <see cref="CDP4Common.DTO.Option"/></param>
        /// <param name="actualState">The <see cref="ActualFiniteState"/></param>
        /// <param name="transaction">The transaction</param>
        /// <param name="partition">The partition</param>
        /// <param name="securityContext">The security context</param>
        /// <returns>The created <see cref="ParameterValueSet"/></returns>
        private ParameterValueSet CreateParameterValueSet(ParameterValueSet oldValue, Parameter parameter, Guid?actualOption, Guid?actualState, NpgsqlTransaction transaction, string partition, ISecurityContext securityContext)
        {
            this.DefaultValueSetFactory.Load(transaction, securityContext);
            var defaultValue = this.DefaultValueSetFactory.CreateDefaultValueArray(parameter.ParameterType);

            var isOldValueNull = oldValue == null;
            var valueSet       = new ParameterValueSet(Guid.NewGuid(), 1)
            {
                Manual       = new ValueArray <string>(isOldValueNull ? defaultValue : oldValue.Manual),
                Computed     = new ValueArray <string>(isOldValueNull ? defaultValue : oldValue.Computed),
                Reference    = new ValueArray <string>(isOldValueNull ? defaultValue : oldValue.Reference),
                Published    = new ValueArray <string>(isOldValueNull ? defaultValue : oldValue.Published),
                Formula      = new ValueArray <string>(isOldValueNull ? defaultValue : oldValue.Formula),
                ActualOption = actualOption,
                ActualState  = actualState,
                ValueSwitch  = isOldValueNull ? CDP4Common.EngineeringModelData.ParameterSwitchKind.MANUAL : oldValue.ValueSwitch
            };

            this.ParameterValueSetService.CreateConcept(transaction, partition, valueSet, parameter);
            return(valueSet);
        }
        /// <summary>
        /// Instantiate and deserialize the properties of a <paramref name="Parameter"/>
        /// </summary>
        /// <param name="jObject">The <see cref="JObject"/> containing the data</param>
        /// <returns>The <see cref="Parameter"/> to instantiate</returns>
        public static CDP4Common.DTO.Parameter FromJsonObject(JObject jObject)
        {
            var iid            = jObject["iid"].ToObject <Guid>();
            var revisionNumber = jObject["revisionNumber"].IsNullOrEmpty() ? 0 : jObject["revisionNumber"].ToObject <int>();
            var parameter      = new CDP4Common.DTO.Parameter(iid, revisionNumber);

            if (!jObject["allowDifferentOwnerOfOverride"].IsNullOrEmpty())
            {
                parameter.AllowDifferentOwnerOfOverride = jObject["allowDifferentOwnerOfOverride"].ToObject <bool>();
            }

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

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

            if (!jObject["expectsOverride"].IsNullOrEmpty())
            {
                parameter.ExpectsOverride = jObject["expectsOverride"].ToObject <bool>();
            }

            if (!jObject["group"].IsNullOrEmpty())
            {
                parameter.Group = jObject["group"].ToObject <Guid?>();
            }

            if (!jObject["isOptionDependent"].IsNullOrEmpty())
            {
                parameter.IsOptionDependent = jObject["isOptionDependent"].ToObject <bool>();
            }

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

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

            if (!jObject["parameterSubscription"].IsNullOrEmpty())
            {
                parameter.ParameterSubscription.AddRange(jObject["parameterSubscription"].ToObject <IEnumerable <Guid> >());
            }

            if (!jObject["parameterType"].IsNullOrEmpty())
            {
                parameter.ParameterType = jObject["parameterType"].ToObject <Guid>();
            }

            if (!jObject["requestedBy"].IsNullOrEmpty())
            {
                parameter.RequestedBy = jObject["requestedBy"].ToObject <Guid?>();
            }

            if (!jObject["scale"].IsNullOrEmpty())
            {
                parameter.Scale = jObject["scale"].ToObject <Guid?>();
            }

            if (!jObject["stateDependence"].IsNullOrEmpty())
            {
                parameter.StateDependence = jObject["stateDependence"].ToObject <Guid?>();
            }

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

            if (!jObject["valueSet"].IsNullOrEmpty())
            {
                parameter.ValueSet.AddRange(jObject["valueSet"].ToObject <IEnumerable <Guid> >());
            }

            return(parameter);
        }