Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/RevitParamsChecker/Models/Checks/Check.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public Check() {

public string Name { get; set; }

public CheckTargetType TargetType { get; set; } = CheckTargetType.Element;

public HashSet<string> Filters { get; set; } = [];

public HashSet<string> Files { get; set; } = [];
Expand All @@ -17,6 +19,7 @@ public Check() {
public Check Copy() {
return new Check() {
Name = Name,
TargetType = TargetType,
Filters = [..Filters],
Files = [..Files],
Rules = [..Rules]
Expand Down
6 changes: 6 additions & 0 deletions src/RevitParamsChecker/Models/Checks/CheckTargetType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace RevitParamsChecker.Models.Checks;

internal enum CheckTargetType {
Element = 0,
Material = 1
}
25 changes: 25 additions & 0 deletions src/RevitParamsChecker/Models/Revit/RevitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,31 @@ public ICollection<ElementModel> GetElements(DocumentModel doc, Filter filter) {
.ToArray();
}

public ICollection<Material> GetElementMaterials(Element element) {
if(element is null) {
throw new ArgumentNullException(nameof(element));
}

var doc = element.Document;
var ids = new HashSet<ElementId>();
foreach(var id in element.GetMaterialIds(false)) {
ids.Add(id);
}

foreach(var id in element.GetMaterialIds(true)) {
ids.Add(id);
}

List<Material> materials = [];
foreach(var id in ids) {
if(doc.GetElement(id) is Material m) {
materials.Add(m);
}
}

return materials;
}

public void SelectElements(ICollection<ElementModel> elements) {
#if REVIT_2023_OR_GREATER
ActiveUIDocument.Selection.SetReferences(elements.Select(e => e.Reference).ToArray());
Expand Down
7 changes: 7 additions & 0 deletions src/RevitParamsChecker/RevitParamsCheckerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,12 @@ private void BindServices(IKernel kernel) {
kernel.Bind<NamesService>()
.ToSelf()
.InSingletonScope();

kernel.Bind<ChecksEngine>()
.To<ElementChecksEngine>()
.InSingletonScope();
kernel.Bind<ChecksEngine>()
.To<MaterialChecksEngine>()
.InSingletonScope();
}
}
34 changes: 12 additions & 22 deletions src/RevitParamsChecker/Services/ChecksEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

using dosymep.SimpleServices;

using RevitParamsChecker.Exceptions;
using RevitParamsChecker.Models.Checks;
using RevitParamsChecker.Models.Filtration;
using RevitParamsChecker.Models.Results;
Expand All @@ -14,14 +13,14 @@

namespace RevitParamsChecker.Services;

internal class ChecksEngine {
private readonly RevitRepository _revitRepo;
private readonly FiltersRepository _filtersRepo;
private readonly RulesRepository _rulesRepo;
private readonly CheckResultsRepository _checkResultsRepo;
private readonly ILocalizationService _localization;
internal abstract class ChecksEngine {
protected readonly RevitRepository _revitRepo;
protected readonly FiltersRepository _filtersRepo;
protected readonly RulesRepository _rulesRepo;
protected readonly CheckResultsRepository _checkResultsRepo;
protected readonly ILocalizationService _localization;

public ChecksEngine(
protected ChecksEngine(
RevitRepository revitRepo,
FiltersRepository filtersRepo,
RulesRepository rulesRepo,
Expand All @@ -34,6 +33,8 @@ public ChecksEngine(
_localization = localization ?? throw new ArgumentNullException(nameof(localization));
}

public abstract CheckTargetType TargetType { get; }

public void Run(Check check, CancellationToken ct = default) {
if(check == null) {
throw new ArgumentNullException(nameof(check));
Expand All @@ -46,20 +47,7 @@ public void Run(Check check, CancellationToken ct = default) {
List<ElementResult> elementResults = [];
foreach(var element in elements) {
ct.ThrowIfCancellationRequested();
try {
bool success = rule.RootRule.Evaluate(element.Element);
var status = success ? StatusCode.Valid : StatusCode.Invalid;
elementResults.Add(new ElementResult(element, status, rule.Name));
} catch(ParamNotFoundException exParam) {
elementResults.Add(
new ElementResult(
element,
StatusCode.ParamNotFound,
rule.Name,
_localization.GetLocalizedString("Exceptions.ParamNotFound", exParam.Message)));
} catch(Autodesk.Revit.Exceptions.ApplicationException exRevit) {
elementResults.Add(new ElementResult(element, StatusCode.Error, rule.Name, exRevit.Message));
}
elementResults.Add(EvaluateElement(element, rule));
}

ruleResults.Add(new RuleResult(elementResults, rule.Copy()));
Expand All @@ -69,6 +57,8 @@ public void Run(Check check, CancellationToken ct = default) {
_checkResultsRepo.AddCheckResult(result);
}

protected abstract ElementResult EvaluateElement(ElementModel element, Rule rule);

private ICollection<ElementModel> GetElements(Check check) {
var filters = check.Filters.Select(f => _filtersRepo.GetFilter(f)).ToArray();
var docs = check.Files.Select(c => _revitRepo.GetDocument(c)).ToArray();
Expand Down
39 changes: 39 additions & 0 deletions src/RevitParamsChecker/Services/ElementChecksEngine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using dosymep.SimpleServices;

using RevitParamsChecker.Exceptions;
using RevitParamsChecker.Models.Checks;
using RevitParamsChecker.Models.Filtration;
using RevitParamsChecker.Models.Results;
using RevitParamsChecker.Models.Revit;
using RevitParamsChecker.Models.Rules;

namespace RevitParamsChecker.Services;

internal class ElementChecksEngine : ChecksEngine {
public ElementChecksEngine(
RevitRepository revitRepo,
FiltersRepository filtersRepo,
RulesRepository rulesRepo,
CheckResultsRepository checkResultsRepo,
ILocalizationService localization)
: base(revitRepo, filtersRepo, rulesRepo, checkResultsRepo, localization) {
}

public override CheckTargetType TargetType => CheckTargetType.Element;

protected override ElementResult EvaluateElement(ElementModel element, Rule rule) {
try {
bool success = rule.RootRule.Evaluate(element.Element);
var status = success ? StatusCode.Valid : StatusCode.Invalid;
return new ElementResult(element, status, rule.Name);
} catch(ParamNotFoundException exParam) {
return new ElementResult(
element,
StatusCode.ParamNotFound,
rule.Name,
_localization.GetLocalizedString("Exceptions.ParamNotFound", exParam.Message));
} catch(Autodesk.Revit.Exceptions.ApplicationException exRevit) {
return new ElementResult(element, StatusCode.Error, rule.Name, exRevit.Message);
}
}
}
59 changes: 59 additions & 0 deletions src/RevitParamsChecker/Services/MaterialChecksEngine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;

using dosymep.SimpleServices;

using RevitParamsChecker.Exceptions;
using RevitParamsChecker.Models.Checks;
using RevitParamsChecker.Models.Filtration;
using RevitParamsChecker.Models.Results;
using RevitParamsChecker.Models.Revit;
using RevitParamsChecker.Models.Rules;

namespace RevitParamsChecker.Services;

internal class MaterialChecksEngine : ChecksEngine {
public MaterialChecksEngine(
RevitRepository revitRepo,
FiltersRepository filtersRepo,
RulesRepository rulesRepo,
CheckResultsRepository checkResultsRepo,
ILocalizationService localization)
: base(revitRepo, filtersRepo, rulesRepo, checkResultsRepo, localization) {
}

public override CheckTargetType TargetType => CheckTargetType.Material;

protected override ElementResult EvaluateElement(ElementModel element, Rule rule) {
var materials = _revitRepo.GetElementMaterials(element.Element);
if(materials.Count == 0) {
return new ElementResult(
element,
StatusCode.ParamNotFound,
rule.Name,
_localization.GetLocalizedString("Exceptions.NoMaterials"));
}

StatusCode status = StatusCode.Valid;
string error = string.Empty;
foreach(var material in materials) {
try {
bool success = rule.RootRule.Evaluate(material);
if(!success) {
status = StatusCode.Invalid;
break;
}
} catch(ParamNotFoundException exParam) {
status = StatusCode.ParamNotFound;
error = _localization.GetLocalizedString("Exceptions.MaterialParamNotFound", exParam.Message);
break;
} catch(Autodesk.Revit.Exceptions.ApplicationException exRevit) {
status = StatusCode.Error;
error = exRevit.Message;
break;
}
}

return new ElementResult(element, status, rule.Name, error);
}
}
24 changes: 22 additions & 2 deletions src/RevitParamsChecker/ViewModels/Checks/CheckViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

using dosymep.WPF.ViewModels;

Expand All @@ -21,10 +23,21 @@ internal class CheckViewModel : BaseViewModel, IEquatable<CheckViewModel>, IName
private ObservableCollection<string> _selectedFilters;
private ObservableCollection<string> _selectedRules;
private bool _modified;
private EngineViewModel _selectedEngine;

public CheckViewModel(Check check) {
public CheckViewModel(Check check, IReadOnlyCollection<EngineViewModel> availableEngines) {
_check = check ?? throw new ArgumentNullException(nameof(check));
if(availableEngines is null) {
throw new ArgumentNullException(nameof(availableEngines));
}

if(availableEngines.Count == 0) {
throw new System.ArgumentOutOfRangeException(nameof(availableEngines));
}

Name = _check.Name;
SelectedEngine = availableEngines.FirstOrDefault(e => e.TargetType == _check.TargetType)
?? availableEngines.First();
Modified = true;
SelectedFiles = [.._check.Files];
SelectedFilters = [.._check.Filters];
Expand All @@ -38,6 +51,11 @@ public string Name {
set => RaiseAndSetIfChanged(ref _name, value);
}

public EngineViewModel SelectedEngine {
get => _selectedEngine;
set => RaiseAndSetIfChanged(ref _selectedEngine, value);
}

public string WarningFiles {
get => _warningFiles;
set => RaiseAndSetIfChanged(ref _warningFiles, value);
Expand Down Expand Up @@ -100,6 +118,7 @@ public override int GetHashCode() {

public Check GetCheck() {
_check.Name = Name;
_check.TargetType = SelectedEngine.TargetType;
_check.Files = [..SelectedFiles];
_check.Filters = [..SelectedFilters];
_check.Rules = [..SelectedRules];
Expand All @@ -110,7 +129,8 @@ private void OnModelPropertyChanged(object sender, PropertyChangedEventArgs e) {
if(e.PropertyName == nameof(Name)
|| e.PropertyName == nameof(SelectedFilters)
|| e.PropertyName == nameof(SelectedFiles)
|| e.PropertyName == nameof(SelectedRules)) {
|| e.PropertyName == nameof(SelectedRules)
|| e.PropertyName == nameof(SelectedEngine)) {
Modified = true;
}
}
Expand Down
30 changes: 20 additions & 10 deletions src/RevitParamsChecker/ViewModels/Checks/ChecksPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal class ChecksPageViewModel : BaseViewModel {
private readonly RevitRepository _revitRepo;
private readonly ChecksConverter _checksConverter;
private readonly NamesService _namesService;
private readonly ChecksEngine _checksEngine;
private readonly EngineViewModel[] _availableEngines;
private string _errorText;
private string _dirPath;
private bool _allSelected;
Expand All @@ -50,7 +50,7 @@ public ChecksPageViewModel(
RevitRepository revitRepo,
ChecksConverter checksConverter,
NamesService namesService,
ChecksEngine checksEngine) {
IEnumerable<ChecksEngine> checksEngines) {
OpenFileDialogService = openFileDialogService ?? throw new ArgumentNullException(nameof(openFileDialogService));
SaveFileDialogService = saveFileDialogService ?? throw new ArgumentNullException(nameof(saveFileDialogService));
MessageBoxService = messageBoxService ?? throw new ArgumentNullException(nameof(messageBoxService));
Expand All @@ -62,14 +62,22 @@ public ChecksPageViewModel(
_revitRepo = revitRepo ?? throw new ArgumentNullException(nameof(revitRepo));
_checksConverter = checksConverter ?? throw new ArgumentNullException(nameof(checksConverter));
_namesService = namesService ?? throw new ArgumentNullException(nameof(namesService));
_checksEngine = checksEngine ?? throw new ArgumentNullException(nameof(checksEngine));
if(checksEngines is null) {
throw new ArgumentNullException(nameof(checksEngines));
}

_availableEngines = [..checksEngines.Select(e => new EngineViewModel(e, _localization))];
if(_availableEngines.Length == 0) {
throw new ArgumentOutOfRangeException(nameof(checksEngines));
}

_dirPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

_availableFiles = [.._revitRepo.GetDocuments().Select(d => d.Name)];
_availableFilters = [.._filtersRepo.GetFilters().Select(f => f.Name)];
_availableRules = [.._rulesRepo.GetRules().Select(r => r.Name)];

Checks = [.._checksRepo.GetChecks().Select(c => new CheckViewModel(c) { Modified = false })];
Checks = [.._checksRepo.GetChecks().Select(c => new CheckViewModel(c, _availableEngines) { Modified = false })];
SelectedCheck = Checks.FirstOrDefault();
AddCheckCommand = RelayCommand.Create(AddCheck);
RenameCheckCommand = RelayCommand.Create<CheckViewModel>(RenameCheck, CanRenameCheck);
Expand Down Expand Up @@ -109,6 +117,8 @@ public ChecksPageViewModel(

public ObservableCollection<CheckViewModel> Checks { get; }

public IReadOnlyList<EngineViewModel> AvailableEngines => _availableEngines;

public CheckViewModel SelectedCheck {
get => _selectedCheck;
set => RaiseAndSetIfChanged(ref _selectedCheck, value);
Expand Down Expand Up @@ -142,7 +152,7 @@ private void AddCheck() {
newCheck.Name = _namesService.CreateNewName(
_localization.GetLocalizedString("ChecksPage.NewCheckPrompt"),
Checks.Select(f => f.Name).ToArray());
var vm = new CheckViewModel(newCheck);
var vm = new CheckViewModel(newCheck, _availableEngines);
vm.PropertyChanged += OnCheckChanged;
Checks.Add(vm);
SelectedCheck = vm;
Expand All @@ -168,7 +178,7 @@ private void CopyCheck(CheckViewModel check) {
_localization.GetLocalizedString("ChecksPage.NewCheckPrompt"),
Checks.Select(f => f.Name).ToArray(),
check.Name);
var vm = new CheckViewModel(copyCheck);
var vm = new CheckViewModel(copyCheck, _availableEngines);
vm.PropertyChanged += OnCheckChanged;
Checks.Add(vm);
SelectedCheck = vm;
Expand Down Expand Up @@ -207,9 +217,9 @@ private void ExecuteChecks() {
var ct = progressDialogService.CreateCancellationToken();
progressDialogService.Show();

var checks = Checks.Where(f => f.IsSelected).Select(c => c.GetCheck()).ToArray();
foreach(var check in checks) {
_checksEngine.Run(check, ct);
var checkVms = Checks.Where(f => f.IsSelected).ToArray();
foreach(var checkVm in checkVms) {
checkVm.SelectedEngine.Engine.Run(checkVm.GetCheck(), ct);
}

progressDialogService?.Close();
Expand Down Expand Up @@ -255,7 +265,7 @@ private void Load() {
var vms = _namesService.GetResolvedCollection(
Checks.ToArray(),
checks.Select(c => {
var check = new CheckViewModel(c);
var check = new CheckViewModel(c, _availableEngines);
check.PropertyChanged += OnCheckChanged;
return check;
})
Expand Down
Loading
Loading