//create group and add it into the group hierarchy (top -> down creation) private IfcGroup CreateGroup(string groupName, string classification, IfcGroup parentGroup) { IfcGroup group = _model.Instances.Where <IfcGroup>(g => g.Name == groupName).FirstOrDefault(); if (group == null) { group = _model.Instances.New <IfcGroup>(g => { g.Name = groupName; g.Description = classification; }); } if (parentGroup != null) { //check if it is not already child group. IfcGroup child = parentGroup.GetGroupedObjects <IfcGroup>().Where(g => g.Name == groupName).FirstOrDefault(); if (child == null) { //ad if it is not parentGroup.AddObjectToGroup(group); } } //add to the root groups if this is root (there is no parent group) if (parentGroup == null) { RootGroups.Add(group); } _numCreated++; return(group); }
/// <summary> /// Performs grouping based on the XML data provided. /// </summary> /// <param name="errLog">Stream for err output</param> /// <returns>True if grouping was successful. False otherwise.</returns> public bool PerformGrouping() { errLog = new StringWriter(); if (_xmlDoc == null) { errLog.WriteLine("No input XML data."); return(false); } //get all group nodes XmlNodeList groups = _xmlDoc.GetElementsByTagName("group"); if (groups == null || groups.Count == 0) { errLog.WriteLine("No group rules in the XML document"); return(false); } //clear groups from elements ClearGroups(_rootGroup); //create group for all non-grouped elements IfcGroup noGroup = GetGroup("No group"); if (noGroup == null) { noGroup = _model.Instances.New <IfcGroup>(gr => { gr.Name = "No group"; gr.Description = ""; }); _rootGroup.AddObjectToGroup(noGroup); } List <IfcElement> allElements = _model.Instances.OfType <IfcElement>().ToList(); List <IfcTypeObject> allTypes = _model.Instances.OfType <IfcTypeObject>().ToList(); foreach (XmlNode group in groups) { grpName = GetName(group); if (String.IsNullOrEmpty(grpName)) { errLog.WriteLine("Group without name detected. All information in this group specification will be skipped."); continue; } //search for the existing group with the same name (convert to upper case for the comparison) and create new group if none exists. IfcGroup iGroup = GetGroup(grpName); if (iGroup == null) { iGroup = _model.Instances.New <IfcGroup>(gr => gr.Name = grpName); _rootGroup.AddObjectToGroup(iGroup); } //process all ifc objects specified for the group XmlNodeList elements = ((XmlElement)group).GetElementsByTagName("element"); foreach (XmlNode element in group) { eName = GetName(element); if (String.IsNullOrEmpty(eName)) { errLog.WriteLine("Element without name detected in group '" + grpName + "'. This element will NOT be included in the"); continue; } //get elemType for reflection of attributes IfcType ifcType; if (!IfcMetaData.TryGetIfcType(eName, out ifcType)) { continue; } else { elemType = ifcType.Type; } XbimQueryBuilder qBuilder = new XbimQueryBuilder(elemType); //process all element attributes XmlNodeList attributeGroups = ((XmlElement)element).GetElementsByTagName("attributes"); //there could be different grouping rules for attribute rules inside (all, none, oneOf, any) foreach (XmlNode attrGroup in attributeGroups) { CreateAttributeCondition(qBuilder, attrGroup); } //process element properties XmlNodeList propertyGroups = ((XmlElement)element).GetElementsByTagName("properties"); //there could be different grouping rules for attribute rules inside (all, none, oneOf, any) foreach (XmlNode propGroup in propertyGroups) { CreatePropertyCondition(qBuilder, propGroup); } //element type processing IEnumerable <IPersistIfcEntity> types = null; XmlNodeList elTypeNodeList = (element as XmlElement).GetElementsByTagName("elementType"); foreach (XmlNode elTypeNode in elTypeNodeList) //there should be just one 'elTypeNode' { XbimQueryBuilder typeQueryBuilder = null; elTypeName = elTypeNode.InnerText; if (string.IsNullOrEmpty(elTypeName)) { errLog.WriteLine("Name of the element type is not specified for element of type '" + eName + "'. Element type conditions will not be applied. "); continue; } IfcType ifcTypeLookup; if (!IfcMetaData.TryGetIfcType(eName, out ifcTypeLookup)) { continue; } else { elemType = ifcTypeLookup.Type; } if (!typeof(IfcTypeObject).IsAssignableFrom(elemType)) { errLog.WriteLine("'" + elTypeName + "' is not type object."); continue; } typeQueryBuilder = new XbimQueryBuilder(elTypeName); //type attributes XmlNodeList typeAttrGroups = ((XmlElement)element).GetElementsByTagName("typeAttributes"); foreach (XmlNode typeAttrGrpNode in typeAttrGroups) { CreateAttributeCondition(typeQueryBuilder, typeAttrGrpNode); } //process element type properties XmlNodeList typePropGroups = ((XmlElement)element).GetElementsByTagName("typeProperties"); //there could be different grouping rules for attribute rules inside (all, none, oneOf, any) foreach (XmlNode propGroup in typePropGroups) { CreatePropertyCondition(typeQueryBuilder, propGroup); } types = _model.Instances.Where <IPersistIfcEntity>(typeQueryBuilder.BuildQuery()); break; } //get elements and element type IEnumerable <IPersistIfcEntity> instances = allElements.Where(qBuilder.BuildQuery().Compile()).ToList(); //check elements against element type (if defined) if (types != null) { instances = FilterElementsByType(instances, types); } //add result to the group foreach (var inst in instances) { IfcElement el = inst as IfcElement; if (el != null && allElements.Remove(el)) { IfcTypeObject type = el.GetDefiningType(); if (allTypes.Remove(type)) //ensure that it is not added twice { iGroup.AddObjectToGroup(type); } //get all elements of this type IEnumerable <IfcRelDefinesByType> rels = _model.Instances.Where <IfcRelDefinesByType>(r => r.RelatingType == type); foreach (var rel in rels) { IEnumerable <IfcElement> elemOfType = rel.RelatedObjects.OfType <IfcElement>(); foreach (var item in elemOfType) { allElements.Remove(item); } } //IfcObjectDefinition objDef = inst as IfcObjectDefinition; //if (objDef != null) iGroup.AddObjectToGroup(objDef); } } } } //fill the no-group group with elements which are not in any group foreach (IfcTypeObject element in allTypes) { noGroup.AddObjectToGroup(element); } return(true); }