internal static BlobBoundParameterModel CreateExtendedBlobModel(FunctionInstanceSnapshot snapshot, FunctionInstanceArgument argument)
        {
            Debug.Assert(argument != null);

            if (argument.Value == null)
            {
                return null;
            }

            string[] components = argument.Value.Split(new char[] { '/' });

            if (components.Length != 2)
            {
                return null;
            }

            var blobParam = new BlobBoundParameterModel();
            blobParam.IsOutput = argument.IsBlobOutput;
            blobParam.ConnectionStringKey = ConnectionStringProvider.GetPrefixedConnectionStringName(argument.AccountName);

            CloudStorageAccount account = argument.GetStorageAccount();
            if (account == null)
            {
                blobParam.IsConnectionStringMissing = true;
                return blobParam;
            }

            CloudBlockBlob blob = account
                .CreateCloudBlobClient()
                .GetContainerReference(components[0])
                .GetBlockBlobReference(components[1]);

            Guid? blobWriter = GetBlobWriter(blob);

            if (!blobWriter.HasValue)
            {
                blobParam.IsBlobMissing = true;
            }
            else
            {
                blobParam.OwnerId = blobWriter.Value;
                if (blobWriter.Value == snapshot.Id)
                {
                    blobParam.IsBlobOwnedByCurrentFunctionInstance = true;
                }
            }

            return blobParam;
        }
        public static void AddParameterModels(string parameterName, FunctionInstanceArgument argument, ParameterLog log,
            FunctionInstanceSnapshot snapshot, ICollection<ParameterModel> parameterModels)
        {
            if (argument == null)
            {
                throw new ArgumentNullException("argument");
            }
            if (parameterModels == null)
            {
                throw new ArgumentNullException("parameterModels");
            }

            ParameterModel model = new ParameterModel
            {
                Name = parameterName,
                ArgInvokeString = argument.Value
            };

            if (log != null)
            {
                model.Status = Format(log);
            }

            if (argument.IsBlob)
            {
                model.ExtendedBlobModel = LogAnalysis.CreateExtendedBlobModel(snapshot, argument);
            }

            parameterModels.Add(model);

            // Special-case IBinder, which adds sub-parameters.
            BinderParameterLog binderLog = log as BinderParameterLog;

            if (binderLog != null)
            {
                IEnumerable<BinderParameterLogItem> items = binderLog.Items;

                if (items != null)
                {
                    int count = items.Count();
                    model.Status = String.Format(CultureInfo.CurrentCulture, "Bound {0} object{1}.", count, count != 1 ? "s" : String.Empty);

                    foreach (BinderParameterLogItem item in items)
                    {
                        if (item == null)
                        {
                            continue;
                        }

                        ParameterSnapshot itemSnapshot = HostIndexer.CreateParameterSnapshot(item.Descriptor);
                        string itemName = parameterName;
                        if (!string.IsNullOrEmpty(itemSnapshot.AttributeText))
                        {
                            itemName += ": " + itemSnapshot.AttributeText;
                        }
                        FunctionInstanceArgument itemArgument = FunctionIndexer.CreateFunctionInstanceArgument(item.Value, item.Descriptor);

                        AddParameterModels(itemName, itemArgument, item.Log, snapshot, parameterModels);
                    }
                }
            }
        }