/// <summary>
        /// Mark as used
        /// </summary>
        /// <param name="enu"></param>
        /// <returns></returns>
        public static bool MarkAsUsed(Enumeration enu)
        {

            // This will check the literal count against bound vocab sets
            // if the enu is currently a concept domain
            if (enu is ConceptDomain && (enu as ConceptDomain).ContextBinding != null)
                enu = (enu as ConceptDomain).ContextBinding[0];
            
            if(!m_markedForUse.Contains(enu))
                m_markedForUse.Add(enu);
            return true;
        }
        /// <summary>
        /// Determine if we'll render this or not
        /// </summary>
        public static string WillRender(Enumeration enu)
        {


            if (!String.IsNullOrEmpty(Datatypes.GetBuiltinVocabulary(enu.Name)))
                return enu.Name;

            // This will check the literal count against bound vocab sets
            // if the enu is currently a concept domain
            if (enu is ConceptDomain && (enu as ConceptDomain).ContextBinding != null && (enu as ConceptDomain).ContextBinding.Count == 1)
                enu = (enu as ConceptDomain).ContextBinding[0];
            else if (enu is ConceptDomain && (enu as ConceptDomain).ContextBinding != null && (enu as ConceptDomain).ContextBinding.Count > 1) // HACK: If there is more than one context binding create a new value set, clear the binding and then re-bind
            {
                // Create the VS
                ValueSet vsNew = new ValueSet()
                {
                    Name = String.Format("{0}AutoGen", enu.Name),
                    BusinessName = enu.BusinessName,
                    Documentation = new Documentation()
                    {
                        Description = new List<string>(new string[] { 
                            String.Format("Value set has automatically been generated by GPMR to allow binding to ConceptDomain '{0}'", enu.Name)
                        }),
                        Rationale = new List<string>()
                    },
                    Id = enu.Id,
                    Literals = new List<Enumeration.EnumerationValue>(),
                    MemberOf = enu.MemberOf,
                    OwnerRealm = enu.OwnerRealm
                };
                    
                // Add literals and documentation
                vsNew.Documentation.Rationale.Add(String.Format("GPMR can normally only redirect context bindings from a concept domain if only 1 is present, however this concept domain has '{0}' present. This value set is a union of content from:", (enu as ConceptDomain).ContextBinding.Count));
                foreach (Enumeration vs in (enu as ConceptDomain).ContextBinding)
                {

                    // If any of the context binding codes are not to be rendered do not render any of them
                    if (WillRender(vs) == String.Empty)
                        return String.Empty;

                    // Output rationale
                    vsNew.Documentation.Rationale.Add(String.Format("<p>- {0} ({1})</p>", vs.Name, vs.EnumerationType));
                    // Add literals
                    vsNew.Literals.AddRange(vs.GetEnumeratedLiterals());
                }
                
                // Now fire parse to add to the domain
                vsNew.FireParsed();

                // Replace the context bindings
                (enu as ConceptDomain).ContextBinding.Clear();
                (enu as ConceptDomain).ContextBinding.Add(vsNew);

                // redirect
                enu = vsNew;

            }
            else if (enu is ConceptDomain)
                return String.Empty;

            // Partial enumerations or suppressed enumerations are not to be included
            if (enu.IsPartial && !RimbaCsRenderer.RenderPartials)
                return String.Empty;

            // Too big
            if (enu.GetEnumeratedLiterals().Count > RimbaCsRenderer.MaxLiterals)
                return String.Empty;

            // Already has a preferred name?
            if (enu.Annotations != null && enu.Annotations.Exists(o => o is RenderAsAnnotation))
                return (enu.Annotations.Find(o => o is RenderAsAnnotation) as RenderAsAnnotation).RenderName;

            // Already being used
            if (m_markedForUse.Exists(o => o.Name == enu.Name && o.GetType() == enu.GetType()))
                return enu.Name;

            string name = enu.Name;

            if (enu.GetEnumeratedLiterals().Count > 0 && enu.GetEnumeratedLiterals().FindAll(l => !l.Annotations.Exists(o => o is SuppressBrowseAnnotation)).Count > 0 &&
                (RimbaCsRenderer.GenerateVocab || (!RimbaCsRenderer.GenerateVocab && enu is ValueSet)))
            {
                // Name collision? Resolve
                if (enu.MemberOf.Find(o => o.Name == enu.Name && o.GetType() != enu.GetType() &&
                    !(o is ConceptDomain)) != null)
                {
                    if (m_markedForUse.Exists(o => o.Name == enu.Name && o.GetType() != enu.GetType()))
                    {
                        name = String.Format("{0}1", enu.Name);
                        if (enu.Annotations == null)
                            enu.Annotations = new List<Annotation>();
                        enu.Annotations.Add(new RenderAsAnnotation() { RenderName = name });
                    }
                }
                return name; // don't process
            }
            return String.Empty;
        }
        /// <summary>
        /// Render literals
        /// </summary>
        private void RenderLiterals(StringWriter sw, Enumeration enu, List<string> rendered, List<String> mnemonics, List<Enumeration.EnumerationValue> literals, string ctorName)
        {
            // Literals
            foreach (Enumeration.EnumerationValue ev in literals)
            {
                string bn = Util.Util.PascalCase(ev.BusinessName);
                string rendName = Util.Util.PascalCase(bn ?? ev.Name) ?? "__Unknown";

                // Already rendered, so warn and skip
                if (rendered.Contains(rendName) || mnemonics.Contains(ev.Name))
                    System.Diagnostics.Trace.WriteLine(String.Format("Enumeration value {0} already rendered, skipping", ev.BusinessName), "warn");
                else if (!ev.Annotations.Exists(o => o is SuppressBrowseAnnotation))
                {
                    sw.Write(DocumentationRenderer.Render(ev.Documentation, 1));
                    if (DocumentationRenderer.Render(ev.Documentation, 1).Length == 0) // Documentation correction
                        sw.WriteLine("\t/** {0} */", (ev.BusinessName ?? ev.Name).Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\r", "").Replace("\n", ""));

                    // Annotations?
                    if (ev.Annotations != null && ev.Annotations.Find(o => o is SuppressBrowseAnnotation) != null)
                    {
                        // Can't suppress browse in Jaba
                        System.Diagnostics.Trace.WriteLine(String.Format("Enumation literal '{0}' won't be rendered as it has SuppressBrowse enabled", ev.Name));
                        //sw.WriteLine("\t\t[EditorBrowsable(EditorBrowsableState.Never)]\r\n\t\t[Browsable(false)]");
                    }

                    // Render ?
                    if (rendered.Find(o => o.Equals(rendName)) != null) // .NET enumeration field will be the same, so render something different
                        sw.Write("\tpublic static final {3} {0} = new {3}(\"{1}\",\"{2}\")", Util.Util.MakeFriendly(rendName + "_" + ev.Name) ?? "__Unknown",
                            ev.Name, ev.CodeSystem ?? enu.ContentOid, Util.Util.MakeFriendly(ctorName));
                    else
                        sw.Write("\tpublic static final {3} {0} = new {3}(\"{1}\",\"{2}\")", rendName, ev.Name, ev.CodeSystem ?? enu.ContentOid, Util.Util.MakeFriendly(ctorName));

                    sw.WriteLine(";"); // Another literal follows

                    sw.Write("\r\n"); // Newline

                    rendered.Add(rendName); // Add to rendered list to keep track
                    mnemonics.Add(ev.Name);

                    
                }
                if (ev.RelatedCodes != null)
                    RenderLiterals(sw, enu, rendered, mnemonics, ev.RelatedCodes, ctorName);
            }
        }
        /// <summary>
        /// Render literals
        /// </summary>
        private void RenderLiterals(StringWriter sw, Enumeration enu, List<string> rendered, List<String> mnemonics, List<Enumeration.EnumerationValue> literals)
        {
            // Literals
            foreach (Enumeration.EnumerationValue ev in literals)
            {
                string bn = Util.Util.PascalCase(ev.BusinessName);
                string rendName = Util.Util.PascalCase(bn ?? ev.Name) ?? "__Unknown";
                
                // Already rendered, so warn and skip
                if (rendered.Contains(rendName) || mnemonics.Contains(ev.Name))
                    System.Diagnostics.Trace.WriteLine(String.Format("Enumeration value {0} already rendered, skipping", ev.BusinessName), "warn");
                else if(!ev.Annotations.Exists(o=>o is SuppressBrowseAnnotation))
                {
                    sw.Write(DocumentationRenderer.Render(ev.Documentation, 2));
                    if (DocumentationRenderer.Render(ev.Documentation, 2).Length == 0) // Documentation correction
                        sw.WriteLine("\t\t/// <summary>{0}</summary>", (ev.BusinessName ?? ev.Name).Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\r", "").Replace("\n", ""));

                    sw.WriteLine("\t\t[Enumeration(Value = \"{0}\", SupplierDomain = \"{1}\")]", ev.Name, ev.CodeSystem ?? enu.ContentOid);

                    // Annotations?
                    if (ev.Annotations != null && ev.Annotations.Find(o => o is SuppressBrowseAnnotation) != null)
                        sw.WriteLine("\t\t[EditorBrowsable(EditorBrowsableState.Never)]\r\n\t\t[Browsable(false)]");

                    // Business name
                    if (!String.IsNullOrEmpty(ev.BusinessName))
                        sw.WriteLine("\t\t[Description(\"{0}\")]", ev.BusinessName.Replace("\r", "").Replace("\n", ""));

                    if (rendered.Find(o => o.Equals(rendName)) != null) // .NET enumeration field will be the same, so render something different
                        sw.Write("\t\t{0}", Util.Util.PascalCase(rendName + "_" + ev.Name) ?? "__Unknown");
                    else
                        sw.Write("\t\t{0}", rendName);

                    sw.WriteLine(","); // Another literal follows

                    sw.Write("\r\n"); // Newline

                    rendered.Add(rendName); // Add to rendered list to keep track
                    mnemonics.Add(ev.Name);

                    
                }
                if (ev.RelatedCodes != null)
                    RenderLiterals(sw, enu, rendered, mnemonics, ev.RelatedCodes);
            }
        }
 /// <summary>
 /// Create structure attribute
 /// </summary>
 private string CreateStructureAnnotation(Enumeration cls)
 {
     return String.Format("@Structure(name = \"{0}\", codeSystem = \"{1}\", structureType = StructureType.{2})", cls.Name, cls.ContentOid, cls.GetType().Name.ToUpper());
 }