using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace MvdLiteSnoop.MvdLite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
///
/// 用于保存从MVDLite文本中解析出的结构化数据的类。
///
public class MvdData
{
///
/// 文件头部的元数据。
/// 例如:# MVDLite_Version = '2.5.0.0'
///
public Dictionary Metadata { get; set; } = [];
///
/// 路径别名定义列表。
/// 例如: "hasAssignments as (IfcObjectDefinition)->HasAssignments->RelatedObjectsType"
///
public List Aliases { get; set; } = [];
///
/// 实体定义列表。
///
public List EntityDefinitions { get; set; } = [];
}
///
/// 代表一个规则定义
///
public class Alias
{
public string Name { get; set; }
public string SourceType { get; set; }
public string Path { get; set; }
public override string ToString() => $"{Name} as ({SourceType}){Path}";
}
///
/// 代表一个在 "定义" 块中定义的实体。
///
public class EntityDefinition
{
///
/// 继承那一行的名称
///
public string Name { get; set; }
///
/// 定义后的第一行描述
///
public string Description { get; set; }
///
/// 继承自的名称
///
public string InheritsFrom { get; set; }
///
/// 新增:专门存放“类型标签”的值列表
///
public List TypeLabels { get; set; } = [];
///
/// 类型判断
///
public List Conditions { get; set; } = [];
///
/// 约束,每个约束就是一个属性条目
///
public List Constraints { get; set; } = [];
public string IfcMap { get; set; } // 来自 "# IFC_MAP = 'IfcElement'" 这样的注释
public override string ToString() => $"Entity: {Name}" + (string.IsNullOrEmpty(InheritsFrom) ? "" : $" inherits {InheritsFrom}");
}
///
/// 代表一个在 "约束" 块中定义的规则,即一个属性条目
///
public class Constraint
{
///
/// 描述约束规则,如:'预制剪力墙 的属性 \"编号\" 应满足值类型约束规则'
///
public string Description { get; set; }
///
/// 表达式,如:预制剪力墙->任意属性集->任意属性('编号')->属性值[Type]>='STRING'
///
public string Expression { get; set; }
///
///用于解析注释中的额外信息,例如: # PropName = '型号规格',key:PropName,Value:型号规格,Key:Range,Value:>=0
/// 固定只有两个,一个是属性名,一个取值范围
///
public Dictionary Properties { get; set; } = [];
public string ParameterType
{
get
{
if (ValueRange.Contains("实数值"))
{
return "Number";
}
return "Text";
}
}
public string[] Values
{
get
{
if (ValueRange.Contains("值类型"))
{
return [];
}
return [.. Regex.Matches(ValueRange, @"\\""([^""]*)\\""").OfType().Select(m => m.Groups[1].Value)];
}
}
public string PropName => Properties.ContainsKey("PropName") ? Properties["PropName"] : string.Empty;
public string ValueRange => Properties.ContainsKey("Range") ? Properties["Range"] : string.Empty;
public override string ToString() => $"Constraint: {PropName} => {ValueRange}";
}
///
/// 一个静态工具类,用于将MVDLite格式的文本数据解析为结构化的C#对象。
///
public class MvdLiteAssists
{
private enum ParserState
{
Idle, // 用于解析元数据和别名
InDefinition,
InConstraint
}
///
/// 不重名属性
///
///
///
public static HashSet GetDistinctProperties(MvdData mvdData)
{
HashSet properties = [];
List definitions = mvdData.EntityDefinitions;
foreach (var entity in definitions)
{
var constraints = entity.Constraints;
foreach (var cons in constraints)
{
if (string.IsNullOrEmpty(cons.PropName) || string.IsNullOrEmpty(cons.Description))
{
continue;
}
var property = $"{cons.PropName},{cons.ParameterType},{cons.ValueRange}";
//var property = new AfcaArchiProperty
//{
// DefinitionName = entity.Name,
// Name = cons.PropName,
// ValueConstraints = cons.Values,
// IsChecked = false
//};
properties.Add(property);
}
}
return properties;
}
///
/// 解析包含MVDLite数据的文本字符串。
///
/// 要解析的文本内容。
/// 一个包含所有解析后数据的 MvdData 对象。
public static MvdData Parse(string textContent)
{
var mvdData = new MvdData();
if (string.IsNullOrWhiteSpace(textContent)) return mvdData;
var lines = textContent.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
ParserState state = ParserState.Idle;
EntityDefinition currentEntity = null;
Constraint currentConstraint = null;
// 用于匹配不同类型行的正则表达式
var metaRegex = new Regex(@"^#\s*([^=]+?)\s*=\s*'(.*)'");
var aliasRegex = new Regex(@"^(\S+)\s+as\s+\((.*?)\)(.*)");
var entityInheritRegex = new Regex(@"^(\S+)\s+继承\s+(\S+)");
var descriptionCommentRegex = new Regex(@"^#\s*'(.*)'");
var ifcMapCommentRegex = new Regex(@"^#\s*IFC_MAP\s*=\s*'(.*)'");
var propCommentRegex = new Regex(@"^#\s*(\w+)\s*=\s*'(.*)'");
// 新增:专门用于匹配“类型标签”的正则表达式
var typeLabelRegex = new Regex(@"^(\S+)->类型标签\s*=\s*(.*)$");
foreach (var line in lines)
{
var trimmedLine = line.Trim();
if (trimmedLine.StartsWith("定义"))
{
state = ParserState.InDefinition;
currentEntity = new EntityDefinition();
mvdData.EntityDefinitions.Add(currentEntity);
continue;
}
if (trimmedLine.StartsWith("约束"))
{
state = ParserState.InConstraint;
currentConstraint = null;
continue;
}
if (trimmedLine.StartsWith("#BLOCK") || string.IsNullOrWhiteSpace(trimmedLine))
{
if (state == ParserState.InConstraint && currentEntity != null && currentConstraint != null && !string.IsNullOrEmpty(currentConstraint.Expression))
{
currentEntity.Constraints.Add(currentConstraint);
}
currentConstraint = null;
if (string.IsNullOrWhiteSpace(trimmedLine)) continue;
if (trimmedLine.StartsWith("#BLOCK"))
{
state = ParserState.Idle;
currentEntity = null;
continue;
}
}
switch (state)
{
case ParserState.Idle:
Match metaMatch = metaRegex.Match(trimmedLine);
if (metaMatch.Success)
{
mvdData.Metadata[metaMatch.Groups[1].Value.Trim()] = metaMatch.Groups[2].Value;
break;
}
Match aliasMatch = aliasRegex.Match(trimmedLine);
if (aliasMatch.Success)
{
mvdData.Aliases.Add(new Alias
{
Name = aliasMatch.Groups[1].Value,
SourceType = aliasMatch.Groups[2].Value,
Path = aliasMatch.Groups[3].Value.Trim()
});
}
break;
case ParserState.InDefinition:
Match descMatch = descriptionCommentRegex.Match(trimmedLine);
if (descMatch.Success)
{
currentEntity.Description = descMatch.Groups[1].Value;
break;
}
Match ifcMapMatch = ifcMapCommentRegex.Match(trimmedLine);
if (ifcMapMatch.Success)
{
currentEntity.IfcMap = ifcMapMatch.Groups[1].Value;
break;
}
// --- 新增逻辑:优先处理类型标签 ---
Match typeLabelMatch = typeLabelRegex.Match(trimmedLine);
if (typeLabelMatch.Success)
{
string allLabelsRaw = typeLabelMatch.Groups[2].Value;
// 使用正则表达式从长字符串中提取所有被单引号包裹的值
var labelMatches = Regex.Matches(allLabelsRaw, @"'([^']*)'");
var labels = labelMatches.Cast()
.Select(m => m.Groups[1].Value)
.ToList();
currentEntity.TypeLabels.AddRange(labels);
break; // 处理完毕,跳过此行后续逻辑
}
// --- 结束新增逻辑 ---
Match entityInheritMatch = entityInheritRegex.Match(trimmedLine);
if (entityInheritMatch.Success)
{
currentEntity.Name = entityInheritMatch.Groups[1].Value;
currentEntity.InheritsFrom = entityInheritMatch.Groups[2].Value;
}
else if (!trimmedLine.StartsWith("#"))
{
// 其他非注释行、非类型标签行,被视为普通条件
currentEntity.Conditions.Add(trimmedLine);
}
break;
case ParserState.InConstraint:
if (trimmedLine.StartsWith("#"))
{
Match constraintDescMatch = descriptionCommentRegex.Match(trimmedLine);
if (constraintDescMatch.Success)
{
if (currentEntity != null && currentConstraint != null && !string.IsNullOrEmpty(currentConstraint.Expression))
{
currentEntity.Constraints.Add(currentConstraint);
}
currentConstraint = new Constraint { Description = constraintDescMatch.Groups[1].Value };
}
else
{
Match propMatch = propCommentRegex.Match(trimmedLine);
if (propMatch.Success)
{
if (currentConstraint == null) currentConstraint = new Constraint();
currentConstraint.Properties[propMatch.Groups[1].Value] = propMatch.Groups[2].Value;
}
}
}
else
{
if (currentConstraint == null)
{
currentConstraint = new Constraint();
}
currentConstraint.Expression = trimmedLine;
if (currentEntity != null)
{
currentEntity.Constraints.Add(currentConstraint);
}
currentConstraint = null;
}
break;
}
}
if (currentEntity != null && currentConstraint != null && !string.IsNullOrEmpty(currentConstraint.Expression))
{
currentEntity.Constraints.Add(currentConstraint);
}
return mvdData;
}
public static List Lookup(MvdData mvdData, string entityName)
{
// 查找所有匹配的实体定义
return mvdData.EntityDefinitions
.Where(e => e.Name.Equals(entityName, StringComparison.OrdinalIgnoreCase))
.ToList();
}
///
/// 查找所有在其类型标签列表中包含指定名称的实体定义。
///
/// 要搜索的数据源。
/// 要查找的类型标签名称。
/// 一个枚举值,指定比较字符串时是否区分大小写。默认为区分大小写。
/// 一个包含所有匹配的实体定义的列表。
public static List FindByTypeLabel(
MvdData mvdData,
string labelToFind,
StringComparison comparisonType = StringComparison.Ordinal)
{
var allDefinitions = mvdData.EntityDefinitions;
// 如果输入为空,则返回一个空列表
if (allDefinitions == null || string.IsNullOrEmpty(labelToFind) || mvdData.EntityDefinitions.Count == 0)
{
return [];
}
// 使用 LINQ 进行高效查询:
// 遍历所有实体定义(def),
// 并在每个实体的 TypeLabels 列表中查找(Any)是否存在一个标签(label)
// 与要查找的标签(labelToFind)相等。
return [.. allDefinitions.Where(
def => def.TypeLabels.Any(label => label.Equals(labelToFind, comparisonType)))];
}
}