/*
         * Adds a KnowledgeComponent to the Unit. Returns true if this KnowledgeComponent is not already a member, and so
         * is added, false otherwise.
         */
        public bool AddComponent(KnowledgeComponent component)
        {
            /*
             * If a KnowledgeComponent of this type has already been previously added, retrieve the HashSet associated
             * with this type and add the KnoweldgeComponent to the HashSet.
             */
            if (LookupComponents(component, out ISet <KnowledgeComponent> components))
            {
                if (components.Add(component))
                {
                    component.ContainingUnit = this;
                    return(true);
                }
                // The HashSet already contained this KnoweledgeComponent; return false.
                return(false);
            }

            // If a set for this component type has not been defined yet, create the set and add the component
            ISet <KnowledgeComponent> newComponents = new HashSet <KnowledgeComponent>
            {
                component
            };

            m_components.Add(GetUnitTypeName(component), newComponents);
            component.ContainingUnit = this;
            return(true);
        }
        /*
         * Removes a KnowledgeComponent from the Unit. Returns true if the Unit contained the KnowledgeComponent, and
         * thus it was successfully removed, false otherwise.
         */
        public bool RemoveComponent(KnowledgeComponent component)
        {
            /*
             * Look up the HashSet associated with the specific type of the KnowledgeComponent and remove the KnowledgeComponent
             * from the HashSet.
             */
            if (LookupComponents(component, out ISet <KnowledgeComponent> components))
            {
                if (components.Remove(component))
                {
                    component.ContainingUnit = null;
                    if (components.Count == 0)
                    {
                        m_components.Remove(GetUnitTypeName(component));
                    }
                    return(true);
                }
            }

            /*
             * If either no KnowledgeComponent of this type has been previously added, or the attempt to remove
             * the KnowledgeComponent failed (so components.Remove() returns false), fall through to here and return false
             * meaning that the Unit did not contain the KnowledgeComponent that was requested to be removed.
             */
            return(false);
        }
        /*
         * Deserialize a Unit from Json. Argument is an IList<JObject>.
         */
        public static Unit DeserializeFromJson(IList <JObject> joList)
        {
            // Create a new Unit that the deserialized KnowledgeComponents will be added to.
            Unit deserializedUnit = new Unit();

            // For each JObject in the list, convert it to a KnowledgeComponent and add it to the Unit.
            foreach (JObject jo in joList)
            {
                KnowledgeComponent kc = ConvertJObjectToKC(jo);
                deserializedUnit.AddComponent(kc);
            }

            return(deserializedUnit);
        }
 /*
  * Returns the type name as a strong of a KnowledgeComponent. Used as a key in the Dictionary of components.
  */
 protected string GetUnitTypeName(KnowledgeComponent component)
 {
     return(component.GetType().FullName);
 }
 /*
  * Given a KnowledgeComponent, returns (in an out variable) the current set of components belonging to this Unit
  * that share the same Knowledgecomponent type.
  */
 private bool LookupComponents(KnowledgeComponent component, out ISet <KnowledgeComponent> components)
 {
     return(m_components.TryGetValue(GetUnitTypeName(component), out components));
 }