/// <summary>Hashes all of the quads about a blank node.</summary>
        /// <remarks>Hashes all of the quads about a blank node.</remarks>
        /// <param name="id">the ID of the bnode to hash quads for.</param>
        /// <param name="bnodes">the mapping of bnodes to quads.</param>
        /// <param name="namer">the canonical bnode namer.</param>
        /// <returns>the new hash.</returns>
        private static string HashQuads(string id,
                                        IDictionary <string, IDictionary <string, object> > bnodes,
                                        UniqueNamer
                                        namer)
        {
            // return cached hash
            if (bnodes[id].ContainsKey("hash"))
            {
                return((string)bnodes[id]["hash"]);
            }

            // serialize all of bnode's quads
            var            quads  = (IList <RdfDataset.Quad>)bnodes[id]["quads"];
            IList <string> nquads = new List <string>();

            for (var i = 0; i < quads.Count; ++i)
            {
                object name;
                nquads.Add(RdfDatasetUtils.ToNQuad(quads[i],
                                                   quads[i].TryGetValue("name", out name)
                                                       ? (string)((IDictionary <string, object>)name)["value"]
                                                       : null,
                                                   id));
            }

            // sort serialized quads
            nquads.SortInPlace(StringComparer.Ordinal);

            // return hashed quads
            var hash = Sha1hash(nquads);

            bnodes[id]["hash"] = hash;
            return(hash);
        }
        // generates unique and duplicate hashes for bnodes
        /// <exception cref="JsonLD.Core.JsonLdError"></exception>
        public virtual object HashBlankNodes(IEnumerable <string> unnamed_)
        {
#if !PORTABLE
            IList <string> unnamed     = new List <string>(unnamed_);
            IList <string> nextUnnamed = new List <string>();
            IDictionary <string, IList <string> > duplicates = new Dictionary <string, IList <string
                                                                                              > >();
            IDictionary <string, string> unique = new Dictionary <string, string>();

            // NOTE: not using the same structure as javascript here to avoid
            // possible stack overflows
            // hash quads for each unnamed bnode
            for (var hui = 0;; hui++)
            {
                if (hui == unnamed.Count)
                {
                    // done, name blank nodes
                    var            named  = false;
                    IList <string> hashes = new List <string>(unique.Keys);
                    hashes.SortInPlace();
                    foreach (var hash in hashes)
                    {
                        var bnode = unique[hash];
                        namer.GetName(bnode);
                        named = true;
                    }

                    // continue to hash bnodes if a bnode was assigned a name
                    if (named)
                    {
                        // this resets the initial variables, so it seems like it
                        // has to go on the stack
                        // but since this is the end of the function either way, it
                        // might not have to
                        // hashBlankNodes(unnamed);
                        hui         = -1;
                        unnamed     = nextUnnamed;
                        nextUnnamed = new List <string>();
                        duplicates  = new Dictionary <string, IList <string> >();
                        unique      = new Dictionary <string, string>();
                        continue;
                    }

                    // name the duplicate hash bnods
                    // names duplicate hash bnodes
                    // enumerate duplicate hash groups in sorted order
                    hashes = new List <string>(duplicates.Keys);
                    hashes.SortInPlace();

                    // process each group
                    for (var pgi = 0;; pgi++)
                    {
                        if (pgi == hashes.Count)
                        {
                            // done, create JSON-LD array
                            // return createArray();
                            IList <string> normalized = new List <string>();

                            // Note: At this point all bnodes in the set of RDF
                            // quads have been
                            // assigned canonical names, which have been stored
                            // in the 'namer' object.
                            // Here each quad is updated by assigning each of
                            // its bnodes its new name
                            // via the 'namer' object
                            // update bnode names in each quad and serialize
                            for (var cai = 0; cai < quads.Count; ++cai)
                            {
                                var quad = quads[cai];
                                foreach (var attr in new[] { "subject", "object", "name" })
                                {
                                    if (quad.ContainsKey(attr))
                                    {
                                        var qa = (IDictionary <string, object>)quad[attr];
                                        if (qa != null && (string)qa["type"] == "blank node" && ((string)qa["value"]).IndexOf
                                                ("_:c14n") != 0)
                                        {
                                            qa["value"] = namer.GetName((string)qa["value"]);
                                        }
                                    }
                                }

                                normalized.Add(RdfDatasetUtils.ToNQuad(quad,
                                                                       quad.ContainsKey("name"
                                                                                        ) && !(quad["name"] == null)
                                                                           ? (string)((IDictionary <string, object>)((IDictionary <string, object>)quad)
                                                                                      ["name"])["value"]
                                                                           : null));
                            }

                            // sort normalized output
                            normalized.SortInPlace();

                            // handle output format
                            if (options.format != null)
                            {
                                if ("application/nquads".Equals(options.format))
                                {
                                    var rval = string.Empty;
                                    foreach (var n in normalized)
                                    {
                                        rval += n;
                                    }
                                    return(rval);
                                }
                                else
                                {
                                    throw new JsonLdError(JsonLdError.Error.UnknownFormat, options.format);
                                }
                            }

                            var rval_1 = string.Empty;
                            foreach (var n_1 in normalized)
                            {
                                rval_1 += n_1;
                            }
                            return(RdfDatasetUtils.ParseNQuads(rval_1));
                        }

                        // name each group member
                        var group = duplicates[hashes[pgi]];
                        IList <HashResult> results = new List <HashResult>();
                        for (var n_2 = 0;; n_2++)
                        {
                            if (n_2 == group.Count)
                            {
                                // name bnodes in hash order
                                results.SortInPlace(new _IComparer_145());
                                foreach (var r in results)
                                {
                                    // name all bnodes in path namer in
                                    // key-entry order
                                    // Note: key-order is preserved in
                                    // javascript
                                    foreach (var key in r.pathNamer.Existing().GetKeys())
                                    {
                                        namer.GetName(key);
                                    }
                                }

                                // processGroup(i+1);
                                break;
                            }
                            else
                            {
                                // skip already-named bnodes
                                var bnode = group[n_2];
                                if (namer.IsNamed(bnode))
                                {
                                    continue;
                                }

                                // hash bnode paths
                                var pathNamer = new UniqueNamer("_:b");
                                pathNamer.GetName(bnode);
                                var result = HashPaths(bnode, bnodes, namer, pathNamer);
                                results.Add(result);
                            }
                        }
                    }
                }

                // hash unnamed bnode
                var bnode_1 = unnamed[hui];
                var hash_1  = HashQuads(bnode_1, bnodes, namer);

                // store hash as unique or a duplicate
                if (duplicates.ContainsKey(hash_1))
                {
                    duplicates[hash_1].Add(bnode_1);
                    nextUnnamed.Add(bnode_1);
                }
                else
                {
                    if (unique.ContainsKey(hash_1))
                    {
                        IList <string> tmp = new List <string>();
                        tmp.Add(unique[hash_1]);
                        tmp.Add(bnode_1);
                        duplicates[hash_1] = tmp;
                        nextUnnamed.Add(unique[hash_1]);
                        nextUnnamed.Add(bnode_1);
                        Collections.Remove(unique, hash_1);
                    }
                    else
                    {
                        unique[hash_1] = bnode_1;
                    }
                }
            }
#else
            throw new PlatformNotSupportedException();
#endif
        }