File: System\Runtime\DurableInstancing\InstancePersistence.cs
Project: ndp\cdf\src\NetFx40\System.Runtime.DurableInstancing\System.Runtime.DurableInstancing.csproj (System.Runtime.DurableInstancing)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
 
namespace System.Runtime.DurableInstancing
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Runtime;
    using System.Xml.Linq;
 
    static class InstancePersistence
    {
        static readonly XNamespace activitiesCommandNamespace = XNamespace.Get("urn:schemas-microsoft-com:System.Activities.Persistence/command");
        static readonly XNamespace activitiesEventNamespace = XNamespace.Get("urn:schemas-microsoft-com:System.Activities.Persistence/event");
 
        internal static XNamespace ActivitiesCommandNamespace
        {
            get
            {
                return InstancePersistence.activitiesCommandNamespace;
            }
        }
 
        internal static XNamespace ActivitiesEventNamespace
        {
            get
            {
                return InstancePersistence.activitiesEventNamespace;
            }
        }
 
        public static void ValidatePropertyBag(this IDictionary<XName, InstanceValue> bag)
        {
            bag.ValidatePropertyBag(false);
        }
 
        public static void ValidatePropertyBag(this IDictionary<XName, InstanceValue> bag, bool allowDelete)
        {
            if (bag != null)
            {
                foreach (KeyValuePair<XName, InstanceValue> property in bag)
                {
                    property.ValidateProperty(allowDelete);
                }
            }
        }
 
        public static void ValidateProperty(this KeyValuePair<XName, InstanceValue> property)
        {
            property.ValidateProperty(false);
        }
 
        public static void ValidateProperty(this KeyValuePair<XName, InstanceValue> property, bool allowDelete)
        {
            if (property.Key == null)
            {
                throw Fx.Exception.AsError(new InvalidOperationException(SRCore.MetadataCannotContainNullKey));
            }
            if (property.Value == null)
            {
                throw Fx.Exception.AsError(new InvalidOperationException(SRCore.MetadataCannotContainNullValue(property.Key)));
            }
            if (!allowDelete && property.Value.IsDeletedValue)
            {
                throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InitialMetadataCannotBeDeleted(property.Key)));
            }
        }
 
        public static bool IsOptional(this InstanceValue value)
        {
            return (value.Options & InstanceValueOptions.Optional) != 0;
        }
 
        public static bool IsWriteOnly(this InstanceValue value)
        {
            return (value.Options & InstanceValueOptions.WriteOnly) != 0;
        }
 
        public static ReadOnlyDictionaryInternal<XName, InstanceValue> ReadOnlyCopy(this IDictionary<XName, InstanceValue> bag, bool allowWriteOnly)
        {
            if (bag != null && bag.Count > 0)
            {
                Dictionary<XName, InstanceValue> copy = new Dictionary<XName, InstanceValue>(bag.Count);
                foreach (KeyValuePair<XName, InstanceValue> value in bag)
                {
                    value.ValidateProperty();
                    if (!value.Value.IsWriteOnly())
                    {
                        copy.Add(value.Key, value.Value);
                    }
                    else if (!allowWriteOnly)
                    {
                        throw Fx.Exception.AsError(new InvalidOperationException(SRCore.LoadedWriteOnlyValue));
                    }
                }
                return new ReadOnlyDictionaryInternal<XName, InstanceValue>(copy);
            }
            else
            {
                return null;
            }
        }
 
        public static ReadOnlyDictionaryInternal<XName, InstanceValue> ReadOnlyMergeInto(this IDictionary<XName, InstanceValue> bag, IDictionary<XName, InstanceValue> existing, bool allowWriteOnly)
        {
            Fx.Assert(existing == null || existing is ReadOnlyDictionaryInternal<XName, InstanceValue>, "Should only be merging into other read-only dictionaries.");
 
            if (bag != null && bag.Count > 0)
            {
                Dictionary<XName, InstanceValue> copy = existing == null ? new Dictionary<XName, InstanceValue>(bag.Count) : new Dictionary<XName, InstanceValue>(existing);
                foreach (KeyValuePair<XName, InstanceValue> value in bag)
                {
                    value.ValidateProperty(true);
                    if (value.Value.IsDeletedValue)
                    {
                        copy.Remove(value.Key);
                    }
                    else if (!value.Value.IsWriteOnly())
                    {
                        copy[value.Key] = value.Value;
                    }
                    else if (!allowWriteOnly)
                    {
                        throw Fx.Exception.AsError(new InvalidOperationException(SRCore.LoadedWriteOnlyValue));
                    }
                    else
                    {
                        copy.Remove(value.Key);
                    }
                }
                return new ReadOnlyDictionaryInternal<XName, InstanceValue>(copy);
            }
            else
            {
                return (ReadOnlyDictionaryInternal<XName, InstanceValue>)existing;
            }
        }
    }
}