Skip to content

Commit 9e4c0ee

Browse files
committed
Added feature to evaluate types on attribute facet
1 parent 5e0ecd0 commit 9e4c0ee

21 files changed

+1983
-1686
lines changed

SolutionTooling/BuildingSmartRepoFiles.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ public static FileInfo GetDocumentationTestCaseFileInfo(string idsFile)
102102
return f;
103103
}
104104

105-
106105
public static IEnumerable<object[]> GetIdsRepositoryTestCaseIdsFiles()
107106
{
108107
// start from current directory and look in relative position for the bs IDS repository

ids-lib.codegen/IfcSchema_AttributesGenerator.cs

Lines changed: 199 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,223 @@
11
using System.Diagnostics;
22
using System.Text;
33
using Xbim.Common.Metadata;
4+
using Xbim.IO.Esent;
5+
using Xbim.Properties;
46

57
namespace IdsLib.codegen;
68

79
class IfcSchema_AttributesGenerator
810
{
11+
private class IfcAttribute
12+
{
13+
public IfcAttribute(string name, string owningClass , string tp)
14+
{
15+
Name = name;
16+
AddClass(owningClass);
17+
AddBase(tp);
18+
}
19+
20+
public string Name { get; init; }
21+
public List<string> XmlBaseTypes { get; set; } = [];
22+
public List<string> ClassesDefining { get; init; } = [];
23+
24+
/// <summary>
25+
/// The IFC type of the backing types
26+
/// </summary>
27+
public List<string> IfcBaseTypes { get; init; } = [];
28+
29+
internal void AddClass(string owningClass)
30+
{
31+
ClassesDefining.Add(owningClass.ToUpperInvariant());
32+
}
33+
34+
internal void AddBase(string tp)
35+
{
36+
if (!IfcBaseTypes.Contains(tp))
37+
{
38+
IfcBaseTypes.Add(tp);
39+
}
40+
}
41+
42+
internal bool TrySetXmlBase(Dictionary<string, typeMetadata> dataTypeDictionary)
43+
{
44+
var xmlBases = IfcBaseTypes.Select(x => GetXmlBase(x, dataTypeDictionary)).Distinct();
45+
if (!xmlBases.Any())
46+
throw new Exception("Invalid measure detected");
47+
XmlBaseTypes = xmlBases.ToList();
48+
XmlBaseTypes.Remove("");
49+
return true;
50+
}
51+
52+
private static string GetXmlBase(string x, Dictionary<string, typeMetadata> dataTypeDictionary)
53+
{
54+
switch (x)
55+
{
56+
case "": // disabled
57+
case "IfcCompoundPlaneAngleMeasure": // disabled
58+
return "";
59+
case "Int64":
60+
return "xs:integer";
61+
case "Boolean":
62+
return "xs:boolean";
63+
case "Double":
64+
return "xs:double";
65+
case "IfcDimensionExtentUsage": // enum
66+
case "IfcSIUnitName":
67+
case "IfcSIPrefix": // enum
68+
case "IfcSurfaceSide": // enum
69+
case "IfcTextPath": // enum
70+
case "IfcBSplineCurveForm": // enum
71+
case "IfcTransitionCode": // enum
72+
case "IfcTrimmingPreference": // enum
73+
case "IfcAheadOrBehind": // enum
74+
case "IfcKnotType": // enum
75+
case "IfcBSplineSurfaceForm": // enum
76+
case "IfcPreferredSurfaceCurveRepresentation": // enum
77+
case "IfcTransitionCurveType": // enum
78+
case "IfcBooleanOperator": // enum
79+
return "xs:string";
80+
}
81+
if (!dataTypeDictionary.TryGetValue(x.ToUpperInvariant(), out var dt))
82+
{
83+
Debug.WriteLine($"Invalid attribute measure: `{x}` not found.");
84+
return "";
85+
}
86+
return dt.XmlBackingType;
87+
}
88+
89+
}
90+
991
/// <summary>
1092
/// SchemaInfo.GeneratedAttributes.cs
1193
/// </summary>
12-
static public string Execute()
94+
static public string Execute(Dictionary<string, typeMetadata> dataTypeDictionary)
1395
{
1496
var source = stub;
15-
1697
foreach (var schemaString in Program.schemas)
17-
{
18-
System.Reflection.Module module = SchemaHelper.GetModule(schemaString);
19-
var metaD = ExpressMetaData.GetMetadata(module);
20-
var sb = new StringBuilder();
98+
{
99+
System.Reflection.Module module = SchemaHelper.GetModule(schemaString);
100+
var metaD = ExpressMetaData.GetMetadata(module);
21101

22-
// trying to find a set of classes that matches the property types
23-
List<string> HandledTypes = new();
24-
foreach (var item in metaD.Types())
25-
{
26-
HandledTypes.Add(item.Name.ToUpperInvariant());
27-
}
28-
Dictionary<string, List<string>> typesByAttribute = new();
29-
foreach (var className in HandledTypes)
30-
{
31-
var daType = metaD.ExpressType(className.ToUpperInvariant());
32-
foreach (var prop in daType.Properties.Values)
33-
{
34-
if (typesByAttribute.TryGetValue(prop.Name, out var lst))
35-
lst.Add(className);
36-
else
37-
{
38-
typesByAttribute.Add(prop.Name, new List<string>() { className });
39-
}
40-
}
41-
}
42-
Debug.WriteLine($"{schemaString}");
43-
foreach (var pair in typesByAttribute)
102+
// create a dictionary that defines the attributes
103+
var attributes = GetAttributes(metaD);
104+
foreach (var item in attributes.Values)
105+
{
106+
item.TrySetXmlBase(dataTypeDictionary);
107+
}
108+
var sb = BuildCode(metaD, attributes);
109+
source = source.Replace($"<PlaceHolder{schemaString}>\r\n", sb.ToString());
110+
}
111+
112+
source = source.Replace($"<PlaceHolderVersion>", VersionHelper.GetFileVersion(typeof(ExpressMetaData)));
113+
return source;
114+
115+
116+
}
117+
118+
private static StringBuilder BuildCode(ExpressMetaData metaD, Dictionary<string, IfcAttribute> owningTypesByAttribute)
119+
{
120+
var sb = new StringBuilder();
121+
122+
// for each pair of attribute and class list
123+
foreach (var attrib in owningTypesByAttribute.Values)
124+
{
125+
var attribute = $"\"{attrib.Name}\"";
126+
// trying to remove all subclasses
127+
// initialize the list of classes to remove
128+
var toRemove = new HashSet<string>();
129+
var onlyTopClasses = attrib.ClassesDefining.ToArray().ToList(); // we start from the entire list, we later remove some
130+
for (int i = 0; i < onlyTopClasses.Count; i++)
131+
{
132+
var thisClassName = onlyTopClasses[i];
133+
var thisClass = metaD.ExpressType(thisClassName);
134+
135+
foreach (var sub in thisClass.AllSubTypes)
136+
{
137+
if (!toRemove.Contains(sub.ExpressNameUpper))
138+
{
139+
toRemove.Add(sub.ExpressNameUpper);
140+
}
141+
}
142+
}
143+
144+
var classesInQuotes = attrib.ClassesDefining.Select(x => $"\"{x}\"").ToArray();
145+
var XmlTypesInQuotes = attrib.XmlBaseTypes.Select(x => $"\"{x}\"").ToArray();
146+
147+
var topClassesInQuotes = onlyTopClasses
148+
.Where(c => !toRemove.Contains(c))
149+
.Select(x => $"\"{x}\"").ToArray();
150+
151+
var line = (attrib.XmlBaseTypes.Any())
152+
? $"\t\tdestinationSchema.AddAttribute({attribute}, new[] {{ {string.Join(", ", topClassesInQuotes)} }}, new[] {{ {string.Join(", ", classesInQuotes)} }}, new[] {{ {string.Join(", ", XmlTypesInQuotes)} }});"
153+
: $"\t\tdestinationSchema.AddAttribute({attribute}, new[] {{ {string.Join(", ", topClassesInQuotes)} }}, new[] {{ {string.Join(", ", classesInQuotes)} }});";
154+
155+
156+
sb.AppendLine(line);
157+
}
158+
159+
return sb;
160+
}
161+
162+
private static Dictionary<string, IfcAttribute> GetAttributes(ExpressMetaData metaD)
163+
{
164+
Dictionary<string, IfcAttribute> owningTypesByAttribute = new();
165+
166+
foreach (var daType in metaD.Types())
167+
{
168+
foreach (var prop in daType.Properties.Values)
169+
{
170+
// we should skip derived and inverse
171+
if (prop.IsInverse || prop.IsDerived)
172+
continue; // no match
173+
var tp = Analyse(prop, metaD);
174+
//if (string.IsNullOrEmpty(tp))
175+
// continue; // no value type
176+
177+
// owning type
178+
if (owningTypesByAttribute.TryGetValue(prop.Name, out var lst))
179+
{
180+
lst.AddClass(daType.Name.ToUpperInvariant());
181+
lst.AddBase(tp);
182+
}
183+
else
184+
{
185+
owningTypesByAttribute.Add(prop.Name, new IfcAttribute(prop.Name, daType.Name, tp));
186+
}
187+
}
188+
}
189+
190+
return owningTypesByAttribute;
191+
}
192+
193+
private static string Analyse(ExpressMetaProperty prop, ExpressMetaData metaD)
194+
{
195+
var tp = prop.PropertyInfo.PropertyType;
196+
197+
if (tp.IsValueType)
198+
{
199+
if (tp.IsGenericType && tp.GetGenericTypeDefinition() == typeof(Nullable<>))
44200
{
45-
var attribute = $"\"{pair.Key}\"";
46-
// trying to remove all subclasses
47-
var toRemove = new HashSet<string>();
48-
var onlyTopClasses = pair.Value.ToList();
49-
for (int i = 0; i < onlyTopClasses.Count; i++)
50-
{
51-
var thisClassName = onlyTopClasses[i];
52-
var thisClass = metaD.ExpressType(thisClassName.ToUpperInvariant());
53-
54-
foreach (var sub in thisClass.AllSubTypes)
55-
{
56-
if(!toRemove.Contains(sub.ExpressNameUpper))
57-
{
58-
toRemove.Add(sub.ExpressNameUpper);
59-
}
60-
}
61-
}
62-
63-
var classesInQuotes = pair.Value.Select(x => $"\"{x}\"").ToArray();
64-
var topClassesInQuotes = onlyTopClasses
65-
.Where(c=> !toRemove.Contains(c))
66-
.Select(x => $"\"{x}\"").ToArray();
67-
var line = $"\t\tdestinationSchema.AddAttribute({attribute}, new[] {{ {string.Join(", ", topClassesInQuotes)} }}, new[] {{ {string.Join(", ", classesInQuotes)} }});";
68-
69-
sb.AppendLine(line);
201+
var t2 = prop.PropertyInfo.PropertyType.GetGenericArguments()[0];
202+
// Debug.WriteLine($"Prop: {prop.Name} : {t2}");
203+
return t2.Name;
70204
}
71-
source = source.Replace($"<PlaceHolder{schemaString}>\r\n", sb.ToString());
205+
// Debug.WriteLine($"Ok Prop: {prop.Name} : {tp.Name}");
206+
return tp.Name;
72207
}
73-
source = source.Replace($"<PlaceHolderVersion>", VersionHelper.GetFileVersion(typeof(ExpressMetaData)));
74-
return source;
75-
}
76-
private const string stub = @"// generated code via ids-lib.codegen using Xbim.Essentials <PlaceHolderVersion> - any changes made directly here will be lost
208+
else
209+
{
210+
// var nm = GetFriendlyTypeName(tp);
211+
// Debug.WriteLine($"### Not ok 1 - Prop: {prop.Name} : {tp.Name}");
212+
}
213+
return "";
214+
}
215+
216+
private const string stub = @"// generated code via ids-lib.codegen using Xbim.Essentials <PlaceHolderVersion> - any changes made directly here will be lost
77217
78218
using System;
79219
80-
namespace IdsLib.IfcSchema;
220+
namespace IdsLib.IfcSchema;
81221
82222
public partial class SchemaInfo
83223
{

ids-lib.codegen/IfcSchema_ClassGenerator.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static string Execute()
1616
foreach (var schema in Program.schemas)
1717
{
1818
System.Reflection.Module module = SchemaHelper.GetModule(schema);
19-
Debug.WriteLine(module.Name);
19+
// Debug.WriteLine(module.Name);
2020
var metaD = ExpressMetaData.GetMetadata(module);
2121

2222
var sb = new StringBuilder();
@@ -27,10 +27,10 @@ public static string Execute()
2727
{
2828
var daType = metaD.ExpressType(className.ToUpperInvariant());
2929
var t = daType.Type.GetInterfaces().Select(x => x.Name).Contains("IExpressValueType");
30-
if (t ) //!string.IsNullOrEmpty(daType?.UnderlyingType?.Name))
31-
{
32-
Debug.WriteLine($"{daType.Name}: {daType.UnderlyingType.Name} - {t}");
33-
}
30+
//if (t ) //!string.IsNullOrEmpty(daType?.UnderlyingType?.Name))
31+
//{
32+
// Debug.WriteLine($"{daType.Name}: {daType.UnderlyingType.Name} - {t}");
33+
//}
3434

3535
// Enriching schema with predefined types
3636
var propPdefT = daType.Properties.Values.FirstOrDefault(x => x.Name == "PredefinedType");

0 commit comments

Comments
 (0)