Global Mapper (GM)
Global Mapper is a comprehensive Revit type-mapping tool that enables users to detect, plan, review, and commit bulk element replacements across families, types, materials, line styles, object styles, and shared parameters.
See also: Specification (Internal)
Overview
Global Mapper provides a unified interface for:
- Family/Type Mapping: Replace family instances with equivalent types from other families
- Duplicate Detection: Identify potential duplicate elements using similarity analysis
- Usage Analysis: Understand material, line style, and object style usage across families
- Deep Scan: Analyze family document contents to extract parameter names, style refs, and material refs
- Shared Parameter Authoring: Bind and embed shared parameters to families/categories
Source:
src/Tools/Common/GM/manifest.yml:1-26
Features
| Feature | Description |
|---|---|
| Duplicates Tab | Detects potential duplicate families, materials, styles, and shared parameters using weighted similarity scoring. Tree nodes show aggregate resolved counts. Inspector pane uses Accept split button (Accept / Accept Once). Metadata expander shows SourceId and InstanceCount. |
| Families Tab | Browse families by category, select target mappings, and configure type replacements |
| Line Styles Tab | View and map line style usage with visual preview |
| Object Styles Tab | View and map object style usage with visual preview |
| Materials Tab | View and map material usage with color preview |
| Shared Parameters Tab | Manage shared parameter bindings across categories and families |
| Cross-View Instance Navigation | Families/SP instance cyclers zoom across views and activate/show the sampled instance |
| Plan + Commit Review Workflow | Main window stages mappings, then Commit Review performs one explicit apply pass |
| Usage-Linked Family Apply Badges | Families rows show OS, MAT, or OS+MAT when Apply is linked from Object Styles/Materials |
| Nested Usage-Link Indicators | Expanded family Object Styles/Materials rows show LK badges (OS/MAT) for rows actively driving linkage |
| Usage-Link Planning Guardrail | Usage-linked family Apply is impact-only; family-owned ops require explicit user ownership of the family row |
| Continue Refresh Pipeline | Continue evicts stale family cache for active category, re-scans, refreshes usage data, and restores expanded detail context |
| Dual-Segment Status Bar | Bottom-left status line renders Global + Active segments and updates live on tab/load/filter/mapping state changes |
| Load-Aware Empty States | All GM tab empty placeholders use load-vs-empty messaging with high-contrast theme brushes |
| Deep Scan | Analyze family documents to extract embedded parameter names, style references, and material references |
| Mapping Persistence | Save and restore mapping targets per-project; restored rows keep Apply=false until user action |
| Conflict Detection | Identify conflicting mappings (including parameter duplicate-target conflicts and type-write policy gating) before applying changes |
Source:
src/Tools/Common/GM/Shell/ViewModels/FamiliesPaneViewModel.cs:305
Source:src/Tools/Common/GM/Shell/ViewModels/SharedParametersPaneViewModel.cs:455
Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:1358
Source:src/Tools/Common/GM/Shell/ViewModels/CommitReviewViewModel.cs:489
Source:src/Tools/Common/GM/Shell/ViewModels/MatchingModels.cs:190
Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.UsageAndFamilies.cs:165
Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:4619
Source:src/Tools/Common/GM/Shell/Services/PlanBuildingService.cs:86
Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:867
Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:814
Source:src/Tools/Common/GM/Shell/ViewModels/UsagePaneViewModel.cs:676
Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.MappingInitAndInfrastructure.cs:487
Commit Review Lifecycle Guarantees
- When opened, Commit Review builds and validates the plan only. No document edits run until the user clicks Apply.
- Apply executes the normalized plan directly through
IMappingService.ApplyPlanAsync(...), then runs verification in the same flow. - Overlay Cancel and Commit Review titlebar close both request cancellation and run graceful shutdown cleanup.
- Overlay cancel wiring is direct (
CancelButton.Click) and setsOverlayState.CancelRequestedwithout throwing on transient DataContext swaps. - Cleanup waits for in-flight apply work to drain before allowing shutdown.
- Apply emits explicit post-apply banners:
- success banner with Applied/Failed/Skipped counts
- failure banner beginning with
Apply completed.(includes Failed/Skipped diagnostics) orApply failed.on exceptions
- Failed apply attempts keep the Commit Review window open so operation errors remain visible.
- Plan building drops style pairs outside the active Line/Object style scopes and surfaces a warning banner instead of sending unsupported style operations to commit.
- Style mappings are normalized to projection
GraphicsStyleIDs before planning/commit so category-ID and style-ID variants resolve to the same operation target. - Object-style scope is explicitly constrained to Detail Items subcategories in both usage indexing and style-plan scope resolution.
- Usage index hydration drops out-of-universe keys so tabs never render stale style/material IDs that are not in the current preview universes.
- Style scope/normalization now uses a shared resolver in both plan and writer paths so accepted style mappings are classified identically during commit.
- Style writer resolution now acquires the active host document through
IRevitCallGatebefore classifying source/target style scope, removing ambient-context dependency during commit. - Scope-mismatch handling logs resolver reasons and explicit fallback acceptance details (line/object usage-backed) to make style commit failures root-cause traceable.
- Material mappings are validated against host-document material existence during plan build; unresolved material pairs are dropped before commit with warning feedback.
- Family reload phases for style/material/nesting/shared-parameter embed now execute through
IRevitCallGatewithout opening a host-document transaction;LoadFamilyis guarded to fail fast if the host document is modifiable. - Shared-parameter host/embed writers now require
ISharedParameterAuthoringServicefrom DI, eliminating silent no-op behavior when authoring dependencies are missing. - Shared-parameter plan building validates symbol-to-family ownership before emitting embed operations, rejecting stale/mismatched SP selections pre-commit.
- While Commit Review is open, the GM main window is disabled (hard guarantee).
- Accept + Continue runs a post-accept refresh pipeline:
- removes the current category families snapshot from session cache
- re-scans families and refreshes usage data
- restores expanded family row-details context so instance cyclers remain available after refresh
- Change apply engine is non-fail-fast across writer stages: writer failures are captured per operation and execution continues through remaining stages.
- Commit Review now includes a full operation-results table (stable operation id, status, stage, source/target, timing, message) in addition to grouped failure summaries.
- Apply results include per-phase timing metrics and total duration for Commit Review diagnostics.
- Apply results now include per-domain summaries (stage-level succeeded/failed/skipped/affected plus family/timing context), surfaced in a dedicated Commit Review section.
- Commit Review uses a staged
TransactionGroup:- Apply begins a transaction group and executes apply + verify inside the group, then keeps the group open
- Commit Review remains modal for the entire apply/accept/rollback session so the transaction group can remain open safely
- Post-apply actions:
- Rollback rolls back the transaction group (discard all changes from that apply session)
- Accept + Continue assimilates the transaction group, closes Commit Review, and returns to GM
- Accept + Close GM assimilates the transaction group, closes Commit Review, and closes GM
Source:
src/Tools/Common/GM/Shell/ViewModels/CommitReviewViewModel.cs:267
Source:src/Tools/Common/GM/Shell/ViewModels/CommitReviewViewModel.cs:286
Source:src/Tools/Common/GM/Shell/ViewModels/CommitReviewViewModel.cs:548
Source:src/Tools/Common/GM/Shell/Views/CommitReviewWindow.xaml.cs:44
Source:src/Tools/Common/GM/Shell/Services/CommitReviewWindowService.cs:61
Source:src/Tools/Common/GM/Shell/ViewModels/CommitReviewViewModel.cs:274
Source:src/Tools/Common/GM/Shell/ViewModels/CommitReviewViewModel.cs:327
Source:src/Tools/Common/GM/Shell/Views/CommitReviewWindow.xaml.cs:60
Source:src/Tools/Common/GM/Shell/Views/CommitReviewWindow.xaml:318
Source:src/Tools/Common/GM/Features/Mapping/Writers/ChangeApplyEngine.cs:69
Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.UsageAndFamilies.cs:236
User Interface
The GM window uses a Fluent Ribbon with six main tabs:
- Duplicates (Index 0) - Duplicate detection and resolution
- Families (Index 1) - Family/type mapping with category filtering
- Line Styles (Index 2) - Line style replacement with preview
- Object Styles (Index 3) - Object style replacement with preview
- Materials (Index 4) - Material replacement with color preview
- Shared Parameters (Index 5) - Parameter binding and authoring
Each tab provides:
- A main DataGrid with source items and target selection dropdowns
- Details-on-demand patterns (expanded row-details for Families, side details pane for Duplicates candidates)
- Duplicates tab data-upfront summary band (counts, top offenders, next actions)
- Nested row-details target columns that mirror top-level target rendering (read-only display + edit-time combobox)
- Nested target default selection logic bound to global Sort Mode + Threshold
- Parent family target changes trigger nested target-list repopulation for expanded rows (manual/saved/externally-originated selections remain sticky)
- Open target dropdowns own mouse-wheel scrolling while hovered; wheel input does not fall through to the host DataGrid
- Dropdown open/close without a logical selection change does not mark rows as user-edited; non-manual rows remain eligible for threshold/sort auto-selection recompute
- Expanded family row usage tabs (Object Styles/Materials) hydrate after usage indices load and auto-refresh in-place for currently expanded/restored rows
- Applied-only filtering keeps externally-originated rows and usage-linked family rows visible
- Usage-pane "Families Using This..." apply indicators for Object Styles and Materials read canonical usage-link state, so indicator badges stay correct even when a referenced family is outside the current Families-tab row scope.
- Empty placeholders are routed through shell-level load-aware message properties (loading vs zero-result copy per tab).
- Visual previews where applicable (color swatches, style weights)
- Action buttons for staging mappings and opening Commit Review
- Duplicates threshold/sort/category changes rebuild from cached detection results (no duplicate re-scan)
- Duplicates search/applied/kind-filter changes refresh through
CollectionView.Filter(no source-row rebuild) - Duplicates family rows are category-scoped from the shared shell category selector, with an in-page selector bound to the same shell state
- Duplicates source grid exposes explicit
Applycheckboxes;Accept AppliedandApplied Onlyboth useApply && HasKeepSelection - Duplicates detail panel exposes full exclusion lifecycle actions (
Exclude,Override This Session,Remove Exclusion,Restore) and exclusion badges (timestamp tooltip fromExcludedAtwhen present) - Duplicates source rows are grouped by
HasCandidateswith explicitWith Candidates/No Candidatesgroup headers - Duplicates tab uses an internal kind filter (
All,Families,Materials,Line Styles,Object Styles,Shared Params) and per-kind summary headers - Family duplicate rows can launch
Edit Type Mapping...to populate_duplicateBatchTypeRules; modal options are similarity-scored and auto-select by threshold - Duplicates rebuilds preserve keep/apply state for all sources (including rows hidden by search/applied filters)
- Shared-parameter candidate exclusions persist with stable type+name keys (not scan-local numeric IDs)
- Shared-parameter duplicate keep/apply choices synchronize into Shared Parameters authoring rows (Map From + Apply) when no explicit user override exists
- Duplicate conflict detection includes duplicate-vs-manual and duplicate multi-target (same source accepted to multiple targets) paths with bulk/single/auto resolution support
- Choosing a non-duplicate winner for duplicate-vs-manual conflict resolution clears that duplicate source row's keep/apply state so row synchronization cannot immediately re-enable the conflicting pair
- Usage-tab duplicate-origin badges are informational (non-click); override happens by editing the target selection directly
Source:
src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:621Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:723Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:814Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:1467Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:664Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:885Source:src/Tools/Common/GM/Shell/ViewModels/DuplicatesPaneViewModel.cs:1537Source:src/Tools/Common/GM/Shell/ViewModels/DuplicatesPaneViewModel.cs:1572Source:src/Tools/Common/GM/Shell/Services/MappingConflictService.cs:467Source:src/Tools/Common/GM/Shell/ViewModels/DuplicatesModels.cs:211Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml.cs:23Source:src/DBTools.Themes/Behaviors/MouseWheelForwarder.cs:53Source:src/DBTools.Core/UI/Behaviors/ComboBoxCommitCommandBehavior.cs:16
Global Header Controls
The header bar provides cross-tab controls:
- Search: Filter visible items by name
- Threshold Slider: Adjust similarity scoring threshold (0-100%)
- Sort Mode: Toggle between Similarity and Alphabetical ordering
- Filters: Hide Unused, Hide Unscanned, Applied Only
Source:
src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:600
Bottom Status Bar
- Left status cell is a single-line composite string:
Global: family/usage/shared-parameter readiness snapshotActive: current tab state (loading, visible rows, and apply-selected counts where applicable)
- Conflict indicator button remains visible at all times and toggles conflict panel with current counts/summary.
- Status updates on tab changes, load transitions, collection changes, and row-level mapping changes.
- Toolbar filter visibility is tab-aware: "Applied Only" hides on Duplicates tab; "Hide Unscanned" shows only on Families and Shared Parameters tabs.
Source:
src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:867
Source:src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:922
Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:4619Source:src/Tools/Common/GM/Shell/Views/GmShellWindow.xaml:4369
Architecture
Module Structure
src/Tools/Common/GM/
+-- GmToolModule.cs # DI module registration entry point
+-- manifest.yml # Tool manifest (window + ribbon registration)
+-- Domain/ # Kernel SSOT (ProjectState) + planning models
+-- Features/ # Feature services (usage, mapping, duplicates, etc.)
| +-- Caching/
| +-- Categories/
| +-- DeepScan/
| +-- Duplicates/
| +-- Families/
| +-- Mapping/
| +-- Previews/
| +-- SavedMappings/
| +-- SharedParameters/
| +-- Similarity/
| +-- Usage/
+-- Shell/ # WPF shell (Views/ViewModels) + shell-level services
| +-- Behaviors/
| +-- Controls/
| +-- Converters/
| +-- Services/
| +-- ViewModels/
| +-- Views/
+-- Tests/ # Unit tests + test support
Source: Directory structure of
src/Tools/Common/GM/
Data Flow
+------------------+
| GmCommand |
+--------+---------+
| Resolves services via DI
v
+------------------+
| GmShellLauncher |
+--------+---------+
| Creates window + ViewModel
v
+-------------------+
| ShellViewModel |
+--------+----------+
|
+------------+------------+------------+------------+
| | | | |
v v v v v
+----------+ +----------+ +---------+ +----------+ +---------+
| Families | | Usage | | Mapping | | Planning | | Kernel |
| Pane VM | | Pane VM | | Service | | Service | | State |
+----------+ +----------+ +---------+ +----------+ +---------+
Kernel Architecture
The ProjectState is the Single Source of Truth (SSOT) for GM domain state. It holds IDs only - no Revit types leak into the kernel.
public sealed class ProjectState
{
public long Version { get; set; }
public SourceSnapshot? SourceSnapshot { get; set; }
public Dictionary<int, FamilyRecord> Families { get; set; } = new();
public UsageIndex Usage { get; set; } = new();
public SharedParameterLedger SharedParameters { get; set; } = new();
public TabStateSet Tabs { get; set; } = new();
public Dictionary<int, string> FamilyNames { get; set; } = new();
public Dictionary<int, string> SymbolNames { get; set; } = new();
public Dictionary<int, IReadOnlyCollection<(string FamilyName, string SymbolName, int Count)>> NestedOwnerNameIndex { get; set; } = new();
}
Source:
src/Tools/Common/GM/Domain/ProjectState.cs:10
The KernelMapper provides read-only projections of kernel data for UI consumption. All projections are version-aware and use a generic GetOrCompute<T> caching pattern:
GetLineStyleFamilyCounts()/GetObjectStyleFamilyCounts()/GetMaterialFamilyCounts()— Usage counts per style/materialGetObjectStylesByFamilyIndex()/GetMaterialsByFamilyIndex()— Reverse lookup: family → styles/materialsGetDeepScanStyleRefsByFamily()/GetDeepScanMaterialRefsByFamily()— DS references by familyGetDeepScanParamNamesByFamily()— DS parameter names by family
Source:
src/Tools/Common/GM/Domain/KernelMapper.cs:54-221
Key Classes
Entry Points
| Class | File | Purpose |
|---|---|---|
GmToolModule |
src/Tools/Common/GM/GmToolModule.cs:8 |
Tool module registration; calls services.AddGm() |
GmCommand |
src/Tools/Common/GM/Shell/GmCommand.cs:13 |
Ribbon command entry point; resolves all services and launches UI |
GmShellLauncher |
src/Tools/Common/GM/Shell/GmShellLauncher.cs:17 |
Static launcher creating GmShellWindow and ShellViewModel |
Source:
src/Tools/Common/GM/GmToolModule.cs:8
View Models
| Class | File | Purpose |
|---|---|---|
ShellViewModel |
src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.*.cs |
Main shell view model (split across partials) |
FamiliesPaneViewModel |
src/Tools/Common/GM/Shell/ViewModels/FamiliesPaneViewModel.cs |
Families tab bindings + commands |
UsagePaneViewModel |
src/Tools/Common/GM/Shell/ViewModels/UsagePaneViewModel.cs |
Usage mapping workflows (matches, options, commands) |
DuplicatesPaneViewModel |
src/Tools/Common/GM/Shell/ViewModels/DuplicatesPaneViewModel.cs |
Duplicates tab state |
SharedParametersPaneViewModel |
src/Tools/Common/GM/Shell/ViewModels/SharedParametersPaneViewModel.cs |
Shared Parameters tab state |
Source:
src/Tools/Common/GM/Shell/ViewModels/FamiliesPaneViewModel.cs:1
Core Services
| Interface | Implementation | Purpose |
|---|---|---|
IProjectLifecycleService |
ProjectLifecycleService |
Build kernel from Revit document |
IProjectQueries |
ProjectQueries |
Query kernel-backed domain views |
IPlanningService |
PlanningService |
Generate normalized mapping plans |
IMappingService |
MappingService |
Apply plans to Revit document (via ChangeApplyEngine) |
IDuplicateDetectionService |
DuplicateDetectionService |
Detect duplicate elements |
INamingSimilarityService |
NamingSimilarityService |
Name-based similarity scoring |
IParameterSimilarityService |
ParameterSimilarityService |
Parameter overlap scoring |
Source:
src/Tools/Common/GM/Shell/Startup.cs:28
Revit Adapters (Change Writers)
All change writers implement IChangeWriter and are dispatched by ChangeApplyEngine via ChangeKind. Individual per-writer interfaces have been removed.
| Implementation | ChangeKind | Purpose |
|---|---|---|
TypeCreationService |
CreateTypes |
Create new type symbols in families |
HostChangeService |
HostReplacements |
Replace host elements when type change requires recreation |
NestingChangeService |
NestedFamilies |
Replace nested family instances by name |
TypeChangeService |
TypeReplacements |
Replace type on instances; execute parameter migrations during type replacements |
StyleChangeService |
StyleReplacements |
Replace line styles (host + family-doc rewrites, creates/syncs target subcategories) |
MaterialChangeServiceWriter |
MaterialReplacements |
Replace materials (host + family-doc rewrites, creates/syncs target materials) |
SharedParameterHostWriter |
SharedParametersHost |
Bind shared parameters to host document categories |
SharedParameterEmbedWriter |
SharedParametersEmbed |
Embed shared parameters into family documents |
Note: Deep scan is executed by DeepScanServiceAdapter (not a change writer).
Source:
src/Tools/Common/GM/Features/Mapping/Writers/IChangeWriter.csSource:src/Tools/Common/GM/Features/Mapping/Writers/ChangeApplyEngine.csSource:src/Tools/Common/GM/Features/Mapping/Writers/StyleChangeService.csSource:src/Tools/Common/GM/Features/Mapping/Writers/MaterialChangeServiceWriter.cs
Configuration
Manifest
id: DBTools.GM
assembly: DBTools
moduleType: DBTools.GM.GmToolModule
order: 0
sandboxWindows:
- id: DBTools.GM.Main
displayName: "Global Mapper"
group: "Common"
windowType: "DBTools.GM.Shell.Views.GmShellWindow"
designTimeViewModelType: "DBTools.GM.Shell.DesignTime.ShellDesignTimeViewModel"
- id: DBTools.GM.CommitReview
displayName: "Global Mapper - Commit Review"
group: "Common"
windowType: "DBTools.GM.Shell.Views.CommitReviewWindow"
designTimeViewModelType: "DBTools.GM.Shell.DesignTime.CommitReviewDesignTimeViewModel"
tool:
ribbonTools:
- internalName: DBTools.GM
commandType: DBTools.GM.Shell.GmCommand
availabilityType: DBTools.App.Availability.DocumentAvailability
runProfile: QueuedModeless
displayText: "Global Mapper"
iconBaseKey: gm
tooltip: "Open Global Mapper"
controlKind: PushButton
order: 30
Source:
src/Tools/Common/GM/manifest.yml:1-26
Caching
GM uses caching strategies (some global, some document-scoped):
| Cache | Strategy | Purpose |
|---|---|---|
| Deep Scan (global) | DeepScanCacheStrategy |
Cache deep-scan results across sessions/documents (portable payload) |
| UI State (document-scoped) | UiStateStrategy |
Persist UI selections between sessions |
| Saved Mappings (document-scoped) | SavedMappingService |
Store user mapping preferences |
Cache files are stored under %APPDATA%/DBTools/Cache/GM/.
Source:
src/Tools/Common/GM/Shell/Startup.cs:108
API Reference
Planning Service
The IPlanningService generates normalized mapping plans:
public interface IPlanningService
{
Task<PlanningResult> BuildPlanAsync(
IReadOnlyDictionary<int, int> typeMappings,
IReadOnlyDictionary<int, int> materialMappings,
IReadOnlyDictionary<int, int> styleMappings,
CancellationToken ct = default);
Task<PlanningResult> BuildPlanAsync(
IReadOnlyDictionary<int, int> typeMappings,
IReadOnlyDictionary<int, int> materialMappings,
IReadOnlyDictionary<int, int> styleMappings,
IReadOnlyCollection<(int sourceId, string? newName)> createType,
ProjectContext? context,
CancellationToken ct = default);
}
Source:
src/Tools/Common/GM/Domain/Planning/IPlanningService.cs:8
Operation Kinds
Plans contain operations of these types:
public enum OperationKind
{
ReplaceType, // Replace type on family instances
ReplaceMaterial, // Replace material parameters
ReplaceStyle, // Replace line/object styles
MapParameter, // Migrate parameter values during type replacements (explicit name mappings)
AddNestedFamily, // Add nested family replacement (by name)
ReplaceHost, // Handle host/placement mismatches
CreateType, // Create new type symbol
BindSharedParameter, // Bind SP at host level
EmbedSharedParameter // Embed SP in family document
}
Source:
src/Tools/Common/GM/Domain/Planning/OperationKind.cs:3
Mapping Service
The IMappingService applies plans to the Revit document:
public interface IMappingService
{
Task ImportAsync(string path, CancellationToken ct = default);
Task ExportAsync(string path, CancellationToken ct = default);
Task ImportSimpleAsync(string path, CancellationToken ct = default);
Task ExportSimpleAsync(string path, CancellationToken ct = default);
Task<MappingValidationResult> ValidateAsync(CancellationToken ct = default);
Task<MappingApplyResult> ApplyAsync(CancellationToken ct = default);
Task<MappingApplyResult> ApplyPlanAsync(PlanningResult plan, IProgress<(string message, double? progress01)>? progress = null,
CancellationToken ct = default);
Task<MappingVerifyResult> VerifyAsync(PlanningResult plan, CancellationToken ct = default);
Task AddDuplicateMappingsAsync(DuplicateApplyBatch batch, CancellationToken ct = default);
}
Source:
src/Tools/Common/GM/Features/Mapping/IMappingService.cs:12
Duplicate Detection
The IDuplicateDetectionService analyzes the kernel for potential duplicates:
public interface IDuplicateDetectionService
{
Task<DuplicateDetectionResult> DetectAsync(
ProjectState kernel,
IProgress<string>? progress = null,
CancellationToken ct = default);
}
Detection uses:
- Families: 70% name similarity + 30% parameter overlap (when DS data available), with floor
combined >= 0.5 - Styles: Preview signature matching (color, weight, pattern), emitted as one directional pair set (
i < j) - Materials: Preview + name similarity
- Shared Parameters: Type display + normalized name
- Family O(n^2) scan performs periodic cancellation checks
- Detection reports progress stages (
families,line-styles,object-styles,materials,shared-parameters) and VM maps these stages to overlay step deltas - DS badge origin tracking: rows display a
DSbadge when the duplicate was found using Deep Scan data; the;ds=userrationale tag persists the origin
Source:
src/Tools/Common/GM/Features/Duplicates/IDuplicateDetectionService.cs:7Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionProgressStages.cs:3Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:42Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:68Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:134Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:176Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:251Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:290Source:src/Tools/Common/GM/Features/Duplicates/DuplicateDetectionService.cs:344Source:src/Tools/Common/GM/Shell/ViewModels/DuplicatesPaneViewModel.cs:653
Testing
GM tests use a shared fixture that opens a dedicated test model:
[NonParallelizable]
public abstract class GmTestFixture
{
protected const string GmModelFileName = "gm_test_model.rvt";
protected UIApplication UiApp { get; private set; }
protected Document? Doc { get; private set; }
protected IRevitCallGate? Gate { get; private set; }
protected ITransactionRunner? TxRunner { get; private set; }
}
Source:
src/Tools/Common/GM/Tests/GMTestFixture.cs:20-53
Test Categories
| Test Class | Purpose |
|---|---|
GM_PlanningServiceTests |
Planning result validation |
GM_MappingServiceTests |
Apply/verify cycle testing |
GM_MappingApplyPlanTests |
End-to-end plan application |
DuplicateDetectionServiceTests |
Duplicate detection accuracy |
GmKernelMapperTests |
Kernel projection correctness |
GmWindowViewModel_*Tests |
ViewModel behavior tests |
Running Tests
# Build test assemblies
bash build.sh BuildTests
# Run via Revit test runner
bash invoke-revit-tests.sh --smart --tool GM -y 2025
Troubleshooting
Common Issues
| Issue | Cause | Resolution |
|---|---|---|
| "No families found" | Category filter too restrictive | Select a different category or clear filters |
| Empty duplicate groups | Similarity threshold too high | Lower the threshold slider |
| Deep scan incomplete | Family document errors | Check Revit error log; try manual deep scan |
| Mapping not applied | Target type not available | Verify target family is loaded in project |
| Conflict panel showing | Multiple sources map to same target | Resolve conflicts in conflict panel |
Logging
GM logs diagnostic information via ILogger. Enable debug logging to see:
- Kernel build timing
- Cache hit/miss statistics
- Plan operation details
- Apply stage progress
_logger.LogDebug("GM: scanned {Count} families for categoryId={CategoryId}",
families.Count, SelectedCategory?.Id);
Source:
src/Tools/Common/GM/Shell/ViewModels/ShellViewModel.CoreAndCommands.cs:1644
Related Documentation
- Architecture Overview - DBTools architecture
- DBTools.Core - Core infrastructure
- Test Pipeline - Test infrastructure
Verification Status
| Check | Status |
|---|---|
| Source anchors for all claims | Yes |
| UNVERIFIED markers where needed | No (all verified) |
| Cross-references added | Yes |
| Examples tested | N/A |
| No assumptions without evidence | Yes |
Verified by: docs-run-20260303-gm-refactor
Date: 2026-03-03