private StringBuilder GenerateMissingMandatoryValuesReport(ConcreteModel model, Assembly assembly)
        {
            StringBuilder report = new StringBuilder();
            //extract names
            Dictionary <string, string> names = GetNames(model.ModelMap, assembly);

            foreach (KeyValuePair <string, SortedDictionary <string, object> > kv in model.ModelMap)
            {
                Type type = assembly.GetType(kv.Key);
                List <PropertyInfo> pInfoList = GetIsMandatoryProperties(type);

                foreach (PropertyInfo pInfo in pInfoList)
                {
                    string propertyName = pInfo.Name.Substring("is".Length);
                    propertyName = propertyName.Substring(0, propertyName.Length - "mandatory".Length);
                    PropertyInfo hasValueProp = type.GetProperty(propertyName + "HasValue");

                    bool firstOccurance = true;
                    foreach (KeyValuePair <string, object> idObjectPair in kv.Value)
                    {
                        if (idObjectPair.Value != null)
                        {
                            if (!(bool)hasValueProp.GetValue(idObjectPair.Value, null))
                            {
                                //no value so add to report
                                if (firstOccurance)
                                {
                                    report.AppendLine("[WARNING] Missing mandatory property " + type.Name + "." + propertyName + " on following entities:");
                                    if (this.missingValuesMap.ContainsKey(idObjectPair.Key))
                                    {
                                        if (!this.missingValuesMap[idObjectPair.Key].Contains(propertyName))
                                        {
                                            this.missingValuesMap[idObjectPair.Key].Add(propertyName);
                                        }
                                    }
                                    else
                                    {
                                        this.missingValuesMap.Add(idObjectPair.Key, new List <string>()
                                        {
                                            propertyName
                                        });
                                    }

                                    firstOccurance = false;
                                }

                                if (this.missingValuesMap.ContainsKey(idObjectPair.Key))
                                {
                                    if (!this.missingValuesMap[idObjectPair.Key].Contains(propertyName))
                                    {
                                        this.missingValuesMap[idObjectPair.Key].Add(propertyName);
                                    }
                                }
                                else
                                {
                                    this.missingValuesMap.Add(idObjectPair.Key, new List <string>()
                                    {
                                        propertyName
                                    });
                                }

                                report.AppendLine("\t - ID: " + idObjectPair.Key + ";" + GetName(names, idObjectPair.Key));
                            }
                        }
                    }
                }
            }
            return(report);
        }
        /// <summary>
        /// Method adds reference to list on property prop
        /// </summary>
        /// <param name="list">list that reference will be added to</param>
        /// <param name="att">attribute containing information about reference</param>
        /// <param name="prop">property containing list</param>
        private void AddReferenceToList(CIMObject element, ref IList list, string attValue, PropertyInfo prop, ConcreteModel model)
        {
            if (!string.IsNullOrEmpty(attValue))
            {
                Type   referencedType = prop.PropertyType;
                string referencedID   = StringManipulationManager.ExtractAllAfterSeparator(attValue, StringManipulationManager.SeparatorSharp);

                string refType = referencedType.ToString();
                if (referencedType.IsGenericType)
                {
                    refType = referencedType.GetGenericArguments()[0].ToString();
                }

                //DataTypes? what about them if in list - should be a way to determine
                object referencedObject = model.GetObjectByID(referencedID);

                if (referencedObject != null)
                {
                    try
                    {
                        list.Add(referencedObject);
                    }
                    catch
                    {
                        OnMessage("Unsuccessful adding item to list on property: " + prop.DeclaringType + "." + prop.Name
                                  + ", elements ID:" + element.ID + " Referenced: " + refType + ", ID: " + referencedID
                                  , MessageLevel.ERROR);
                        string referencedTypeWithoutPrefix = StringManipulationManager.ExtractAllAfterSeparator(refType, StringManipulationManager.SeparatorDot);
                    }
                }
                else
                {
                    OnMessage("Referenced object on property: " + prop.DeclaringType + "." + prop.Name + ", elements ID:" + element.ID + " not in model. Referenced: "
                              + refType + ", ID:" + referencedID
                              , MessageLevel.WARNING);
                    string referencedTypeWithoutPrefix = StringManipulationManager.ExtractAllAfterSeparator(refType, StringManipulationManager.SeparatorDot);
                }
            }
        }
        private void SetReferenceToProperty(CIMObject element, object something, string attValue, PropertyInfo prop, ConcreteModel model)
        {
            if (!string.IsNullOrEmpty(attValue))
            {
                Type   referencedType = prop.PropertyType;
                string referencedID   = StringManipulationManager.ExtractAllAfterSeparator(attValue, StringManipulationManager.SeparatorSharp);


                object referencedObject = model.GetObjectByID(referencedID);
                if (referencedObject == null)
                {
                    if (!(referencedType.GetProperty("Value") != null &&
                          referencedType.GetProperty("Multiplier") != null &&
                          referencedType.GetProperty("Unit") != null) && referencedType.Name != "AbsoluteDate")
                    {
                        OnMessage("Referenced object on property: " + prop.DeclaringType + "." + prop.Name + ", elements ID:" + element.ID + " not in model. Referenced: "
                                  + referencedType.ToString() + ", ID:" + referencedID
                                  , MessageLevel.WARNING);
                        string propertyType = StringManipulationManager.ExtractAllAfterSeparator(referencedType.FullName, StringManipulationManager.SeparatorDot);
                    }
                    ////otherwise its DataType and its already set
                }
                else
                {
                    if (referencedObject.GetType().Equals(referencedType) || referencedObject.GetType().IsSubclassOf(referencedType))
                    {
                        prop.SetValue(something, referencedObject, null);
                    }
                    else
                    {
                        string referencedObjectType = StringManipulationManager.ExtractAllAfterSeparator(referencedObject.GetType().FullName, StringManipulationManager.SeparatorDot);
                        string propertyType         = StringManipulationManager.ExtractAllAfterSeparator(referencedType.FullName, StringManipulationManager.SeparatorDot);
                    }
                }
            }
        }
        /// <summary>
        /// Method instantiates all classes from <c>CIM_Model</c> using class definitions from <c>assembly</c>
        /// All instances will have ID, and properties, that are not references, set and will be stored in model
        /// </summary>
        /// <param name="CIM_Model">model representing cim/xml</param>
        /// <param name="assembly">assembly that contains classes used in model</param>
        private void InstantiateClassesWithSimpleValues(CIMModel CIM_Model, Assembly assembly, ref ConcreteModel concreteModel)
        {
            ////FOREACH TYPE IN MODEL
            foreach (string type in CIM_Model.ModelMap.Keys)
            {
                SortedDictionary <string, CIMObject> objects = CIM_Model.ModelMap[type];
                ////FOREACH OBJECT WITH ID THAT BELONGS TO TYPE
                foreach (string objID in objects.Keys)
                {
                    ////GET THE OBJECT
                    CIMObject element = objects[objID];
                    Type      classType;
                    ////AQUIRE TYPE FROM ASSEMBLY
                    classType = assembly.GetType(ActiveNamespace + "." + type);
                    if (classType == null)
                    {
                        OnMessage("Class for element (" + element.ID + ") not found in assembly:" + ActiveNamespace + "." + type + "  - validation of document failed!"
                                  , MessageLevel.ERROR);
                        continue;
                    }

                    ////WITH TYPE MAKE AN INSTANCE
                    object instance = Activator.CreateInstance(classType);

                    ////AND SET ID TO THAT INSTANCE
                    PropertyInfo propID = classType.GetProperty("ID");
                    propID.SetValue(instance, objID, null);

                    ////SET SIMPLE VALUE ATTRIBUTES
                    ProcessAttributes(assembly, element, classType, instance);

                    ////SAVE OBJECT IN MODEL
                    string insertEl = concreteModel.InsertObjectInModelMap(instance, classType);
                    if (!string.IsNullOrEmpty(insertEl))
                    {
                        OnMessage(string.Format("Inserting in model error on element ID {0} . Message: {1}", objID, insertEl), MessageLevel.WARNING);
                    }
                }
            }
        }
        /// <summary>
        /// Creates ConcreteModel from CIMModel using classes from assembly
        /// </summary>
        /// <param name="CIM_Model">model of cim/xml that is used to create ConcreteModel</param>
        /// <param name="assembly">contains classes for model</param>
        public ConcreteModelBuildingResult GenerateModel(CIMModel CIM_Model, Assembly assembly, string type, ref ConcreteModel model)
        {
            //model = new ConcreteModel();
            result          = new ConcreteModelBuildingResult();
            activeNamespace = type;

            if (CIM_Model != null && assembly != null)
            {
                try
                {
                    //two iterations
                    //- first - only simple value/enumerations and instantiate the class
                    //- second - create connections
                    InstantiateClassesWithSimpleValues(CIM_Model, assembly, ref model);

                    //second iteration for setting up references (excluding dataTypes)GOES HERE
                    ConnectModelElements(CIM_Model, assembly, ref model);

                    result.MissingValues = GenerateMissingMandatoryValuesReport(model, assembly);
                }
                catch (Exception ex)
                {
                    OnMessage(ex.Message, MessageLevel.ERROR);
                }
            }
            else
            {
                OnMessage("Model or assembly are not selected.", MessageLevel.ERROR);
            }

            return(result);
        }
        private void ConnectModelElements(CIMModel CIM_Model, Assembly assembly, ref ConcreteModel concreteModel)
        {
            foreach (string type in CIM_Model.ModelMap.Keys)
            {
                SortedDictionary <string, CIMObject> objects = CIM_Model.ModelMap[type];
                foreach (string objID in objects.Keys)
                {
                    CIMObject element = objects[objID];
                    Type      classType;
                    classType = assembly.GetType(ActiveNamespace + "." + type);
                    if (classType == null)
                    {
                        OnMessage("Element (" + element.ID + ") not found in assembly:" + ActiveNamespace + "."
                                  + type + "  - validation of document failed!", MessageLevel.ERROR);
                        continue;
                    }

                    ////aquire object from concrete model
                    object currentObject = concreteModel.GetObjectByTypeAndID(classType, objID);
                    if (currentObject != null)
                    {
                        foreach (int attKey in element.MyAttributes.Keys)
                        {
                            string propertyName = StringManipulationManager.ExtractShortestName(CIM_Model.ModelContext.ReadAttributeWithCode(attKey), StringManipulationManager.SeparatorDot);
                            propertyName = StringManipulationManager.CreateHungarianNotation(propertyName);

                            if (propertyName.Equals(type))
                            {
                                propertyName = propertyName + "P";
                            }

                            PropertyInfo prop = classType.GetProperty(propertyName);
                            if (prop == null)
                            {
                                OnMessage("Property " + propertyName + " not found in class "
                                          + element.CIMType + ", elements ID:" + element.ID + "  - validation of document failed!", MessageLevel.ERROR);
                                continue;
                            }
                            ////if it is a list or collection of references
                            if (prop.PropertyType.IsGenericType)
                            {
                                Type propertyListType          = prop.PropertyType.GetGenericArguments()[0];
                                List <ObjectAttribute> attList = element.MyAttributes[attKey];
                                ////get the property as IList
                                IList list = (IList)prop.GetValue(currentObject, null);
                                foreach (ObjectAttribute att in attList)
                                {
                                    ////this part should add a reference to IList
                                    if (!IsSimpleValue(propertyListType) && !propertyListType.IsEnum)
                                    {
                                        AddReferenceToList(element, ref list, att.Value, prop, concreteModel);
                                    }
                                }
                            }
                            else
                            {
                                List <ObjectAttribute> attList = element.MyAttributes[attKey];
                                ////if its not a list...
                                ObjectAttribute att = attList.ElementAt(0);

                                if (null != prop && prop.CanWrite)
                                {
                                    if (!IsSimpleValue(prop.PropertyType) && !prop.PropertyType.IsEnum)
                                    {
                                        SetReferenceToProperty(element, currentObject, att.Value, prop, concreteModel);
                                    }
                                }
                            }
                        }
                        ////embeded elements - lists
                        if (element.GetEmbeddedChildren() != null)
                        {
                            foreach (string attKey in element.GetEmbeddedChildren().Keys)
                            {
                                ////first is the name of property
                                string propertyName = StringManipulationManager.ExtractShortestName(attKey, StringManipulationManager.SeparatorDot);
                                propertyName = StringManipulationManager.CreateHungarianNotation(propertyName);

                                if (propertyName.Equals(type))
                                {
                                    propertyName = propertyName + "P";
                                }
                                PropertyInfo prop = classType.GetProperty(propertyName);
                                if (prop != null && prop.PropertyType.IsGenericType)
                                {
                                    Type          propertyListType = prop.PropertyType.GetGenericArguments()[0];
                                    List <string> attList          = element.GetEmbeddedChildren()[attKey];
                                    ////get the property as IList
                                    IList list = (IList)prop.GetValue(currentObject, null);
                                    foreach (string att in attList)
                                    {
                                        ////this part should add a reference to IList
                                        if (!IsSimpleValue(propertyListType) && !propertyListType.IsEnum)
                                        {
                                            AddReferenceToList(element, ref list, att, prop, concreteModel);
                                        }
                                    }
                                }
                                else
                                {
                                    List <string> attList = element.GetEmbeddedChildren()[attKey];
                                    ////if its not a list...
                                    string att = attList.ElementAt(0);

                                    if (prop != null && prop.CanWrite)
                                    {
                                        if (!IsSimpleValue(prop.PropertyType) && !prop.PropertyType.IsEnum)
                                        {
                                            SetReferenceToProperty(element, currentObject, att, prop, concreteModel);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        OnMessage("Object of class:" + classType + ", with ID:" + objID + " not found in model! Unable to create concrete model."
                                  , MessageLevel.ERROR);
                    }
                }
            }
        }